我正在使用 Keras 中的代码实现多任务回归模型 API在共享层部分下。
有两个数据集,我们称它们为data_1
和data_2
如下。
data_1 : shape(1434, 185, 37)
data_2 : shape(283, 185, 37)
data_1
由 1434 个样本组成,每个样本的长度为 185 个字符,37 表示唯一字符的总数为 37 或换句话说 vocab_size
。比较data_2
由283个字符组成。
我将 data_1
和 data_2
转换为二维 numpy 数组,然后将其提供给嵌入层。
data_1=np.argmax(data_1, axis=2)
data_2=np.argmax(data_2, axis=2)
这使得数据的形状如下。
print(np.shape(data_1))
(1434, 185)
print(np.shape(data_2))
(283, 185)
矩阵中的每个数字代表索引整数。
多任务模型如下。
user_input = keras.layers.Input(shape=((185, )), name='Input_1')
products_input = keras.layers.Input(shape=((185, )), name='Input_2')
shared_embed=(keras.layers.Embedding(vocab_size, 50, input_length=185))
user_vec_1 = shared_embed(user_input )
user_vec_2 = shared_embed(products_input )
input_vecs = keras.layers.concatenate([user_vec_1, user_vec_2], name='concat')
input_vecs_1=keras.layers.Flatten()(input_vecs)
input_vecs_2=keras.layers.Flatten()(input_vecs)
# Task 1 FC layers
nn = keras.layers.Dense(90, activation='relu',name='layer_1')(input_vecs_1)
result_a = keras.layers.Dense(1, activation='linear', name='output_1')(nn)
# Task 2 FC layers
nn1 = keras.layers.Dense(90, activation='relu', name='layer_2')(input_vecs_2)
result_b = keras.layers.Dense(1, activation='linear',name='output_2')(nn1)
model = Model(inputs=[user_input , products_input], outputs=[result_a, result_b])
model.compile(optimizer='rmsprop',
loss='mse',
metrics=['accuracy'])
然后我按如下方式拟合模型。
model.fit([data_1, data_2], [Y_1,Y_2], epochs=10)
错误:
ValueError: All input arrays (x) should have the same number of samples. Got array shapes: [(1434, 185), (283, 185)]
在 Keras 中有什么方法可以使用两个不同的样本大小输入或一些技巧来避免此错误以实现我的多任务回归目标。
这是用于测试的最低工作代码。
data_1=np.array([[25, 5, 11, 24, 6],
[25, 5, 11, 24, 6],
[25, 0, 11, 24, 6],
[25, 11, 28, 11, 24],
[25, 11, 6, 11, 11]])
data_2=np.array([[25, 11, 31, 6, 11],
[25, 11, 28, 11, 31],
[25, 11, 11, 11, 31]])
Y_1=np.array([[2.33],
[2.59],
[2.59],
[2.54],
[4.06]])
Y_2=np.array([[2.9],
[2.54],
[4.06]])
user_input = keras.layers.Input(shape=((5, )), name='Input_1')
products_input = keras.layers.Input(shape=((5, )), name='Input_2')
shared_embed=(keras.layers.Embedding(37, 3, input_length=5))
user_vec_1 = shared_embed(user_input )
user_vec_2 = shared_embed(products_input )
input_vecs = keras.layers.concatenate([user_vec_1, user_vec_2], name='concat')
input_vecs_1=keras.layers.Flatten()(input_vecs)
input_vecs_2=keras.layers.Flatten()(input_vecs)
nn = keras.layers.Dense(90, activation='relu',name='layer_1')(input_vecs_1)
result_a = keras.layers.Dense(1, activation='linear', name='output_1')(nn)
# Task 2 FC layers
nn1 = keras.layers.Dense(90, activation='relu', name='layer_2')(input_vecs_2)
result_b = keras.layers.Dense(1, activation='linear',name='output_2')(nn1)
model = Model(inputs=[user_input , products_input], outputs=[result_a, result_b])
model.compile(optimizer='rmsprop',
loss='mse',
metrics=['accuracy'])
model.fit([data_1, data_2], [Y_1,Y_2], epochs=10)
最佳答案
新答案:
在这里,我正在使用 TensorFlow 2 编写一个解决方案。 所以,你需要的是:
定义一个从数据中获取其形状的动态输入
使用平均池化,因此您的密集层维度独立于输入维度。
分别计算损失
这里是你修改后的例子:
## Do this
#pip install tensorflow==2.0.0
import tensorflow.keras as keras
import numpy as np
from tensorflow.keras.models import Model
data_1=np.array([[25, 5, 11, 24, 6],
[25, 5, 11, 24, 6],
[25, 0, 11, 24, 6],
[25, 11, 28, 11, 24],
[25, 11, 6, 11, 11]])
data_2=np.array([[25, 11, 31, 6, 11],
[25, 11, 28, 11, 31],
[25, 11, 11, 11, 31]])
Y_1=np.array([[2.33],
[2.59],
[2.59],
[2.54],
[4.06]])
Y_2=np.array([[2.9],
[2.54],
[4.06]])
user_input = keras.layers.Input(shape=((None,)), name='Input_1')
products_input = keras.layers.Input(shape=((None,)), name='Input_2')
shared_embed=(keras.layers.Embedding(37, 3, input_length=5))
user_vec_1 = shared_embed(user_input )
user_vec_2 = shared_embed(products_input )
x = keras.layers.GlobalAveragePooling1D()(user_vec_1)
nn = keras.layers.Dense(90, activation='relu',name='layer_1')(x)
result_a = keras.layers.Dense(1, activation='linear', name='output_1')(nn)
# Task 2 FC layers
x = keras.layers.GlobalAveragePooling1D()(user_vec_2)
nn1 = keras.layers.Dense(90, activation='relu', name='layer_2')(x)
result_b = keras.layers.Dense(1, activation='linear',name='output_2')(nn1)
model = Model(inputs=[user_input , products_input], outputs=[result_a, result_b])
loss = tf.keras.losses.MeanSquaredError()
optimizer = tf.keras.optimizers.Adam()
loss_values = []
num_iter = 300
for i in range(num_iter):
with tf.GradientTape() as tape:
# Forward pass.
logits = model([data_1, data_2])
loss_value = loss(Y_1, logits[0]) + loss(Y_2, logits[1])
loss_values.append(loss_value)
gradients = tape.gradient(loss_value, model.trainable_weights)
optimizer.apply_gradients(zip(gradients, model.trainable_weights))
import matplotlib.pyplot as plt
plt.plot(range(num_iter), loss_values)
plt.xlabel("iterations")
plt.ylabel('loss value')
旧答案:
看来你的问题不是编码问题,而是机器学习问题!你必须配对你的数据集:这意味着,你必须在每一轮的两个输入层上提供你的 Keras 模型。
解决方案是以两个数据集的大小相同的方式对较小的数据集进行上采样。您执行此操作的方式取决于数据集的语义。另一种选择是对更大的数据集进行下采样,不推荐这样做。
在一个非常基本的情况下,如果我们假设样本是独立同分布的。跨数据集,您可以使用以下代码:
random_indices = np.random.choice(data_2.shape[0],
data_1.shape[0], replace=True)
upsampled_data_2 = data_2[random_indices]
因此,您获得了较小数据集的新版本 upsampled_data_2
,其中包含一些重复样本,但与较大数据集的大小相同。
关于python - 两种不同输入样本大小的 Keras 多任务学习,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57216216/