tutorial net machine-learning neural-network deep-learning caffe gradient-descent

machine-learning - tutorial - net forward



Causas comunes de nans durante el entrenamiento (4)

He notado que una ocurrencia frecuente durante el entrenamiento es la introducción de NAN .

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

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

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


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

Explosión de gradiente

Motivo: los grandes gradientes 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 representada por una variable de coma flotante y se convertirá en nan .

¿Qué puedes hacer? Disminuye la 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 del aumento de gradiente y disminuir el loss_weight (en train_val.prototxt) para esa capa específica, en lugar del base_lr general.

Mala política de aprendizaje y parámetros

Motivo: caffe no puede calcular una tasa de aprendizaje válida y obtiene ''inf'' o ''nan'' , 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, debería ver que la tasa de aprendizaje se convierte en ''nan'' , por ejemplo:

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

Qué puede hacer: corrija todos los parámetros que afectan la velocidad de aprendizaje en su archivo ''solver.prototxt'' .
Por ejemplo, si usa lr_policy: "poly" y olvida definir el parámetro max_iter , 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 que aparezcan nan s. Por ejemplo, Alimentando la capa InfogainLoss con valores no normalizados , usando la 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 disminuye gradualmente y de repente aparece un nan .

Qué puede hacer: ver si puede reproducir el error, agregar una copia impresa a la capa de pérdida y depurar el error.

Por ejemplo: una vez utilicé una pérdida que normalizó la penalización por la frecuencia de aparición de la etiqueta 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 nan s. 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

Motivo: ¡tienes una entrada con nan !

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 disminuye gradualmente y de repente aparece un nan .

Qué puede hacer: reconstruir sus conjuntos de datos de entrada (lmdb / leveldn / hdf5 ...) asegúrese de no tener archivos de imágenes defectuosos en su conjunto de capacitación / 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 mayor que el tamaño del núcleo en la capa "Pooling"

Por alguna razón, elegir stride > kernel_size para la agrupación puede dar como resultado 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 algunas configuraciones, la capa "BatchNorm" puede generar nan s debido a inestabilidades numéricas.
Este issue se planteó en bvlc / caffe y issue está intentando solucionarlo.

Recientemente, me di cuenta del indicador debug_info : establecer debug_info: true en ''solver.prototxt'' hará que caffe print registre más información de depuración (incluidas las magnitudes de gradiente y los 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 .


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: valor "constante": 0}


Esta respuesta no se trata de una causa de nan s, 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 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 } }


Estaba tratando de construir un autoencoder escaso y tenía varias capas para inducir la 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 habían desaparecido. Entonces, supongo que demasiada escasez puede conducir a NaN también (¡algunos cálculos 0/0 pueden haberse invocado !?)