|
1 | | -IfOp should have only one branch. An IfOp operator takes a `cond` variable whose value must be a vector of N boolean elements. Its return value has N instances. If cond[i] == True, input instance input[i] will go through true_block() and generate output[i]; otherwise it will produce output from false_bloack(). |
| 1 | +# The `IfElse` Operator |
2 | 2 |
|
3 | | -```python |
4 | | -import paddle as pd |
| 3 | +PaddlePaddle's `IfElse` operator differs from TensorFlow's: |
5 | 4 |
|
6 | | -x = var() |
7 | | -y = var() |
8 | | -cond = var() |
9 | | -default_value = var() |
10 | | -b = pd.create_ifelseop(inputs=[x], output_num=1) |
11 | | -with b.true_block(): |
12 | | - x = b.inputs(0) |
13 | | - z = operator.add(x, y) |
14 | | - b.set_output(0, operator.softmax(z)) |
15 | | - |
16 | | -with b.false_block(): |
17 | | - x = b.inputs(0) |
18 | | - z = layer.fc(x) |
19 | | - b.set_output(0, operator.softmax(z)) |
20 | | - |
21 | | -out = b(cond) |
22 | | -``` |
| 5 | +- the TensorFlow version takes a scalar boolean value as the condition so that the whole mini-batch goes to either the true or the false branch, whereas |
| 6 | +- the PaddlePaddle version takes a vector of boolean value as the condition, and instances corresponding to true values go to the true branch, those corresponding to false values go to the false branch. |
| 7 | + |
| 8 | +## Example |
| 9 | + |
| 10 | +The following PaddlePaddle program shows the usage of the IfElse operator: |
23 | 11 |
|
24 | | -If only true_block is set in an IfElseOp, a special case is that we can have a default value for false as: |
25 | 12 | ```python |
26 | 13 | import paddle as pd |
27 | 14 |
|
28 | | -x = var() |
29 | | -y = var() |
30 | | -cond = var() |
31 | | -default_value = var() |
32 | | -b = pd.create_ifelseop(inputs=[x], output_num=1, default_value) |
33 | | - |
34 | | -with b.true_block(): |
35 | | - x = b.inputs(0) |
36 | | - z = operator.add(x, y) |
37 | | - b.set_output(0, operator.softmax(z)) |
| 15 | +x = minibatch([10, 20, 30]) # shape=[None, 1] |
| 16 | +y = var(1) # shape=[1], value=1 |
| 17 | +z = minibatch([10, 20, 30]) # shape=[None, 1] |
| 18 | +cond = larger_than(x, 15) # [false, true, true] |
| 19 | + |
| 20 | +ie = pd.ifelse() |
| 21 | +with ie.true_block(): |
| 22 | + d = pd.layer.add(x, y) |
| 23 | + ie.output(d, pd.layer.softmax(d)) |
| 24 | +with ie.false_block(): |
| 25 | + d = pd.layer.fc(z) |
| 26 | + ie.output(d, d+1) |
| 27 | +o1, o2 = ie(cond) |
| 28 | +``` |
38 | 29 |
|
39 | | -out = b(cond) |
| 30 | +A challenge to implement the `IfElse` operator is to infer those variables to be split, or, say, to identify the variable of the mini-batch or those derived from the mini-batch. |
| 31 | + |
| 32 | +An equivalent C++ program is as follows: |
| 33 | + |
| 34 | +```c++ |
| 35 | +namespace pd = paddle; |
| 36 | + |
| 37 | +int x = 10; |
| 38 | +int y = 1; |
| 39 | +int z = 10; |
| 40 | +bool cond = false; |
| 41 | +int o1, o2; |
| 42 | +if (cond) { |
| 43 | + int d = x + y; |
| 44 | + o1 = z; |
| 45 | + o2 = pd::layer::softmax(z); |
| 46 | +} else { |
| 47 | + int d = pd::layer::fc(z); |
| 48 | + o1 = d; |
| 49 | + o2 = d+1; |
| 50 | +} |
40 | 51 | ``` |
41 | | -where default_value is a list of vars for `cond` == False. |
|
0 commit comments