多GPU架构,梯度平均 - 模型不太准确?

blu*_*sky 6 neural-network tensorflow

当我按照https://www.tensorflow.org/tutorials/deep_cnn所述执行cifar10模型时,使用单个GPU大约4小时后达到86%的准确率,当我使用2个GPU时,精度降至84%但达到84 2 GPU上的%准确度比1快.

我的直觉是,在https://github.com/tensorflow/models/blob/master/tutorials/image/cifar10/cifar10_multi_gpu_train.py中定义的average_gradients函数会返回一个不太精确的渐变值,因为渐变的平均值将不如实际的梯度值.

如果梯度不太准确,则控制作为训练一部分学习的函数的参数不太准确.查看代码(https://github.com/tensorflow/models/blob/master/tutorials/image/cifar10/cifar10_multi_gpu_train.py)为什么平均多个GPU上的梯度比在单个GPU上计算梯度更不准确?

我对平均值的平均值是否产生一个不太准确的值是正确的?

模型中的随机性描述为:

The images are processed as follows:
They are cropped to 24 x 24 pixels, centrally for evaluation or randomly for training.
They are approximately whitened to make the model insensitive to dynamic range.
For training, we additionally apply a series of random distortions to artificially increase the data set size:

Randomly flip the image from left to right.
Randomly distort the image brightness.
Randomly distort the image contrast.
Run Code Online (Sandbox Code Playgroud)

src:https://www.tensorflow.org/tutorials/deep_cnn

这会对训练准确性产生影响吗?

更新:

试图进一步研究这一点,用不同数量的GPU进行损失函数值训练.

Training with 1 GPU : loss value : .7 , Accuracy : 86%
Training with 2 GPU's : loss value : .5 , Accuracy : 84%
Run Code Online (Sandbox Code Playgroud)

对于更高的精度,损失值是否应该更低,反之则不然?

Eng*_*ero 5

这里对此有一个很好的讨论(不是我的内容)。基本上,当您分发 SGD 时,您必须以某种方式在工作人员之间来回传达梯度。这本质上是不完美的,因此分布式 SGD 通常至少在某种程度上不同于顺序的单工作 SGD。它通常也更快,因此需要权衡。

[张等。等人。,2015]提出了一种称为弹性平均 SGD 的分布式 SGD 方法。本文进行了稳定性分析,描述了不同通信约束下梯度的行为。它变得有点沉重,但它可能会解释为什么您会看到这种行为。

编辑:关于损失是否应该更低以获得更高的准确度,这将取决于几个因素。首先,我假设您使用 softmax 交叉熵来计算损失(如您链接的 deep_cnn 教程中所述),并假设准确度是正确预测的总数除以样本总数。在这种情况下,同一数据集上较低的损失应该与较高的准确性相关。强调的重点很重要。

如果您在训练期间报告损失,但随后报告验证(或测试)数据集的准确性,则这两者可能只是松散相关。这是因为在整个训练过程中,模型会拟合(最小化损失)总样本的某个子集,然后针对以前从未见过的新样本进行测试,以验证其泛化能力是否良好。针对此测试/验证集的损失可能(并且很可能)高于针对训练集的损失,因此,如果从不同的集合报告这两个数字,您可能无法进行比较,例如“1 个 GPU 的损失” case 应该较低,因为其准确性较低”。

其次,如果您要分发培训,那么您将计算多个工作人员的损失(我相信),但最终只有一个准确度,同样是针对测试或验证集。也许所报告的损失是任何一名工人所见过的最好的损失,但总的来说,平均损失更高。

基本上,我认为我们没有足够的信息来果断地说明为什么损失和准确性似乎与您期望的方式不相关,但有多种方式可能会发生这种情况,所以我不会立即驳回它。


Max*_*axB 5

在您链接的代码中,使用average_gradient具有 2 个 GPU的函数完全等同于(1) 仅使用具有两倍批量大小的1 个 GPU 。

你可以在定义中看到它:

grad = tf.concat(axis=0, values=grads)
grad = tf.reduce_mean(grad, 0)
Run Code Online (Sandbox Code Playgroud)

使用更大的批量大小(给定相同的时期数)会对您的结果产生任何影响。

因此,如果您想在 1-GPU 或 2-GPU 情况下进行完全等效的 (1) 计算,您可能希望在后一种情况下批量大小减半。(人们有时会避免这样做,因为在某些情况下,较小的批量大小也可能会使每个 GPU 上的计算速度变慢)

此外,这里需要注意学习率衰减。如果你使用它,你想确保n在 1-GPU 和 2-GPU 情况下的第 epoch 中的学习率相同——我不完全确定这段代码在这里做正确的事情。我倾向于在日志中打印学习率,比如

print sess.run(lr)
Run Code Online (Sandbox Code Playgroud)

应该在这里工作。

(1) 忽略与伪随机数、有限精度或不能被批量大小整除的数据集大小相关的问题。