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ónscipy/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.