训练出现“资源耗尽”错误。

16
我是新手,刚开始学习tensorflow和机器学习。最近我在构建一个模型,我的模型如下:
  1. 字符级别嵌入向量-> 嵌入查找 -> LSTM1

  2. 单词级别嵌入向量 -> 嵌入查找 -> LSTM2

  3. [LSTM1 + LSTM2] -> 单层MLP -> softmax层

  4. [LSTM1 + LSTM2] -> 单层MLP -> WGAN鉴别器

  5. rnn模型代码

在构建该模型时,遇到了以下错误。我认为批次太多了。因此,我试图将批次大小从20减少到10,但仍然不起作用。

ResourceExhaustedError (见上面的回溯): 当分配具有形状 [24760,100] 的张量时OOM [[节点: chars/bidirectional_rnn/bw/bw/while/bw/lstm_cell/split = Split[T=DT_FLOAT, num_split=4, _device="/job:localhost/replica:0/task:0/device:GPU:0"](gradients_2/Add_3/y, chars/bidirectional_rnn/bw/bw/while/bw/lstm_cell/BiasAdd)]] [[节点: bi-lstm/bidirectional_rnn/bw/bw/stack/_167 = _Recvclient_terminated=false, recv_device="/job:localhost/replica:0/task:0/device:CPU:0", send_device="/job:localhost/replica:0/task:0/device:GPU:0", send_device_incarnation=1, tensor_name="edge_636_bi-lstm/bidirectional_rnn/bw/bw/stack", tensor_type=DT_INT32, _device="/job:localhost/replica:0/task:0/device:CPU:0"]]

张量[24760,100]的含义是2476000*32/8*1024*1024 = 9.44519043 MB内存。我正在使用Titan X(11 GB)GPU运行代码。哪里出了问题?为什么会发生这种错误? *额外信息*:LSTM1的大小为100。对于双向LSTM,变成了200。 LSTM2的大小为300。对于双向LSTM,它变成了600。 *注*:该错误发生在第32个时期之后。我的问题是为什么在第32个时期之后才有错误。为什么不是在最初的时期出现错误。

我没有遇到过类似"W tensorflow/core/common_runtime/bfc_allocator.cc:271] Ran out of memory trying to allocate 957.03MiB. See logs for memory state."这样的错误,但解决方案似乎是相似的。请注意下面的注意事项 - Maruf
3个回答

9

最近我一直在调整来解决这个问题。

最终,我没有解决问题描述中的内存大小之谜。我猜想在计算梯度时,tensorflow积累了大量用于计算梯度的额外内存。此时,我需要检查tensorflow的源代码,但这似乎非常麻烦。您可以通过以下命令从终端检查您的模型使用了多少内存:

nvidia-smi

从这个命令您可以猜测可以使用多少附加内存。
但是,解决这些问题的方法在于减少批处理大小,
对于我的情况,将批次大小减小到3就可以。 这可能因模型而异。
但是,如果您使用的模型中嵌入矩阵比您无法加载到内存的大得多怎么办?
解决方案是编写一些麻烦的代码。
您必须查找嵌入矩阵,然后将嵌入加载到模型中。简而言之,对于每个批处理,您必须将查找矩阵提供给模型(通过feed_dict参数在sess.run()中提供它们)。
接下来,您将面临一个新问题,
您不能以这种方式使嵌入可训练。解决方案是在placeholder中使用嵌入并将其分配给Variable(例如说A)。在每个训练批次之后,学习算法更新变量A。然后通过tensorflow计算A向量的输出并将其分配给位于模型外部的嵌入矩阵。(我说过这个过程很麻烦)
现在您的下一个问题应该是,如果您无法将嵌入查找提供给模型,因为它太大了怎么办。这是一个基本的问题,您无法避免。这就是为什么NVIDIA GTX 1080、1080ti和NVIDA TITAN Xp之间有如此巨大的价格差异,尽管NVIDIA 1080ti和1080具有更高的频率来运行执行。

在训练过程中,你是否观察到当使用较大的批量大小时,资源使用量会增加?可以使用nvidia-smitop来观察。 - Dylan F
不,我没有检查资源大小是否在增加。但我一定会检查并告诉你。 - Maruf
@DylanF 看起来资源使用量没有增加。 - Maruf

4

*注意*:在第32个时期之后发生了错误。我的问题是为什么会在第32次时期后出现错误,而不是在最初的时期。

这是一个重要的线索,表明图在执行过程中并不是静态的。我的意思是,你很可能正在执行sess.run(tf.something)而不是

my_something = tf.something
with tf.Session() as sess: 
    sess.run(my_something)

我在尝试实现有状态的RNN时遇到了同样的问题。我偶尔会重置状态,因此我会执行sess.run([reset if some_condition else tf.no_op()])。只需将nothing = tf.no_op()添加到我的图表中,并使用sess.run([reset if some_condition else nothing])解决了我的问题。

如果您能发布训练循环,就更容易判断是否出了问题。


0

我在训练卷积自编码器模型时也遇到了同样的问题。通过减小批量大小来解决它。我的早期批量大小为64。为了解决这个错误,我将其减小到32,然后它就可以工作了!!!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接