【问题标题】:Resource Exhausted when training a neural network - keras训练神经网络时资源耗尽 - keras
【发布时间】:2018-07-25 13:29:14
【问题描述】:

我有一个包含 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、 作为堆栈的一部分,我收到以下错误:

资源耗尽:分配具有 shape[15318793,100] 的张量并通过分配器 GPU_0_bfc 在 /job:localhost/replica:0/task:0/device:GPU:0 上键入 float 时出现 OOM

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

【问题讨论】:

  • OOM := 内存不足。减少批量大小。
  • 我确实将它减少到 8,但我仍然得到了。它需要小多少?
  • tensor with shape[15318793,100] 看起来很大,是来自embedding_layer吗?
  • 是的。当我为该图层设置 trainable='false' 时,减小尺寸时我没有收到错误。但我需要它是可训练的。
  • 你自己训练过这个嵌入吗?

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


【解决方案1】:

问题在于您的Embedding。它需要分配一个大小为15318793 * 100 * 4 bytes = 5.7 GB 的矩阵,它肯定大于GeForce 940 MX 内存。有几种方法可以解决这个问题:

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

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

  3. 使用 Embedding 的线性变换而不是重新训练嵌入 - 正如您提到的,使用标志 trainable=False 使您的算法正常工作,您可以将其设置为 False 并添加:

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

    在现有嵌入的基础上训练新嵌入。

  4. 更换设备 - 如果您有巨大的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 进行。缺点是RAMGPU 之间的传输可能非常慢。

【讨论】:

    【解决方案2】:

    您不太可能拥有足够大的数据集来涵盖 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)
    

    正如另一位评论者所说。 这很重要,因为如果您将其用于生产中的推理,其中一个未触及的嵌入可能会使模型变得非常疯狂。 线性变换移动嵌入空间,这将以理想的方式对看不见的数据执行。

    【讨论】:

      猜你喜欢
      • 2017-11-27
      • 2011-04-07
      • 1970-01-01
      • 2017-02-20
      • 2019-12-17
      • 2020-06-07
      • 2010-11-20
      • 2019-09-15
      • 1970-01-01
      相关资源
      最近更新 更多