J'ai écrit le script suivant:
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
Mais j'ai eu ce résultat et l'erreur s'est produite:
nan
C:\Users\Desktop\test.py:16: RuntimeWarning: invalid value encountered in double_scalars
res = answer.sum()/answer1.sum()
Il semble que l'élément d'entrée soit trop petit pour que python les convertisse en zéros, mais la division a bien son résultat.
Comment résoudre ce genre de problème?
Vous ne pouvez pas le résoudre. Simplement answer1.sum()==0
, et vous ne pouvez pas effectuer de division par zéro.
Cela est dû au fait que answer1
est l'exponentielle de 2 très grands nombres négatifs, de sorte que le résultat est arrondi à zéro.
nan
est retourné dans ce cas en raison de la division par zéro.
Maintenant, pour résoudre votre problème, vous pouvez:
scipy/numpy
qui fait exactement ce que vous voulez! Découvrez la réponse de @Warren Weckesser.Ici, j’explique comment faire des manipulations mathématiques qui aident à résoudre ce problème. Nous avons cela pour le numérateur:
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)))
où ci-dessus x=3* 1089
et y=3* 1093
. Maintenant, l'argument de cette exponentielle est
-x + log(1+exp(-y+x)) = -x + 6.1441934777474324e-06
Pour le dénominateur, vous pouvez procéder de la même manière, mais obtenez que log(1+exp(-z+k))
est déjà arrondi à 0
, de sorte que l'argument de la fonction exponentielle au dénominateur est simplement arrondi à -z=-3000
. Vous avez alors que votre résultat est
exp(-x + log(1+exp(-y+x)))/exp(-z) = exp(-x+z+log(1+exp(-y+x))
= exp(-266.99999385580668)
ce qui est déjà très proche du résultat que vous obtiendriez si vous ne gardiez que les 2 termes principaux (c'est-à-dire le premier nombre 1089
dans le numérateur et le premier nombre 1000
au dénominateur):
exp(3*(1089-1000))=exp(-267)
Pour le plaisir, voyons à quelle distance nous sommes de la solution de Wolfram alpha ( lien ):
Log[(exp[-3*1089]+exp[-3*1093])/([exp[-3*1000]+exp[-3*4443])] -> -266.999993855806522267194565420933791813296828742310997510523
La différence entre ce nombre et l'exposant ci-dessus est +1.7053025658242404e-13
, donc l'approximation que nous avons faite au dénominateur était correcte.
Le résultat final est
'exp(-266.99999385580668) = 1.1050349147204485e-116
De wolfram alpha est ( lien )
1.105034914720621496.. × 10^-116 # Wolfram alpha.
et encore, il est prudent d'utiliser numpy ici aussi.
Vous pouvez utiliser np.logaddexp
(qui implémente l'idée dans la réponse 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
_
Ou vous pouvez utiliser scipy.special.logsumexp
:
_In [52]: from scipy.special import logsumexp
In [53]: res = np.exp(logsumexp(-3*d) - logsumexp(-3*e))
In [54]: res
Out[54]: 1.1050349147204485e-116
_