将多个输入样本映射到Keras中的单个输出样本

时间:2018-03-22 19:09:46

标签: python numpy tensorflow machine-learning keras

我正在使用Keras进行项目,该项目具有大量输入数据和较少量的输出/标签数据(即图像)。输入 - 输出数据的映射是连续且一致的,即前1000个输入样本对应于第一图像,第二个1000个输入样本对应于第二图像,依此类推。

由于输出数据是图像,因此需要大量内存,因此在numpy数组中有相同图像的数千个不必要的副本。 我一直在寻找一种方式来使用" soft" numpy数组中的链接,这样索引只是映射到一个较小的数组,但我找不到一种可接受的方法。

编辑:我应该在这里添加更多信息,因为我可能没有在上面正确解释这种情况。

我正在进行的项目拍摄视频,分割音频和视频,使用音频进行输入,并使用视频中的各个帧作为输出。在" rawest"在形式上,网络将具有单个输入(一个音频样本)和一组卷积层以形成输出。

当然,可用的输入点数(比如48kHz音频每秒48,000个样本)会大大影响输出点的数量(~24 fps)。即时简单选项(以及我输出数据较小时的选项I)将只复制数组中的数据,并将pony复制到额外的RAM使用情况。不幸的是,这不是一个选项,因为它需要将数组增加大约2000倍,对于已经很大的数据集,它会非常快地生成OOM。

希望对我所处的情况有更好的解释。到目前为止,我考虑过/尝试过的一个选项是重载numpy数组类中的某些函数,例如: getitem ,目的是将索引映射到较小的数组。我放弃了这个,因为我确定Keras的后端只是从numpy中取出一个连续的块然后使用它。 我考虑的另一个选择是使用更小的批次,并尽可能地复制图像,训练并移动到下一组图像。虽然这很麻烦(感觉就像放弃了)。

我认为最好的选择,以及我接下来尝试的选项,是使用ldavid对Keras'的建议。 TimeDistributed函数。如果我理解正确,我可以用它来批处理"输入采样到一组具有相同输出数据大小的样本。

1 个答案:

答案 0 :(得分:2)

我相信这可以通过TimeDistributed和平均结果来实现。

您的问题中有很多缺少的信息,但我会假设您的输入形状为(batch_size, 224, 224, 3),输出形状为(batch_size, 7, 7, 512),以说明如何完成此操作。

假设您拥有可以为一个输出分配一个输入的模型(假设它是VGG19):

from keras import Input, Model, backend as K
from keras.applications import VGG16
from keras.layers import TimeDistributed, Lambda

input_shape = (224, 224, 3)

vgg19 = VGG16(input_shape=input_shape,
              include_top=False,
              weights=None)

您可以将此模型传播到1000个图像中的每一个,并将输出组合起来:

x = Input(shape=(1000, 224, 224, 3))
y = TimeDistributed(vgg19)(x)                         (None, 1000, 7, 7, 512)
y = Lambda(lambda inputs: K.mean(inputs, axis=1))(y)  (None, 7, 7, 512)

model = Model(x, y)
model.compile(loss='mse', optimizer='adam')

由于您要对1,000个输入图像求平均值,因此当您在不同数量的样本之间分配时,此模型也应该有用(例如input_shape=(batch_size, 30, 224, 224, 3))。

使用MNIST的工作示例,每个标签有10个输入图像:

import numpy as np
from keras import Input, Model, backend as K
from keras.datasets import mnist
from keras.layers import TimeDistributed, Lambda, Conv2D

(x_train, y_train), (x_test, y_test) = mnist.load_data()

x_train, x_test = (np.repeat(x.reshape(x.shape[0], 1, 28, 28, 1), 10, axis=1)
                   for x in (x_train, x_test))
# samples in x_train are repeated 10 times, shape=(60000, 10, 28, 28, 1)

y_train, y_test = (np.tile(y.reshape(y.shape[0], 1, 1, 1), (1, 3, 3, 16))
                   for y in (y_train, y_test))
# samples in y_train are repeated (3, 3, 16) times, shape=(60000, 3, 3, 16)

x = Input((28, 28, 1))
y = Conv2D(16, 3, strides=9, activation='relu')(x)
base_model = Model(x, y)

x = Input(shape=(10, 28, 28, 1))
y = TimeDistributed(base_model)(x)
y = Lambda(lambda inputs: K.mean(inputs, axis=1))(y)

model = Model(x, y)
model.compile(loss='mse',
              optimizer='adam')

print('initial train loss:', model.evaluate(x_train, y_train, verbose=2))
print('initial test loss:', model.evaluate(x_test, y_test, verbose=2))

model.fit(x_train, y_train,
          batch_size=1024,
          epochs=10,
          verbose=2)

print('final train loss:', model.evaluate(x_train, y_train, verbose=2))
print('final test loss:', model.evaluate(x_test, y_test, verbose=2))
initial train loss: 891.6627651529948
initial test loss: 931.27085390625
Epoch 1/10
 - 2s - loss: 383.4519
...
Epoch 10/10
 - 2s - loss: 27.5036
final train loss: 27.394255329386393
final test loss: 27.324540267944336