From 2bbf77d41442cf421da17377e8dfdca3e3e81091 Mon Sep 17 00:00:00 2001 From: Dang Qingqing Date: Wed, 16 May 2018 18:50:11 +0800 Subject: [PATCH] Refine smooth L1 loss. --- paddle/fluid/operators/smooth_l1_loss_op.cc | 25 +++++++++++++++++++-- python/paddle/fluid/layers/nn.py | 16 ++++++------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/paddle/fluid/operators/smooth_l1_loss_op.cc b/paddle/fluid/operators/smooth_l1_loss_op.cc index c44c5f164b2d8..622420c1c33a6 100644 --- a/paddle/fluid/operators/smooth_l1_loss_op.cc +++ b/paddle/fluid/operators/smooth_l1_loss_op.cc @@ -105,7 +105,7 @@ class SmoothL1LossGradOp : public framework::OperatorWithKernel { using framework::OperatorWithKernel::OperatorWithKernel; void InferShape(framework::InferShapeContext* ctx) const override { - auto in_dims = ctx->GetInputDim("X"); + auto in_dims = ctx->GetInputDim("Diff"); auto out_dims = ctx->GetInputDim(framework::GradVarName("Out")); PADDLE_ENFORCE_GE(out_dims.size(), 2, @@ -127,12 +127,33 @@ class SmoothL1LossGradOp : public framework::OperatorWithKernel { } }; +class SmoothL1LossGradMaker : public framework::SingleGradOpDescMaker { + public: + using framework::SingleGradOpDescMaker::SingleGradOpDescMaker; + + protected: + std::unique_ptr Apply() const override { + auto* op = new framework::OpDesc(); + op->SetType("smooth_l1_loss_grad"); + op->SetInput("InsideWeight", Input("InsideWeight")); + op->SetInput("OutsideWeight", Input("OutsideWeight")); + op->SetInput("Diff", Output("Diff")); + op->SetInput(framework::GradVarName("Out"), OutputGrad("Out")); + + op->SetAttrMap(Attrs()); + + op->SetOutput(framework::GradVarName("X"), InputGrad("X")); + op->SetOutput(framework::GradVarName("Y"), InputGrad("Y")); + return std::unique_ptr(op); + } +}; + } // namespace operators } // namespace paddle namespace ops = paddle::operators; REGISTER_OPERATOR(smooth_l1_loss, ops::SmoothL1LossOp, ops::SmoothL1LossOpMaker, - paddle::framework::DefaultGradOpDescMaker); + ops::SmoothL1LossGradMaker); REGISTER_OPERATOR(smooth_l1_loss_grad, ops::SmoothL1LossGradOp); REGISTER_OP_CPU_KERNEL( smooth_l1_loss, diff --git a/python/paddle/fluid/layers/nn.py b/python/paddle/fluid/layers/nn.py index 1786be22fdcd0..93c5e6ba96f66 100644 --- a/python/paddle/fluid/layers/nn.py +++ b/python/paddle/fluid/layers/nn.py @@ -3263,35 +3263,35 @@ def smooth_l1(x, y, inside_weight=None, outside_weight=None, sigma=None): """ **Smooth L1 Loss Operator. ** - This operator computes the smooth l1 loss for X and Y. + This operator computes the smooth L1 loss for X and Y. The operator takes the first dimension of X and Y as batch size. - For each instance, it computes the smooth l1 loss element by element first + For each instance, it computes the smooth L1 loss element by element first and then sums all the losses. So the shape of Out is [batch_size, 1]. Args: x (Variable): A tensor with rank at least 2. The input value of smooth - l1 loss op with shape [batch_size, dim1, ..., dimN]. + L1 loss op with shape [batch_size, dim1, ..., dimN]. y (Variable): A tensor with rank at least 2. The target value of smooth - l1 loss op with same shape as x. + L1 loss op with same shape as x. inside_weight (Variable|None): A tensor with rank at least 2. This input is optional and should have same shape with x. If provided, the result of (x - y) will be multiplied by this tensor element by element. outside_weight (Variable|None): A tensor with rank at least 2. This input is optional and should have same shape with x. If provided, - the out smooth l1 loss will be multiplied by this tensor element + the out smooth L1 loss will be multiplied by this tensor element by element. - sigma (float|None): Hyper parameter of smooth l1 loss op. A float scalar + sigma (float|None): Hyper parameter of smooth L1 loss op. A float scalar with default value 1.0. Returns: - Variable: A tensor with rank be 2. The output smooth l1 loss with + Variable: A tensor with rank be 2. The output smooth L1 loss with shape [batch_size, 1]. Examples: .. code-block:: python data = fluid.layers.data(name='data', shape=[128], dtype='float32') - label = fluid.layers.data(name='label', shape=[100], dtype='int64') + label = fluid.layers.data(name='label', shape=[100], dtype='float32') fc = fluid.layers.fc(input=data, size=100) out = fluid.layers.smooth_l1(x=fc, y=label) """