Python 如何使用tf.data.Dataset和tf.keras进行多输入多输出?

Python 如何使用tf.data.Dataset和tf.keras进行多输入多输出?,python,tensorflow,keras,Python,Tensorflow,Keras,我遇到了一个关于使用tf.keras构建模型和使用tf.data.Dataset作为输入管道的多输出的问题。下面是我的代码: a = tf.keras.layers.Input(shape=(368, 368, 3)) conv1 = tf.keras.layers.Conv2D(64, 3, 1)(a) conv2 = tf.keras.layers.Conv2D(64, 3, 1)(conv1) maxpool = tf.keras.layers.MaxPooling2D(p

我遇到了一个关于使用tf.keras构建模型和使用tf.data.Dataset作为输入管道的多输出的问题。下面是我的代码:

  a = tf.keras.layers.Input(shape=(368, 368, 3))
  conv1 = tf.keras.layers.Conv2D(64, 3, 1)(a)
  conv2 = tf.keras.layers.Conv2D(64, 3, 1)(conv1)
  maxpool = tf.keras.layers.MaxPooling2D(pool_size=8, strides=8, 
   padding='same')(conv2)
  conv3 = tf.keras.layers.Conv2D(5, 1, 1)(maxpool)
  conv4 = tf.keras.layers.Conv2D(6, 1, 1)(maxpool)

  inputs = a
  outputs = [conv3, conv4]

  model = tf.keras.models.Model(inputs=inputs, outputs=outputs)


  model.compile(optimizer=tf.keras.optimizers.SGD(),
          loss=tf.keras.losses.mean_squared_error)


  import numpy as np
  data = np.random.rand(10, 368, 368, 3)
  cpm  = np.random.rand(10, 46, 46, 5)
  paf  = np.random.rand(10, 46, 46, 6)

  dataset1 = tf.data.Dataset.from_tensor_slices((data))
  dataset2 = tf.data.Dataset.from_tensor_slices((cpm, paf))
  dataset1 = dataset1.batch(10).repeat()
  dataset2 = dataset2.batch(10).repeat()

  dataset  = tf.data.Dataset.zip((dataset1, dataset2))

  model.fit(dataset, epochs=200, steps_per_epoch=30)
我使用tensorflow==1.10.1,得到如下错误:

 File "/home/ulsee/work/tensorflow-HalfBodyPose/learnkeras.py", line 123, in <module>
model.fit(dataset, epochs=200, steps_per_epoch=30)
 File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training.py", line 1278, in fit
validation_split=validation_split)
 File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training.py", line 917, in _standardize_user_data
exception_prefix='target')
 File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training_utils.py", line 143, in standardize_input_data
data = [standardize_single_array(x) for x in data]
 File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training_utils.py", line 143, in <listcomp>
data = [standardize_single_array(x) for x in data]
 File "/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training_utils.py", line 81, in standardize_single_array
elif x.ndim == 1:
AttributeError: 'tuple' object has no attribute 'ndim'
文件“/home/ulsee/work/tensorflow HalfBodyPose/learnkeras.py”,第123行,中
拟合(数据集,历元=200,每历元步长=30)
文件“/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training.py”,第1278行,适合
验证分割=验证分割)
文件“/usr/local/lib/python3.5/dist packages/tensorflow/python/keras/engine/training.py”,第917行,在用户数据中
异常(前缀='target')
文件“/usr/local/lib/python3.5/dist packages/tensorflow/python/keras/engine/training\u utils.py”,第143行,标准化输入数据
数据=[为数据中的x标准化单个数组(x)]
文件“/usr/local/lib/python3.5/dist-packages/tensorflow/python/keras/engine/training_-utils.py”,第143行,在
数据=[为数据中的x标准化单个数组(x)]
文件“/usr/local/lib/python3.5/dist packages/tensorflow/python/keras/engine/training\u utils.py”,第81行,标准化单数组
elif x.ndim==1:
AttributeError:“tuple”对象没有属性“ndim”
更新
在升级tf==1.11.0之后,我使这段代码正常工作。所以也许我认为这是一个版本错误

您可以尝试的一件事是连接输出,然后对目标numpy数组执行相同的操作。就应用程序逻辑而言,它是否有意义,我不确定

def conc_op(tensors):
    return K.concatenate(tensors) # K refers to Keras backend

def conc_op_shape(input_shapes):
    shape1 = list(input_shapes[0])
    shape2 = list(input_shapes[1])
    return tuple(shape1[:-1], shape1[-1]+shape2[-1])

a = tf.keras.layers.Input(shape=(368, 368, 3))
conv1 = tf.keras.layers.Conv2D(64, 3, 1)(a)
conv2 = tf.keras.layers.Conv2D(64, 3, 1)(conv1)
maxpool = tf.keras.layers.MaxPooling2D(pool_size=8, strides=8, padding='same')(conv2)
conv3 = tf.keras.layers.Conv2D(5, 1, 1)(maxpool)
conv4 = tf.keras.layers.Conv2D(6, 1, 1)(maxpool)

inputs = a
outputs = [conv3, conv4]
conc_outputs = Lambda(conc_op, output_shape=conc_op_shape)(outputs) # This is a keras layer
model = tf.keras.models.Model(inputs=inputs, outputs=conc_outputs)

model.compile(optimizer=tf.keras.optimizers.SGD(), loss=keras.losses.mean_squared_error)
model.summary()
data = np.random.rand(10, 368, 368, 3)
cpm  = np.random.rand(10, 46, 46, 5)
paf  = np.random.rand(10, 46, 46, 6)
label = np.concatenate((cpm, paf), axis=-1)

dataset = tf.data.Dataset.from_tensor_slices((data, label))
dataset = dataset.batch(2).repeat()
model.fit(dataset.make_one_shot_iterator(), epochs=2, steps_per_epoch=5) # Just to check if it runs
返回结果:

Epoch 1/2
5/5 [==============================] - 15s 3s/step - loss: 0.4057
Epoch 2/2
5/5 [==============================] - 0s 32ms/step - loss: 0.2282

我不是张量流专家,但看起来你给了它一个需要张量的元组。最好的猜测是你的
输出
.dataset1=tf.data.Dataset.from_tensor_slices((数据))dataset2=tf.data.Dataset.from_tensor_slices((cpm,paf))看着你的网络,你对网络的输入应该是(批量大小,368,368,3)。您执行上述两个步骤然后构建复杂数据集是有原因的吗?@kvish,因为此模型有两个输出,所以我想在数据集中传递两个标签,这就是我执行构建复杂数据集的两个步骤的原因。我不确定这种方式对不对,你能给我一些建议吗?谢谢。@Matthew Hou我在答案中写了一个建议。请随时检查这是否适合您。嗨,谢谢您的回复。实际上,在升级tf==1.11.0之后,我使我的代码可以工作。所以也许我认为这是一个版本错误。但也谢谢你的好意。@Matthew Hou太好了!有趣的是,它通过升级得到了修复