训练多个输入和输出Keras模型(ValueError:无法将NumPy数组转换为张量(不支持的对象类型列表)) [英] Training Multiple Input and Output Keras Model (ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list))

查看:66
本文介绍了训练多个输入和输出Keras模型(ValueError:无法将NumPy数组转换为张量(不支持的对象类型列表))的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有六个不同的 Sequnstial Keras模型,我希望将它们连接起来,如下所示:

I have six different Sequnstial Keras models and I desire to concatenate them like the following:

activation = 'tanh'
model1 = Sequential()
model1.add(Dense(3, input_dim=3, activation=activation))
model1.add(Dense(3, activation=activation))
model1.add(Dense(1))

model2 = Sequential()
model2.add(Dense(3, input_dim=3, activation=activation))
model2.add(Dense(3, activation=activation))
model2.add(Dense(1))

model3 = Sequential()
model3.add(Dense(1, input_dim=1, activation=activation))
model3.add(Dense(1, activation=activation))
model3.add(Dense(1))

model4 = Sequential()
model4.add(Dense(6, input_dim=6, activation=activation))
model4.add(Dense(3, activation=activation))
model4.add(Dense(1))

model5 = Sequential()
model5.add(Dense(2, input_dim=2, activation=activation))
model5.add(Dense(2, activation=activation))
model5.add(Dense(1))

model6 = Sequential()
model6.add(Dense(6, input_dim=6, activation=activation))
model6.add(Dense(4, activation=activation))
model6.add(Dense(1))

串联

model_concat = concatenate([model1.output, model2.output, model3.output, model4.output, model5.output, model6.output])

composed_model = Model(
    inputs=[model1.input, model2.input, model3.input, model4.input, model5.input, model6.input],
    outputs=model_concat
)
composed_model.compile(optimizer=SGD(lr=0.001), loss='mse')

所有模型的输出尺寸均为1,但模型的输入尺寸不同.

The output dimensions of all models are 1, but the input dimensions of models are different.

以上代码将完全运行,没有任何错误.

The above code will run completely without any error.

现在,问题在于训练模型.我将尝试运行以下代码来训练一个数据实例的模型(每个子数组的维数等于相应模型的输入维数):

Now, the problem is for training the model. I will try to run the following code to train the model with one data instance (the dimension of each subarray is equal to the input dimension of the corresponding model):

x_input = [[[-50.0, -50.0, 10.0], [-10.0, -20.0, 30.0], \
            [20.0], [10.0, 10.0, 10.0, 10.0, 10.0, 10.0], [50.0, 50.0],\
            [10.0, 10.0, 10.0, 10.0, 10.0, 10.0]]]

y_output = [[1.0, 1.0, 1.0, 1.0,1.0,1.0]]
composed_model.fit(x_input, y_output)

但是,我遇到以下错误:

However, I have the following error:

ValueError:无法将NumPy数组转换为张量(不支持的对象类型列表).

ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type list).

我找到了相关帖子,但是它不能解决我的问题.

I found a related post, but it does not solve my problem.

推荐答案

据我所知,我们不能只是将所有可变大小的输入一起传递给 fit 用于多输入模型.您将训练对传递给模型的方式,肯定无法解开关注输入层.您提到的相关帖子也是要考虑的重要事实.

As far as I can tell we can't just pass all variable-size inputs together in fit for the multi-input model. The way you pass your training pairs to the model, it surely unable to unpack for concern input layers. The related post that you mentioned is also an important fact to consider.

但是,在 tensorflow 中,我们可以将 tf.ragged.RaggedTensor 用于可变长度输入序列,在

However, in tensorflow, we can use tf.ragged.RaggedTensor for variable-length input sequence, discussed here. But not sure if there is any workaround possible by converting to the ragged tensor. It probably would possible if a single input layer takes a different length of the input sequence.

如果您阅读拟合方法的训练对输入,则会看到 keras 期望 x 参数如下:

If you read the fit method's training pairs input you would see keras expects the x paramer as follows:

Arguments

x: Input data. It could be:
    1. A Numpy array (or array-like), or a list of arrays (in case the model 
       has multiple inputs).
    2. A TensorFlow tensor, or a list of tensors (in case the model 
       has multiple inputs).
    3. A dict mapping input names to the corresponding array/tensors, 
       if the model has named inputs.
...
...

对于您的情况,选择选项3非常方便,它会将字典映射的输入名称与训练对一起传递.这是我们可以做到这一点的一种方法.首先为每个模型的输入层设置一些名称.我们设置 model1 model2 等...

For your case, option 3 is pretty convenient to choose from, which is passing the dictionary mapped input names with training pairs. Here is one way we can do this. First set some names to the input layer of each model. We set model1, model2, ... etc.

from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense 

activation = 'tanh'
model1 = Sequential()
model1.add(Dense(3, input_dim=3, activation=activation, name='model1'))
model1.add(Dense(3, activation=activation))
model1.add(Dense(1))

model2 = Sequential()
model2.add(Dense(3, input_dim=3, activation=activation, name='model2'))
model2.add(Dense(3, activation=activation))
model2.add(Dense(1))

model3 = Sequential()
model3.add(Dense(1, input_dim=1, activation=activation, name='model3'))
model3.add(Dense(1, activation=activation))
model3.add(Dense(1))

model4 = Sequential()
model4.add(Dense(6, input_dim=6, activation=activation, name='model4'))
model4.add(Dense(3, activation=activation))
model4.add(Dense(1))

model5 = Sequential()
model5.add(Dense(2, input_dim=2, activation=activation, name='model5'))
model5.add(Dense(2, activation=activation))
model5.add(Dense(1))

model6 = Sequential()
model6.add(Dense(6, input_dim=6, activation=activation, name='model6'))
model6.add(Dense(4, activation=activation))
model6.add(Dense(1))

现在,构建整个最终模型,并在其中设置最后一个图层名称,此处将其设置为 target_concatenate .

Now, build whole the final model where we also set the last layer name, which is set here as target_concatenate.

import tensorflow as tf 

model_concat = tf.keras.layers.concatenate(
    [
     model1.output, model2.output, model3.output, 
     model4.output, model5.output, model6.output
    ], name='target_concatenate')

composed_model = tf.keras.Model(
    inputs=[model1.input, model2.input, model3.input, 
            model4.input, model5.input, model6.input],
    outputs=model_concat
)
composed_model.compile(optimizer='sgd', loss='mse')

数据集

如上所述,您提供的样本数据对于模型训练不合法.首先,它不应该是 list ,而应该是 numpy ;其次,对于多输入变量大小,可以方便地分别传递它们.

The sample data you provided is not legal for model training as we mentioned above. Firstly it should not be a list but numpy and secondly, for multi-input variable size, it convenient to pass them separately.

import numpy as np 

# Six Inputs 
one = np.random.randint(-50, 10, size=(1, 3))
two = np.random.randint(-10, 30, size=(1, 3))
thr = np.random.randint(20, size=(1))
fur = np.random.randint(10, size=(1, 6))
fiv = np.random.randint(50, size=(1,2))
six = np.random.randint(10, size=(1, 6))

# One Target
tar = np.random.randint(2, size=(1, 6))

print(one, one.shape)
print(two, two.shape)
print(thr, thr.shape)
print(fur, fur.shape)
print(fiv, fiv.shape)
print(six, six.shape)
print(tar, tar.shape)

[[-42   9 -34]] (1, 3)
[[28 22  7]] (1, 3)
[19] (1,)
[[4 4 1 7 4 7]] (1, 6)
[[40 35]] (1, 2)
[[3 6 1 1 3 8]] (1, 6)
[[0 0 1 1 0 0]] (1, 6)

当我们调用 .fit 时,我们会将这些数据集作为dict映射模型的输入和输出名称传递给相应的数组.因此,让我们检查一下以获取组成模型的名称.

When we call .fit, we will pass these datasets as dict mapping model's input and output names to the corresponding array. So, let's check to get the names of the composed model.

# viewing the model shapes and layers name 
# tf.keras.utils.plot_model(composed_model, 
#                            show_shapes=True, show_layer_names=True)
composed_model.input_names, composed_model.output_names

(['model1_input',
  'model2_input',
  'model3_input',
  'model4_input',
  'model5_input',
  'model6_input'],
 ['target_concatenate'])

太好了,现在我们可以方便地通过巴黎培训,以适应 fit 方法.

Great, now we can pass training Paris as follow conveniently to the fit method.

composed_model.fit(
    {
         "model1_input": one, "model2_input": two, "model3_input": thr,
         "model4_input": fur, "model5_input": fiv, "model6_input": six
     },
     {
         "target_concatenate": tar
     },
    epochs=10,
    batch_size=32,
    verbose=2
)

Epoch 1/10
496ms/step - loss: 0.6022
Epoch 2/10
5ms/step - loss: 0.5428
Epoch 3/10
7ms/step - loss: 0.4888
Epoch 4/10
16ms/step - loss: 0.4426
Epoch 5/10
8ms/step - loss: 0.4041
Epoch 6/10
8ms/step - loss: 0.3719
Epoch 7/10
9ms/step - loss: 0.3448
Epoch 8/10
5ms/step - loss: 0.3215
Epoch 9/10
7ms/step - loss: 0.3011
Epoch 10/10
5ms/step - loss: 0.2830

这篇关于训练多个输入和输出Keras模型(ValueError:无法将NumPy数组转换为张量(不支持的对象类型列表))的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆