Ik wil numpy.exp
als volgt gebruiken:
cc = np.array([
[0.120,0.34,-1234.1]
])
print 1/(1+np.exp(-cc))
Maar dit geeft me een foutmelding:
/usr/local/lib/python2.7/site-packages/ipykernel/__main__.py:5: RuntimeWarning: overflow encountered in exp
Ik begrijp niet waarom? Hoe kan ik dit oplossen? Het lijkt erop dat het probleem zit in het derde nummer (-1234.1)
Antwoord 1, autoriteit 100%
Zoals Fuglede zegt, is het probleem hier dat np.float64
een getal zo groot als exp(1234.1)
niet aankan. Probeer in plaats daarvan np.float128
te gebruiken:
>>> cc = np.array([[0.120,0.34,-1234.1]], dtype=np.float128)
>>> cc
array([[ 0.12, 0.34, -1234.1]], dtype=float128)
>>> 1 / (1 + np.exp(-cc))
array([[ 0.52996405, 0.58419052, 1.0893812e-536]], dtype=float128)
Houd er echter rekening mee dat er bepaalde eigenaardigheden zijn bij het gebruik van uitgebreide precisie. Het werkt mogelijk niet op Windows; je krijgt niet de volledige 128 bits precisie; en je zou de precisie kunnen verliezen wanneer het nummer door pure python gaat. U kunt hiermeer lezen over de details.
Voor de meeste praktische doeleinden kunt u 1 / (1 + <a large number>)
waarschijnlijk op nul schatten. Dat wil zeggen, negeer de waarschuwing en ga verder. Numpy zorgt voor de benadering voor u (bij gebruik van np.float64
):
>>> 1 / (1 + np.exp(-cc))
/usr/local/bin/ipython3:1: RuntimeWarning: overflow encountered in exp
#!/usr/local/bin/python3.4
array([[ 0.52996405, 0.58419052, 0. ]])
Als je de waarschuwing wilt onderdrukken, kun je scipy.special.expit
, zoals voorgesteld door WarrenWeckesser in een reactie op de vraag:
>>> from scipy.special import expit
>>> expit(cc)
array([[ 0.52996405, 0.58419052, 0. ]])
Antwoord 2, autoriteit 38%
De grootste waarde die kan worden weergegeven door een numpy
float is 1.7976931348623157e+308, waarvan de logaritme ongeveer 709.782 is, dus er is geen manier om np.exp(1234.1)
weer te geven .
In [1]: import numpy as np
In [2]: np.finfo('d').max
Out[2]: 1.7976931348623157e+308
In [3]: np.log(_)
Out[3]: 709.78271289338397
In [4]: np.exp(709)
Out[4]: 8.2184074615549724e+307
In [5]: np.exp(710)
/usr/local/bin/ipython:1: RuntimeWarning: overflow encountered in exp
#!/usr/local/bin/python3.5
Out[5]: inf
Antwoord 3, autoriteit 9%
Een mogelijke oplossing is om de module decimal
te gebruiken, waarmee je met willekeurige precisie-floats kunt werken. Hier is een voorbeeld waarbij een numpy
array van floats met een precisie van 100 cijfers wordt gebruikt:
import numpy as np
import decimal
# Precision to use
decimal.getcontext().prec = 100
# Original array
cc = np.array(
[0.120,0.34,-1234.1]
)
# Fails
print(1/(1 + np.exp(-cc)))
# New array with the specified precision
ccd = np.asarray([decimal.Decimal(el) for el in cc], dtype=object)
# Works!
print(1/(1 + np.exp(-ccd)))
Antwoord 4, autoriteit 6%
exp(-1234.1) is te klein voor 32-bits of 64-bits drijvende-kommagetallen. Omdat het niet kan worden weergegeven, geeft numpy de juiste waarschuwing.
Met behulp van IEEE 754 32bit floating-point
getallen, is het kleinste positieve getal dat het kan vertegenwoordigen 2^(-149)
, wat ongeveer 1e-45 is.
Als u IEEE 754 64 bit floating-point
getallen gebruikt, is het kleinste positieve getal 2^(-1074)
, wat ruwweg 1e-327 is.
In beide gevallen kan het geen getal vertegenwoordigen dat zo klein is als exp(-1234.1) wat ongeveer 1e-535 is.
U zou de functie expit
van scipy moeten gebruiken om de sigmoid-functie te berekenen. Dit zou je een betere precisie geven.
Voor praktische doeleinden is exp(-1234.1) een heel klein getal. Als afronden naar nul zinvol is in uw gebruiksscenario, levert numpy goedaardige resultaten op door het naar nul af te ronden.
Antwoord 5
Als je niet om precisie geeft, kun je numpy.clip
gebruiken.
In float64
:
cc = np.clip(cc, -709.78, 709.78)
In float32
:
cc = np.clip(cc, -88.72, 88.72)