Estoy usando TensorFlow para construir un modelo de aprendizaje profundo. Y nuevo en TensorFlow.
Por 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 variación alta.
Entonces, quiero usar algún truco para aumentar el tamaño del lote. Mi idea es almacenar los gradientes de cada minilote, por ejemplo, 64 minilotes, y luego sumar los gradientes, usar los gradientes medios de estos 64 minilotes 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 de los 64 mini lotes, 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 ciclo 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 este código?
Tuve el mismo problema y lo acabo de resolver.
Primero obtenga gradientes simbólicos, luego defina gradientes acumulados como tf.Variables. (Parece que tf.global_variables_initializer() debe ejecutarse antes de definir grads_accum . De lo contrario, obtuve errores, 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 el entrenamiento, puede acumular gradientes (guardados en gradients_accum ) en cada lote y actualizar el modelo después de ejecutar el lote 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 consultar tensorflow/tensorflow/python/training/optimizer_test.py para ver un 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 generar inestabilidad en el entrenamiento. 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 usa de la misma manera que el proporcionado por @weixsong.