Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add huber loss operator. #3989

Merged
merged 6 commits into from
Oct 27, 2017
Merged

Add huber loss operator. #3989

merged 6 commits into from
Oct 27, 2017

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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants