From 648f1d5b3fae64528240384e76f3f454856699cb Mon Sep 17 00:00:00 2001 From: Yang Zhang Date: Tue, 14 Apr 2020 12:03:16 +0800 Subject: [PATCH] API/OP error message enhancement (#23684) * `l1_norm` error message enhancement test=develop * `norm` error message enhancement test=develop * `squared_l2_norm` error message enhancement test=develop * `squared_l2_distance` error message enhancement test=develop * `conv_shift_op` error message enhancement test=develop * `sample_logits_op` error message enhancement test=develop * Fix format test=develop * use `PADDLE_ENFORCE_EQ` for '||' conditional test=develop * Fix string format test=develop * Add test for `sample_logits` test=develop * Add error message test=develop * Use ordered dict for outputs test=develop * Hard code fetch list so that order is deterministic test=develop * Fix license header year test=develop --- paddle/fluid/operators/conv_shift_op.cc | 59 +++++++--- paddle/fluid/operators/l1_norm_op.cc | 14 +-- paddle/fluid/operators/l1_norm_op.h | 5 +- paddle/fluid/operators/norm_op.cc | 12 +- paddle/fluid/operators/sample_logits_op.cc | 83 ++++++++------ paddle/fluid/operators/sample_logits_op.h | 68 ++++++++--- .../fluid/operators/squared_l2_distance_op.cc | 80 ++++++++----- paddle/fluid/operators/squared_l2_norm_op.cc | 14 +-- paddle/fluid/operators/squared_l2_norm_op.h | 6 +- .../tests/unittests/test_sample_logits_op.py | 107 ++++++++++++++++++ 10 files changed, 331 insertions(+), 117 deletions(-) create mode 100644 python/paddle/fluid/tests/unittests/test_sample_logits_op.py diff --git a/paddle/fluid/operators/conv_shift_op.cc b/paddle/fluid/operators/conv_shift_op.cc index 3c04b988dd5..5fc70f4017b 100644 --- a/paddle/fluid/operators/conv_shift_op.cc +++ b/paddle/fluid/operators/conv_shift_op.cc @@ -29,25 +29,50 @@ class ConvShiftOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext *ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasInput("Y"), "Input(Y) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), "Output(Out) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "ConvShiftOp"); + OP_INOUT_CHECK(ctx->HasInput("Y"), "Input", "Y", "ConvShiftOp"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "ConvShiftOp"); auto x_dims = ctx->GetInputDim("X"); auto y_dims = ctx->GetInputDim("Y"); - PADDLE_ENFORCE_EQ(x_dims.size(), 2, "Input(X)'s rank should be 2."); - PADDLE_ENFORCE_EQ(y_dims.size(), 2, "Input(Y)'s rank should be 2."); + PADDLE_ENFORCE_EQ( + x_dims.size(), 2, + platform::errors::InvalidArgument( + "Input(X)'s dimensions of ConvShiftOp should be 2." + "But received X's shape = [%s] and the dimension is %d.", + x_dims, x_dims.size())); + PADDLE_ENFORCE_EQ( + y_dims.size(), 2, + platform::errors::InvalidArgument( + "Input(Y)'s dimensions of ConvShiftOp should be 2.", + "But received Y's shape = [%s] and the dimension is %d.", y_dims, + y_dims.size())); if (ctx->IsRuntime() || (x_dims[0] > 0 && y_dims[0] > 0)) - PADDLE_ENFORCE_EQ(x_dims[0], y_dims[0], - "The 1st dimension of Input(X) and Input(Y) should " - "be equal."); + PADDLE_ENFORCE_EQ( + x_dims[0], y_dims[0], + platform::errors::InvalidArgument( + "The first dimension of Input(X) and Input(Y) of ConvShiftOp ", + "should be equal.", + "But received X's shape = [%s], Y's shape = [%s],", + "and the first dimensions are %d and %d respectively.", x_dims, + y_dims, x_dims[0], y_dims[0])); if (ctx->IsRuntime() || y_dims[1] > 0) - PADDLE_ENFORCE_EQ(y_dims[1] % 2, 1, - "The 2nd dimension of Input(Y) should be odd."); + PADDLE_ENFORCE_EQ( + y_dims[1] % 2, 1, + platform::errors::InvalidArgument( + "The second dimension of Input(Y) of ConvShiftOp should be odd." + "But received Y's shape = [%s] and the second dimension is %d.", + y_dims, y_dims[1])); if (ctx->IsRuntime() || (x_dims[1] > 0 && y_dims[1] > 0)) - PADDLE_ENFORCE_LE(y_dims[1], x_dims[1], - "The 2nd dimension of Input(Y) should be less than or " - "equal to the 2nd dimension of Input(X)."); + PADDLE_ENFORCE_LE( + y_dims[1], x_dims[1], + platform::errors::InvalidArgument( + "The second dimension of Input(Y) of ConvShiftOp should be less " + "than or " + "equal to the 2nd dimension of Input(X)." + "But received X's shape = [%s], Y's shape = [%s],", + "and the second dimensions are %d and %d respectively.", x_dims, + y_dims, x_dims[1], y_dims[1])); ctx->ShareDim("X", /*->*/ "Out"); ctx->ShareLoD("X", /*->*/ "Out"); } @@ -58,10 +83,10 @@ class ConvShiftGradOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext *ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasInput("Y"), "Input(Y) should be not null."); - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")), - "Input(Out@GRAD) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "ConvShiftGradOp"); + OP_INOUT_CHECK(ctx->HasInput("Y"), "Input", "Y", "ConvShiftGradOp"); + OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")), "Input", + "Out@GRAD", "ConvShiftGradOp"); auto x_grad_name = framework::GradVarName("X"); if (ctx->HasOutput(x_grad_name)) { diff --git a/paddle/fluid/operators/l1_norm_op.cc b/paddle/fluid/operators/l1_norm_op.cc index 8e5fbeb0e52..e8f83f6b622 100644 --- a/paddle/fluid/operators/l1_norm_op.cc +++ b/paddle/fluid/operators/l1_norm_op.cc @@ -25,8 +25,8 @@ class L1NormOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), "Output(Out) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "L1NormOp"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "L1NormOp"); ctx->SetOutputDim("Out", {1}); } @@ -37,11 +37,11 @@ class L1NormGradOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")), - "Input(Out@GRAD) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("X")), - "Output(X@GRAD) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "L1NormGradOp"); + OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")), "Input", + "Out@GRAD", "L1NormGradOp"); + OP_INOUT_CHECK(ctx->HasOutput(framework::GradVarName("X")), "Output", + "X@GRAD", "L1NormGradOp"); ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X")); } diff --git a/paddle/fluid/operators/l1_norm_op.h b/paddle/fluid/operators/l1_norm_op.h index 7c6503bb215..c2a302ed05f 100644 --- a/paddle/fluid/operators/l1_norm_op.h +++ b/paddle/fluid/operators/l1_norm_op.h @@ -45,7 +45,10 @@ class L1NormGradKernel : public framework::OpKernel { const framework::Tensor *x = context.Input("X"); const framework::Tensor *d_out = context.Input(framework::GradVarName("Out")); - PADDLE_ENFORCE(d_out->numel() == 1, "L1 Norm Gradient should be scalar"); + PADDLE_ENFORCE_EQ( + d_out->numel(), 1, + platform::errors::InvalidArgument( + "Input(GRAD@Out) of L1NormGradOP should be a scalar.")); framework::Tensor *dx = context.Output(framework::GradVarName("X")); dx->mutable_data(context.GetPlace()); diff --git a/paddle/fluid/operators/norm_op.cc b/paddle/fluid/operators/norm_op.cc index eb554bb202a..1fc51e76e25 100644 --- a/paddle/fluid/operators/norm_op.cc +++ b/paddle/fluid/operators/norm_op.cc @@ -55,10 +55,8 @@ class NormOp : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), - "Input(X) of NormOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), - "Output(Out) of NormOp should not be null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "NormOp"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "NormOp"); auto xdim = ctx->GetInputDim("X"); ctx->SetOutputDim("Out", xdim); int axis = ctx->Attrs().Get("axis"); @@ -72,9 +70,9 @@ class NormOpGrad : public framework::OperatorWithKernel { public: using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) must not be null."); - PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("X")), - "Input(X@GRAD) should not be null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "NormOpGrad"); + OP_INOUT_CHECK(ctx->HasOutput(framework::GradVarName("X")), "Input", + "X@GRAD", "NormOpGrad"); ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X")); } }; diff --git a/paddle/fluid/operators/sample_logits_op.cc b/paddle/fluid/operators/sample_logits_op.cc index 32d83ac9cdc..ecf09203e75 100644 --- a/paddle/fluid/operators/sample_logits_op.cc +++ b/paddle/fluid/operators/sample_logits_op.cc @@ -112,32 +112,37 @@ class SampleLogitsOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("Logits"), - "Input(Logits) should be not null."); - PADDLE_ENFORCE(ctx->HasInput("Labels"), - "Input(Labels) should be not null."); - - PADDLE_ENFORCE(ctx->HasOutput("Samples"), - "Output(Samples) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("Probabilities"), - "Output(Probabilities) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("SampledLogits"), - "Output(SampledLogits) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("SampledLabels"), - "Output(SampledLabels) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("LogitsDim"), - "Output(LogitsDim) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("LabelsDim"), - "Output(LabelsDim) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("Labels"), "Input", "Logits", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasInput("Labels"), "Input", "Logits", + "SampleLogitsOp"); + + OP_INOUT_CHECK(ctx->HasOutput("Samples"), "Output", "Samples", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasOutput("Probabilities"), "Output", "Probabilities", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasOutput("SampledLogits"), "Output", "SampledLogits", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasOutput("SampledLabels"), "Output", "SampledLabels", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasOutput("LogitsDim"), "Output", "LogitsDim", + "SampleLogitsOp"); + OP_INOUT_CHECK(ctx->HasOutput("LabelsDim"), "Output", "LabelsDim", + "SampleLogitsOp"); auto logits_dims = ctx->GetInputDim("Logits"); auto labels_dims = ctx->GetInputDim("Labels"); - PADDLE_ENFORCE_EQ( - logits_dims.size(), 2UL, - "The logits of softmax_with_cross_entropy should be a 2-D tensor."); + PADDLE_ENFORCE_EQ(logits_dims.size(), 2UL, + platform::errors::InvalidArgument( + "Input(Logits) of SampleLogitsOp should be 2D.", + "But received shape = [%s] and dimension is %d.", + logits_dims, logits_dims.size())); PADDLE_ENFORCE_EQ(labels_dims.size(), 2UL, - "The labels should be a 2-D tensor."); + platform::errors::InvalidArgument( + "Input(Labels) of SampleLogitsOp should be 2D.", + "But received shape = [%s] and dimension is %d.", + labels_dims, labels_dims.size())); const int num_samples = ctx->Attrs().Get("num_samples"); int num_sampled_classes = labels_dims[1] + num_samples; @@ -175,25 +180,33 @@ class SampleLogitsOpGrad : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("LogitsDim"), - "Input(LogitsDim) should not be null."); - PADDLE_ENFORCE(ctx->HasInput("LabelsDim"), - "Input(LabelsDim) should be not null."); - PADDLE_ENFORCE(ctx->HasInput("Samples"), - "Input(Samples) should be not null."); - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("SampledLogits")), - "Input(SampledLogits@Grad) should not be null."); - PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("Logits")), - "Output(Logits@Grad) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("LogitsDim"), "Input", "LogitsDim", + "SampleLogitsOpGrad"); + OP_INOUT_CHECK(ctx->HasInput("LabelsDim"), "Input", "LabelsDim", + "SampleLogitsOpGrad"); + OP_INOUT_CHECK(ctx->HasInput("Samples"), "Input", "SamplesabelsDim", + "SampleLogitsOpGrad"); + OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("SampledLogits")), + "Input", "SampledLogits@GRAD", "SampleLogitsOpGrad"); + OP_INOUT_CHECK(ctx->HasOutput(framework::GradVarName("Logits")), "Output", + "Logits@GRAD", "SampleLogitsOpGrad"); auto logits_dims = ctx->GetInputDim("LogitsDim"); logits_dims = framework::DDim(logits_dims.Get(), logits_dims.size() - 1); auto labels_dims = ctx->GetInputDim("LabelsDim"); labels_dims = framework::DDim(labels_dims.Get(), labels_dims.size() - 1); - PADDLE_ENFORCE_EQ(labels_dims.size(), 2UL, - "The label should be a 2-D tensor."); - PADDLE_ENFORCE_EQ(logits_dims.size(), 2UL, - "The logits should be a 2-D tensor."); + PADDLE_ENFORCE_EQ( + logits_dims.size(), 2UL, + platform::errors::InvalidArgument( + "Input(LogitsDim) of SampleLogitsOpGrad should be 2D.", + "But received shape = [%s] and dimension is %d.", logits_dims, + logits_dims.size())); + PADDLE_ENFORCE_EQ( + labels_dims.size(), 2UL, + platform::errors::InvalidArgument( + "Input(LabelsDim) of SampleLogitsOpGrad should be 2D.", + "But received shape = [%s] and dimension is %d.", labels_dims, + labels_dims.size())); ctx->SetOutputDim(framework::GradVarName("Logits"), logits_dims); } diff --git a/paddle/fluid/operators/sample_logits_op.h b/paddle/fluid/operators/sample_logits_op.h index 5c0d3a677db..200d066d5d7 100644 --- a/paddle/fluid/operators/sample_logits_op.h +++ b/paddle/fluid/operators/sample_logits_op.h @@ -49,17 +49,37 @@ static void CPUTakeAlongD1(const platform::DeviceContext& ctx, const framework::Tensor& array, const framework::Tensor& index, framework::Tensor* value) { - PADDLE_ENFORCE_EQ(platform::is_cpu_place(ctx.GetPlace()), true); + PADDLE_ENFORCE_EQ( + platform::is_cpu_place(ctx.GetPlace()), true, + platform::errors::InvalidArgument("This kernel only runs on CPU.")); // UNDERSTAND: check shape src(B, C), index(B, K), out should also be (B, K) - PADDLE_ENFORCE_EQ(index.dims().size(), 2); - PADDLE_ENFORCE_EQ(array.dims().size(), 2); - PADDLE_ENFORCE_EQ(index.dims()[0], array.dims()[0]); - PADDLE_ENFORCE_EQ(index.dims(), value->dims()); - const auto batch_size = index.dims()[0]; const auto num_take = index.dims()[1]; const auto array_dims = array.dims(); const auto idx_dims = index.dims(); + PADDLE_ENFORCE_EQ(idx_dims.size(), 2, + platform::errors::InvalidArgument( + "index of CPUTakeAlongD1 should be 2D.", + "But received shape = [%s] and dimension is %d.", + idx_dims, idx_dims.size())); + PADDLE_ENFORCE_EQ(array_dims.size(), 2, + platform::errors::InvalidArgument( + "array of CPUTakeAlongD1 should be 2D.", + "But received shape = [%s] and dimension is %d.", + array_dims, array_dims.size())); + PADDLE_ENFORCE_EQ(idx_dims[0], array_dims[0], + platform::errors::InvalidArgument( + "The first dimension of index and array of ", + "CPUTakeAlongD1 should be equal.", + "But received index shape = [%s], array shape = [%s],", + "and the first dimensions are %d and %d.", idx_dims, + array_dims, idx_dims[0], array_dims[0])); + PADDLE_ENFORCE_EQ( + idx_dims, value->dims(), + platform::errors::InvalidArgument( + "index and array of CPUTakeAlongD1 should have ", "the same shape.", + "But received index shape = [%s], array shape = [%s].", idx_dims, + value->dims())); // UNDERSTAND: no allocations here const T* p_array = array.data(); @@ -89,16 +109,37 @@ static void CPUPutAlongD1(const platform::DeviceContext& ctx, framework::Tensor* array, const framework::Tensor& index, const framework::Tensor& value) { - PADDLE_ENFORCE_EQ(platform::is_cpu_place(ctx.GetPlace()), true); + PADDLE_ENFORCE_EQ( + platform::is_cpu_place(ctx.GetPlace()), true, + platform::errors::InvalidArgument("This kernel only runs on CPU.")); // UNDERSTAND: check shape src(B, C), index(B, K), out should also be (B, K) - PADDLE_ENFORCE_EQ(index.dims().size(), 2); - PADDLE_ENFORCE_EQ(array->dims().size(), 2); - PADDLE_ENFORCE_EQ(index.dims()[0], array->dims()[0]); - PADDLE_ENFORCE_EQ(index.dims(), value.dims()); const auto batch_size = index.dims()[0]; const auto num_put = index.dims()[1]; auto array_dims = array->dims(); auto idx_dims = index.dims(); + PADDLE_ENFORCE_EQ(idx_dims.size(), 2, + platform::errors::InvalidArgument( + "index of CPUPutAlongD1 should be 2D.", + "But received shape = [%s] and dimension is %d.", + idx_dims, idx_dims.size())); + PADDLE_ENFORCE_EQ(array_dims.size(), 2, + platform::errors::InvalidArgument( + "array of CPUPutAlongD1 should be 2D.", + "But received shape = [%s] and dimension is %d.", + array_dims, array_dims.size())); + PADDLE_ENFORCE_EQ(idx_dims[0], array_dims[0], + platform::errors::InvalidArgument( + "The first dimension of index and array of ", + "CPUPutAlongD1 should be equal.", + "But received index shape = [%s], array shape = [%s],", + "and the first dimensions are %d and %d.", idx_dims, + array_dims, idx_dims[0], array_dims[0])); + PADDLE_ENFORCE_EQ( + idx_dims, value.dims(), + platform::errors::InvalidArgument( + "index and array of CPUPutAlongD1 should have ", "the same shape.", + "But received index shape = [%s], array shape = [%s].", idx_dims, + value.dims())); // UNDERSTAND: no allocations here T* p_array = array->data(); @@ -149,8 +190,9 @@ class SampleLogitsKernel : public framework::OpKernel { public: using Tensor = framework::Tensor; void Compute(const framework::ExecutionContext& context) const override { - PADDLE_ENFORCE_EQ(platform::is_cpu_place(context.GetPlace()), true, - "This kernel only runs on CPU."); + PADDLE_ENFORCE_EQ( + platform::is_cpu_place(context.GetPlace()), true, + platform::errors::InvalidArgument("this kernel only runs on cpu.")); VLOG(3) << "Enter SampleLogitsKernel"; // get necessary inputs const Tensor* logits = context.Input("Logits"); diff --git a/paddle/fluid/operators/squared_l2_distance_op.cc b/paddle/fluid/operators/squared_l2_distance_op.cc index 8288d136973..5ee5ffc2178 100644 --- a/paddle/fluid/operators/squared_l2_distance_op.cc +++ b/paddle/fluid/operators/squared_l2_distance_op.cc @@ -26,44 +26,59 @@ class SquaredL2DistanceOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), - "Input(X) of SquaredL2DistanceOp should not be null."); - PADDLE_ENFORCE(ctx->HasInput("Y"), - "Input(Y) of SquaredL2DistanceOp should not be null."); - PADDLE_ENFORCE( - ctx->HasOutput("sub_result"), - "Output(sub_result) of SquaredL2DistanceOp should not be null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), - "Output(Out) of SquaredL2DistanceOp should not be null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "SquaredL2DistanceOp"); + OP_INOUT_CHECK(ctx->HasInput("Y"), "Input", "Y", "SquaredL2DistanceOp"); + OP_INOUT_CHECK(ctx->HasOutput("sub_result"), "Output", "sub_result", + "SquaredL2DistanceOp"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", + "SquaredL2DistanceOp"); auto x_dims = ctx->GetInputDim("X"); auto y_dims = ctx->GetInputDim("Y"); - PADDLE_ENFORCE_EQ(framework::arity(x_dims), framework::arity(y_dims), - "Tensor rank of both SquaredL2DistanceOp's " - "inputs must be same."); + PADDLE_ENFORCE_EQ( + framework::arity(x_dims), framework::arity(y_dims), + platform::errors::InvalidArgument( + "Input(X) and Input(X) of SquaredL2DistanceOp should ", + "have same dimensions.", + "But received X's shape = [%s] and Y's shape = [%s],", + "the dimensions are %d and %d respectively", x_dims, y_dims, + framework::arity(x_dims), framework::arity(y_dims))); int rank = framework::arity(x_dims); - PADDLE_ENFORCE_GE(rank, 2, "Tensor rank should be at least equal to 2."); + PADDLE_ENFORCE_GE( + rank, 2, + platform::errors::InvalidArgument( + "Input dimensions of SquaredL2DistanceOp should be ", "at least 2.", + "But received shape = [%s] and dimension is %d.", x_dims, rank)); bool check = true; if ((!ctx->IsRuntime()) && (framework::product(x_dims) <= 0 || framework::product(y_dims) <= 0)) { check = false; } if (check) { - PADDLE_ENFORCE_EQ(product(x_dims) / x_dims[0], - product(y_dims) / y_dims[0], - "Product of dimensions expcet the first dimension of " - "input and target must be equal."); + PADDLE_ENFORCE_EQ( + product(x_dims) / x_dims[0], product(y_dims) / y_dims[0], + platform::errors::InvalidArgument( + "Input(X) and Input(Y) of SquaredL2DistanceOp should ", + "have same dimensions.", + "But received X's shape = [%s] and Y's shape = [%s]", + ", the products are %d and %d respectively", x_dims, y_dims, + product(x_dims) / x_dims[0], product(y_dims) / y_dims[0])); } check = true; if ((!ctx->IsRuntime()) && (y_dims[0] <= 0 || x_dims[0] <= 0)) { check = false; } if (check) { - PADDLE_ENFORCE(y_dims[0] == 1 || y_dims[0] == x_dims[0], - "First dimension of target must be equal to input " - "or to 1."); + PADDLE_ENFORCE_EQ( + y_dims[0] == 1 || y_dims[0] == x_dims[0], true, + platform::errors::InvalidArgument( + "First dimension of Input(Y) of SquaredL2DistanceOp ", + "must be equal to 1", "or to first dimension of Input(X).", + "But received X's shape = [%s] and Y's shape = [%s],", + "the first dimensions are %d and %d respectively", x_dims, y_dims, + x_dims[0], y_dims[0])); } ctx->SetOutputDim("sub_result", {x_dims[0], product(x_dims) / x_dims[0]}); ctx->SetOutputDim("Out", {x_dims[0], 1}); @@ -126,19 +141,28 @@ class SquaredL2DistanceGradOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")), - "Gradient of Out should not be null"); - PADDLE_ENFORCE(ctx->HasInput("sub_result"), "SubResult should not be null"); + OP_INOUT_CHECK(ctx->HasInput("sub_result"), "Input", "sub_result", + "SquaredL2DistanceGradOp"); + OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")), "Input", + "Out@GRAD", "SquaredL2DistanceGradOp"); auto out_dims = ctx->GetInputDim(framework::GradVarName("Out")); auto x_dims = ctx->GetInputDim("X"); auto y_dims = ctx->GetInputDim("Y"); if (ctx->IsRuntime()) { - PADDLE_ENFORCE_EQ(out_dims[0], x_dims[0], - "First dimension of output gradient and " - "input value must be equal."); + PADDLE_ENFORCE_EQ( + out_dims[0], x_dims[0], + platform::errors::InvalidArgument( + "First dimension of output gradient and Input(X) ", + "of SquaredL2DistanceGradOp must be equal", + "But received X's shape = [%s] and grad's shape = [%s],", + "the first dimensions are %d and %d respectively", x_dims, + out_dims, x_dims[0], out_dims[0])); PADDLE_ENFORCE_EQ(out_dims[1], 1, - "Second dimension of output gradient " - "must be 1."); + platform::errors::InvalidArgument( + "Second dimension of output gradient of ", + "SquaredL2DistanceGradOp must be 1." + "But received grad's shape = [%s],", + "with first dimensions %d", out_dims, out_dims[1])); } auto x_grad_name = framework::GradVarName("X"); auto y_grad_name = framework::GradVarName("Y"); diff --git a/paddle/fluid/operators/squared_l2_norm_op.cc b/paddle/fluid/operators/squared_l2_norm_op.cc index 2d3d3ba5d09..79781dde58d 100644 --- a/paddle/fluid/operators/squared_l2_norm_op.cc +++ b/paddle/fluid/operators/squared_l2_norm_op.cc @@ -26,8 +26,8 @@ class SquaredL2NormOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput("Out"), "Output(Out) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "SquaredL2NormOp"); + OP_INOUT_CHECK(ctx->HasOutput("Out"), "Output", "Out", "SquaredL2NormOp"); ctx->SetOutputDim("Out", {1}); } @@ -56,11 +56,11 @@ class SquaredL2NormGradOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - PADDLE_ENFORCE(ctx->HasInput("X"), "Input(X) should be not null."); - PADDLE_ENFORCE(ctx->HasInput(framework::GradVarName("Out")), - "Input(Out@GRAD) should be not null."); - PADDLE_ENFORCE(ctx->HasOutput(framework::GradVarName("X")), - "Output(X@GRAD) should be not null."); + OP_INOUT_CHECK(ctx->HasInput("X"), "Input", "X", "SquaredL2NormGradOp"); + OP_INOUT_CHECK(ctx->HasInput(framework::GradVarName("Out")), "Input", + "Out@GRAD", "SquaredL2NormGradOp"); + OP_INOUT_CHECK(ctx->HasOutput(framework::GradVarName("X")), "Output", + "X@GRAD", "SquaredL2NormGradOp"); ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X")); } diff --git a/paddle/fluid/operators/squared_l2_norm_op.h b/paddle/fluid/operators/squared_l2_norm_op.h index b32db4569e7..d44eec1a80b 100644 --- a/paddle/fluid/operators/squared_l2_norm_op.h +++ b/paddle/fluid/operators/squared_l2_norm_op.h @@ -45,8 +45,10 @@ class SquaredL2NormGradKernel : public framework::OpKernel { const framework::Tensor *X = context.Input("X"); const framework::Tensor *dOut = context.Input(framework::GradVarName("Out")); - PADDLE_ENFORCE(dOut->numel() == 1, - "Squared L2 Norm Gradient should be scalar"); + PADDLE_ENFORCE_EQ( + dOut->numel(), 1, + platform::errors::InvalidArgument( + "Input(GRAD@Out) of SquaredL2NormGradOP should be a scalar.")); framework::Tensor *dX = context.Output(framework::GradVarName("X")); dX->mutable_data(context.GetPlace()); diff --git a/python/paddle/fluid/tests/unittests/test_sample_logits_op.py b/python/paddle/fluid/tests/unittests/test_sample_logits_op.py new file mode 100644 index 00000000000..a3eaf24bd6b --- /dev/null +++ b/python/paddle/fluid/tests/unittests/test_sample_logits_op.py @@ -0,0 +1,107 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import collections +import numpy as np +from op_test import OpTest + + +class TestSampleLogitsOp(OpTest): + def setUp(self): + self.op_type = "sample_logits" + self.dtype = np.float64 + self.use_mkldnn = False + bs = 2 + K = 20 + NT = 10 + S = 5 + + Samples = np.random.random([bs, NT + S]).astype('int64') + Probabilities = np.random.random([bs, NT + S]).astype('float64') + LogitsDim = np.array([bs, K], dtype=np.int64) + LabelsDim = np.array([bs, NT], dtype=np.int64) + SampledLogits = np.random.random([bs, NT + S]).astype('float64') + SampledLabels = np.random.random([bs, NT]).astype('int64') + + self.bs = bs + self.K = K + self.NT = NT + self.S = S + Labels = np.array(list(range(self.NT)) * self.bs).astype('int64') + self.Labels = Labels.reshape(self.bs, -1) + self.Logits = np.random.random([self.bs, self.K]).astype('float64') + + self.inputs = {"Logits": self.Logits, "Labels": self.Labels} + self.fetch_list = [ + 'Samples', 'Probabilities', 'SampledLogits', 'SampledLabels' + ] + self.outputs = collections.OrderedDict( + (('Samples', Samples), ('Probabilities', Probabilities), + ('LogitsDim', LogitsDim), ('LabelsDim', LabelsDim), + ('SampledLogits', SampledLogits), ('SampledLabels', + SampledLabels))) + + self.attrs = {'num_samples': self.S} + + def test_check_output(self): + places = self._get_places() + for p in places: + (Samples, Probabilities, SampledLogits, + SampledLabels) = [np.array(o) for o in self.calc_output(p)] + + assert Samples.dtype == np.int64, \ + "Samples dtype is {}, not int64".format(Samples.dtype) + assert Probabilities.dtype == np.float64, \ + "Probabilities dtype is {}, not float64".format( + Probabilities.dtype) + assert SampledLogits.dtype == np.float64, \ + "SampledLogits dtype is {}, not float64".format( + SampledLogits.dtype) + assert SampledLabels.dtype == np.int64, \ + "SampledLabels dtype is {}, not int64".format( + SampledLabels.dtype) + + assert Samples.shape == (self.bs, self.NT + self.S) + assert Probabilities.shape == (self.bs, self.NT + self.S) + assert SampledLogits.shape == (self.bs, self.NT + self.S) + assert SampledLabels.shape == (self.bs, self.NT) + + assert (SampledLabels == self.Labels).all() + sampled_logits = self.Logits[:, Samples[0][:self.NT]] + sampled_logits -= np.log(Probabilities[:, :self.NT]) + np.testing.assert_almost_equal(sampled_logits, + SampledLogits[:, :self.NT]) + + def test_check_grad(self): + self._check_grad_helper() + for p in self._get_places(): + grads = self._get_gradient(['Logits'], p, ['SampledLogits'], []) + np.testing.assert_almost_equal(grads[0].sum(), np.array([1.])) + + +class TestSampleLogitsOpNoUniq(TestSampleLogitsOp): + def setUp(self): + super(TestSampleLogitsOpNoUniq, self).setUp() + self.attrs = {'num_samples': self.S, 'uniq': False} + + +class TestSampleLogitsOpWithAccidentalHits(TestSampleLogitsOp): + def setUp(self): + super(TestSampleLogitsOpWithAccidentalHits, self).setUp() + self.attrs = {'num_samples': self.S, 'remove_accidental_hits': False} + + +if __name__ == "__main__": + unittest.main() -- GitLab