-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Design of if else op #3828
Design of if else op #3828
Changes from 5 commits
ff3ec3c
f075141
2f2dd23
d156dfa
e39a2c9
32244b5
d76c60b
523eb23
e0c27a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
In an if_op, only inputs with condition satisfied will be run. The op could have multiple inputs and multiple outputs. | ||
We should have the following design: | ||
|
||
```python | ||
# A 1-d bool vector | ||
cond = Var() | ||
# create an op | ||
if = pd.if_op() | ||
|
||
with if.true_block() as block: | ||
x1 = if.input(x1) | ||
x2 = if.input(x2) | ||
y = pd.add(x1, x2) | ||
y2 = pd.fc(x1) # contains (w,b) | ||
if.output(y) | ||
if.output(y2) | ||
|
||
o1, o2 = if(cond) | ||
``` | ||
|
||
In an if_op, only inputs with condition satisfied will be run. | ||
We should have the following design: | ||
```python | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IfOp should have only one branch. An IfOp operator takes a import paddle as pd
x = var()
y = var()
cond = var()
b = pd.create_ifop_builder(inputs=[x], output_num=1)
with b.true_block():
x = b.inputs(0)
z = operator.add(x, y)
b.set_output(0, operator.softmax(z))
out = b(cond) If we want the output still has N instances, we can use IfElseOp with a default value, whose minibatch size must be N: import paddle as pd
x = var()
y = var()
cond = var()
default_value = var()
b = pd.create_ifelseop_builder(inputs=[x], output_num=1, default_value)
with b.true_block():
x = b.inputs(0)
z = operator.add(x, y)
b.set_output(0, operator.softmax(z))
out = b(cond) If the IfElseOp has multiple return values, the default_value must be a list of variables with corresponding shapes. |
||
# A 1-d bool vector | ||
cond = Var() | ||
# create an op | ||
if = pd.if_op() | ||
|
||
with if.true_block() as block: | ||
x1 = if.input(x1) | ||
x2 = if.input(x2) | ||
y = pd.add(x1, x2) | ||
y2 = pd.fc(x1) # contains (w,b) | ||
if.output(y, name="y") | ||
if.output(y2, name="y2") | ||
|
||
with if.false_block() as block: | ||
x1 = if.input(x1) | ||
x2 = if.input(x2) | ||
y = pd.fc(x2) | ||
y2 = pd.softmax(x1) | ||
if.output(y, name="y") | ||
if.output(y2, name="y2") | ||
|
||
o1, o2 = if(cond) | ||
``` | ||
|
||
Some questions: | ||
1. how to know which inputs will be selected by condition? | ||
```python | ||
True_block(): | ||
y = pd.fc(x) | ||
# we will have x, w, b all as inputs | ||
# but only x will be selected by cond, how can the block know? | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basing on #3827, Python bindings of operators and layers should return Vars. So I think that this usage could be
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wangkuiyi
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe @Superjom 's proposal is better than mine because
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Above example breaks the convention that Python operator bindings must return Vars.
However, mine has a severe problem that the two branches would overwrite y1 and y2. A right solution should keep two copies of y1 and y2 for the left and the right branches respectively and then merge these two copies into the global variables y1 and y2.
A correct solution can be derived easily from @Superjom 's solution -- to rename
paddle.IfElseOp
intopaddle.create_ifelseop_builder
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.