Comprobación numérica de gradiente: ¿qué tan cerca está lo suficientemente cerca?

8

Hice una red neuronal convolucional y quería comprobar que mis gradientes se calculan correctamente utilizando la comprobación numérica de gradiente. La pregunta es, ¿qué tan cerca está lo suficientemente cerca?

Mi función de verificación solo escupe la derivada calculada, la derivada aproximada numéricamente, la diferencia entre los dos y si los dos valores tienen o no el mismo signo (uno es positivo y el otro negativo es un gran no-no) para cada uno peso.

La principal preocupación que tengo es que para todas las capas completamente conectadas y todas las capas convolucionales, excepto la primera, las diferencias se ven similares: los primeros 9-13 caracteres de los dos números coincidirán. Eso suena bastante bien, ¿verdad? Pero para los pesos de la primera capa convolucional, a veces obtengo hasta 12 decimales para que coincidan, pero también puede ser tan bajo como solo 3. ¿Es eso suficiente o podría haber un posible error?

Una cosa buena a tener en cuenta es que el signo de los dos valores siempre coincide, lo que es bueno, por lo que la red siempre hará movimientos en la dirección correcta, incluso si la magnitud del movimiento es un poco diferente. Pero esa es la pregunta ... ¿hay alguna posibilidad de que esté apagado?

Frobot
fuente

Respuestas:

9

Lo más cerca que he visto de abordar esto fue en el tutorial de Stanford UFLDL dentro de la sección de regresión de softmax . Copiando la declaración clave:

La norma de la diferencia entre el gradiente numérico y su gradiente analítico debe ser pequeña, del orden de .109

En python, el código se vería así:

norm(gradients - numericalGradients)/norm(gradients + numericalGradients)

¿dónde gradientsestán los resultados de la derivada y numericalGradientsson los gradientes aproximados?

cdeterman
fuente
Gracias, ¿qué pasa si mis gradientes se almacenan en una matriz de matriz 2D? Después de restar 2 matrices entre sí, ¿cómo debo evaluar la norma de la matriz de "diferencia" resultante?
Kari
1
@Kari Los aplanaría en vectores y usaría el mismo código que se muestra arriba. Por ejemplo, si tiene una matriz numpy, podría usar el flattenmétodo.
cdeterman
7

Teoría de antecedentes que es útil

Un pequeño hecho que puede usar para ayudar a comprender si una derivada numérica se calcula correctamente o no es el resto Cauchy de la expansión de Taylor. Es decir,

f(x+h)=f(x)+hf(x)+h22f(ξ) para algunosξ[x,x+h]

Esto es útil, porque probablemente haya aproximado su primera derivada por

f(x)f(x+h)f(xh)2h

con un poco de (normalmente uso , pero estoy seguro de que algún día me encontraré con un caso en el que no es apropiado).h104

Después de un poco de álgebra, podemos usar el resto de Cauchy para ver que nuestra aproximación numérica en teoría debería estar dentro de de .hf(ξ),ξ[xh,x+h]f(x)

De hecho, puedes vincularlo con , donde y ... que es equivalente a , .h(f(ξ1)f(ξ2))ξ1[xh,x]ξ2[x,x+h]h2f(ξ)ξ[xh,x+h]

Problemas en la práctica

De acuerdo, tenemos una buena teoría que limita el error de la derivada numérica. Pero hay dos agujeros en tratar directamente de usar esos resultados:

1.) No sabemos (y probablemente no queremos pasar el tiempo aproximándolo)f(x)

2.) como , sufre de inestabilidad numéricah0f(x+h)f(xh)2h

Entonces, usando lo que sabemos de la forma en que verifico mis derivadas analíticas (que podría no ser la mejor manera) es escribir la función de derivada numérica como una función de . Si no puedo decir si la diferencia entre las derivadas numéricas y analíticas se debe a un error de codificación o simplemente a una aproximación numérica, puedo reducir y ver si mi derivada numérica se acerca a mi derivada analítica antes de sufrir inestabilidad numérica (cuando esto sucede, sus aproximaciones numéricas serán menos consistentes a medida que haga más pequeña). Tenga en cuenta que el término debería desaparecer cuadráticamente, por lo que si mi error es aproximadamente conhhhf(ξ)0.01h=104 , debe estar alrededor de con suponiendo que la inestabilidad numérica aún no haya comenzado .0.0001h=105

Desafortunadamente, no hay una guía dura y rápida para determinar siempre estas cosas; depende mucho de cuán estable sea la función (y me refiero a ambos en términos de estabilidad numérica y derivados más altos). Pero en mi experiencia, nunca he visto un caso en el que el error de no fuera definitivamente a 0 (es decir, usar dio prácticamente la misma respuesta que ) para cuando la inestabilidad numérica de entró en acción.h2f(ξ)h=104h=105h0

Acantilado
fuente
5

Consulte este tutorial http://cs231n.github.io/neural-networks-3/#ensemble . La sección "Verificación de degradado" es muy detallada y útil.

Como sugiere gung, incluyo los puntos principales de este enlace:

  • Utilice aproximación, donde .f(w+h)f(wh)2hh105

  • Monitoree la fracción de , donde es el gradiente analítico y es el gradiente numéricamente aproximado. Por lo general, el rango preferido de esta fracción debería ser .|fa(w)fn(w)|max(|fa(w)|,|fn(w)|)fa(w)fn(w)<102

  • Use doble precisión en lugar de flotación.

  • Mente de torcedura (s) en las funciones de activación, por ejemplo, cuando uno usa ReLU. Cuando hay torceduras, uno necesita monitorear los valores de y . Si estos dos valores están en dos lados de un pliegue, uno debería excluir esta verificación de gradiente.x=0xhx+h

  • Use pocos puntos de datos.

  • No verifique el gradiente en la etapa inicial del proceso de capacitación.

  • Primero verifique el modelo sin regularización y luego con él.

  • Apague el abandono y el abandono invertido al hacer la verificación de gradiente.

  • Solo verifique al azar algunas dimensiones.

Fengchong Wang
fuente