From 3e13b9122fef2ac8dc53bad340ad41902f2a4ccd Mon Sep 17 00:00:00 2001 From: caoying03 Date: Tue, 5 Sep 2017 12:18:51 +0800 Subject: [PATCH] add softmax_with_cost_op. --- paddle/operators/softmax_with_cost_op.cc | 82 +++++++++++++++++++ paddle/operators/softmax_with_cost_op.h | 40 +++++++++ paddle/pybind/pybind.cc | 1 + .../tests/test_softmax_with_cost_op.py | 22 +++++ 4 files changed, 145 insertions(+) create mode 100644 paddle/operators/softmax_with_cost_op.cc create mode 100644 paddle/operators/softmax_with_cost_op.h create mode 100644 python/paddle/v2/framework/tests/test_softmax_with_cost_op.py diff --git a/paddle/operators/softmax_with_cost_op.cc b/paddle/operators/softmax_with_cost_op.cc new file mode 100644 index 00000000000..a4537691a03 --- /dev/null +++ b/paddle/operators/softmax_with_cost_op.cc @@ -0,0 +1,82 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +:A +limitations under the License. */ + +#include "paddle/operators/softmax_op.h" + +namespace paddle { +namespace operators { + +class SoftmaxWithLossOp : public framework::OperatorWithKernel { + public: + using framework::OperatorWithKernel::OperatorWithKernel; + + protected: + void InferShape(const framework::InferShapeContext &ctx) const override { + auto logits = ctx.Input("logits"); + PADDLE_ENFORCE(logits->dims().size() == 2UL, + "The input of softmax_with_loss_op should be a 2-d tensor."); + PADDLE_ENFORCE(ctx.Input("lables")->dims().size() == 1UL, + "The label should be a 1-d tensor."); + ctx.Output("loss")->Resize({logits->dims()[0]}); + } +}; + +class SoftmaxWithLossOpMaker : public framework::OpProtoAndCheckerMaker { + public: + SoftmaxWithLossOpMaker(framework::OpProto *proto, + framework::OpAttrChecker *op_checker) + : OpProtoAndCheckerMaker(proto, op_checker) { + AddInput("logits", + "The unscaled log probabilities which is a 2-D tensor with" + "shape [N x K]. N is the batch_size, and K is the class number."); + AddInput("label", "The ground truth. A 1-D tensor with shape N."); + AddOutput("loss", "A 1-D tensor with shape N."); + AddComment(R"DOC( +Cross entropy loss with softmax are used as the output layer extensively. This +operator computes the softmax normalized values for each row of the input +tensor, after which cross-entropy loss is then computed. This provides a more +numerically stable gradient. + +Because this operators performs a softmax on logits internally, it expects +unscaled logits. Please do not call this op with the output of softmax operator, +which will produce incorrect results. + +This operators expects mutually exclusive hard labels, each sample in a batch +is in exactly one class with probabilities 1. Each sample in the batch with one +and only one label. +)DOC"); + } +}; + +class SoftmaxWithLossOpGrad : public framework::OperatorWithKernel { + public: + using framework::OperatorWithKernel::OperatorWithKernel; + + protected: + void InferShape(const framework::InferShapeContext &ctx) const override {} +}; + +} // namespace operators +} // namespace paddle + +namespace ops = paddle::operators; + +REGISTER_OP(softmax, ops::SoftmaxWithLossOp, ops::SoftmaxWithLossOpMaker, + softmax_grad, ops::SoftmaxWithLossOpGrad); +REGISTER_OP_CPU_KERNEL( + softmax, ops::SoftmaxWithLossKernel); +REGISTER_OP_CPU_KERNEL( + softmax_grad, + ops::SoftmaxWithLossGradKernel); diff --git a/paddle/operators/softmax_with_cost_op.h b/paddle/operators/softmax_with_cost_op.h new file mode 100644 index 00000000000..fb544842b70 --- /dev/null +++ b/paddle/operators/softmax_with_cost_op.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once +#include "paddle/framework/eigen.h" +#include "paddle/framework/op_registry.h" + +namespace paddle { +namespace operators { + +using Tensor = framework::Tensor; +template +using EigenMatrix = framework::EigenMatrix; + +template +class SoftmaxWithLossKernel : public framework::OpKernel { + public: + void Compute(const framework::ExecutionContext& context) const override {} +}; + +template +class SoftmaxWithLossGradKernel : public framework::OpKernel { + public: + void Compute(const framework::ExecutionContext& context) const override {} +}; + +} // namespace operators +} // namespace paddle diff --git a/paddle/pybind/pybind.cc b/paddle/pybind/pybind.cc index 6896422617b..e86f4dfe26e 100644 --- a/paddle/pybind/pybind.cc +++ b/paddle/pybind/pybind.cc @@ -37,6 +37,7 @@ USE_OP(mul); USE_OP(mean); USE_OP(sigmoid); USE_OP(softmax); +USE_OP(softmax_with_loss); USE_OP(rowwise_add); USE_OP(fill_zeros_like); USE_NO_KERNEL_OP(recurrent); diff --git a/python/paddle/v2/framework/tests/test_softmax_with_cost_op.py b/python/paddle/v2/framework/tests/test_softmax_with_cost_op.py new file mode 100644 index 00000000000..f7b9f54a91f --- /dev/null +++ b/python/paddle/v2/framework/tests/test_softmax_with_cost_op.py @@ -0,0 +1,22 @@ +import unittest + +import numpy as np + +from gradient_checker import GradientChecker, create_op +from op_test_util import OpTestMeta + + +class TestSoftmaxWithLossOp(unittest.TestCase): + __metaclass__ = OpTestMeta + + def setUp(self): + pass + + +class SoftmaxWithLossGradOpTest(GradientChecker): + def test_softmax(self): + pass + + +if __name__ == '__main__': + unittest.main() -- GitLab