python - 两种不同输入样本大小的 Keras 多任务学习

标签 python tensorflow machine-learning keras nlp

我正在使用 Keras 中的代码实现多任务回归模型 API在共享层部分下。

有两个数据集,我们称它们为data_1data_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_1data_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'])

模型可视化如下。 enter image description here

然后我按如下方式拟合模型。

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 编写一个解决方案。 所以,你需要的是:

  1. 定义一个从数据中获取其形状的动态输入

  2. 使用平均池化,因此您的密集层维度独立于输入维度。

  3. 分别计算损失

这里是你修改后的例子:

## 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')

enter image description here

旧答案:

看来你的问题不是编码问题,而是机器学习问题!你必须配对你的数据集:这意味着,你必须在每一轮的两个输入层上提供你的 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/

相关文章:

python - django-tables2 : Table subclassing and Meta inner class attributes

python - 在多进程中使用一张图运行 tensorflow

docker - 在带有 gpu 的 docker 中使用 tensorflow

python - CNN 仅针对 binary_crossentropy 损失函数收敛并且在测试数据集上失败

python - 为什么 python 不允许在函数名和变量名中使用连字符?

python - 默认导入pprint作为调试工具

python可以将图像文件读取为二进制文件

tensorflow - 在 Tensorflow 中将 3 阶张量与 2 阶张量相乘

performance - 推荐系统 - Recall@K 和 Precision@K

python - scikit-learn中MLPRegressor的超参数优化