blackJack
blackJack

Reputation: 1

Unable to give Keras neural network multiple inputs

I am trying to get a data pipeline of text based data into a neural network with two heads. Made use of the official documentation that tells you to zip it into a dictionary of values, but it did not work.

<MapDataset shapes: (None, 32), types: tf.int64>
<MapDataset shapes: (None, 32), types: tf.int64>

These are the shapes of the data that will go into each head. Have been converted into sequences of ints using the VectorizeLayer()

This is the graph of the neural network

enter image description here

I am constructing the final dataset using

final_dataset=tf.data.Dataset.from_tensors((
    {"input_1":vectorized_sen1,"input_2":vectorized_sen2},
    {"output":label_db}
)).batch(64)

But this is the error it keeps throwing

TypeError: Failed to convert object of type <class 'tensorflow.python.data.ops.dataset_ops._NestedVariant'> to Tensor. Contents: <tensorflow.python.data.ops.dataset_ops._NestedVariant object at 0x7f9b073af780>. Consider casting elements to a supported type.

Upvotes: 0

Views: 284

Answers (1)

msg45f
msg45f

Reputation: 845

From what I can tell of your problem it seems that your two input layers are already datasets. from_tensors likely is expecting tensor objects, not datasets. For instance given a model of this shape:

input_a = keras.Input(10,name="initial_input")
input_b = keras.Input(5, name="secondary_input")

dense_1 = keras.layers.Dense(100, activation="relu")(input_a)
concat = keras.layers.concatenate([dense_1, input_b])
layer = keras.layers.Dense(105, activation="relu")(concat)
layer = keras.layers.Dense(10, activation="softmax", name="output")(layer)

model = keras.Model([input_a, input_b], layer)
model.summary()
keras.utils.plot_model(model, "multi-output.png", show_shapes=True)

Model shape:

model shape

Normally, I could provide inputs like this:

a = tf.ones([1000, 10], dtype=tf.dtypes.int64)
b = tf.ones([1000, 5], dtype=tf.dtypes.int64)
output = tf.random.normal([1000, 10])
input_dataset = tf.data.Dataset.from_tensor_slices(({'initial_input': a, 'secondary_input': b}, {'output': output})).batch(25)

This is fairly straight forward, as all of the data (a, b, output) are Tensors. In your case though it seems that some or all of the input data are already TF datasets. In this scenario you will want to zip the datasets into a single dataset, then map them to the proper structure. For example, with the exact same tensors converted to datasets first, I could use this:

# Let's say for example that they're each already datasets and I need to combine them
a_ds = tf.data.Dataset.from_tensor_slices(a)
b_ds = tf.data.Dataset.from_tensor_slices(b)
o_ds = tf.data.Dataset.from_tensor_slices(output)

full_dataset = tf.data.Dataset.zip((a_ds, b_ds, o_ds)).map(lambda a, b, o:
  ({'initial_input': a, 'secondary input': b}, {'output': o})
).batch(25)

In this example I turn each of the tensors into their own datasets. Then I zip them using the Dataset helper zip function. This behaves similar to Python's native zip function so the behavior is fairly intuitive. However, the dataset isn't quite in the right structure, so I map it into the proper structure using a simple lambda.

For reference, here is the notebook used to tinker with this: https://colab.research.google.com/drive/1vVF2tbzLFZ-9pZql1uT3SBTvNloMwFpp?usp=sharing

Upvotes: 1

Related Questions