提交 4f2ee63c 编写于 作者: L Liu Yiqun

Get rid of the calling of inplace op in FCOp.

上级 4223ff8c
...@@ -26,38 +26,43 @@ class FCOp : public NetOp { ...@@ -26,38 +26,43 @@ class FCOp : public NetOp {
: NetOp(type, inputs, outputs, attrs) { : NetOp(type, inputs, outputs, attrs) {
auto x = Inputs("X"); auto x = Inputs("X");
auto w = Inputs("W"); auto w = Inputs("W");
auto mul_out = Outputs("mul_out");
PADDLE_ENFORCE_EQ( PADDLE_ENFORCE_EQ(
x.size(), w.size(), x.size(), w.size(),
"The size of inputs X(%d) should be the same as that of weights W(%d).", "The size of inputs X(%d) should be the same as that of weights W(%d).",
x.size(), w.size()); x.size(), w.size());
PADDLE_ENFORCE_EQ(mul_out.size(), x.size(),
"The size of intermediate mul_out(%d) should be the same "
"as that of inputs X(%d).",
mul_out.size(), x.size());
int n = x.size(); int n = x.size();
PADDLE_ENFORCE_GE(n, 1, PADDLE_ENFORCE_GE(n, 1,
"The size of inputs X(%d) should be no less than 1.", n); "The size of inputs X(%d) should be no less than 1.", n);
// mul_out = X[0] * W[0] + ... + X[n-1] * W[n-1] // mul_out[i] = X[i] * W[i]
AppendOp( for (int i = 0; i < n; i++) {
framework::OpRegistry::CreateOp("mul", {{"X", {x[0]}}, {"Y", {w[0]}}}, AppendOp(framework::OpRegistry::CreateOp(
{{"Out", {Output("mul_out")}}}, {})); "mul", {{"X", {x[i]}}, {"Y", {w[i]}}}, {{"Out", {mul_out[i]}}}, {}));
}
for (int i = 1; i < n; i++) { // sum_out = X[0] * W[0] + ... + X[n-1] * W[n-1]
// mul_out = mul_out + X[i] * W[i] if (n > 1) {
AppendOp( AppendOp(framework::OpRegistry::CreateOp(
framework::OpRegistry::CreateOp("mul", {{"X", {x[i]}}, {"Y", {w[i]}}}, "sum", {{"X", {mul_out}}}, {{"Out", {Output("sum_out")}}}, {}));
{{"Out", {Output("add_out")}}}, {})); } else {
AppendOp(framework::OpRegistry::CreateOp( AppendOp(framework::OpRegistry::CreateOp(
"add", {{"X", {Output("mul_out")}}, {"Y", {Output("add_out")}}}, "identity", {{"X", {mul_out[0]}}}, {{"Y", {Output("sum_out")}}}, {}));
{{"Out", {Output("mul_out")}}}, {}));
} }
// add_out = sum_out + b
auto b = Input("b"); auto b = Input("b");
std::string add_out = "mul_out"; std::string add_out = "sum_out";
if (b != framework::kEmptyVarName) { if (b != framework::kEmptyVarName) {
// add_out = mul_out + b
AppendOp(framework::OpRegistry::CreateOp(
"rowwise_add", {{"X", {Output("mul_out")}}, {"b", {Input("b")}}},
{{"Out", {Output("add_out")}}}, {}));
add_out = "add_out"; add_out = "add_out";
AppendOp(framework::OpRegistry::CreateOp(
"rowwise_add", {{"X", {Output("sum_out")}}, {"b", {Input("b")}}},
{{"Out", {Output(add_out)}}}, {}));
} else { } else {
if (Output("add_out") != framework::kEmptyVarName) { if (Output("add_out") != framework::kEmptyVarName) {
this->Rename(Output("add_out"), framework::kEmptyVarName); this->Rename(Output("add_out"), framework::kEmptyVarName);
...@@ -68,8 +73,6 @@ class FCOp : public NetOp { ...@@ -68,8 +73,6 @@ class FCOp : public NetOp {
AppendOp(framework::OpRegistry::CreateOp( AppendOp(framework::OpRegistry::CreateOp(
activation, {{"X", {Output(add_out)}}}, {{"Y", {Output("Y")}}}, {})); activation, {{"X", {Output(add_out)}}}, {{"Y", {Output("Y")}}}, {}));
CompleteAddOp(false); CompleteAddOp(false);
std::cout << DebugString() << std::endl;
} }
}; };
...@@ -77,14 +80,24 @@ class FCOpMaker : public framework::OpProtoAndCheckerMaker { ...@@ -77,14 +80,24 @@ class FCOpMaker : public framework::OpProtoAndCheckerMaker {
public: public:
FCOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker) FCOpMaker(framework::OpProto *proto, framework::OpAttrChecker *op_checker)
: OpProtoAndCheckerMaker(proto, op_checker) { : OpProtoAndCheckerMaker(proto, op_checker) {
AddInput("X", "The 2-D input matrix of FC operator.").AsDuplicable(); AddInput("X", "The inputs of FC operator, a ordered vector of 2-D matrix.")
AddInput("W", "The 2-D weight matrix of FC operator.").AsDuplicable(); .AsDuplicable();
AddInput("W", "The weights of FC operator, a ordered vector of 2-D matrix.")
.AsDuplicable();
AddInput("b", "The 1-D bias vector of FC operator"); AddInput("b", "The 1-D bias vector of FC operator");
AddOutput("Y", "The activated output matrix of FC operator"); AddOutput("Y", "The activated output matrix of FC operator");
AddOutput("mul_out", "The non-actived output of FC operator, X * W") AddOutput("mul_out",
"The intermediate outputs of FC operator, "
"saving the product of X[i] * W[i]")
.AsIntermediate()
.AsDuplicable();
AddOutput("sum_out",
"The intermediate output of FC operator, "
"saving the sum of products, sum(X[i] * W[i])")
.AsIntermediate(); .AsIntermediate();
AddOutput("add_out", "The non-actived output of FC operator, X * W + b") AddOutput("add_out",
"The non-actived output of FC operator, saving X * W + b")
.AsIntermediate(); .AsIntermediate();
AddAttr<std::string>("activation", "The activation type of FC operator.") AddAttr<std::string>("activation", "The activation type of FC operator.")
.SetDefault("identity") .SetDefault("identity")
......
...@@ -3,33 +3,65 @@ import numpy as np ...@@ -3,33 +3,65 @@ import numpy as np
from op_test import OpTest from op_test import OpTest
class TestFCOp(OpTest): class TestFCOp1(OpTest):
def setUp(self): def setUp(self):
print "Run"
self.op_type = "fc" self.op_type = "fc"
x0 = np.random.random((32, 256)).astype("float32") x1 = np.random.random((16, 32)).astype("float32")
x1 = np.random.random((32, 256)).astype("float32") w1 = np.random.random((32, 10)).astype("float32")
w0 = np.random.random((256, 100)).astype("float32") b = np.random.random(10).astype("float32")
w1 = np.random.random((256, 100)).astype("float32") self.inputs = {"X": {"X1": x1}, "W": {"W1": w1}, "b": b}
b = np.random.random(100).astype("float32") mul_out1 = np.dot(x1, w1)
sum_out = mul_out1
add_out = sum_out + b
identity_out = add_out
self.outputs = {
"mul_out": {
"mul_out1": mul_out1,
},
"sum_out": sum_out,
"add_out": add_out,
"Y": identity_out
}
def test_check_output(self):
self.check_output()
def test_check_grad(self):
self.check_grad(["X1", "W1", "b"], "Y", max_relative_error=0.05)
class TestFCOp2(OpTest):
def setUp(self):
self.op_type = "fc"
x1 = np.random.random((16, 32)).astype("float32")
x2 = np.random.random((16, 32)).astype("float32")
w1 = np.random.random((32, 10)).astype("float32")
w2 = np.random.random((32, 10)).astype("float32")
b = np.random.random(10).astype("float32")
self.inputs = { self.inputs = {
"X": { "X": {
"X0": x0, "X1": x1,
"X1": x1 "X2": x2
}, },
"W": { "W": {
"W0": w0, "W1": w1,
"W1": w1 "W2": w2
}, },
"b": b "b": b
} }
#self.attrs = {"activation": "sigmoid"} #self.attrs = {"activation": "sigmoid"}
mul_out = np.dot(x0, w0) + np.dot(x1, w1) mul_out1 = np.dot(x1, w1)
add_out = np.add(mul_out, b) mul_out2 = np.dot(x2, w2)
sum_out = mul_out1 + mul_out2
add_out = np.add(sum_out, b)
#sigmoid_out = 1 / (1 + np.exp(-add_out)) #sigmoid_out = 1 / (1 + np.exp(-add_out))
sigmoid_out = add_out sigmoid_out = add_out
self.outputs = { self.outputs = {
"mul_out": mul_out, "mul_out": {
"mul_out0": mul_out1,
"mul_out1": mul_out2
},
"sum_out": sum_out,
"add_out": add_out, "add_out": add_out,
"Y": sigmoid_out "Y": sigmoid_out
} }
...@@ -37,8 +69,9 @@ class TestFCOp(OpTest): ...@@ -37,8 +69,9 @@ class TestFCOp(OpTest):
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(["X0", "X1", "W0", "W1", "b"], "Y") self.check_grad(
["X1", "X2", "W1", "W2", "b"], "Y", max_relative_error=0.05)
if __name__ == '__main__': if __name__ == '__main__':
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册