Add huber loss operator.#3989
Conversation
paddle/operators/huber_loss_op.cc
Outdated
| auto* x = ctx.Input<Tensor>("X"); | ||
| auto* y = ctx.Input<Tensor>("Y"); | ||
|
|
||
| PADDLE_ENFORCE_EQ(x->dims(), y->dims(), |
There was a problem hiding this comment.
PADDLE_ENFORCE_EQ means assert equality, so the comment is useless.
no comment is ok.
There was a problem hiding this comment.
I have a question here, if no error information is given, does PADDLE_ENFORCE_EQ gives a meaningful error log, for example, x = 5 is not equal to y = 3.
paddle/operators/huber_loss_op.cc
Outdated
| // we constraint shape of X to (N, 1), may expand to (N, x, ...) if needed | ||
| PADDLE_ENFORCE_EQ(framework::arity(x->dims()), 2, | ||
| "Tensor rank of X must be 2."); | ||
| PADDLE_ENFORCE_EQ(x->dims()[1], 1, "2nd dimension of X must be 1."); |
There was a problem hiding this comment.
the comment tell no extra information than the enforce_eq, delete the comment or make a description why it should be 1.
paddle/operators/huber_loss_op.cc
Outdated
| input to (N, 1). The formulation is: | ||
|
|
||
| L_delta(y, f(x)) = 0.5 * (y - f(x))^2 for |y - f(x)| <= delta, | ||
| delta * (|y - f(x)| - 0.5 * delta) otherwise. |
There was a problem hiding this comment.
need to format the indent here?
There was a problem hiding this comment.
Changed to Latex style.
paddle/operators/huber_loss_op.cc
Outdated
| auto* x_grad = ctx.Output<Tensor>(framework::GradVarName("X")); | ||
| auto* y_grad = ctx.Output<Tensor>(framework::GradVarName("Y")); | ||
|
|
||
| PADDLE_ENFORCE_NOT_NULL(x, "Input X must not be null."); |
There was a problem hiding this comment.
these comments lack information.
paddle/operators/huber_loss_op.cc
Outdated
| PADDLE_ENFORCE_EQ(x->dims()[1], 1, "2nd dimension of X must be 1."); | ||
|
|
||
| ctx.Output<Tensor>("Residual")->Resize(x->dims()); | ||
| ctx.Output<Tensor>("Out")->Resize({x->dims()[0], 1}); |
There was a problem hiding this comment.
Output<framework::LoDTensor>
paddle/operators/huber_loss_op.cc
Outdated
| auto* residual = ctx.Input<Tensor>("Residual"); | ||
| auto* out_grad = ctx.Input<Tensor>(framework::GradVarName("Out")); | ||
| auto* x_grad = ctx.Output<Tensor>(framework::GradVarName("X")); | ||
| auto* y_grad = ctx.Output<Tensor>(framework::GradVarName("Y")); |
There was a problem hiding this comment.
Output<framework::LoDTensor>
paddle/operators/huber_loss_op.h
Outdated
| auto* in1 = context.Input<Tensor>("Y"); | ||
| auto* out0 = context.Output<Tensor>("Residual"); | ||
| auto* out1 = context.Output<Tensor>("Out"); | ||
| auto delta = static_cast<T>(context.op().Attr<AttrType>("delta")); |
| using Tensor = framework::Tensor; | ||
| template <typename T, int MajorType = Eigen::RowMajor, | ||
| typename IndexType = Eigen::DenseIndex> | ||
| using EigenVector = framework::EigenVector<T, MajorType, IndexType>; |
There was a problem hiding this comment.
Do not use using in the header file.
paddle/operators/huber_loss_op.h
Outdated
| } | ||
| } | ||
|
|
||
| bool is_x; |
|
|
||
| def test_check_grad_ingore_y(self): | ||
| self.check_grad( | ||
| ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('residual')) |
There was a problem hiding this comment.
The max relative error is too large.
paddle/operators/huber_loss_op.cc
Outdated
| auto* x = ctx.Input<Tensor>("X"); | ||
| auto* y = ctx.Input<Tensor>("Y"); | ||
|
|
||
| PADDLE_ENFORCE_EQ(x->dims(), y->dims(), |
There was a problem hiding this comment.
I have a question here, if no error information is given, does PADDLE_ENFORCE_EQ gives a meaningful error log, for example, x = 5 is not equal to y = 3.
paddle/operators/huber_loss_op.cc
Outdated
|
|
||
| PADDLE_ENFORCE_EQ(x->dims(), y->dims(), | ||
| "Dimensions of X and Y must be the same."); | ||
| // we constraint shape of X to (N, 1), may expand to (N, x, ...) if needed |
There was a problem hiding this comment.
- This comment has grammar errors.
we constraint shape of X to (N, 1), may expand to (N, x, ...) if neededdoes this means the current implementation is a simplified version, and in future, we will fix this? If so, this should be a TODO.- actually, I am not sure about the intent of this comment.
There was a problem hiding this comment.
yes, PADDLE_ENFORCE_EQ will behave like Gtest's ASSERT_EQ, display details of the comparison if failed.
@lcy-seso
paddle/operators/huber_loss_op.cc
Outdated
| // we constraint shape of X to (N, 1), may expand to (N, x, ...) if needed | ||
| PADDLE_ENFORCE_EQ(framework::arity(x->dims()), 2, | ||
| "Tensor rank of X must be 2."); | ||
| PADDLE_ENFORCE_EQ(x->dims()[1], 1, "2nd dimension of X must be 1."); |
paddle/operators/huber_loss_op.cc
Outdated
| HuberLossOpMaker(framework::OpProto* proto, | ||
| framework::OpAttrChecker* op_checker) | ||
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("X", "Input value of HuberLossOp."); |
There was a problem hiding this comment.
- Input value --> The input value,the definite article should be used in the sentence.
- I think "The input tensor with shape N × K" is better. The input value is not a technically accurate description.
paddle/operators/huber_loss_op.cc
Outdated
| framework::OpAttrChecker* op_checker) | ||
| : OpProtoAndCheckerMaker(proto, op_checker) { | ||
| AddInput("X", "Input value of HuberLossOp."); | ||
| AddInput("Y", "Target value of HuberLossOp."); |
There was a problem hiding this comment.
Target value --> The output tensor with shape **
There was a problem hiding this comment.
In fact, Y is also input tensor, already refined the description.
paddle/operators/huber_loss_op.cc
Outdated
| "Save residual value between Y and X. " | ||
| "Will be reused in backward.") | ||
| .AsIntermediate(); | ||
| AddOutput("Out", "Huber loss between input and target."); |
There was a problem hiding this comment.
Please use "the output tensor " instead, and give information of its dimension.
paddle/operators/huber_loss_op.cc
Outdated
| input to (N, 1). The formulation is: | ||
|
|
||
| L_delta(y, f(x)) = 0.5 * (y - f(x))^2 for |y - f(x)| <= delta, | ||
| delta * (|y - f(x)| - 0.5 * delta) otherwise. |
paddle/operators/huber_loss_op.cc
Outdated
| PADDLE_ENFORCE_NOT_NULL(x, "Input X must not be null."); | ||
| PADDLE_ENFORCE_NOT_NULL(y, "Target Y must not be null."); | ||
| PADDLE_ENFORCE_NOT_NULL(residual, "Residual value must not be null."); | ||
| PADDLE_ENFORCE_NOT_NULL(out_grad, "Out gradient must not be null."); |
There was a problem hiding this comment.
line 83 ~ 85, the definite article should be added.
paddle/operators/huber_loss_op.cc
Outdated
| PADDLE_ENFORCE_NOT_NULL(out_grad, "Out gradient must not be null."); | ||
|
|
||
| PADDLE_ENFORCE_EQ(residual->dims(), x->dims(), | ||
| "Dimension of X and residual value must be the same."); |
paddle/operators/huber_loss_op.cc
Outdated
| "Dimension of X and residual value must be the same."); | ||
| PADDLE_ENFORCE_EQ( | ||
| out_grad->dims(), x->dims(), | ||
| "Dimension of Out gradient and X must be the same (N*1)."); |
|
please update this code and merge it asap. |
paddle/operators/huber_loss_op.h
Outdated
| HOSTDEVICE T operator()(const T& val) const { | ||
| T abs_val = std::abs(val); | ||
| if (abs_val <= delta) { | ||
| return 0.5 * val * val; |
paddle/operators/huber_loss_op.h
Outdated
| if (abs_val <= delta) { | ||
| return 0.5 * val * val; | ||
| } else { | ||
| return delta * (abs_val - 0.5 * delta); |
Resolves #3923