训练深度学习模型时如何计算小批量记忆影响?


17

我正在尝试根据Andrej Karphaty的以下注释计算GPU训练模型所需的内存量:http ://cs231n.github.io/convolutional-networks/#computational-considerations

我的网络有532,752个激活19,072,984个参数(权重和偏差)。这些都是32位浮点值,因此每个值占用4个字节的内存。

我的输入图像是180x50x1(宽度x高度x深度)= 9,000个 float 32值。我不使用图像增强,因此我认为杂项内存仅与最小批处理大小有关。我使用的是128张图像的小批量。

根据Andrej的建议,我得到以下内存大小:

激活: 532,752 * 4 /(1024 ^ 2)= 2.03 MB

参数: 19,072,984 * 4 /(1024 ^ 2)* 3 = 218.27 MB

杂项: 128 * 9,000 * 4 /(1024 ^ 2)= 4.39 MB

因此,训练该网络的总内存为224,69 MB

我正在使用TensorFlow,但我想缺少一些东西。我还没有参加培训,但是我很确定(根据过去的经验)正在使用的内存将比我计算的要高得多。

如果对于小批量中的每个图像,TensorFlow保持其梯度,以便稍后可以对它们进行归一化以进行单个权重/偏差更新步骤,那么我认为内存应考虑另一个532,752 * 128值(每个图像中的梯度)小批量)。如果真是这样,那么我需要更多260.13 MB来训练具有128张图像/微型批处理的模型。

您可以帮助我理解训练深度学习模型的内存注意事项吗?以上考虑对吗?


在此处查看我对您的问题的(建议)答案。
亚当·亨德利

Answers:


5

我认为您在正确的轨道上。

是的,您将需要存储激活的派生参数和用于反向传播的参数。

此外,您对优化的选择可能很重要。您是否正在使用SGD,Adam或Adagrad进行培训?这些都有不同的内存要求。例如,您将不得不为基于动量的方法存储步长缓存,尽管与您提到的其他内存考虑相比,它应该是次要的。

因此,总的来说,您似乎已经计算出向前通过的内存需求。安德烈·卡帕蒂Andrej Karpathy)提到,后向传递可能会占用正向传递记忆的3倍,因此这可能就是为什么您会看到这种差异(在网站上向下滚动至“案例研究”以查看VGGNet的示例)。


5

@StatsSorceress TL;博士:

我正在通过此活动来查看自己是否可以计算所需的内存:

激活数: 532,752 * 2 * 4 /(1024 ^ 2)= 4.06 MB

参数: 19,072,984 * 4 /(1024 ^ 2)* 3 = 218.27 MB

杂: 128 * 9,000 * 4 /(1024 ^ 2)= 4.39 MB

总内存:(4.06 * 128)+ 218.27 + 4.39 = 742.34 MB

如果我错了,请有人对此进行纠正。仅供参考,您已经将杂项乘以128,所以我没有在上面乘以128


我会为您指出这篇文章相应的视频。他们帮助我更好地了解了发生了什么。

注意: 使用网络进行预测所需的内存远远少于训练所需的内存,这有两个原因:

  • 进行预测时,我们只会通过网络向前发送图像,而不会向后发送图像(因此我们不会将内存X 3乘以;请参见下文)
  • 每个图像有一个预测(因此,我们不需要将一个图像所需的内存乘以批处理大小,因为我们无需在预测中使用批处理)。

处理(要训练的记忆)

  1. 计算在一幅图像上训练所需的内存
  2. 将此数字乘以批处理中的图像数量

记住: 迷你批处理说,我们获取数据的一个子集,计算该子集中每个图像的梯度和误差,然后对它们进行平均并朝平均方向前进。对于卷积,权重和偏差是共享的,但是激活数量乘以批处理中的图像数量。)。

步骤1:存储1张图片

要训​​练一张图像,您必须为以下内容保留内存:

  • 型号参数:

    每层的权重偏差,它们的梯度和它们的动量变量(如果使用Adam,Adagrad,RMSProp等,则使用优化程序)

    要对此内存进行近似估算,请计算存储权重和偏差所需的内存,然后将其乘以3(即“乘以3”),因为我们是说存储权重和偏差所需的内存量(大致)等于梯度和动量变量所需的时间)

    方程式:

    卷积:

    权重(n)=深度(n)*(内核宽度*内核高度)*深度(n-1)

    偏差(n)=深度(n)

    完全连接(密集)层:

    权重(n)=输出(n)*输入(n)

    偏差(n)=输出(n)

其中Ñ是当前层和n-1个是上一层,和输出是从FC层输出的数量和输入是输入到FC层的数目(如果先前的层不是完全连接的层,输入的数量等于展平的那一层的大小)。

注意:仅用于权重和偏差的内存,再加上用于激活一幅图像的内存(请参见下文),是预测所需的内存总量(不包括用于卷积的内存开销和其他一些东西)。

  • 激活(在Caffe中为“斑点”):

(我在这里宽松地使用术语,请多多包涵)

卷积层中的每个卷积都会产生“ 图像中的像素数量 ”激活(即,通过单个卷积传递图像,会得到包含“ m ”个激活的单个特征图,其中“ m ”是来自您的像素的像素数量)图片/输入)。

对于完全连接的层,您产生的激活次数等于输出的大小。

卷积:

激活次数(n)=图片宽度*图片高度*图片编号通道

完全连接(密集)层:

激活(n)=输出(n)

请注意,您输入的内容实际上只是网络开始时的图像。卷积后,它变成了其他东西(特征图)。因此,实际上,将“ image_width”,“ image_height”和“ image_num_channels”分别替换为“ input_width”,“ input_height”和“ layer_depth”。(对于我来说,从图像的角度来看这个概念更容易。)

由于我们还需要存储每一层激活的错误(用于后向传递),因此我们将激活次数乘以2,以获得需要在存储空间中腾出空间的实体总数。激活数量随批次中图像的数量而增加,因此您可以将该数量乘以批次大小。

步骤2:记忆训练批次

将权重和偏差的数量(3倍)和激活次数(2倍批量大小)相加。将此乘以4,即可得到训练批处理所需的字节数。您可以除以1024 ^ 2得到GB的答案。


为什么说“我们在预测中不使用批次”?如果用户需要对大量图像进行预测,则可以在预测中使用批处理。
user3731622 '19

1

另外,我认为您可以使用任何探查器库来分析程序的内存和CPU使用率。有许多python库可以按特定的线程或进程(以毫秒为间隔)为您提供内存和CPU使用情况的快照。

您可以使用popen在其他子过程中运行要监视的程序部分。并使用其PID监视其内存和CPU使用情况。

psutil我发现这种工作很好。虽然还有很多。

我希望这将有所帮助。


3
感谢您的回答,@ Anwar。我正在寻找一种分析计算,而不是经验观察。
barbolo 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.