Replacing placeholder for tensorflow v2 Replacing placeholder for tensorflow v2 python python

Replacing placeholder for tensorflow v2


Make your code work with TF 2.0

Below is a sample code which you can use with TF 2.0.It relies on the compatibility APIthat is accessible as tensorflow.compat.v1, and requires to disable v2 behaviors.I don't know if it behaves as you expected.If not, then provide us more explanation of what you try to achieve.

import tensorflow.compat.v1 as tftf.disable_v2_behavior()@tf.functiondef construct_graph(graph_dict, inputs, outputs):    queue = inputs[:]    make_dict = {}    for key, val in graph_dict.items():        if key in inputs:            make_dict[key] = tf.placeholder(tf.float32, name=key)        else:            make_dict[key] = None    # Breadth-First search of graph starting from inputs    while len(queue) != 0:        cur = graph_dict[queue[0]]        for outg in cur["outgoing"]:            if make_dict[outg[0]]: # If discovered node, do add/multiply operation                make_dict[outg[0]] = tf.add(make_dict[outg[0]], tf.multiply(outg[1], make_dict[queue[0]]))            else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue                make_dict[outg[0]] = tf.multiply(make_dict[queue[0]], outg[1])                for outgo in graph_dict[outg[0]]["outgoing"]:                    queue.append(outgo[0])        queue.pop(0)    # Returns one data graph for each output    return [make_dict[x] for x in outputs]def main():    graph_def = {        "B": {            "incoming": [],            "outgoing": [("A", 1.0)]        },        "C": {            "incoming": [],            "outgoing": [("A", 1.0)]        },        "A": {            "incoming": [("B", 2.0), ("C", -1.0)],            "outgoing": [("D", 3.0)]        },        "D": {            "incoming": [("A", 2.0)],            "outgoing": []        }    }    outputs = construct_graph(graph_def, ["B", "C"], ["A"])    print(outputs)if __name__ == "__main__":    main()
[<tf.Tensor 'PartitionedCall:0' shape=<unknown> dtype=float32>]

 Migrate your code to TF 2.0

While the above snippet is valid, it is still tied to TF 1.0.To migrate it to TF 2.0 you have to refactor a little bit your code.

Instead of returning a list of tensors, which were callables with TF 1.0, I advise you to return a list ofkeras.layers.Model.

Below is a working example:

import tensorflow as tfdef construct_graph(graph_dict, inputs, outputs):    queue = inputs[:]    make_dict = {}    for key, val in graph_dict.items():        if key in inputs:            # Use keras.Input instead of placeholders            make_dict[key] = tf.keras.Input(name=key, shape=(), dtype=tf.dtypes.float32)        else:            make_dict[key] = None    # Breadth-First search of graph starting from inputs    while len(queue) != 0:        cur = graph_dict[queue[0]]        for outg in cur["outgoing"]:            if make_dict[outg[0]] is not None: # If discovered node, do add/multiply operation                make_dict[outg[0]] = tf.keras.layers.add([                    make_dict[outg[0]],                    tf.keras.layers.multiply(                        [[outg[1]], make_dict[queue[0]]],                    )],                )            else: # If undiscovered node, input is just coming in multiplied and add outgoing to queue                make_dict[outg[0]] = tf.keras.layers.multiply(                    [make_dict[queue[0]], [outg[1]]]                )                for outgo in graph_dict[outg[0]]["outgoing"]:                    queue.append(outgo[0])        queue.pop(0)    # Returns one data graph for each output    model_inputs = [make_dict[key] for key in inputs]    model_outputs = [make_dict[key] for key in outputs]    return [tf.keras.Model(inputs=model_inputs, outputs=o) for o in model_outputs]def main():    graph_def = {        "B": {            "incoming": [],            "outgoing": [("A", 1.0)]        },        "C": {            "incoming": [],            "outgoing": [("A", 1.0)]        },        "A": {            "incoming": [("B", 2.0), ("C", -1.0)],            "outgoing": [("D", 3.0)]        },        "D": {            "incoming": [("A", 2.0)],            "outgoing": []        }    }    outputs = construct_graph(graph_def, ["B", "C"], ["A"])    print("Builded models:", outputs)    for o in outputs:        o.summary(120)        print("Output:", o((1.0, 1.0)))if __name__ == "__main__":    main()

What to notice here?

  • Change from placeholder to keras.Input, requiring to set the shape of the input.
  • Use keras.layers.[add|multiply] for computation.This is probably not required, but stick to one interface.However, it requires to wrap factors inside a list (to handle batching)
  • Build keras.Model to return
  • Call your model with a tuple of values (not a dictionary anymore)

Here is the output of the code.

Builded models: [<tensorflow.python.keras.engine.training.Model object at 0x7fa0b49f0f50>]Model: "model"________________________________________________________________________________________________________________________Layer (type)                           Output Shape               Param #       Connected to                            ========================================================================================================================B (InputLayer)                         [(None,)]                  0                                                     ________________________________________________________________________________________________________________________C (InputLayer)                         [(None,)]                  0                                                     ________________________________________________________________________________________________________________________tf_op_layer_mul (TensorFlowOpLayer)    [(None,)]                  0             B[0][0]                                 ________________________________________________________________________________________________________________________tf_op_layer_mul_1 (TensorFlowOpLayer)  [(None,)]                  0             C[0][0]                                 ________________________________________________________________________________________________________________________add (Add)                              (None,)                    0             tf_op_layer_mul[0][0]                                                                                                   tf_op_layer_mul_1[0][0]                 ========================================================================================================================Total params: 0Trainable params: 0Non-trainable params: 0________________________________________________________________________________________________________________________Output: tf.Tensor([2.], shape=(1,), dtype=float32)