TensorFlow 并行平均小批量梯度

TensorFlow averaging minibatch gradients in parallel

我想使用批量梯度下降训练神经网络,但我想并行化该过程。我想将 batch 分成 mini-batches,跨进程分发梯度计算,然后将它们带回 master 进程进行平均并应用到训练中。

作为一个简单的例子,使用这个脚本在抛物线 y = x^2:

的 N 个数据点上训练神经网络
import tensorflow as tf
import numpy as np

def add_layer(inputs, in_size, out_size, activation_function=None):
    Weights = tf.Variable(tf.random_normal([in_size, out_size]))
    biases = tf.Variable(tf.random_normal([1, out_size]))
    Wx_plus_b = tf.matmul(inputs, Weights) + biases
    if activation_function is None:
        outputs = Wx_plus_b
    else:
        outputs = activation_function(Wx_plus_b)
    return outputs

# Make up some real data
N = 50
x_data = np.linspace(-2, 2, N)[:, np.newaxis]
noise = np.random.normal(0, 0.05, x_data.shape)
y_data = np.square(x_data) # - 0.5 + noise

# Define placeholder for x_data and y_data
xs = tf.placeholder(tf.float32, [None, 1])
ys = tf.placeholder(tf.float32, [None, 1])

""" Build the network"""
# Add hidden layer
l1 = add_layer(xs, 1, 5, activation_function=tf.tanh)
# Add output layer
prediction = add_layer(l1, 5, 1, activation_function=None)

# Define loss
loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys-prediction), reduction_indices=[1]))

# Define optimizer
opt = tf.train.GradientDescentOptimizer(learning_rate=1e-2)
# Compute the gradients for a list of variables.
grads_and_vars = opt.compute_gradients(loss)
# Ask the optimizer to apply the gradients
train_opt = opt.apply_gradients(grads_and_vars)

# Initialize global variables
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

for i in range(2000):
    # training
    sess.run(train_opt, feed_dict={xs: x_data, ys: y_data})
    if i % 50 == 0:
        prediction_value = sess.run(prediction, feed_dict={xs: x_data})
        print(sess.run(loss, feed_dict={xs: x_data, ys: y_data}))

我要并行化的部分是梯度的计算,然后我想将这些梯度带回主进程进行平均,然后应用于训练步骤。我想将 x_data 中的 N 个数据点拆分到 P 个进程。

我认为这就是所谓的 "synchronous training",我已经看到相关资源,但从来没有人解释过。

如何以同步方式并行化这个简单示例?

您可能找不到太多关于同步训练的信息,因为它大多被放弃以支持异步训练。

在同步梯度下降中,所有的小批量都必须完成,同时应用它们各自的梯度来更新网络参数。在异步情况下,每当一个小批量的梯度可用时,网络参数就会更新。这些更新或多或少以随机顺序出现。似乎此方法无效:例如,假设网络参数已迭代 1342 次,您开始计算一些小批量的梯度。到计算完成时,网络参数可能已经更新了 1349 次,因为 7 个较旧的小批量报告了它们的梯度。因此,您将对不是在计算开始时指定的网络参数应用梯度校正。

从我上面写的来看,异步下降似乎是错误的,但你必须明白随机梯度下降是一个 sloppy/inexact 过程,并且从异步更新中添加额外的草率并不是有害的。另一方面,在进行同步更新时,一些 GPU 会经常闲置,因为它们必须等待所有其他 GPU 完成。

我很快试图在网上找到关于此的适当参考,但找不到。我记得使用异步更新的技巧被不同的小组多次重新发现。 Jeff Dean 有这个旧的 paper,但他们不分析同步与异步。

tensorflow 官方文档有一个示例asynchronous training,但可能会有更好的教程。

我上面链接的网页也指向这个synchronous training example