with what seq2seq peepholes paper neural network machine learning graves celda python machine-learning tensorflow deep-learning lstm

python - what - ¿Cómo aplicar el recorte de degradado en TensorFlow?



tensorflow neural network (6)

A pesar de lo que parece ser popular, es probable que desee recortar todo el gradiente según su norma global:

optimizer = tf.train.AdamOptimizer(1e-3) gradients, variables = zip(*optimizer.compute_gradients(loss)) gradients, _ = tf.clip_by_global_norm(gradients, 5.0) optimize = optimizer.apply_gradients(zip(gradients, variables))

Recortar cada matriz de gradiente cambia individualmente su escala relativa, pero también es posible:

optimizer = tf.train.AdamOptimizer(1e-3) gradients, variables = zip(*optimizer.compute_gradients(loss)) gradients = [ None if gradient is None else tf.clip_by_norm(gradient, 5.0) for gradient in gradients] optimize = optimizer.apply_gradients(zip(gradients, variables))

Teniendo en cuenta el código de ejemplo .

Me gustaría saber cómo aplicar el recorte de gradiente en esta red en el RNN, donde existe la posibilidad de explotar gradientes.

tf.clip_by_value(t, clip_value_min, clip_value_max, name=None)

Este es un ejemplo que podría usarse, pero ¿dónde presento esto? En la definición de RNN

lstm_cell = rnn_cell.BasicLSTMCell(n_hidden, forget_bias=1.0) # Split data because rnn cell needs a list of inputs for the RNN inner loop _X = tf.split(0, n_steps, _X) # n_steps tf.clip_by_value(_X, -1, 1, name=None)

Pero esto no tiene sentido ya que el tensor _X es la entrada y no el grad, ¿qué se debe recortar?

¿Tengo que definir mi propio optimizador para esto o hay una opción más simple?


El recorte de degradado básicamente ayuda en caso de explosión o desaparición de gradientes. Supongamos que su pérdida es demasiado alta, lo que provocará que los gradientes exponenciales fluyan a través de la red, lo que puede dar como resultado valores de Nan. Para superar esto, recortamos los gradientes dentro de un rango específico (-1 a 1 o cualquier rango según la condición).

clipped_value=tf.clip_by_value(grad, -range, +range), var) for grad, var in grads_and_vars

donde los grados _y_vars son los pares de gradientes (que calcula a través de tf.compute_gradients) y sus variables a las que se aplicarán.

Después del recorte, simplemente aplicamos su valor utilizando un optimizador. optimizer.apply_gradients(clipped_value)


El recorte de gradiente debe ocurrir después de calcular los gradientes, pero antes de aplicarlos para actualizar los parámetros del modelo. En su ejemplo, el método AdamOptimizer.minimize() maneja ambas cosas.

Para recortar sus gradientes, deberá calcularlos, recortarlos y aplicarlos explícitamente como se describe en esta sección en la documentación de la API de TensorFlow . Específicamente, deberá sustituir la llamada al método minimize() con algo como lo siguiente:

optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) gvs = optimizer.compute_gradients(cost) capped_gvs = [(tf.clip_by_value(grad, -1., 1.), var) for grad, var in gvs] train_op = optimizer.apply_gradients(capped_gvs)


En mi opinión, la mejor solución es envolver su optimizador con el decorador de estimadores de TF tf.contrib.estimator.clip_gradients_by_norm :

original_optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate) optimizer = tf.contrib.estimator.clip_gradients_by_norm(original_optimizer, clip_norm=5.0) train_op = optimizer.minimize(loss)

De esta manera, solo tiene que definir esto una vez, y no ejecutarlo después de cada cálculo de gradientes.

Documentación: https://www.tensorflow.org/api_docs/python/tf/contrib/estimator/clip_gradients_by_norm


Esto se explica correctamente en la documentación. :

Llamar a minim () se encarga tanto de calcular los gradientes como de aplicarlos a las variables. Si desea procesar los gradientes antes de aplicarlos, puede utilizar el optimizador en tres pasos:

  • Calcule los gradientes con compute_gradients ().
  • Procese los gradientes como desee.
  • Aplique los gradientes procesados ​​con apply_gradients ().

Y en el ejemplo que proporcionan, usan estos 3 pasos:

# Create an optimizer. opt = GradientDescentOptimizer(learning_rate=0.1) # Compute the gradients for a list of variables. grads_and_vars = opt.compute_gradients(loss, <list of variables>) # grads_and_vars is a list of tuples (gradient, variable). Do whatever you # need to the ''gradient'' part, for example cap them, etc. capped_grads_and_vars = [(MyCapper(gv[0]), gv[1]) for gv in grads_and_vars] # Ask the optimizer to apply the capped gradients. opt.apply_gradients(capped_grads_and_vars)

Aquí MyCapper es cualquier función que MyCapper su gradiente. La lista de funciones útiles (aparte de tf.clip_by_value() ) está here .


Para aquellos que deseen comprender la idea del recorte de degradado (por norma):

Siempre que la norma de gradiente sea mayor que un umbral particular, recortamos la norma de gradiente para que permanezca dentro del umbral. Este umbral a veces se establece en 5 .

Deje que el gradiente sea g y el max_norm_threshold sea j .

Ahora, si || g || > j , hacemos:

g = ( j * g ) / || g ||

Esta es la implementación realizada en tf.clip_by_norm