Skip to content

Commit bfe6dcb

Browse files
Superjomnwangkuiyi
authored andcommitted
fix RNN and IfElse syntax in Block design (#4210)
* fix block syntax * add builder * fix argument names * uniform all Var to var * fix c demo * factor set_outputs * update block * delete as_ifelse_input interface from block design * simplify set_outputs and output_num * make the c++ codes compatible with demo * fix compatible * fix syntax * update ie * update syntax
1 parent 9989573 commit bfe6dcb

File tree

1 file changed

+48
-48
lines changed

1 file changed

+48
-48
lines changed

doc/design/block.md

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -55,96 +55,96 @@ Let us consolidate the discussion by presenting some examples.
5555
The following C++ programs shows how blocks are used with the `if-else` structure:
5656

5757
```c++
58+
namespace pd = paddle;
59+
5860
int x = 10;
59-
int y = 20;
60-
int out;
61+
int y = 1;
62+
int z = 10;
6163
bool cond = false;
64+
int o1, o2;
6265
if (cond) {
6366
int z = x + y;
64-
out = softmax(z);
67+
o1 = z;
68+
o2 = pd::layer::softmax(z);
6569
} else {
66-
int z = fc(x);
67-
out = z;
70+
int d = pd::layer::fc(z);
71+
o1 = d;
72+
o2 = d+1;
6873
}
74+
6975
```
7076
7177
An equivalent PaddlePaddle program from the design doc of the [IfElseOp operator](./if_else_op.md) is as follows:
7278
7379
```python
7480
import paddle as pd
7581
76-
x = var(10)
77-
y = var(20)
78-
cond = var(false)
79-
ie = pd.create_ifelseop(inputs=[x], output_num=1)
82+
x = minibatch([10, 20, 30]) # shape=[None, 1]
83+
y = var(1) # shape=[1], value=1
84+
z = minibatch([10, 20, 30]) # shape=[None, 1]
85+
cond = larger_than(x, 15) # [false, true, true]
86+
87+
ie = pd.ifelse()
8088
with ie.true_block():
81-
x = ie.inputs(true, 0)
82-
z = operator.add(x, y)
83-
ie.set_output(true, 0, operator.softmax(z))
89+
d = pd.layer.add_scalar(x, y)
90+
ie.output(d, pd.layer.softmax(d))
8491
with ie.false_block():
85-
x = ie.inputs(false, 0)
86-
z = layer.fc(x)
87-
ie.set_output(true, 0, operator.softmax(z))
88-
out = b(cond)
92+
d = pd.layer.fc(z)
93+
ie.output(d, d+1)
94+
o1, o2 = ie(cond)
8995
```
9096

91-
In both examples, the left branch computes `softmax(x+y)` and the right branch computes `fc(x)`.
97+
In both examples, the left branch computes `x+y` and `softmax(x+y)`, the right branch computes `x+1` and `fc(x)`.
9298

9399
A difference is that variables in the C++ program contain scalar values, whereas those in the PaddlePaddle programs are mini-batches of instances. The `ie.input(true, 0)` invocation returns instances in the 0-th input, `x`, that corresponds to true values in `cond` as the local variable `x`, where `ie.input(false, 0)` returns instances corresponding to false values.
94100

101+
95102
### Blocks with `for` and `RNNOp`
96103

97104
The following RNN model from the [RNN design doc](./rnn.md)
98105

99106
```python
100-
x = sequence([10, 20, 30])
101-
m = var(0)
102-
W = tensor()
103-
U = tensor()
104-
105-
rnn = create_rnn(inputs=[input])
106-
with rnn.stepnet() as net:
107-
x = net.set_inputs(0)
108-
h = net.add_memory(init=m)
109-
fc_out = pd.matmul(W, x)
110-
hidden_out = pd.matmul(U, h.pre(n=1))
111-
sum = pd.add_two(fc_out, hidden_out)
112-
act = pd.sigmoid(sum)
113-
h.update(act) # update memory with act
114-
net.set_outputs(0, act, hidden_out) # two outputs
115-
107+
x = sequence([10, 20, 30]) # shape=[None, 1]
108+
m = var(0) # shape=[1]
109+
W = var(0.314, param=true) # shape=[1]
110+
U = var(0.375, param=true) # shape=[1]
111+
112+
rnn = pd.rnn()
113+
with rnn.step():
114+
h = rnn.memory(init = m)
115+
hh = rnn.previous_memory(h)
116+
a = layer.fc(W, x)
117+
b = layer.fc(U, hh)
118+
s = pd.add(a, b)
119+
act = pd.sigmoid(s)
120+
rnn.update_memory(h, act)
121+
rnn.output(a, b)
116122
o1, o2 = rnn()
117-
print o1, o2
118123
```
119-
120124
has its equivalent C++ program as follows
121125

122126
```c++
123127
int* x = {10, 20, 30};
124-
int m = 0;
125-
int W = some_value();
126-
int U = some_other_value();
128+
int* m = {0};
129+
int* W = {0.314};
130+
int* U = {0.375};
127131

128132
int mem[sizeof(x) / sizeof(x[0]) + 1];
129133
int o1[sizeof(x) / sizeof(x[0]) + 1];
130134
int o2[sizeof(x) / sizeof(x[0]) + 1];
131135
for (int i = 1; i <= sizeof(x)/sizeof(x[0]); ++i) {
132136
int x = x[i-1];
133137
if (i == 1) mem[0] = m;
134-
int fc_out = W * x;
135-
int hidden_out = Y * mem[i-1];
136-
int sum = fc_out + hidden_out;
138+
int a = W * x;
139+
int b = Y * mem[i-1];
140+
int s = fc_out + hidden_out;
137141
int act = sigmoid(sum);
138142
mem[i] = act;
139143
o1[i] = act;
140144
o2[i] = hidden_out;
141145
}
142-
143-
print_array(o1);
144-
print_array(o2);
145146
```
146147

147-
148148
## Compilation and Execution
149149

150150
Like TensorFlow programs, a PaddlePaddle program is written in Python. The first part describes a neural network as a protobuf message, and the rest part executes the message for training or inference.
@@ -210,11 +210,11 @@ a = pd.Varaible(shape=[20, 20])
210210
b = pd.fc(a, params=["fc.w", "fc.b"])
211211

212212
rnn = pd.create_rnn()
213-
with rnn.stepnet() as net:
214-
x = net.set_inputs(a)
213+
with rnn.stepnet()
214+
x = a.as_step_input()
215215
# reuse fc's parameter
216216
fc_without_b = pd.get_variable("fc.w")
217-
net.set_outputs(fc_without_b)
217+
rnn.output(fc_without_b)
218218

219219
out = rnn()
220220
```

0 commit comments

Comments
 (0)