未验证 提交 b9badff4 编写于 作者: Y Yibing Liu 提交者: GitHub

Add detailed error messages for nce layer (#20231) (#20341)

* Add detailed error messages for nce layer

* Fix some problems

* Fix unit test coverage

test=release/1.6
上级 f25834a5
......@@ -27,31 +27,52 @@ class NCEOp : public framework::OperatorWithKernel {
using framework::OperatorWithKernel::OperatorWithKernel;
void InferShape(framework::InferShapeContext *ctx) const override {
PADDLE_ENFORCE(ctx->HasInput("Input"));
PADDLE_ENFORCE(ctx->HasInput("Label"));
PADDLE_ENFORCE(ctx->HasInput("Weight"));
PADDLE_ENFORCE(ctx->HasOutput("Cost"));
PADDLE_ENFORCE(ctx->HasOutput("SampleLogits"));
PADDLE_ENFORCE(ctx->HasOutput("SampleLabels"));
PADDLE_ENFORCE_EQ(ctx->HasInput("Input"), true);
PADDLE_ENFORCE_EQ(ctx->HasInput("Label"), true);
PADDLE_ENFORCE_EQ(ctx->HasInput("Weight"), true);
PADDLE_ENFORCE_EQ(ctx->HasOutput("Cost"), true);
PADDLE_ENFORCE_EQ(ctx->HasOutput("SampleLogits"), true);
PADDLE_ENFORCE_EQ(ctx->HasOutput("SampleLabels"), true);
auto x_dims = ctx->GetInputDim("Input");
auto label_dims = ctx->GetInputDim("Label");
if (ctx->IsRuntime() || (x_dims[0] > 0 && label_dims[0] > 0)) {
PADDLE_ENFORCE_EQ(x_dims[0], label_dims[0]);
PADDLE_ENFORCE_EQ(
x_dims[0], label_dims[0],
"ShapeError: the first dimension of Input(Input) and Input(Label) "
"should be equal in runtime. But received: Input(Input)'s shape = "
"[%s] with 1st dim = %d, Input(Label)'s shape = [%s] with 1st "
"dim = %d.",
x_dims, x_dims[0], label_dims, label_dims[0]);
}
int num_true_classes = label_dims.size() == 2 ? label_dims[1] : 1;
if (ctx->HasInput("Bias")) {
PADDLE_ENFORCE_EQ(ctx->GetInputDim("Weight")[0],
ctx->GetInputDim("Bias")[0]);
PADDLE_ENFORCE_EQ(
ctx->GetInputDim("Weight")[0], ctx->GetInputDim("Bias")[0],
"ShapeError: the first dimension of Input(Weight) and Input(Bias) "
"should be equal. But received: Input(Weight)'s shape = [%s] with "
"1st dim = %d, Input(Bias)'s shape = [%s] with 1st dim = %d.",
ctx->GetInputDim("Weight"), ctx->GetInputDim("Weight")[0],
ctx->GetInputDim("Bias"), ctx->GetInputDim("Bias")[0]);
}
auto num_neg_samples = ctx->Attrs().Get<int>("num_neg_samples");
auto num_total_classes = ctx->Attrs().Get<int>("num_total_classes");
std::vector<int> custom_neg_classes =
ctx->Attrs().Get<std::vector<int>>("custom_neg_classes");
PADDLE_ENFORCE_EQ(num_total_classes, ctx->GetInputDim("Weight")[0]);
PADDLE_ENFORCE_EQ(
num_total_classes, ctx->GetInputDim("Weight")[0],
"ShapeError: the number of total classes should be equal to the first "
"dimension of Input(Weight). But received: Attr(num_total_classes) = "
"%d, Input(Weight)'s shape = [%s] with 1st dim = %d.",
num_total_classes, ctx->GetInputDim("Weight"),
ctx->GetInputDim("Weight")[0]);
if (custom_neg_classes.size() > 0) {
PADDLE_ENFORCE_EQ(custom_neg_classes.size(),
static_cast<size_t>(num_neg_samples));
PADDLE_ENFORCE_EQ(
custom_neg_classes.size(), static_cast<size_t>(num_neg_samples),
"ShapeError: the size of Attr(custom_neg_classes) should be equal "
"to the number of negative samples. But received: "
"custom_neg_classes.size() = %d, num_neg_samples = %d.",
custom_neg_classes.size(), num_neg_samples);
}
// set dims of output(Out)
std::vector<int64_t> out_dims;
......
......@@ -102,9 +102,27 @@ class NCEKernel : public framework::OpKernel<T> {
auto dist_alias = context.Input<Tensor>("CustomDistAlias");
auto dist_alias_probs = context.Input<Tensor>("CustomDistAliasProbs");
PADDLE_ENFORCE_EQ(dist_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(dist_alias->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(dist_alias_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_probs->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistProbs) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistProbs).numel() = %d, Attr(num_total_classes) "
"= %d.",
dist_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_alias->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistAlias) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistAlias).numel() = %d, Attr(num_total_classes) "
"= %d.",
dist_alias->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_alias_probs->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistAliasProbs) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistAliasProbs).numel() = %d, "
"Attr(num_total_classes) = %d.",
dist_alias_probs->numel(), num_total_classes);
const float *probs_data = dist_probs->data<float>();
const int *alias_data = dist_alias->data<int>();
......@@ -121,7 +139,11 @@ class NCEKernel : public framework::OpKernel<T> {
const int64_t *sample_labels_data = sample_labels->data<int64_t>();
for (int x = 0; x < sample_labels->numel(); x++) {
PADDLE_ENFORCE_GE(sample_labels_data[x], 0, "nce sample label %d", x);
PADDLE_ENFORCE_GE(sample_labels_data[x], 0,
"ValueError: Every sample label should be "
"non-negative. But received: "
"Input(SampleLabels)[%d] = %d",
x, sample_labels_data[x]);
}
auto sample_out = context.Output<Tensor>("SampleLogits");
......@@ -289,9 +311,27 @@ class NCEGradKernel : public framework::OpKernel<T> {
auto dist_alias = context.Input<Tensor>("CustomDistAlias");
auto dist_alias_probs = context.Input<Tensor>("CustomDistAliasProbs");
PADDLE_ENFORCE_EQ(dist_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(dist_alias->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(dist_alias_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_probs->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistProbs) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistProbs).numel() = %d, Attr(num_total_classes) "
"= %d.",
dist_probs->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_alias->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistAlias) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistAlias).numel() = %d, Attr(num_total_classes) "
"= %d.",
dist_alias->numel(), num_total_classes);
PADDLE_ENFORCE_EQ(
dist_alias_probs->numel(), num_total_classes,
"ShapeError: The number of elements in Input(CustomDistAliasProbs) "
"should be equal to the number of total classes. But Received: "
"Input(CustomDistAliasProbs).numel() = %d, "
"Attr(num_total_classes) = %d.",
dist_alias_probs->numel(), num_total_classes);
const float *probs_data = dist_probs->data<float>();
const int *alias_data = dist_alias->data<int>();
......
......@@ -6827,8 +6827,23 @@ def nce(input,
custom_dist=dist)
"""
helper = LayerHelper('nce', **locals())
assert isinstance(input, Variable)
assert isinstance(label, Variable)
if not isinstance(input, Variable):
raise TypeError(
"The type of 'input' in nce layer must be Variable, but received %s"
% (type(input)))
if not isinstance(label, Variable):
raise TypeError(
"The type of 'label' in nce layer must be Variable, but received %s"
% (type(label)))
if convert_dtype(input.dtype) not in ['float32', 'float64']:
raise TypeError(
"The data type of 'input' in nce layer must be float32 or float64, but received %s."
% (convert_dtype(input.dtype)))
if convert_dtype(label.dtype) not in ['int64']:
raise TypeError(
"The data type of 'label' in nce layer must be int64, but received %s."
% (convert_dtype(label.dtype)))
dim = input.shape[1]
num_true_class = label.shape[1]
......
......@@ -19,6 +19,7 @@ import unittest
import paddle.fluid as fluid
import paddle.fluid.initializer as initializer
from paddle.fluid import Program, program_guard
from op_test import OpTest
......@@ -219,5 +220,37 @@ class TestNCECase1SelectedRows(unittest.TestCase):
self.assertEqual(rets[0], rets[1])
class TestNCE_OpError(OpTest):
def test_errors(self):
with program_guard(Program(), Program()):
input1 = fluid.create_lod_tensor(
np.array([0.0, 3.0, 2.0, 4.0]), [[1, 1, 2]], fluid.CPUPlace())
label1 = fluid.layers.data(
name='label1', shape=[-1, 4], dtype="int64")
# the input(input) of nce layer must be Variable.
self.assertRaises(TypeError, fluid.layers.nce, input1, label1, 5)
input2 = fluid.layers.data(
name='input2', shape=[-1, 4], dtype="float32")
label2 = fluid.create_lod_tensor(
np.array([0.0, 3.0, 2.0, 4.0]), [[1, 1, 2]], fluid.CPUPlace())
# the input(label) of nce layer must be Variable.
self.assertRaises(TypeError, fluid.layers.nce, input2, label2, 5)
input3 = fluid.layers.data(
name='input3', shape=[-1, 4], dtype="float16")
label3 = fluid.layers.data(
name='label3', shape=[-1, 1], dtype="int64")
# the data type of input(input) must be float32 or float64.
self.assertRaises(TypeError, fluid.layers.nce, input3, label3, 5)
input4 = fluid.layers.data(
name='input4', shape=[-1, 4], dtype="float32")
label4 = fluid.layers.data(
name='label4', shape=[-1, 1], dtype="int32")
# the data type of input(label) must be int64.
self.assertRaises(TypeError, fluid.layers.nce, input4, label4, 5)
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册