Causas comunes de nans durante el entrenamiento


He notado que una ocurrencia frecuente durante el entrenamiento se está introduciendo NAN.

Muchas veces parece ser introducido por pesos en capas de producto interno/completamente conectadas o de convolución que explotan.

¿Ocurre esto porque el cálculo del gradiente está explotando? ¿O es debido a la inicialización de peso (si es así, por qué la inicialización de peso tiene este efecto)? ¿O es probablemente causada por la naturaleza de los datos de entrada?

La cuestión general aquí es simplemente: ¿Cuál es la razón más común para que las NAN ocurran durante el entrenamiento? Y en segundo lugar, ¿cuáles son algunos métodos para combatir esto (y por qué funcionan)?

Author: Shai, 2015-11-27

4 answers

Buena pregunta.
Me encontré con este fenómeno varias veces. Aquí están mis observaciones:


Gradiente explotar

Motivo: los gradientes grandes desvían el proceso de aprendizaje.

Lo que debe esperar: Mirando el registro de tiempo de ejecución, debe mirar los valores de pérdida por iteración. Notarás que la pérdida comienza a crecer significativamente de iteración a iteración, eventualmente la pérdida será demasiado grande para ser representado por una variable de punto flotante y se convertirá en nan.

Qué puedes hacer: Disminuye el base_lr (en el solucionador.prototxt) por un orden de magnitud (al menos). Si tiene varias capas de pérdida, debe inspeccionar el registro para ver qué capa es responsable de la explosión del gradiente y disminuir el loss_weight (en train_val.prototxt) para esa capa específica, en lugar de la general base_lr.


Mala política de tasas de aprendizaje y parámetros

Razón: caffe no puede calcular una tasa de aprendizaje válida y obtiene 'inf' o 'nan' en su lugar, esta tasa no válida multiplica todas las actualizaciones y, por lo tanto, invalida todos los parámetros.

Lo que debería esperar: Mirando el registro de tiempo de ejecución, debería ver que la tasa de aprendizaje en sí misma se convierte en 'nan', por ejemplo:

... sgd_solver.cpp:106] Iteration 0, lr = -nan

Qué puedes hacer: corrige todos los parámetros que afectan la tasa de aprendizaje en tu archivo 'solver.prototxt'.
Por ejemplo, si usas lr_policy: "poly" y te olvidas de definir el parámetro max_iter, terminarás con lr = nan...
Para obtener más información sobre la tasa de aprendizaje en caffe, consulte este hilo.


Función de pérdida defectuosa

Razón: A veces los cálculos de la pérdida en las capas de pérdida hacen que nan aparezcan. Por ejemplo, La alimentación InfogainLoss capa con valores no normalizados , usando capa de pérdida personalizada con errores, etc.

Lo que usted debe esperar: Mirando el registro de tiempo de ejecución probablemente no notará nada inusual: la pérdida está disminuyendo gradualmente, y de repente aparece un nan.

Qué puede hacer: Vea si puede reproducir el error, agregar impresión a la capa de pérdida y depurar el error.

Por ejemplo: Una vez utilicé una pérdida que normalizaba la penalización por la frecuencia de ocurrencia de la etiqueta en un lote. Simplemente sucedió que si una de las etiquetas de entrenamiento no aparecía en el lote , la pérdida computed produced nans. En ese caso, trabajar con lotes lo suficientemente grandes (con respecto al número de etiquetas en el conjunto) fue suficiente para evitar este error.


Entrada defectuosa

Razón: usted tiene una entrada con nan en ella!

Lo que debe esperar: una vez que el proceso de aprendizaje "golpea" esta entrada - salida defectuosa se convierte en nan. Mirando el registro de tiempo de ejecución, probablemente no notará nada inusual: la pérdida está disminuyendo gradualmente, y de repente aparece un nan.

Qué puede hacer: vuelva a construir sus conjuntos de datos de entrada (lmdb/leveldn/hdf5...) asegúrese de no tener archivos de imagen defectuosos en su conjunto de entrenamiento/validación. Para depurar puede construir una red simple que lea la capa de entrada, tenga una pérdida ficticia encima y se ejecute a través de todas las entradas: si una de ellas es defectuosa, esta red ficticia también debería producir nan.


Zancada mayor que el tamaño del núcleo en "Pooling" capa

Por alguna razón, elegir stride > kernel_size para la agrupación puede resultados con nan s. Por ejemplo:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

Resultados con nan s en y.


Inestabilidades en "BatchNorm"

Se informó que bajo algunos ajustes "BatchNorm" capa puede salida nans debido a inestabilidades numéricas.
Este problema se planteó en bvlc/caffe y PR #5136 está tratando de solucionarlo.


Recientemente, me di cuenta de debug_info bandera: establecer debug_info: true en 'solver.prototxt' hará que caffe imprimir para registrar más información de depuración (incluyendo magnitudes de gradiente y valores de activación) durante el entrenamiento: Esta información puede ayudar a detectar explosiones de gradiente y otros problemas en el proceso de entrenamiento.

 86
Author: Shai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:38

En mi caso, no establecer el sesgo en las capas de convolución/deconvolución fue la causa.

Solución: agregue lo siguiente a los parámetros de la capa de convolución.

Bias_filler { tipo: "constante" valor: 0 }

 3
Author: izady,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-11 20:24:44

Esta respuesta no se trata de una causa para nans, sino que propone una forma de ayudar a depurarla. Puedes tener esta capa de python:

class checkFiniteLayer(caffe.Layer):
  def setup(self, bottom, top):
    self.prefix = self.param_str
  def reshape(self, bottom, top):
    pass
  def forward(self, bottom, top):
    for i in xrange(len(bottom)):
      isbad = np.sum(1-np.isfinite(bottom[i].data[...]))
      if isbad>0:
        raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" %
                        (self.prefix,i,100*float(isbad)/bottom[i].count))
  def backward(self, top, propagate_down, bottom):
    for i in xrange(len(top)):
      if not propagate_down[i]:
        continue
      isf = np.sum(1-np.isfinite(top[i].diff[...]))
        if isf>0:
          raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" %
                          (self.prefix,i,100*float(isf)/top[i].count))

Agregar esta capa a su train_val.prototxt en ciertos puntos que sospecha que puede causar problemas:

layer {
  type: "Python"
  name: "check_loss"
  bottom: "fc2"
  top: "fc2"  # "in-place" layer
  python_param {
    module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH
    layer: "checkFiniteLayer"
    param_str: "prefix-check_loss" # string for printouts
  }
}
 2
Author: Shai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-23 10:53:59

Estaba tratando de construir un autoencoder disperso y tenía varias capas para inducir la dispersión. Al eliminar algunas de las capas (en mi caso, en realidad tuve que eliminar 1), descubrí que las NaN desaparecieron. Por lo tanto, supongo que demasiada escasez puede conducir a NaN también (algunos cálculos 0/0 pueden haber sido invocados!?)

 -1
Author: LKB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-20 09:39:14