title: tf.data with multiple inputs / outputs in Keras
body: <p>For the application, such as <strong>pair text similarity</strong>, the input data is similar to: <code>pair_1, pair_2</code>. In these problems, we usually have multiple input data. Previously, I implemented my models successfully:</p>
  
  <pre><code>model.fit([pair_1, pair_2], labels, epochs=50)
  </code></pre>
  
  <p>I decided to replace my input pipeline with <a href="https://www.tensorflow.org/api_docs/python/tf/data" rel="noreferrer">tf.data</a> API. To this end, I create a Dataset similar to:</p>
  
  <pre><code>dataset = tf.data.Dataset.from_tensor_slices((pair_1, pair2, labels))
  </code></pre>
  
  <p>It compiles successfully but when start to train it throws the following exception:</p>
  
  <pre><code>AttributeError: 'tuple' object has no attribute 'ndim'
  </code></pre>
  
  <p>My Keras and Tensorflow version respectively are <code>2.1.6</code> and <code>1.11.0</code>. I found a similar issue in Tensorflow repository:
  <a href="https://github.com/tensorflow/tensorflow/issues/20698" rel="noreferrer">tf.keras multi-input models don't work when using tf.data.Dataset</a>.</p>
  
  <p>Does anyone know how to fix the issue?</p>
  
  <p><strong>Here is some main part of the code</strong>:</p>
  
  <pre class="lang-py prettyprint-override"><code>(q1_test, q2_test, label_test) = test
  (q1_train, q2_train, label_train) = train
  
      def tfdata_generator(sent1, sent2, labels, is_training):
          '''Construct a data generator using tf.Dataset'''
  
          dataset = tf.data.Dataset.from_tensor_slices((sent1, sent2, labels))
          if is_training:
              dataset = dataset.shuffle(1000)  # depends on sample size
  
          dataset = dataset.repeat()
          dataset = dataset.prefetch(tf.contrib.data.AUTOTUNE)
  
          return dataset
  
  train_dataset = tfdata_generator(q1_train, q2_train, label_train, is_training=True, batch_size=_BATCH_SIZE)
  test_dataset = tfdata_generator(q1_test, q2_test, label_test, is_training=False, batch_size=_BATCH_SIZE)
  
  
  inps1 = keras.layers.Input(shape=(50,))
  inps2 = keras.layers.Input(shape=(50,))
  
  embed = keras.layers.Embedding(input_dim=nb_vocab, output_dim=300, weights=[embedding], trainable=False)
  embed1 = embed(inps1)
  embed2 = embed(inps2)
  
  gru = keras.layers.CuDNNGRU(256)
  gru1 = gru(embed1)
  gru2 = gru(embed2)
  
  concat = keras.layers.concatenate([gru1, gru2])
  
  preds = keras.layers.Dense(1, 'sigmoid')(concat)
  
  model = keras.models.Model(inputs=[inps1, inps2], outputs=preds)
  model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
  print(model.summary())
  
  model.fit(
      train_dataset.make_one_shot_iterator(),
      steps_per_epoch=len(q1_train) // _BATCH_SIZE,
      epochs=50,
      validation_data=test_dataset.make_one_shot_iterator(),
      validation_steps=len(q1_test) // _BATCH_SIZE,
      verbose=1)
  </code></pre>