如何处理Keras中极长的卷积序列内存大小?

时间:2018-03-20 18:10:32

标签: python tensorflow deep-learning keras gpu

我认为这是一个独特的问题,但如果它们存在,肯定会将我与其他地方的其他答案联系起来。我在Keras有一个卷积顺序网络,非常类似于guide to the sequential model (and here is their model):

中的网络
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.layers import Embedding
from keras.layers import Conv1D, GlobalAveragePooling1D, MaxPooling1D

model = Sequential()
model.add(Conv1D(64, 3, activation='relu', input_shape=(seq_length, 100)))
model.add(Conv1D(64, 3, activation='relu'))
model.add(MaxPooling1D(3))
model.add(Conv1D(128, 3, activation='relu'))
model.add(Conv1D(128, 3, activation='relu'))
model.add(GlobalAveragePooling1D())
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

model.fit(x_train, y_train, batch_size=16, epochs=10)
score = model.evaluate(x_test, y_test, batch_size=16)

不幸的是,我的序列大小非常庞大(高达一百万),我真的很喜欢嵌入。有了这个,我想做2d卷积(可能还有更深层次的架构)。我的GPU运行得足够快,因为卷积很容易,但它有2GB的内存。因此,我甚至无法一次训练网络一个样本。一旦我引入嵌入,它就会爆炸网络的大小 - 在本例中,(batch_size,1000000,100,embed_size)。

我知道fit_generator,但是使用fit_generator(和TimeSeriesGenerator)要求我为序列的分解时间步长的每一步都有一个标签。我的问题是一个简单的分类问题,所以在例如序列的前1000个步骤之后提供标签与百万分之一相比没有意义。我的印象是网络可能正在为分解序列的每个部分运行GlobalAveragePooling。作为证明,当我在一个小数据集上运行fit_generator与regular_fit相比时,fit_generator的性能会受到很大影响。

因此,我的问题是:我可以使用什么来创建一个大型网络,以便在Keras的极长序列上运行?我是否有可能误解fit_generator?或者是否有其他方法可以将长序列分解为多个部分?如果这绝对不存在,我可以自己写一下并将其提交给Keras,但我不愿意。

这与序列长度极长的LSTM不同,因为我不关心TBTT,卷积网络没有状态。

2 个答案:

答案 0 :(得分:2)

你有一系列句子,嵌入一次只能应用于一个句子,所以你需要将它包装在TimeDistributed层中

ClassLoader loader = Thread.currentThread().getContextClassLoader();
Properties properties = new Properties();
try (InputStream resourceStream = loader.getResourceAsStream("application.properties")) {
    properties.load(resourceStream);
} catch (IOException e) {
    e.printStackTrace();
}

以上为我提供了一个from keras.models import Sequential from keras.layers import Embedding, TimeDistributed # plug-in your own values vocab_size = 10000 embed_size = 200 seq_length = 1000000 model = Sequential() model.add(TimeDistributed(Embedding(vocab_size, embed_size), input_shape=(seq_length, 100))) 的input_shape和一个(None, 1000000, 100)的输出形状,有200万个参数。

答案 1 :(得分:1)

如果有人偶然发现此问题,要解决此问题,我只是使用大小为10的最大池化层(而不是平均池化)作为输入。这样可以有效地将序列中的项数减少10倍,从而为嵌入层留出空间。

它的效果很好,所以我认为减少输入量不会产生不利影响。使用“最大池化”实质上只是随机选择项目,因为每个项目的数字值都是随机选择的。