【问题标题】:How to handle extremely long convolutional sequence memory size in Keras?如何在 Keras 中处理极长的卷积序列内存大小?
【发布时间】:2018-08-29 16:34:36
【问题描述】:

我相信这是一个独特的问题,但如果存在其他答案,请务必将我链接到其他地方。我在 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)

不幸的是,我的序列大小非常庞大(高达一百万),我真的很想进行嵌入。有了这个,我想做二维卷积(可能还有更深的架构)。我的 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,而卷积网络没有状态。

【问题讨论】:

  • 有趣的是,如果一个样本不适合内存,fit_generator 将无法工作。所以不,你没有弄错fit_generator。我把你的模型拉进去了,它有 105,729 个可训练的参数。如果您使用 32 位浮点数,大约 0.008 gbs - 训练模型应该不是问题。但是,我没有用 np.random,randn(100, 1000000, 100) 模拟 x_train 的内存不足,所以我尝试了np.random.rand(1, 1000000, 100),我可以将它放入内存中。你试过一个例子吗?
  • @putonspectacles 是的,我试过这个模型。抱歉,显示的模型只是文档中的示例,以保持问题简短。当我尝试将嵌入作为第一层时,我的问题就出现了,因为这会将大小增加到例如 (1, 1000000, 100, embed_size)。即使进行大小为 2 的嵌入也不适合我。我将编辑问题以使其更清楚。
  • ahhhh,您需要所有序列中的元素吗?即,由于这是一项分类任务,您可能会认为序列中可能存在冗余
  • 您能解释一下您的数据是什么吗?如我所见,一个 100 维向量的序列(最多一百万)。传递给嵌入对我来说没有意义,因为它需要索引。我是不是误会了?
  • @putonspectacles 序列的所有元素都是必要的,很可能......虽然我会调查。这是一个有趣的想法。但是,我怀疑许多向量是相同的,请阅读我的下一条评论

标签: python tensorflow deep-learning keras gpu


【解决方案1】:

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

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

上面给出了(None, 1000000, 100) 的输入形状和(None, 1000000, 100, 200) 的输出形状,有200 万个参数。

【讨论】:

  • 啊,我的错。这就说得通了。但是,运行它仍然会导致我原来的问题,即矩阵无法放入我的记忆中。
【解决方案2】:

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

它的表现很棒,所以我认为减少输入不会产生不利影响。使用 Max pooling 本质上只是随机选择项目,因为每个项目的数值都是随机选择的。

【讨论】:

    猜你喜欢
    • 2019-09-21
    • 2017-11-12
    • 1970-01-01
    • 1970-01-01
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2018-07-30
    • 1970-01-01
    相关资源
    最近更新 更多