¿Cómo actualizar los parámetros del modelo con gradientes acumulados?

Estoy usando TensorFlow para construir un modelo de aprendizaje profundo. Y nuevo en TensorFlow.

Debido a alguna razón, mi modelo tiene un tamaño de lote limitado, entonces este tamaño de lote limitado hará que el modelo tenga una gran variación.

Por lo tanto, quiero usar algún truco para boost el tamaño del lote. Mi idea es almacenar los gradientes de cada mini lote, por ejemplo, 64 mini lotes, y luego sumr los gradientes juntos, usar los gradientes medios de estos 64 mini lotes de datos de entrenamiento para actualizar los parámetros del modelo.

Esto significa que para los primeros 63 mini lotes, no actualice los parámetros y, después del 64 mini lote, actualice los parámetros del modelo solo una vez.

Pero como TensorFlow se basa en gráficos, ¿alguien sabe cómo implementar esta característica deseada?

Muchas gracias.

Encontré una solución aquí: https://github.com/tensorflow/tensorflow/issues/3994#event-766328647

opt = tf.train.AdamOptimizer() tvs = tf.trainable_variables() accum_vars = [tf.Variable(tf.zeros_like(tv.initialized_value()), trainable=False) for tv in tvs] zero_ops = [tv.assign(tf.zeros_like(tv)) for tv in accum_vars] gvs = opt.compute_gradients(rmse, tvs) accum_ops = [accum_vars[i].assign_add(gv[0]) for i, gv in enumerate(gvs)] train_step = opt.apply_gradients([(accum_vars[i], gv[1]) for i, gv in enumerate(gvs)]) 

En el circuito de entrenamiento:

 while True: sess.run(zero_ops) for i in xrange(n_minibatches): sess.run(accum_ops, feed_dict=dict(X: Xs[i], y: ys[i])) sess.run(train_step) 

Pero este código no parece muy limpio y bonito, ¿alguien sabe cómo optimizar estos códigos?

Tuve el mismo problema y lo resolví.

Primero obtenga los gradientes simbólicos, luego defina los gradientes acumulados como tf.Variables. (Parece que tf.global_variables_initializer() tiene que ejecutarse antes de definir grads_accum . grads_accum errores de lo contrario, no estoy seguro de por qué).

 tvars = tf.trainable_variables() optimizer = tf.train.GradientDescentOptimizer(lr) grads = tf.gradients(cost, tvars) # initialize tf.local_variables_initializer().run() tf.global_variables_initializer().run() grads_accum = [tf.Variable(tf.zeros_like(v)) for v in grads] update_op = optimizer.apply_gradients(zip(grads_accum, tvars)) 

En la capacitación, puede acumular gradientes (guardados en gradients_accum ) en cada lote y actualizar el modelo después de ejecutar el lote número 64:

 feed_dict = dict() for i, _grads in enumerate(gradients_accum): feed_dict[grads_accum[i]] = _grads sess.run(fetches=[update_op], feed_dict=feed_dict) 

Puede referirse a tensorflow / tensorflow / python / training / optimizer_test.py para el uso de ejemplo, particularmente esta función: testGradientsAsVariables() .

Espero eso ayude.

Las soluciones anteriores no calculan el promedio de los gradientes acumulados, lo que puede provocar inestabilidad en la capacitación. He modificado el código anterior, que debería resolver este problema.

 # Fetch a list of our network's trainable parameters. trainable_vars = tf.trainable_variables() # Create variables to store accumulated gradients accumulators = [ tf.Variable( tf.zeros_like(tv.initialized_value()), trainable=False ) for tv in trainable_vars ] # Create a variable for counting the number of accumulations accumulation_counter = tf.Variable(0.0, trainable=False) # Compute gradients; grad_pairs contains (gradient, variable) pairs grad_pairs = optimizer.compute_gradients(loss, trainable_vars) # Create operations which add a variable's gradient to its accumulator. accumulate_ops = [ accumulator.assign_add( grad ) for (accumulator, (grad, var)) in zip(accumulators, grad_pairs) ] # The final accumulation operation is to increment the counter accumulate_ops.append(accumulation_counter.assign_add(1.0)) # Update trainable variables by applying the accumulated gradients # divided by the counter. Note: apply_gradients takes in a list of # (grad, var) pairs train_step = optimizer.apply_gradients( [(accumulator / accumulation_counter, var) \ for (accumulator, (grad, var)) in zip(accumulators, grad_pairs)] ) # Accumulators must be zeroed once the accumulated gradient is applied. zero_ops = [ accumulator.assign( tf.zeros_like(tv) ) for (accumulator, tv) in zip(accumulators, trainable_vars) ] # Add one last op for zeroing the counter zero_ops.append(accumulation_counter.assign(0.0)) 

Este código se utiliza de la misma manera que el proporcionado por @weixsong.