Causas comunes de nans durante el entrenamiento

85

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

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

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

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

Aidan Gómez
fuente
¿Está llamando a funciones específicas de MATLAB? ¿Es todo tu propio código?
Matthew Gunn
2
@MatthewGunn No creo que esta pregunta sea específica de Matlab, sino más bien cafferelacionada.
Shai

Respuestas:

134

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: en el registro de tiempo de ejecución, debe observar los valores de pérdida por iteración. Notará que la pérdida comienza a crecer significativamente de una iteración a otra, eventualmente la pérdida será demasiado grande para ser representada por una variable de punto flotante y se convertirá en nan.

Qué puede hacer: Disminuya el base_lr(en el solver.prototxt) en 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 loss_weight(en train_val.prototxt) para esa capa específica, en lugar de la general base_lr.


Política y parámetros de mala tasa de aprendizaje

Motivo: caffe no calcula 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 debe esperar: al observar el registro de tiempo de ejecución, debe ver que la tasa de aprendizaje en sí se convierte 'nan', por ejemplo, en:

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

Qué puede hacer: corrija todos los parámetros que afectan la tasa de aprendizaje en su 'solver.prototxt'archivo.
Por ejemplo, si usa lr_policy: "poly"y se olvida de definir el max_iterparámetro, terminará 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

Motivo: A veces, los cálculos de la pérdida en las capas de pérdida hacen nanque aparezca s. Por ejemplo, InfogainLosscapa de alimentación con valores no normalizados , uso de capa de pérdida personalizada con errores, etc.

Lo que debe esperar: al mirar el registro de tiempo de ejecución, probablemente no notará nada inusual: la pérdida está disminuyendo gradualmente y, de repente, nanaparece a.

Qué puede hacer: vea si puede reproducir el error, agregue la impresión a la capa de pérdida y depure el error.

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


Entrada defectuosa

Razón: ¡tienes una entrada nanen él!

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

Qué puede hacer: reconstruya 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 la depuración, puede construir una red simple que lea la capa de entrada, tenga una pérdida ficticia encima y recorra todas las entradas: si una de ellas es defectuosa, esta red ficticia también debería producir nan.


zancada más grande que el tamaño del grano en la "Pooling"capa

Por alguna razón, elegir stride> kernel_sizepara agrupar puede resultar con nans. Por ejemplo:

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

resultados con nans en y.


Inestabilidades en "BatchNorm"

Se informó que, en algunas configuraciones, la "BatchNorm"capa puede generar nanmensajes de correo electrónico debido a inestabilidades numéricas.
Este problema se planteó en bvlc / caffe y el PR # 5136 está intentando solucionarlo.


Recientemente, me di cuenta de debug_infoflag: setting debug_info: truein 'solver.prototxt'hará que caffe print registre más información de depuración (incluidas 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 .

Shai
fuente
Gracias, ¿cómo se interpretan esos números? ¿Cuáles son estos números? pastebin.com/DLYgXK5v ¿por qué hay solo un número por salida de capa? ¿Cómo deberían verse esos números para que alguien sepa que hay un problema o que no lo hay?
Rika
@Hossein, esto es exactamente de lo que trata esta publicación .
Shai
Gracias por esta respuesta. Recibo pérdida de NAN para una aplicación de segmentación de imágenes entrenada con pérdida DICE (incluso después de agregar una pequeña constante de epsilon / suavidad). Mi conjunto de datos contiene algunas imágenes cuya verdad fundamental correspondiente que no contienen ninguna etiqueta de primer plano y cuando eliminé estas imágenes del entrenamiento, la pérdida se estabilizó. No estoy seguro de por qué es eso.
samra irshad
@samrairshad, ¿ha intentado aumentar el épsilon en la pérdida de DICE?
Shai
Sí, lo hice. Abrí la publicación en stack-overflow y pegué la evolución de pérdidas para algunas épocas. Aquí está la referencia: stackoverflow.com/questions/62259112/…
samra irshad
5

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

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

bias_filler {tipo: valor "constante": 0}

izady
fuente
¿Cómo se vería eso en matconvnet? Tengo algo como 'sesgos'.init_bias * ones (1,4, single)
h612
4

Esta respuesta no se trata de una causa para nans, sino que propone una forma de ayudar a depurarlo. 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.prototxten ciertos puntos que sospecha 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
  }
}
Shai
fuente
1

learning_rate es alto y debe reducirse La precisión en el código RNN fue nan, con seleccione el valor bajo para la tasa de aprendizaje que corrige

Mohammad Rasoul tanhatalab
fuente
-1

Estaba tratando de construir un codificador automático escaso y tenía varias capas para inducir escasez. Mientras ejecutaba mi red, me encontré con los NaN. Al eliminar algunas de las capas (en mi caso, tuve que eliminar 1), descubrí que los NaN desaparecieron. Entonces, supongo que demasiada escasez también puede conducir a NaN (¿¡algunos cálculos 0/0 pueden haber sido invocados !?)

LKB
fuente
¿Podrías ser un poco más específico? ¿Puede proporcionar detalles sobre la configuración que tenía nansy la configuración fija? que tipo de capas? que parámetros?
Shai
1
@shai Había usado varias capas de InnerProduct (lr_mult 1, decay_mult 1, lr_mult 2, decay_mult 0, xavier, std: 0.01) cada una seguida de ReLU (excepto la última). Estaba trabajando con MNIST, y si mal no recuerdo, la arquitectura era 784 -> 1000 -> 500 -> 250 -> 100 -> 30 (y una fase de decodificador simétrico); quitar la capa 30 junto con su ReLU hizo desaparecer los NaN.
LKB