From 4e3ba65f193b01a4b514f5cf0ba975cd35beb41e Mon Sep 17 00:00:00 2001 From: yangyaming Date: Wed, 20 Sep 2017 15:59:33 +0800 Subject: [PATCH] Refine doc. --- paddle/operators/smooth_l1_loss_op.cc | 63 +++++++++++-------- paddle/operators/smooth_l1_loss_op.h | 4 +- .../framework/tests/test_smooth_l1_loss_op.py | 14 ++--- 3 files changed, 46 insertions(+), 35 deletions(-) diff --git a/paddle/operators/smooth_l1_loss_op.cc b/paddle/operators/smooth_l1_loss_op.cc index 427ca96d1f..9ee6fff8db 100644 --- a/paddle/operators/smooth_l1_loss_op.cc +++ b/paddle/operators/smooth_l1_loss_op.cc @@ -23,19 +23,15 @@ class SmoothL1LossOp : public framework::OperatorWithKernel { protected: void InferShape(const framework::InferShapeContext& ctx) const override { - PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("X"), - "Input of SmoothL1LossOp must be initialized."); - PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("Y"), - "Target of SmoothL1LossOp must be initialized."); + PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("X"), "X must be initialized."); + PADDLE_ENFORCE_NOT_NULL(ctx.InputVar("Y"), "Y must be initialized."); auto* x = ctx.Input("X"); auto* y = ctx.Input("Y"); PADDLE_ENFORCE_EQ(x->dims(), y->dims(), - "Dimensions of SmoothL1LossOp's input and target " - "must be same."); + "The shape of X and Y must be the same."); PADDLE_ENFORCE_GE(x->dims().size(), 2, - "Tensor rank of SmoothL1LossOp's input must be " - "at least 2."); + "The tensor rank of X must be at least 2."); auto* inside_weight = ctx.Input("InsideWeight"); if (inside_weight) { auto* outside_weight = ctx.Input("OutsideWeight"); @@ -43,10 +39,9 @@ class SmoothL1LossOp : public framework::OperatorWithKernel { "If weights are provided, must specify both " "inside and outside weights."); PADDLE_ENFORCE_EQ(inside_weight->dims(), x->dims(), - "Dimensions of inside weight must be same with input."); - PADDLE_ENFORCE_EQ( - outside_weight->dims(), x->dims(), - "Dimensions of outside weight must be same with input."); + "The shape of InsideWeight must be same as X."); + PADDLE_ENFORCE_EQ(outside_weight->dims(), x->dims(), + "The shape of OutsideWeight must be same as X."); } auto* diff = ctx.Output("Diff"); @@ -63,21 +58,37 @@ class SmoothL1LossOpMaker : public framework::OpProtoAndCheckerMaker { SmoothL1LossOpMaker(framework::OpProto* proto, framework::OpAttrChecker* op_checker) : OpProtoAndCheckerMaker(proto, op_checker) { - AddInput("X", "Input of SmoothL1LossOp."); - AddInput("Y", "Target of SmoothL1LossOp."); - AddInput("InsideWeight", "Optional input to scale (X-Y)."); - AddInput("OutsideWeight", "Optinal input to scale smooth l1 loss."); - AddOutput("Diff", "Intermediate variable to cache Win*(X-Y).") + AddInput("X", + "The input tensor of smooth l1 loss op." + "The rank should be greater or equal to 2 with shape " + "[batch_size, value_dim1, value_dim2, ..., value_dimN]"); + AddInput("Y", + "The target tensor of smooth l1 loss op " + "with the same shape as X."); + AddInput("InsideWeight", + "Optional input tensor of smooth l1 loss op with the same shape " + "as X. If provided, the result of (X - Y) will be multiplied " + "by this tensor element by element."); + AddInput("OutsideWeight", + "Optinal input of smooth l1 loss op with the same shape as X." + "If provided, the output smooth l1 loss will be multiplied by " + "this tensor element by element."); + AddOutput("Diff", "Intermediate variable to cache InsideWeight*(X-Y).") .AsIntermediate(); - AddOutput("Out", "Final smooth l1 loss of inputs."); - AddAttr("sigma", "Hyper parameter, default value is 3.0 .") + AddOutput("Out", "Smooth l1 loss."); + AddAttr("sigma", + "Hyper parameter of smooth l1 loss op." + "A float scalar with default value 3.0.") .SetDefault(3.0); AddComment(R"DOC( -Compute SmoothL1Loss for input and target. +Compute smooth l1 loss for input and target. The operator take the 1st +dimension of input as batch size. For each instance, it will compute +smooth l1 loss element by element first and sum all losses to one value. +So the output shape is [batch_size, 1]. The equation is: -loss = 0.5 * (sigma * (x - y)) ^ 2 if abs(x - y) < 1 / sigma^2 - abs(x - y) - 0.5 / sigma^2 otherwise +loss = 0.5 * (sigma * (x-y))^2 if abs(x - y) < 1 / sigma^2 + abs(x - y) - 0.5 / sigma^2 otherwise )DOC"); } @@ -98,12 +109,12 @@ class SmoothL1LossGradOp : public framework::OperatorWithKernel { ctx.Output(framework::GradVarName("Y")); PADDLE_ENFORCE_GE(out_dims.size(), 2, - "Tensor rank of output gradient should be 2."); + "The tensor rank of Input(Out@Grad) should be 2."); PADDLE_ENFORCE_EQ(out_dims[0], in_dims[0], - "First dimension of ouptut gradient must be " - "same with input."); + "The 1st dimension of Input(Out@Grad) must be " + "same as input."); PADDLE_ENFORCE_EQ(out_dims[1], 1, - "Second dimension of output gradient must be 1."); + "The 2nd dimension of Input(Out@Grad) must be 1."); if (x_grad) x_grad->Resize(in_dims); if (y_grad) y_grad->Resize(in_dims); diff --git a/paddle/operators/smooth_l1_loss_op.h b/paddle/operators/smooth_l1_loss_op.h index 90f23f5a0c..0604fb5e1c 100644 --- a/paddle/operators/smooth_l1_loss_op.h +++ b/paddle/operators/smooth_l1_loss_op.h @@ -59,7 +59,7 @@ class SmoothL1LossKernel : public framework::OpKernel { out1->mutable_data(context.GetPlace()); auto place = context.GetEigenDevice(); - auto sigma = static_cast(context.op().Attr("sigma")); + auto sigma = static_cast(context.Attr("sigma")); T sigma2 = sigma * sigma; bool has_weight = (in2 != nullptr) && (in3 != nullptr); @@ -122,7 +122,7 @@ class SmoothL1LossGradKernel : public framework::OpKernel { auto* in1 = context.Input("OutsideWeight"); auto* in2 = context.Input("Diff"); auto* og = context.Input(framework::GradVarName("Out")); - auto sigma = static_cast(context.op().Attr("sigma")); + auto sigma = static_cast(context.Attr("sigma")); T sigma2 = sigma * sigma; bool has_weight = (in0 != nullptr) && (in1 != nullptr); diff --git a/python/paddle/v2/framework/tests/test_smooth_l1_loss_op.py b/python/paddle/v2/framework/tests/test_smooth_l1_loss_op.py index 1b79f16abe..be940327ec 100644 --- a/python/paddle/v2/framework/tests/test_smooth_l1_loss_op.py +++ b/python/paddle/v2/framework/tests/test_smooth_l1_loss_op.py @@ -14,7 +14,7 @@ def smooth_l1_loss_forward(val, sigma2): class TestSmoothL1LossOp1(OpTest): def setUp(self): self.op_type = "smooth_l1_loss" - dims = (6, 10) + dims = (5, 10) self.inputs = { 'X': np.random.random(dims).astype("float32"), 'Y': np.random.random(dims).astype("float32") @@ -35,17 +35,17 @@ class TestSmoothL1LossOp1(OpTest): def test_check_grad_ingore_x(self): self.check_grad( - ['Y'], 'Out', max_relative_error=0.02, no_grad_set=set("X")) + ['Y'], 'Out', max_relative_error=0.03, no_grad_set=set("X")) def test_check_grad_ingore_y(self): self.check_grad( - ['X'], 'Out', max_relative_error=0.02, no_grad_set=set('Y')) + ['X'], 'Out', max_relative_error=0.03, no_grad_set=set('Y')) class TestSmoothL1LossOp2(OpTest): def setUp(self): self.op_type = "smooth_l1_loss" - dims = (6, 10) + dims = (5, 10) self.inputs = { 'X': np.random.random(dims).astype("float32"), 'Y': np.random.random(dims).astype("float32"), @@ -66,20 +66,20 @@ class TestSmoothL1LossOp2(OpTest): self.check_output() def test_check_grad_normal(self): - self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.02) + self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.03) def test_check_grad_ingore_x(self): self.check_grad( ['Y'], 'Out', - max_relative_error=0.02, + max_relative_error=0.03, no_grad_set=set(['X', 'InsideWeight', 'OutsideWeight'])) def test_check_grad_ingore_y(self): self.check_grad( ['X'], 'Out', - max_relative_error=0.02, + max_relative_error=0.03, no_grad_set=set(['Y', 'InsideWeight', 'OutsideWeight'])) -- GitLab