提交 f50e36e2 编写于 作者: Q qijun

follow comments

上级 a22606ca
...@@ -123,6 +123,15 @@ OperatorBase::OperatorBase(const std::string& type, ...@@ -123,6 +123,15 @@ OperatorBase::OperatorBase(const std::string& type,
CheckAllInputOutputSet(); CheckAllInputOutputSet();
} }
std::vector<std::string> OperatorBase::InputVars() const {
std::vector<std::string> ret_val;
for (auto& o : outputs_) {
ret_val.reserve(ret_val.size() + o.second.size());
ret_val.insert(ret_val.end(), o.second.begin(), o.second.end());
}
return ret_val;
}
std::vector<std::string> OperatorBase::OutputVars(bool has_intermediate) const { std::vector<std::string> OperatorBase::OutputVars(bool has_intermediate) const {
std::vector<std::string> ret_val; std::vector<std::string> ret_val;
if (has_intermediate) { if (has_intermediate) {
......
...@@ -95,31 +95,13 @@ class OperatorBase { ...@@ -95,31 +95,13 @@ class OperatorBase {
const VariableNameMap& Inputs() const { return inputs_; } const VariableNameMap& Inputs() const { return inputs_; }
const VariableNameMap& Outputs() const { return outputs_; } const VariableNameMap& Outputs() const { return outputs_; }
const std::vector<std::string> InputsNames() const {
std::vector<std::string> result;
for (auto& kv : inputs_) {
for (auto& name : kv.second) {
result.push_back(name);
}
}
return result;
}
const std::vector<std::string> OutputsNames() const {
std::vector<std::string> result;
for (auto& kv : outputs_) {
for (auto& name : kv.second) {
result.push_back(name);
}
}
return result;
}
//! Get a input with argument's name described in `op_proto` //! Get a input with argument's name described in `op_proto`
std::string Input(const std::string& name) const; std::string Input(const std::string& name) const;
//! Get a input which has multiple variables. //! Get a input which has multiple variables.
const std::vector<std::string>& Inputs(const std::string& name) const; const std::vector<std::string>& Inputs(const std::string& name) const;
std::vector<std::string> InputVars() const;
//! Get a output with argument's name described in `op_proto` //! Get a output with argument's name described in `op_proto`
std::string Output(const std::string& name) const; std::string Output(const std::string& name) const;
//! Get an output which has multiple variables. //! Get an output which has multiple variables.
......
...@@ -26,10 +26,14 @@ class SumOp : public framework::OperatorWithKernel { ...@@ -26,10 +26,14 @@ class SumOp : public framework::OperatorWithKernel {
auto *out = ctx.Output<framework::Tensor>("Out"); auto *out = ctx.Output<framework::Tensor>("Out");
int N = ins.size(); int N = ins.size();
PADDLE_ENFORCE_GT(N, 1, "Input tensors count should > 1."); auto in_dim = ins[0]->dims();
auto dim_zero = ins[0]->dims(); PADDLE_ENFORCE_GT(N, 1, "Input tensors count should > 1.");
out->Resize(dim_zero); for (int i = 1; i < N; i++) {
auto dim = ins[i]->dims();
PADDLE_ENFORCE(in_dim == dim, "Input tensors must have same shape");
}
out->Resize(in_dim);
} }
}; };
......
...@@ -214,15 +214,10 @@ All parameter, weight, gradient are variables in Paddle. ...@@ -214,15 +214,10 @@ All parameter, weight, gradient are variables in Paddle.
-> std::map<std::string, std::vector<std::string>> { -> std::map<std::string, std::vector<std::string>> {
return op.Outputs(); return op.Outputs();
}) })
.def("outputs_names", .def("output_vars",
[](const OperatorBase &op) -> std::vector<std::string> { [](const OperatorBase &op) { return op.OutputVars(true); })
return op.OutputsNames();
})
.def("inputs", [](const OperatorBase &op) { return op.Inputs(); }) .def("inputs", [](const OperatorBase &op) { return op.Inputs(); })
.def("inputs_names", .def("input_vars", [](const OperatorBase &op) { return op.InputVars(); })
[](const OperatorBase &op) -> std::vector<std::string> {
return op.InputsNames();
})
.def("__str__", &OperatorBase::DebugString) .def("__str__", &OperatorBase::DebugString)
.def("no_intermediate_outputs", .def("no_intermediate_outputs",
[](const OperatorBase &op) { return op.OutputVars(false); }) [](const OperatorBase &op) { return op.OutputVars(false); })
......
...@@ -9,54 +9,40 @@ def grad_var_name(var_name): ...@@ -9,54 +9,40 @@ def grad_var_name(var_name):
return var_name + "@GRAD" return var_name + "@GRAD"
def remove_grad_var_name(var_name):
return var_name[0:-5]
def create_op(scope, op_type, inputs, outputs, attrs=None): def create_op(scope, op_type, inputs, outputs, attrs=None):
kwargs = dict() kwargs = dict()
for ins in Operator.get_op_inputs(op_type): for in_name, in_dup in Operator.get_op_inputs(op_type):
in_name = ins[0]
in_dup = ins[1]
if in_name in inputs: if in_name in inputs:
kwargs[in_name] = [] kwargs[in_name] = []
if in_dup: if in_dup:
sub_in = inputs[in_name] sub_in = inputs[in_name]
for sub_in_name in sub_in: for sub_in_name in sub_in:
var = scope.new_var(sub_in_name) var = scope.new_var(sub_in_name)
tensor = var.get_tensor()
kwargs[in_name].append(sub_in_name) kwargs[in_name].append(sub_in_name)
else: else:
var = scope.new_var(in_name) var = scope.new_var(in_name)
tensor = var.get_tensor()
kwargs[in_name].append(in_name) kwargs[in_name].append(in_name)
for outs in Operator.get_op_outputs(op_type): for out_name, out_dup in Operator.get_op_outputs(op_type):
out_name = outs[0]
out_dup = outs[1]
if out_name in outputs: if out_name in outputs:
kwargs[out_name] = [] kwargs[out_name] = []
if out_dup: if out_dup:
sub_in = outputs[out_name] sub_in = outputs[out_name]
for sun_in_name in sub_in: for sun_in_name in sub_in:
var = scope.new_var(sun_in_name) var = scope.new_var(sun_in_name)
tensor = var.get_tensor()
kwargs[out_name].append(sun_in_name) kwargs[out_name].append(sun_in_name)
else: else:
var = scope.new_var(out_name) var = scope.new_var(out_name)
tensor = var.get_tensor()
kwargs[out_name].append(out_name) kwargs[out_name].append(out_name)
# for attr_name in Operator.get_op_attr_names(op_type): for attr_name in Operator.get_op_attr_names(op_type):
# kwargs[attr_name] = attrs[attr_name] kwargs[attr_name] = attrs[attr_name]
return Operator(op_type, **kwargs) return Operator(op_type, **kwargs)
def set_input(scope, op, inputs, place): def set_input(scope, op, inputs, place):
for ins in Operator.get_op_inputs(op.type()): for in_name, in_dup in Operator.get_op_inputs(op.type()):
in_name = ins[0]
in_dup = ins[1]
if in_name in inputs: if in_name in inputs:
if in_dup: if in_dup:
sub_in = inputs[in_name] sub_in = inputs[in_name]
...@@ -75,9 +61,7 @@ def set_input(scope, op, inputs, place): ...@@ -75,9 +61,7 @@ def set_input(scope, op, inputs, place):
def set_output_grad(scope, op, outputs, place): def set_output_grad(scope, op, outputs, place):
for outs in Operator.get_op_outputs(op.type()): for out_name, out_dup in Operator.get_op_outputs(op.type()):
out_name = outs[0]
out_dup = outs[1]
if out_name in outputs: if out_name in outputs:
if out_dup: if out_dup:
sub_out = outputs[out_name] sub_out = outputs[out_name]
...@@ -150,10 +134,10 @@ def get_numeric_gradient(scope, ...@@ -150,10 +134,10 @@ def get_numeric_gradient(scope,
def get_backward_op(scope, op, no_grad_set): def get_backward_op(scope, op, no_grad_set):
backward_op = core.Operator.backward(op, no_grad_set) backward_op = core.Operator.backward(op, no_grad_set)
for input in backward_op.inputs_names(): for input in backward_op.input_vars():
var = scope.new_var(input) var = scope.new_var(input)
var.get_tensor() var.get_tensor()
for output in backward_op.outputs_names(): for output in backward_op.output_vars():
var = scope.new_var(output) var = scope.new_var(output)
var.get_tensor() var.get_tensor()
return backward_op return backward_op
...@@ -182,7 +166,7 @@ def get_gradient(scope, op, inputs, outputs, grad_name, place, ...@@ -182,7 +166,7 @@ def get_gradient(scope, op, inputs, outputs, grad_name, place,
class OpTest(unittest.TestCase): class OpTest(unittest.TestCase):
def check_output(self, place): def check_output_with_place(self, place):
self.scope = core.Scope() self.scope = core.Scope()
self.op = create_op(self.scope, self.op_type, self.inputs, self.outputs) self.op = create_op(self.scope, self.op_type, self.inputs, self.outputs)
if isinstance(place, core.GPUPlace) and not self.op.support_gpu(): if isinstance(place, core.GPUPlace) and not self.op.support_gpu():
...@@ -192,9 +176,7 @@ class OpTest(unittest.TestCase): ...@@ -192,9 +176,7 @@ class OpTest(unittest.TestCase):
ctx = core.DeviceContext.create(place) ctx = core.DeviceContext.create(place)
self.op.run(self.scope, ctx) self.op.run(self.scope, ctx)
for outs in Operator.get_op_outputs(self.op.type()): for out_name, out_dup in Operator.get_op_outputs(self.op.type()):
out_name = outs[0]
out_dup = outs[1]
if out_dup: if out_dup:
sub_out = self.outputs[out_name] sub_out = self.outputs[out_name]
for sub_out_name in sub_out: for sub_out_name in sub_out:
...@@ -213,6 +195,13 @@ class OpTest(unittest.TestCase): ...@@ -213,6 +195,13 @@ class OpTest(unittest.TestCase):
actual, expect, atol=1e-05), actual, expect, atol=1e-05),
"output name: " + out_name + "has diff") "output name: " + out_name + "has diff")
def check_output(self):
places = [core.CPUPlace()]
if core.is_compile_gpu() and self.op.support_gpu():
places.append(core.GPUPlace(0))
for place in places:
self.check_output_with_place(place)
def __assert_is_close(self, numeric_grads, analytic_grads, names, def __assert_is_close(self, numeric_grads, analytic_grads, names,
max_relative_error, msg_prefix): max_relative_error, msg_prefix):
...@@ -255,17 +244,32 @@ class OpTest(unittest.TestCase): ...@@ -255,17 +244,32 @@ class OpTest(unittest.TestCase):
grad_var_name(input_to_check) for input_to_check in inputs_to_check grad_var_name(input_to_check) for input_to_check in inputs_to_check
] ]
places = [core.CPUPlace()] cpu_place = core.CPUPlace()
if core.is_compile_gpu() and self.op.support_gpu(): cpu_analytic_grads = [
places.append(core.GPUPlace(0)) get_gradient(self.scope, self.op, self.inputs, self.outputs,
grad_name, cpu_place, no_grad_set)
for grad_name in grad_names
]
for place in places: self.__assert_is_close(numeric_grads, cpu_analytic_grads, grad_names,
analytic_grads = [ max_relative_error,
"Gradient Check On %s" % str(cpu_place))
if core.is_compile_gpu() and self.op.support_gpu():
gpu_place = core.GPUPlace(0)
gpu_analytic_grads = [
get_gradient(self.scope, self.op, self.inputs, self.outputs, get_gradient(self.scope, self.op, self.inputs, self.outputs,
grad_name, place, no_grad_set) grad_name, gpu_place, no_grad_set)
for grad_name in grad_names for grad_name in grad_names
] ]
self.__assert_is_close(numeric_grads, analytic_grads, grad_names, self.__assert_is_close(numeric_grads, gpu_analytic_grads,
max_relative_error, grad_names, max_relative_error,
"Gradient Check On %s" % str(place)) "Gradient Check On %s" % str(gpu_place))
for c_grad, g_grad, name in itertools.izip(
cpu_analytic_grads, gpu_analytic_grads, grad_names):
self.assertTrue(
numpy.allclose(
c_grad, g_grad, atol=1e-4),
"output name: " + name + " has diff")
import unittest import unittest
import numpy import numpy
from op_test import OpTest from op_test import OpTest
import paddle.v2.framework.core as core
class TestCrossEntropy(OpTest): class TestCrossEntropy(OpTest):
def setUp(self): def setUp(self):
self.op_type = "onehot_cross_entropy" self.op_type = "onehot_cross_entropy"
batch_size = 4 batch_size = 30
class_num = 4 class_num = 10
X = numpy.random.random((batch_size, class_num)).astype("float32") X = numpy.random.random((batch_size, class_num)).astype("float32")
label = (class_num / 2) * numpy.ones(batch_size).astype("int32") label = (class_num / 2) * numpy.ones(batch_size).astype("int32")
self.inputs = {'X': X, 'label': label} self.inputs = {'X': X, 'label': label}
...@@ -18,8 +17,7 @@ class TestCrossEntropy(OpTest): ...@@ -18,8 +17,7 @@ class TestCrossEntropy(OpTest):
self.outputs = {'Y': numpy.array(Y).astype("float32")} self.outputs = {'Y': numpy.array(Y).astype("float32")}
def test_check_output(self): def test_check_output(self):
self.check_output(core.CPUPlace()) self.check_output()
self.check_output(core.GPUPlace(0))
def test_check_grad(self): def test_check_grad(self):
self.check_grad(["X"], "Y") self.check_grad(["X"], "Y")
......
import unittest import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
import paddle.v2.framework.core as core
class TestSigmoid(OpTest): class TestSigmoid(OpTest):
...@@ -13,8 +12,7 @@ class TestSigmoid(OpTest): ...@@ -13,8 +12,7 @@ class TestSigmoid(OpTest):
self.outputs = {'Y': 1 / (1 + np.exp(-self.inputs['X']))} self.outputs = {'Y': 1 / (1 + np.exp(-self.inputs['X']))}
def test_check_output(self): def test_check_output(self):
self.check_output(core.CPUPlace()) self.check_output()
self.check_output(core.GPUPlace(0))
def test_check_grad(self): def test_check_grad(self):
self.check_grad(["X"], "Y", max_relative_error=0.007) self.check_grad(["X"], "Y", max_relative_error=0.007)
......
import unittest import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
import paddle.v2.framework.core as core
class TestSumOp(OpTest): class TestSumOp(OpTest):
...@@ -15,8 +14,7 @@ class TestSumOp(OpTest): ...@@ -15,8 +14,7 @@ class TestSumOp(OpTest):
self.outputs = {'Out': y} self.outputs = {'Out': y}
def test_check_output(self): def test_check_output(self):
self.check_output(core.CPUPlace()) self.check_output()
self.check_output(core.GPUPlace(0))
def test_check_grad(self): def test_check_grad(self):
self.check_grad(["x0"], "Out") self.check_grad(["x0"], "Out")
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册