Posterior a consultar con especialistas en esta materia, programadores de diversas ramas y profesores dimos con la respuesta al problema y la compartimos en esta publicación.
Solución:
Scipy llama a la implementación original de L-BFGS-B. Que es un fortran77 (código antiguo pero hermoso y súper rápido) y nuestro problema es que la dirección de descenso en realidad está subiendo. El problema comienza en la línea 2533 (enlace al código en la parte inferior)
gd = ddot(n,g,1,d,1)
if (ifun .eq. 0) then
gdold=gd
if (gd .ge. zero) then
c the directional derivative >=0.
c Line search is impossible.
if (iprint .ge. 0) then
write(0,*)' ascent direction in projection gd = ', gd
endif
info = -4
return
endif
endif
En otras palabras, le estás diciendo que baje la colina subiendo la colina. El código intenta algo llamado búsqueda de línea un total de 20 veces en la dirección de descenso que proporciona y se da cuenta de que NO le está diciendo que vaya cuesta abajo, sino cuesta arriba. Las 20 veces.
El tipo que lo escribió (Jorge Nocedal, que por cierto es un tipo muy inteligente) puso 20 porque casi es suficiente. Machine epsilon es 10E-16, creo que 20 es en realidad un poco demasiado. Entonces, mi dinero para la mayoría de las personas que tienen este problema es que su gradiente no coincide con su función.
Ahora, también podría ser que “2. los errores de redondeo dominen el cálculo”. Con esto quiere decir que tu función es una superficie muy plana en la que los incrementos son del orden de máquina épsilon (en cuyo caso tal vez podrías reescalar la función). Ahora, estaba pensando que tal vez debería haber una tercera opción, cuando tu función es demasiado extraña. ¿Oscilaciones? Pude ver algo como $sin(frac1x)$ causando este tipo de problema. Pero no soy un tipo listo, así que no asumas que hay un tercer caso.
Así que creo que la solución del OP debería ser que su función es demasiado plana. O mira el código fortran.
https://github.com/scipy/scipy/blob/master/scipy/optimize/lbfgsb/lbfgsb.f
Aquí está la línea de búsqueda para aquellos que quieran verlo. https://en.wikipedia.org/wiki/Line_search
Nota. Esto es 7 meses demasiado tarde. Lo pongo aquí por el bien del futuro.
Como se señaló en la respuesta de Wilmer E. Henao, el problema probablemente esté en el gradiente. Ya que estás usando approx_grad=True
, el gradiente se calcula numéricamente. En este caso, la reducción del valor de epsilon
, que es el tamaño de paso utilizado para calcular numéricamente el gradiente, puede ayudar.
También recibí el error “ABNORMAL_TERMINATION_IN_LNSRCH” usando el optimizador L-BFGS-B.
Mientras que mi función de gradiente apuntaba en la dirección correcta, volví a escalar el real gradiente de la función por su norma L2. Quitar eso o agregar otro tipo apropiado de cambio de escala funcionó. Antes, supongo que el gradiente era tan grande que se salía de los límites inmediatamente.
El problema de OP fue ilimitado si leí correctamente, por lo que esto ciertamente no ayudará en la configuración de este problema. Sin embargo, al buscar en Google el error “ABNORMAL_TERMINATION_IN_LNSRCH” aparece esta página como uno de los primeros resultados, por lo que podría ayudar a otros…