Pregunta ¿Cómo se pueden depurar los valores de NaN en TensorFlow?


Estaba ejecutando TensorFlow y tengo algo que cede un NaN. Me gustaría saber de qué se trata, pero no sé cómo hacer esto. El problema principal es que en un programa de procedimiento "normal" solo escribiría una declaración impresa justo antes de que se ejecute la operación. El problema con TensorFlow es que no puedo hacer eso porque primero declaro (o defino) el gráfico, por lo que agregar declaraciones de impresión a la definición del gráfico no ayuda. ¿Hay reglas, consejos, heurística, cualquier cosa para rastrear lo que podría estar causando el NaN?


En este caso, sé más precisamente qué línea mirar porque tengo lo siguiente:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 

cuando esta línea está presente, tengo que devuelve NaN según lo declarado por mis escritores de resumen. ¿Por qué es esto? ¿Hay alguna forma de, al menos, explorar qué valor tiene Z después de estar enraizado?


Para el ejemplo específico que publiqué, lo intenté tf.Print(0,Z) pero sin éxito no imprimió nada. Como en:

Delta_tilde = 2.0*tf.matmul(x,W) - tf.add(WW, XX) #note this quantity should always be positive because its pair-wise euclidian distance
Z = tf.sqrt(Delta_tilde)
tf.Print(0,[Z]) # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)
A = tf.exp(Z) 

De hecho, no entiendo qué tf.Print se supone que hacer. ¿Por qué necesita dos argumentos? Si quiero imprimir 1 tensor ¿por qué debería pasar 2? Me parece extraño.


Estaba viendo la función tf.add_check_numerics_ops () pero no dice cómo usarlo (además, los documentos parecen no ser muy útiles). ¿Alguien sabe cómo usar esto?


Como he tenido comentarios para abordar los datos pueden ser malos, estoy usando MNIST estándar. Sin embargo, estoy calculando una cantidad que es positiva (distancia euclediana por pares) y luego la raíz cuadrada. Por lo tanto, no veo cómo los datos específicamente serían un problema.


32
2017-08-07 02:47


origen


Respuestas:


Hay un par de razones POR LAS que puede obtener un resultado NaN, a menudo es debido a una tasa de aprendizaje demasiado alta, pero existen muchos otros motivos, como por ejemplo datos corruptos en su cola de entrada o un registro de 0 cálculos.

De todos modos, la depuración con una impresión como se describe no se puede hacer con una simple impresión (ya que esto solo daría como resultado la impresión de la información del tensor dentro del gráfico y no imprimiría ningún valor real).

Sin embargo, si usa tf.print como una operación para construir el gráfico (tf.print) luego, cuando se ejecuta el gráfico obtendrá los valores reales impresos (y ES un buen ejercicio observar estos valores para depurar y comprender el comportamiento de su red).

Sin embargo, está utilizando la declaración de impresión no del todo de la manera correcta. Esto es una operación, por lo que debe pasarle un tensor y solicitar un tensor de resultados con el que deba trabajar más adelante en el gráfico de ejecución. De lo contrario, el op no se ejecutará y no se imprimirá. Prueba esto:

Z = tf.sqrt(Delta_tilde)
Z = tf.Print(Z,[Z], message="my Z-values:") # <-------- TF PRINT STATMENT
Z = Transform(Z) # potentially some transform, currently I have it to return Z for debugging (the identity)
Z = tf.pow(Z, 2.0)

17
2017-08-09 07:49



Parece que puede llamarlo después de completar la creación del gráfico.

check = tf.add_check_numerics_ops()

Creo que esto agregará el cheque para todas las operaciones de coma flotante. Luego, en la función de ejecución de sesiones, puede agregar la operación de verificación.

sess.run([check, ...])


8
2017-08-07 11:08



A partir de la versión 0.12, TensorFlow se envía con un depurador incorporado llamado tfdbg. Optimiza el flujo de trabajo de depuración de este tipo de problemas de valor numérico malo (como infy nan) La documentación está en: https://www.tensorflow.org/programmers_guide/debugger


5
2017-12-16 20:21



En primer lugar, debe verificar que ingresó los datos correctamente. En la mayoría de los casos, esta es la razón. Pero no siempre, por supuesto.

Usualmente uso Tensorboard para ver qué pasa mientras entreno. Para que pueda ver los valores en cada paso con

Z = tf.pow(Z, 2.0)    
summary_z = tf.scalar_summary('z', Z) 
#etc..
summary_merge = tf.merge_all_summaries()
#on each desired step save: 
    summary_str = sess.run(summary_merge)
    summary_writer.add_summary(summary_str, i)

También puede simplemente evaluar e imprimir el valor actual:

 print(sess.run(Z))

1
2017-08-09 08:22



Solía ​​encontrar que es mucho más difícil determinar dónde pueden ocurrir los nans y los infs que corregir el error. Como complemento a la respuesta de @ scai, me gustaría agregar algunos puntos aquí:

El módulo de depuración, puede ser importado por:

from tensorflow.python import debug as tf_debug

es mucho mejor que cualquier impresión o afirmación.

Puede simplemente agregar la función de depuración cambiando su sesión contenedora por:

sess = tf_debug.LocalCLIDebugWrapperSession(sess)
sess.add_tensor_filter("has_inf_or_nan", tf_debug.has_inf_or_nan)

Y solicitarás una interfaz de línea de comando, luego ingresas: run -f has_inf_or_nany lt -f has_inf_or_nan para encontrar dónde están los nans o infs. El primero es el primer lugar donde ocurre la catástrofe. Por el nombre de la variable puede rastrear el origen en su código.

Referencia: https://developers.googleblog.com/2017/02/debug-tensorflow-models-with-tfdbg.html


1
2018-02-11 07:25



Implementación actual de tfdbg.has_inf_or_nan parece que no se rompe inmediatamente al golpear cualquier tensor que contenga NaN. Cuando se detiene, la enorme lista de tensores que se muestran son no ordenados en orden de su ejecución. Un posible truco para encontrar la primera aparición de Nans es descargar todos los tensores a un directorio temporal e inspeccionarlos después. Aquí hay un rápido y sucio ejemplo Para hacer eso. (Suponiendo que NaNs aparecen en las primeras carreras)


0
2018-05-15 13:16