1

バッチ勾配降下を使用してニューラルネットワークを訓練したいが、私はそのプロセスを並列化したい。バッチをミニバッチに分割し、プロセス間でグラディエント計算を分散し、それらを平均プロセスに戻して平均化し、トレーニングに適用したいと考えています。簡単な例としてTensorFlowは、ミニブッチ勾配を平均して平均化する

、放物線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個のプロセスに分けたいと思っています。

私はこれを「同期トレーニング」と呼んでいますが、これはリソースを見てきましたが、誰もそれを説明していないと思います。

この単純な例を同期的に並列化するにはどうすればよいですか?

+1

なぜこれをやりたいですか?その悪い考えを言っているのではない、私はちょうど興味がある – user3684792

+0

私の実際のアプリケーションでは、ノードに多くのレイヤーを持つ深い神経網を使って、約30,000の例があります。ミニバッチトレーニングを並列化できれば、私はこれを恥ずかしそうに並行させることができます。たとえば、30個のプロセスで実行すると、1,000個の例に適合する速度を達成できます。 – Drew

+0

テンソルフローに並列化を処理させるだけの利点は何ですか? – user3684792

答えて

1

ほとんどの場合、非同期トレーニングに賛成して放棄されたため、同期トレーニングについてはあまり気にしません。

同期勾配降下では、すべてのミニバッチを終了し、それぞれの勾配をすべて同時に適用してネットワークパラメータを更新します。非同期の場合、ネットワークパラメータは、1つのミニバッチからの勾配が利用可能になるたびに更新される。これらの更新は、多かれ少なかれランダムな順序で行われます。このメソッドは有効ではないようです:たとえば、ネットワークパラメータが1342回反復され、いくつかのミニバッチのグラデーションの計算を開始するとします。計算が終了するまでに、7つの古いミニバッチでグラディエントが報告されたため、ネットワークパラメータは1349回更新されている可能性があります。したがって、計算の開始時に指定されたものではないネットワークパラメータにグラディエント補正を適用することになります。

非同期降下が間違っているようですが、確率的な勾配降下は厄介な/不正確なプロセスであり、非同期更新からの余計な追加を加えることは有害ではないことを理解する必要があります。一方、同期的な更新を行う場合、他のすべてのGPUが終了するのを待たなければならないため、一部のGPUは頻繁にアイドル状態になることがあります。

私はすぐにウェブ上で適切な参考文献を見つけようとしましたが、できませんでした。私は、非同期更新の使い方が異なるグループによって何度も再発見されたことを覚えています。 Jeff Deanのこの古いpaperがありますが、同期と非同期を分析しません。

テンソルフローの公式ドキュメントには、asynchronous trainingの例がありますが、より良いチュートリアルがあります。

上記リンク先のWebページもsynchronous training exampleです。

+0

同期トレーニングをより扱いやすくするMPIを使用するTensorFlow拡張モジュールがあります:https://github.com/uber/horovod。私はそれを試して、それは動作しますが、性能は私のラップトップで悪化しています - より多くのCPUコアで試す必要があります。 – Drew

+0

@Drewあなたは非同期と比較してパフォーマンスを比較すべきですが、それは真実であり、MPIはそのために作られていないようです。 GPUで数日かかる重い計算を実行する場合は、他の方法で非同期を実行する方法を見てみてください。それはあなたの最後の時間を節約することができます。 – toto2