with warning quitar off mostrar eliminar catch_warnings python numpy warnings

quitar - warning off python



división numpy con RuntimeWarning: valor no válido encontrado en double_scalars (2)

Puede usar np.logaddexp (que implementa la idea en la respuesta de @gg349):

In [33]: d = np.array([[1089, 1093]]) In [34]: e = np.array([[1000, 4443]]) In [35]: log_res = np.logaddexp(-3*d[0,0], -3*d[0,1]) - np.logaddexp(-3*e[0,0], -3*e[0,1]) In [36]: log_res Out[36]: -266.99999385580668 In [37]: res = exp(log_res) In [38]: res Out[38]: 1.1050349147204485e-116

O puede usar scipy.misc.logsumexp :

In [52]: from scipy.misc import logsumexp In [53]: res = np.exp(logsumexp(-3*d) - logsumexp(-3*e)) In [54]: res Out[54]: 1.1050349147204485e-116

Escribí el siguiente guión:

import numpy d = numpy.array([[1089, 1093]]) e = numpy.array([[1000, 4443]]) answer = numpy.exp(-3 * d) answer1 = numpy.exp(-3 * e) res = answer.sum()/answer1.sum() print res

Pero obtuve este resultado y con el error ocurrido:

nan C:/Users/Desktop/test.py:16: RuntimeWarning: invalid value encountered in double_scalars res = answer.sum()/answer1.sum()

Parece ser que el elemento de entrada era demasiado pequeño para que Python los convirtiera en ceros, pero de hecho la división tiene su resultado.

¿Cómo resolver este tipo de problema?


no puedes resolverlo Simplemente answer1.sum()==0 , y no puede realizar una división por cero.

Esto sucede porque answer1 es el exponencial de 2 números negativos muy grandes, de modo que el resultado se redondea a cero.

nan se devuelve en este caso debido a la división por cero.

Ahora para resolver su problema usted podría:

  • vaya a una biblioteca de matemáticas de alta precisión, como mpmath . Pero eso es menos divertido.
  • como alternativa a un arma más grande, haz algo de manipulación matemática, como se detalla a continuación.
  • scipy/numpy función scipy/numpy medida que hace exactamente lo que quieres! Mira la respuesta de @Warren Weckesser.

Aquí explico cómo hacer algo de manipulación matemática que ayuda con este problema. Tenemos eso para el numerador:

exp(-x)+exp(-y) = exp(log(exp(-x)+exp(-y))) = exp(log(exp(-x)*[1+exp(-y+x)])) = exp(log(exp(-x) + log(1+exp(-y+x))) = exp(-x + log(1+exp(-y+x)))

donde arriba x=3* 1089 y=3* 1093 . Ahora, el argumento de esta exponencial es

-x + log(1+exp(-y+x)) = -x + 6.1441934777474324e-06

Para el denominador puede proceder de manera similar, pero obtenga ese log(1+exp(-z+k)) ya está redondeado a 0 , de modo que el argumento de la función exponencial en el denominador simplemente se redondea a -z=-3000 . Entonces tienes que tu resultado es

exp(-x + log(1+exp(-y+x)))/exp(-z) = exp(-x+z+log(1+exp(-y+x)) = exp(-266.99999385580668)

que ya está muy cerca del resultado que obtendría si tuviera solo los 2 términos principales (es decir, el primer número 1089 en el numerador y el primer número en el denominador):

exp(3*(1089-1000))=exp(-267)

Por el bien de él, veamos cuán cerca estamos de la solución de Wolfram alpha ( link ):

Log[(exp[-3*1089]+exp[-3*1093])/([exp[-3*1000]+exp[-3*4443])] -> -266.999993855806522267194565420933791813296828742310997510523

La diferencia entre este número y el exponente anterior es +1.7053025658242404e-13 , por lo que la aproximación que hicimos en el denominador fue correcta.

El resultado final es

''exp(-266.99999385580668) = 1.1050349147204485e-116

De Wolfram alfa es ( link )

1.105034914720621496.. × 10^-116 # Wolfram alpha.

y de nuevo, es seguro usar numpy aquí también.