La discesa del gradiente asincrono è supportata nel rilascio open source di TensorFlow, senza nemmeno modificare il grafico. Il modo più semplice per farlo è quello di eseguire più passi simultanei in parallelo:
loss = ...
# Any of the optimizer classes can be used here.
train_op = tf.train.GradientDescentOptimizer(0.01).minimize(loss)
sess = tf.Session()
sess.run(tf.initialize_all_variables())
def train_function():
# TODO: Better termination condition, e.g. using a `max_steps` counter.
while True:
sess.run(train_op)
# Create multiple threads to run `train_function()` in parallel
train_threads = []
for _ in range(NUM_CONCURRENT_STEPS):
train_threads.append(threading.Thread(target=train_function))
# Start the threads, and block on their completion.
for t in train_threads:
t.start()
for t in train_threads:
t.join()
questo esempio fino NUM_CONCURRENT_STEPS
chiamate verso sess.run(train_op)
. Poiché non c'è coordinamento tra questi thread, procedono in modo asincrono.
In realtà è più difficile da raggiungere sincrono formazione parallela (attualmente), perché questo richiede un coordinamento supplementare per garantire che tutte le repliche di leggere la stessa versione dei parametri, e che tutti i loro aggiornamenti diventano visibili contemporaneamente . Lo multi-GPU example for CIFAR-10 training esegue gli aggiornamenti sincroni creando più copie della "torre" nel grafico di allenamento con parametri condivisi e facendo una media esplicita dei gradienti tra le torri prima di applicare l'aggiornamento.
N.B. Il codice in questa risposta colloca tutti i calcoli sullo stesso dispositivo, che non sarà ottimale se nella macchina sono presenti più GPU. Se si desidera utilizzare tutte le GPU, seguire l'esempio di multi-GPU CIFAR-10 model e creare più "torri" con le loro operazioni bloccate su ciascuna GPU. Il codice sarà o meno come segue:
train_ops = []
for i in range(NUM_GPUS):
with tf.device("/gpu:%d" % i):
# Define a tower on GPU `i`.
loss = ...
train_ops.append(tf.train.GradientDescentOptimizer(0.01).minimize(loss))
def train_function(train_op):
# TODO: Better termination condition, e.g. using a `max_steps` counter.
while True:
sess.run(train_op)
# Create multiple threads to run `train_function()` in parallel
train_threads = []
for train_op in train_ops:
train_threads.append(threading.Thread(target=train_function, args=(train_op,))
# Start the threads, and block on their completion.
for t in train_threads:
t.start()
for t in train_threads:
t.join()
noti che si potrebbe trovare conveniente usare un "variable scope" per facilitare la condivisione variabili tra le torri.
Vorrei solo essere abbastanza furbo da capire anche questa domanda. Buona fortuna. – GojiraDeMonstah