Skip to content

Add huber loss operator.#3989

Merged
pkuyym merged 6 commits intoPaddlePaddle:developfrom
pkuyym:fix-3923-r
Oct 27, 2017
Merged

Add huber loss operator.#3989
pkuyym merged 6 commits intoPaddlePaddle:developfrom
pkuyym:fix-3923-r

Conversation

@pkuyym
Copy link
Contributor

@pkuyym pkuyym commented Sep 9, 2017

Resolves #3923

auto* x = ctx.Input<Tensor>("X");
auto* y = ctx.Input<Tensor>("Y");

PADDLE_ENFORCE_EQ(x->dims(), y->dims(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PADDLE_ENFORCE_EQ means assert equality, so the comment is useless.
no comment is ok.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// 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.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment tell no extra information than the enforce_eq, delete the comment or make a description why it should be 1.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @Superjom

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to format the indent here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @Superjom

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to Latex style.

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.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these comments lack information.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

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});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output<framework::LoDTensor>

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"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Output<framework::LoDTensor>

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"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

context.Attr<>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

using Tensor = framework::Tensor;
template <typename T, int MajorType = Eigen::RowMajor,
typename IndexType = Eigen::DenseIndex>
using EigenVector = framework::EigenVector<T, MajorType, IndexType>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use using in the header file.

}
}

bool is_x;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is is_x ?


def test_check_grad_ingore_y(self):
self.check_grad(
['X'], 'Out', max_relative_error=0.5, no_grad_set=set('residual'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max relative error is too large.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

auto* x = ctx.Input<Tensor>("X");
auto* y = ctx.Input<Tensor>("Y");

PADDLE_ENFORCE_EQ(x->dims(), y->dims(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • This comment has grammar errors.
  • we constraint shape of X to (N, 1), may expand to (N, x, ...) if needed does 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, PADDLE_ENFORCE_EQ will behave like Gtest's ASSERT_EQ, display details of the comparison if failed.
@lcy-seso

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

// 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.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @Superjom

HuberLossOpMaker(framework::OpProto* proto,
framework::OpAttrChecker* op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("X", "Input value of HuberLossOp.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 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.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

framework::OpAttrChecker* op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("X", "Input value of HuberLossOp.");
AddInput("Y", "Target value of HuberLossOp.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Target value --> The output tensor with shape **

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, Y is also input tensor, already refined the description.

"Save residual value between Y and X. "
"Will be reused in backward.")
.AsIntermediate();
AddOutput("Out", "Huber loss between input and target.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use "the output tensor " instead, and give information of its dimension.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with @Superjom

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.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 83 ~ 85, the definite article should be added.

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.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dimension

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

"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).");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dimension

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@qingqing01
Copy link
Contributor

please update this code and merge it asap.

lcy-seso
lcy-seso previously approved these changes Oct 27, 2017
Copy link
Contributor

@lcy-seso lcy-seso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

HOSTDEVICE T operator()(const T& val) const {
T abs_val = std::abs(val);
if (abs_val <= delta) {
return 0.5 * val * val;
Copy link
Contributor

@lcy-seso lcy-seso Oct 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_cast<T>(0.5)

if (abs_val <= delta) {
return 0.5 * val * val;
} else {
return delta * (abs_val - 0.5 * delta);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static_cast<T>(0.5)

Copy link
Contributor

@lcy-seso lcy-seso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@pkuyym pkuyym merged commit fd5199f into PaddlePaddle:develop Oct 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

4 participants