Skip to content
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 IfThenElse operator and layer #3119

Closed
wangkuiyi opened this issue Jul 31, 2017 · 6 comments
Closed

Design of IfThenElse operator and layer #3119

wangkuiyi opened this issue Jul 31, 2017 · 6 comments

Comments

@wangkuiyi
Copy link
Collaborator

wangkuiyi commented Jul 31, 2017

After talking with @zchen0211 and @Canpio , here is the very early draft of the idea of IfThenElse operator and layer:

A Simple Example

The Python Application Program

cost = paddle.layer.mse(
    paddel.layer.fc(
        paddle.layer.data(name="features"),
        output_size = 100),
    paddle.layer.data(name="label"))
parameters = paddle.train(cost, minist_reader(), {"features":0, "label":1})
print paddle.inf(cost, parameters, inference_input_reader())

FC Layer as a Python Function

def fc(input):
    output = paddle.framework.tensor()
    W = paddle.framework.tensor(label="parameter")
    b = paddle.framework.tensor(label="parameter")
    paddle.operator.fc(input, W, b, output)
    return output

FC Operator as a C++ Class

class FC : public framework:Operator {...};

The IfThenElse Layer and Operator

Another Example Using IfThenElse Layer

def a_network(input):
    A = paddle.layer.fc(input, parameter_name="A")
    B = paddle.layer.fc(input, parameter_name="B")
    return paddle.layer.if_then_else(
        paddle.layer.less_than(A, B),
        paddle.layer.fc(
            paddle.layer.fc(
                paddle.layer.fc
                paddle.layer.fc(A, output_size = 100))),
        paddle.layer.fc(
            paddle.layer.fc(
                paddle.layer.fc(B, output_size = 100))))

The IfThenElse Layer

def if_then_else(cond, left, right) :
    ret = paddle.framework.tensor()
    paddle.operator.if_then_else(cond, left, right, ret)
    return ret

The IfThenElseOp C++ Class

class IfThenElseOp : public framework::Operator {
 // Check that cond returns a minibatch of boolean values.
 // Check that left and right outputs are of the same size.
};
@Superjomn
Copy link
Contributor

need a cond_op design.

cond_op get multiple inputs, and output a batch of bool?

maybe if_then_else is just a syntax wrapper of switch_op , cond_op(xxx) -> gather(xxx) -> switch_op(if_true_net, else_net) ?

gather_op is an operator to gather bools from cond_op and split the original input into different small batches of data, each small batch has the same cond_bool.

@zchen0211
Copy link
Contributor

zchen0211 commented Jul 31, 2017

Tensorflow has a switch_op, and merge_op looks like this:

ret = tf.cond(cond, f_true, f_false)

cond: a bool scalar
f_true: a function
f_false: a function
when cond == true, ret = f_true(); ret=f_false(), otherwise.

In TF, it calls like this:

  x = tf.constant(2)
  y = tf.constant(5)
  def f1(): return tf.multiply(x, 17)
  def f2(): return tf.add(y, 23)
  r = tf.cond(tf.less(x, y), f1, f2)

r is set to f1().
Operations in f2 (e.g., tf.add) are not executed.

Since we are dynamic in Paddle, we need one more arguments input, the data to operate on

ret = paddle.cond(cond, f_true, f_false, input)

cond: a bool vector
f_true: a function
f_false: a function
when cond[i] == true, ret[i] = f_true(input[i]); ret[i]=f_false(input[i]), otherwise
Am I right?
@Superjom @wangkuiyi @emailweixu @Canpio

Our dynamic case

@Superjomn
Copy link
Contributor

Superjomn commented Jul 31, 2017

That works fine. cond_op should "tag" the inputs and split them into different batches, each batch has the items of different tags.

But I've no idea how to mark the inputs with the original orders, for example, in infer period, the switch_op will make inputs out of order, but the final outputs should be in the same order of the original inputs.

Do every input instance need an order id? by which the outputs are sorted?

@zchen0211

@emailweixu
Copy link
Collaborator

It's possible that the true and false branches need different input, so the interface should be like:
paddle.cond(cond, f_true, f_false, input, input_false=None)
when input_false is None, input is used for both f_true and f_false
when input_false is not None, "input" is used for f_true, "input_false" is used for f_false

@emailweixu
Copy link
Collaborator

For the actual user interface, it should be possible to make it such that the user does not need to specify input or input_false. The framework can figure out the input of f_true and f_false automatically.

@qingqing01
Copy link
Contributor

Closed since IfElse operator had been done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants