From 1543eeb4ce20b8173ac8a60c5e2a348b296dcf18 Mon Sep 17 00:00:00 2001 From: superjom Date: Wed, 16 Aug 2017 18:03:18 +0800 Subject: [PATCH] init --- paddle/framework/pybind.cc | 7 ++++ paddle/operators/recurrent_op.cc | 1 - .../v2/framework/tests/gradient_checker.py | 12 +++--- .../v2/framework/tests/test_recurrent_op.py | 40 ++++++++++++++++++- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/paddle/framework/pybind.cc b/paddle/framework/pybind.cc index fe0c87bc570..13f23a68198 100644 --- a/paddle/framework/pybind.cc +++ b/paddle/framework/pybind.cc @@ -275,6 +275,13 @@ All parameter, weight, gradient are variables in Paddle. const std::shared_ptr &net) -> void { self.set_stepnet(net); }); + + rnn.def("backward", [](const operators::RecurrentOp &forwardOp, + const std::unordered_set &no_grad_vars) { + const auto &op = *static_cast(&forwardOp); + return Backward(op, no_grad_vars); + }); + ExposeOperator(rnn); m.def("unique_integer", UniqueIntegerGenerator); diff --git a/paddle/operators/recurrent_op.cc b/paddle/operators/recurrent_op.cc index 78ce0ba3c0f..8c7300a3508 100644 --- a/paddle/operators/recurrent_op.cc +++ b/paddle/operators/recurrent_op.cc @@ -77,7 +77,6 @@ void RecurrentAlgorithm::CreateScopes(const Scope& scope) const { // Now all variables in scope must be created outside of op. PADDLE_ENFORCE_NOT_NULL(stepnet_); PADDLE_ENFORCE(!(*stepnet_)->Outputs().empty(), "stepnet_ op has no outputs"); - PADDLE_ENFORCE(!(*stepnet_)->Outputs().empty(), "net_op has no outputs"); if (seq_len_ > step_scopes->size()) { for (size_t i = step_scopes->size(); i < seq_len_; ++i) { diff --git a/python/paddle/v2/framework/tests/gradient_checker.py b/python/paddle/v2/framework/tests/gradient_checker.py index 501cf6110ff..b6d8131be98 100644 --- a/python/paddle/v2/framework/tests/gradient_checker.py +++ b/python/paddle/v2/framework/tests/gradient_checker.py @@ -29,13 +29,13 @@ def get_numeric_gradient(op, local_scope=None): """ Get Numeric Gradient for an operator's input. - - :param op: C++ operator instance, could be an network - :param input_values: The input variables. Should be an dictionary, key is - variable name. Value is numpy array. - :param output_name: The final output variable name. + + :param op: C++ operator instance, could be an network + :param input_values: The input variables. Should be an dictionary, key is + variable name. Value is numpy array + :param output_name: The final output variable name. :param input_to_check: The input variable need to get gradient. - :param delta: The perturbation value for numeric gradient method. The + :param delta: The perturbation value for numeric gradient method. The smaller delta is, the more accurate result will get. But if that delta is too small, it could occur numerical stability problem. :param local_scope: The local scope used for get_numeric_gradient. diff --git a/python/paddle/v2/framework/tests/test_recurrent_op.py b/python/paddle/v2/framework/tests/test_recurrent_op.py index 3d4a34d8d71..0da56c1ad9a 100644 --- a/python/paddle/v2/framework/tests/test_recurrent_op.py +++ b/python/paddle/v2/framework/tests/test_recurrent_op.py @@ -3,6 +3,7 @@ import paddle.v2.framework.core as core import unittest import numpy as np from paddle.v2.framework.op import Operator, RecurrentOp +from gradient_checker import GradientChecker def py_sigmoid(x): @@ -69,7 +70,7 @@ def create_tensor(scope, name, shape, np_data): return tensor -class TestRecurrentOp(unittest.TestCase): +class RecurrentOpTest(unittest.TestCase): ''' Test RNNOp @@ -164,5 +165,42 @@ class TestRecurrentOp(unittest.TestCase): self.assertEqual(pd_output.shape, py_output.shape) +class RecurrentGradientOpTest(unittest.TestCase): + def create_forward_op(self): + self.forward_op = RecurrentOp( + # inputs + inlinks=["x"], + boot_memories=["h_boot"], + step_net="stepnet", + # outputs + outlinks=["h"], + step_scopes="step_scopes", + # attributes + inlink_alias=["x@alias"], + outlink_alias=["h@alias"], + pre_memories=["h@pre"], + memories=["h@alias"]) + + # create a stepnet for RNN + stepnet = core.Net.create() + x_fc_op = Operator("mul", X="x@alias", Y="W", Out="Wx") + h_fc_op = Operator("mul", X="h@pre", Y="U", Out="Uh") + sum_op = Operator("add_two", X="Wx", Y="Uh", Out="sum") + sig_op = Operator("sigmoid", X="sum", Y="h@alias") + + for op in [x_fc_op, h_fc_op, sum_op, sig_op]: + stepnet.add_op(op) + stepnet.complete_add_op(True) + self.forward_op.set_stepnet(stepnet) + + def create_gradient_op(self): + a = set() + backward_op = core.RecurrentOp.backward(self.forward_op, a) + + def test_grad(self): + self.create_forward_op() + self.create_gradient_op() + + if __name__ == '__main__': unittest.main() -- GitLab