资源在训练神经网络时耗尽 - keras

时间:2018-02-14 21:09:46

标签: tensorflow machine-learning neural-network deep-learning keras

我有65668个文件的数据集。

我正在使用Keras进行CNN,这些是我的层:

embedding_layer = Embedding(len(word_index) + 1,
                        EMBEDDING_DIM,
                        weights=[embedding_matrix],
                        input_length=MAX_SEQUENCE_LENGTH,
                        trainable=True)
sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = Conv1D(128, 5, activation='relu')(embedded_sequences)
x = MaxPooling1D(5)(x)
x = Conv1D(256, 5, activation='relu')(x)
x = MaxPooling1D(5)(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
preds = Dense(len(labels_index), activation='softmax')(x)

在GloVE.6B.100d上训练第一个嵌入层。 拟合数据:

# fitting the data
model.fit(x_train, y_train, validation_data=(x_val, y_val),
      epochs=20, batch_size=128)

MAX_SEQUENCE_LENGTH是500。 我正在训练GPU,Nvidia GeForce 940MX, 我得到以下错误作为堆栈的一部分:

  

资源耗尽:OOM在分配形状[15318793,100]的张量并在/ job上键入float:localhost / replica:0 / task:0 / device:GPU:0 by allocator GPU_0_bfc

我尝试将批量大小减少到16,甚至8,我仍然得到相同的错误。 问题是什么?

2 个答案:

答案 0 :(得分:5)

问题在于你的set fo+=a。它需要分配一个大小为Embedding的矩阵,该矩阵肯定大于15318793 * 100 * 4 bytes = 5.7 GB内存。如何克服这个问题的方法很少:

  1. 减少词汇量/语料库大小:尝试采取例如1M最常用的单词而不是完整的单词集。这将大大减少嵌入矩阵的大小。

  2. 使用生成器代替GeForce 940 MX :您可以使用生成器将序列转换为单词向量序列,而不是使用Embedding

  3. 使用Embedding的线性转换,而不是重新嵌入嵌入 - 正如您所提到的那样,使用标记Embedding使您的算法正常工作,您可以将其设置为{{ 1}}并添加:

    trainable=False

    基于现有嵌入来训练新的嵌入。

  4. 更改设备 - 如果您拥有巨大的False内存,则可以尝试以下策略:

    Dense(new_embedding_size, activation='linear')(embedding)
    

    在此设计中,RAM图层的计算将使用with tf.device('/cpu:0'): embedding_layer = Embedding(len(word_index) + 1, EMBEDDING_DIM, weights=[embedding_matrix], input_length=MAX_SEQUENCE_LENGTH, trainable=True) sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32') embedded_sequences = embedding_layer(sequence_input) Embedding进行。缺点是CPURAM之间的转移可能非常缓慢。

答案 1 :(得分:0)

您不可能拥有足够大的数据集来覆盖GloVE嵌入中的所有单词,因此将嵌入设置为可训练可能仅覆盖部分嵌入,因此当您对其进行训练时,这些嵌入会移动移到稍有不同的空间,但未触及的空间将保留在原始的GloVE空间中。尝试设置trainable = False并通过执行线性变换来解决问题,例如:

sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = TimeDistributed(Dense(EMBEDDING_DIM))(embedded_sequences)
x = Conv1D(128, 5, activation='relu')(x)

正如另一位评论者所说。 这一点很重要,因为如果您将其用于生产中的推理,那么未经修改的嵌入之一可能会使模型变得有些呆板。 线性变换可以移动嵌入空间,并且可以以理想的方式对可见数据执行可接受的工作。