提交 6b3e9ccb 编写于 作者: Y Yibing Liu

pass unit test for margin_rank_loss_op

上级 2f122561
...@@ -19,11 +19,7 @@ namespace operators { ...@@ -19,11 +19,7 @@ namespace operators {
class MarginRankLossOp : public framework::OperatorWithKernel { class MarginRankLossOp : public framework::OperatorWithKernel {
public: public:
MarginRankLossOp(const std::string &type, using framework::OperatorWithKernel::OperatorWithKernel;
const framework::VariableNameMap &inputs,
const framework::VariableNameMap &outputs,
const framework::AttributeMap &attrs)
: OperatorWithKernel(type, inputs, outputs, attrs) {}
protected: protected:
void InferShape(const framework::InferShapeContext &ctx) const override { void InferShape(const framework::InferShapeContext &ctx) const override {
...@@ -35,13 +31,11 @@ class MarginRankLossOp : public framework::OperatorWithKernel { ...@@ -35,13 +31,11 @@ class MarginRankLossOp : public framework::OperatorWithKernel {
auto label_dims = ctx.Input<framework::Tensor>("Label")->dims(); auto label_dims = ctx.Input<framework::Tensor>("Label")->dims();
auto x1_dims = ctx.Input<framework::Tensor>("X1")->dims(); auto x1_dims = ctx.Input<framework::Tensor>("X1")->dims();
auto x2_dims = ctx.Input<framework::Tensor>("X2")->dims(); auto x2_dims = ctx.Input<framework::Tensor>("X2")->dims();
PADDLE_ENFORCE((label_dims.size() == 1) && (x1_dims.size() == 1) && PADDLE_ENFORCE((label_dims == x1_dims) && (x1_dims == x2_dims) &&
(x2_dims.size() == 1), (label_dims.size() == 2) && (label_dims[1] == 1),
"The rank of all inputs must be 1."); "All inputs must be vector with the same size");
PADDLE_ENFORCE((label_dims == x1_dims) && (x1_dims == x2_dims),
"All inputs must have the same size");
ctx.Output<framework::LoDTensor>("Out")->Resize(label_dims);
ctx.Output<framework::LoDTensor>("Activated")->Resize(label_dims); ctx.Output<framework::LoDTensor>("Activated")->Resize(label_dims);
ctx.Output<framework::LoDTensor>("Out")->Resize(label_dims);
} }
}; };
...@@ -51,18 +45,27 @@ class MarginRankLossOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -51,18 +45,27 @@ class MarginRankLossOpMaker : public framework::OpProtoAndCheckerMaker {
MarginRankLossOpMaker(framework::OpProto *proto, MarginRankLossOpMaker(framework::OpProto *proto,
framework::OpAttrChecker *op_checker) framework::OpAttrChecker *op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) { : OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("Label", "The label indicating X1 ranked higher than X2 or not."); AddInput("X1", "The first input of MarginRankLossOp, row vector.");
AddInput("X1", "The first input of MarginRankLossOp."); AddInput("X2", "The second input of MarginRankLossOp, row vector.");
AddInput("X2", "The second input of MarginRankLossOp"); AddInput("Label",
AddAttr<AttrType>("margin", "Margin for MarginRankLossOp").SetDefault(0); "The label indicating X1 ranked higher than X2 "
AddOutput("Out", "The output loss of MarginRankLoss operator"); "or not, row vector.");
AddAttr<AttrType>("margin", "Margin for MarginRankLossOp, scalar.")
.SetDefault(0);
AddOutput("Activated", AddOutput("Activated",
"Intermediate tensor to indicate " "Intermediate tensor to indicate whether each element of "
"whether Output(Out) is activated") "Output(Out) is activated")
.AsIntermediate(); .AsIntermediate();
AddComment(R"DOC(MarginRankLoss operator AddOutput("Out", "The output loss of MarginRankLoss operator");
AddComment(R"DOC(
MarginRankLoss operator measures the loss given a pair of input {`X1`, `X2`}
and `Label` with attribuute `margin`, where `Label == 1` indicating X1 is
ranked higher than `X2`, otherwise `Label == -1`. The loss turns out
loss(X1, X2, Label) = max(0, -Label * (X1-X2) + margin)
loss(x1, x2, y) = max(0, -label * (x1-x2) + margin) For batch input, `X1`, `X2` and `Label` all have the same size batch_size x 1.
)DOC"); )DOC");
} }
...@@ -70,11 +73,7 @@ loss(x1, x2, y) = max(0, -label * (x1-x2) + margin) ...@@ -70,11 +73,7 @@ loss(x1, x2, y) = max(0, -label * (x1-x2) + margin)
class MarginRankLossGradOp : public framework::OperatorWithKernel { class MarginRankLossGradOp : public framework::OperatorWithKernel {
public: public:
MarginRankLossGradOp(const std::string &type, using framework::OperatorWithKernel::OperatorWithKernel;
const framework::VariableNameMap &inputs,
const framework::VariableNameMap &outputs,
const framework::AttributeMap &attrs)
: OperatorWithKernel(type, inputs, outputs, attrs) {}
protected: protected:
void InferShape(const framework::InferShapeContext &ctx) const override { void InferShape(const framework::InferShapeContext &ctx) const override {
......
...@@ -14,9 +14,11 @@ ...@@ -14,9 +14,11 @@
#include "paddle/operators/margin_rank_loss_op.h" #include "paddle/operators/margin_rank_loss_op.h"
namespace ops = paddle::operators;
REGISTER_OP_GPU_KERNEL( REGISTER_OP_GPU_KERNEL(
margin_rank_loss, margin_rank_loss,
paddle::operators::MarginRankLossKernel<paddle::platform::GPUPlace, float>); ops::MarginRankLossKernel<paddle::platform::GPUPlace, float>);
REGISTER_OP_GPU_KERNEL(margin_rank_loss_grad, REGISTER_OP_GPU_KERNEL(
paddle::operators::MarginRankLossGradKernel< margin_rank_loss_grad,
paddle::platform::GPUPlace, float>); ops::MarginRankLossGradKernel<paddle::platform::GPUPlace, float>);
...@@ -46,8 +46,8 @@ template <typename Place, typename T, typename AttrType = T> ...@@ -46,8 +46,8 @@ template <typename Place, typename T, typename AttrType = T>
class MarginRankLossKernel : public framework::OpKernel { class MarginRankLossKernel : public framework::OpKernel {
public: public:
void Compute(const framework::ExecutionContext& ctx) const { void Compute(const framework::ExecutionContext& ctx) const {
auto* out_t = ctx.Output<framework::LoDTensor>("Out"); auto* out_t = ctx.Output<framework::Tensor>("Out");
auto* act_t = ctx.Output<framework::LoDTensor>("Activated"); auto* act_t = ctx.Output<framework::Tensor>("Activated");
auto* label_t = ctx.Input<framework::Tensor>("Label"); auto* label_t = ctx.Input<framework::Tensor>("Label");
auto* x1_t = ctx.Input<framework::Tensor>("X1"); auto* x1_t = ctx.Input<framework::Tensor>("X1");
...@@ -65,8 +65,8 @@ class MarginRankLossKernel : public framework::OpKernel { ...@@ -65,8 +65,8 @@ class MarginRankLossKernel : public framework::OpKernel {
auto x2 = framework::EigenVector<T>::Flatten(*x2_t); auto x2 = framework::EigenVector<T>::Flatten(*x2_t);
auto& dev = ctx.GetEigenDevice<Place>(); auto& dev = ctx.GetEigenDevice<Place>();
act.device(dev) = (-label * (x1 - x2) + margin).unaryExpr(Heaviside<T>());
out.device(dev) = (-label * (x1 - x2) + margin).unaryExpr(ReLU<T>()); out.device(dev) = (-label * (x1 - x2) + margin).unaryExpr(ReLU<T>());
act.device(dev) = out.unaryExpr(Heaviside<T>());
} }
}; };
...@@ -78,15 +78,15 @@ class MarginRankLossGradKernel : public framework::OpKernel { ...@@ -78,15 +78,15 @@ class MarginRankLossGradKernel : public framework::OpKernel {
ctx.Output<framework::LoDTensor>(framework::GradVarName("X1")); ctx.Output<framework::LoDTensor>(framework::GradVarName("X1"));
auto* d_x2_t = auto* d_x2_t =
ctx.Output<framework::LoDTensor>(framework::GradVarName("X2")); ctx.Output<framework::LoDTensor>(framework::GradVarName("X2"));
auto* act_t = ctx.Output<framework::LoDTensor>("Activated");
auto* act_t = ctx.Input<framework::Tensor>("Activated");
auto* d_out_t = ctx.Input<framework::Tensor>(framework::GradVarName("Out")); auto* d_out_t = ctx.Input<framework::Tensor>(framework::GradVarName("Out"));
auto* label_t = ctx.Input<framework::Tensor>("Label"); auto* label_t = ctx.Input<framework::Tensor>("Label");
auto& dev = ctx.GetEigenDevice<Place>();
auto d_out = framework::EigenVector<T>::Flatten(*d_out_t); auto d_out = framework::EigenVector<T>::Flatten(*d_out_t);
auto act = framework::EigenVector<T>::Flatten(*act_t); auto act = framework::EigenVector<T>::Flatten(*act_t);
auto label = framework::EigenVector<T>::Flatten(*label_t); auto label = framework::EigenVector<T>::Flatten(*label_t);
auto& dev = ctx.GetEigenDevice<Place>();
// compute d_x1 // compute d_x1
if (d_x1_t) { if (d_x1_t) {
......
...@@ -8,23 +8,23 @@ class TestMarginRankLossOp(OpTest): ...@@ -8,23 +8,23 @@ class TestMarginRankLossOp(OpTest):
self.op_type = "margin_rank_loss" self.op_type = "margin_rank_loss"
batch_size = 5 batch_size = 5
margin = 0.1 margin = 0.1
# labels_{i} = {0, 1.0} or {0, 0.5, 1.0} # labels_{i} = {-1, 1}
label = np.random.randint(0, 2, size=(batch_size, )).astype("float32") label = 2 * np.random.randint(
x1 = np.random.random((batch_size, )).astype("float32") 0, 2, size=(batch_size, 1)).astype("float32") - 1
x2 = np.random.random((batch_size, )).astype("float32") x1 = np.random.random((batch_size, 1)).astype("float32")
x2 = np.random.random((batch_size, 1)).astype("float32")
# loss = max(0, -label * (x1 - x2) + margin) # loss = max(0, -label * (x1 - x2) + margin)
loss = [ loss = -label * (x1 - x2) + margin
max(0, -label[i] * (x1[i] - x2[i]) + margin) loss = np.where(loss > 0, loss, 0)
for i in range(batch_size) act = np.where(loss > 0, 1., 0.)
]
self.attrs = {'margin': margin} self.attrs = {'margin': margin}
self.inputs = {'Label': label, 'X1': x1, 'X2': x2} self.inputs = {'Label': label, 'X1': x1, 'X2': x2}
self.outputs = {'Out': loss} self.outputs = {'Activated': act, 'Out': loss}
def test_check_output(self): def test_check_output(self):
self.check_output() self.check_output()
"""
def test_check_grad(self): def test_check_grad(self):
self.check_grad(["X1", "X2"], "Out") self.check_grad(["X1", "X2"], "Out")
...@@ -33,7 +33,6 @@ class TestMarginRankLossOp(OpTest): ...@@ -33,7 +33,6 @@ class TestMarginRankLossOp(OpTest):
def test_check_grad_ignore_x2(self): def test_check_grad_ignore_x2(self):
self.check_grad(["X1"], "Out", no_grad_set=set('X2')) self.check_grad(["X1"], "Out", no_grad_set=set('X2'))
"""
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册