提交 c108d610 编写于 作者: Y Yu Yang

Identity operator and its gradient

上级 0d9846f3
...@@ -55,5 +55,6 @@ cc_library(paddle_pybind SHARED ...@@ -55,5 +55,6 @@ cc_library(paddle_pybind SHARED
recurrent_op recurrent_op
uniform_random_op uniform_random_op
gaussian_random_op gaussian_random_op
fill_zeros_like_op) fill_zeros_like_op
identity_op)
endif(WITH_PYTHON) endif(WITH_PYTHON)
...@@ -42,6 +42,7 @@ USE_OP(fill_zeros_like); ...@@ -42,6 +42,7 @@ USE_OP(fill_zeros_like);
USE_OP_ITSELF(recurrent_op); USE_OP_ITSELF(recurrent_op);
USE_OP(gaussian_random); USE_OP(gaussian_random);
USE_OP(uniform_random); USE_OP(uniform_random);
USE_OP(identity);
namespace paddle { namespace paddle {
namespace framework { namespace framework {
......
...@@ -68,3 +68,4 @@ op_library(recurrent_op SRCS recurrent_op.cc rnn/recurrent_op_utils.cc ...@@ -68,3 +68,4 @@ op_library(recurrent_op SRCS recurrent_op.cc rnn/recurrent_op_utils.cc
DEPS framework_proto tensor op_registry operator net_op) DEPS framework_proto tensor op_registry operator net_op)
op_library(uniform_random_op op_library(uniform_random_op
SRCS uniform_random_op.cc uniform_random_op.cu) SRCS uniform_random_op.cc uniform_random_op.cu)
op_library(identity_op SRCS identity_op.cc identity_op.cu DEPS net_op)
/* 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. */
#include "paddle/operators/identity_op.h"
#include "paddle/operators/net_op.h"
namespace paddle {
namespace operators {
class IdentityOp : public framework::OperatorWithKernel {
public:
IdentityOp(const std::string &type, const VarNameMap &inputs,
const VarNameMap &outputs, const framework::AttributeMap &attrs)
: OperatorWithKernel(type, inputs, outputs, attrs) {}
protected:
void InferShape(const framework::InferShapeContext &ctx) const override {
auto *in = ctx.Input<framework::Tensor>("X");
auto *out = ctx.Output<framework::Tensor>("Out");
out->Resize(in->dims());
}
};
class IdentityOpMaker : public framework::OpProtoAndCheckerMaker {
public:
IdentityOpMaker(framework::OpProto *proto,
framework::OpAttrChecker *op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("X", "The input tensor of identity operator.").NotInGradient();
AddOutput("Out", "The output tensor of identity operator.").NotInGradient();
AddComment(R"DOC(Identity operator
The equation is: Out = X
)DOC");
}
};
// Identity Op's gradient is identity op, too.
// Grad(Out=identity_op(X)) => Grad(X) = identity_op(Grad(Out))
class IdentityGradOp : public NetOp {
public:
IdentityGradOp(const std::string &type, const VarNameMap &inputs,
const VarNameMap &outputs,
const framework::AttributeMap &attrs)
: NetOp(type, inputs, outputs, attrs) {
AddOp(framework::OpRegistry::CreateOp(
"identity", {{"X", {Input(framework::GradVarName("Out"))}}},
{{"Out", {Output(framework::GradVarName("X"))}}}, {}));
CompleteAddOp(false);
}
};
} // namespace operators
} // namespace paddle
namespace ops = paddle::operators;
REGISTER_OP(identity, ops::IdentityOp, ops::IdentityOpMaker, identity_grad,
ops::IdentityGradOp);
REGISTER_OP_CPU_KERNEL(identity, ops::IdentityKernel<float>);
/* 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. */
#include "paddle/operators/identity_op.h"
REGISTER_OP_GPU_KERNEL(identity, paddle::operators::IdentityKernel<float>);
/* 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/op_registry.h"
#include "paddle/memory/memcpy.h"
namespace paddle {
namespace operators {
template <typename T>
class IdentityKernel : public framework::OpKernel {
public:
virtual void Compute(const framework::ExecutionContext& context) const {
auto* tensor = context.Output<framework::Tensor>("Out");
auto* in = context.Input<framework::Tensor>("X");
tensor->CopyFrom<T>(*in, in->place());
}
};
} // namespace operators
} // namespace paddle
...@@ -27,3 +27,4 @@ py_test(test_uniform_random_op SRCS test_uniform_random_op.py) ...@@ -27,3 +27,4 @@ py_test(test_uniform_random_op SRCS test_uniform_random_op.py)
py_test(test_recurrent_op SRCS test_recurrent_op.py) py_test(test_recurrent_op SRCS test_recurrent_op.py)
py_test(test_sgd_op SRCS test_sgd_op.py) py_test(test_sgd_op SRCS test_sgd_op.py)
py_test(test_gradient_checker SRCS test_gradient_checker.py) py_test(test_gradient_checker SRCS test_gradient_checker.py)
py_test(test_identity_op SRCS test_identity_op.py)
import unittest
from op_test_util import OpTestMeta
from gradient_checker import GradientChecker, create_op
import numpy as np
class IdentityTest(unittest.TestCase):
__metaclass__ = OpTestMeta
def setUp(self):
self.type = "identity"
self.inputs = {'X': np.random.random((32, 784)).astype("float32")}
self.outputs = {'Out': self.inputs['X']}
class IdentityGradOpTest(GradientChecker):
def test_normal(self):
op = create_op("identity")
inputs = {"X": np.random.random((10, 10)).astype("float32")}
self.check_grad(op, inputs, set("X"), "Out")
if __name__ == '__main__':
unittest.main()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册