问题
I'm using the warnings
module to raise warnings as errors.
When I call my function plot_fig_4
, I get the following error:
In [5]: plot_amit.plot_fig_4()
g: 1 of 3
theta_E: 1 of 1000
---------------------------------------------------------------------------
RuntimeWarning Traceback (most recent call last)
<ipython-input-5-5a631d2493d7> in <module>()
----> 1 plot_amit.plot_fig_4()
/home/dan/Science/dopa_net/plot_amit.pyc in plot_fig_4()
130 tau_0, tau,
131 theta_E_,
--> 132 H)
133
134 # Iterate through theta_I, starting at the lowest value.
/home/dan/Science/dopa_net/plot_support.py in _get_d_phi(mu, sigma, tau_0, tau_i, theta_i, H)
2059 for (i, mu_), (j, sigma_) in itertools.product(enumerate(mu),
2060 enumerate(sigma)):
-> 2061 phi[i, j] = _get_phi(tau_0, tau_i, theta_i, mu_, sigma_, H)
2062 import pdb
2063 pdb.set_trace()
/home/dan/Science/dopa_net/plot_support.py in _get_phi(tau_0, tau, theta_over_J, mu_over_J, sigma_over_J, H)
1835
1836 # Compute the integral.
-> 1837 integral = _integrate_little_phi(lower, alpha)
1838
1839 # Compute phi.
/home/dan/Science/dopa_net/plot_support.py in _integrate_little_phi(lower, upper)
1869 upper_int = _integrate(upper)
1870 lower_int = _integrate(lower)
-> 1871 return upper_int - lower_int
1872
1873
RuntimeWarning: invalid value encountered in double_scalars
OK. So I stick a pdb.set_trace
inside _integrate_little_phi
, just before the line at which the error is raised, re-run, and inspect the values of the relevant variables:
In [7]: plot_amit.plot_fig_4()
g: 1 of 3
theta_E: 1 of 1000
> /home/dan/Science/dopa_net/plot_support.py(1873)_integrate_little_phi()
-> return upper_int - lower_int
(Pdb) upper_int
inf
(Pdb) lower_int
inf
(Pdb) type(upper_int)
<type 'numpy.float64'>
(Pdb) type(lower_int)
<type 'numpy.float64'>
Huh. So the error was raised because I was subtracting infinity from infinity. Can I replicate that?
(Pdb) upper_int - lower_int
*** RuntimeWarning: invalid value encountered in double_scalars
Yes. But wait a minute. Let's try one more thing:
(Pdb) np.inf
inf
(Pdb) type(np.inf)
<type 'float'>
(Pdb) np.inf - np.inf
nan
What the what? When I directly subtract infinity from infinity using np.inf
(where np
is numpy
), I get nan
, not the RuntimeWarning
.
Why do I get nan
in this instance and RuntimeWarning
in the other? I have posted the difference in type (float
versus float64
) deliberately. The question is, why do these (trivially) different types produce different results?
回答1:
Because in the case of np.inf
, the type is float
(the basic datatype) , whereas in case of upper_int
/ lower_int
the data type is numpy.float64
. Similar issue can be reproduced by -
In [7]: a = np.float64('inf')
In [8]: type(a)
Out[8]: numpy.float64
In [9]: a - a
RuntimeWarning: invalid value encountered in double_scalars
if __name__ == '__main__':
Out[9]: nan
For the case of np.inf
/ float
-
In [3]: float('inf') - float('inf')
Out[3]: nan
In [11]: np.inf
Out[11]: inf
In [12]: type(np.inf)
Out[12]: float
I think this may be because in case of normal inf
, you cannot get it from calculation. Example -
>>> 123123123123. ** 2
1.5159303447561418e+22
>>> _ ** 2
2.298044810152475e+44
>>> _ ** 2
5.281009949468725e+88
>>> _ ** 2
2.788906608638767e+177
>>> _ ** 2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: (34, 'Result too large')
Instead you always get an overflow error.
Whereas when using np.float64
, you can get the infinity value from calculation (though even that time it would throw a warning) -
In [63]: n = np.float64('123123123123123123123')
In [64]: n
Out[64]: 1.2312312312312313e+20
In [65]: n = n ** 2
In [66]: n = n ** 2
In [67]: n = n ** 2
In [68]: n = n ** 2
C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: overflow encountered in double_scalars
if __name__ == '__main__':
In [69]: n
Out[69]: inf
Hence, since you can get np.float64
infinity through calculation, they are throwing more warnings, when you try to do more calculations on it that may try to reduce the number from infinity to a much smaller value , that is subtracting/dividing by infinity (multiplication or addition of infinity is fine, since adding infinity to infinity would only give back infinity). Example -
In [71]: n - n
C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: invalid value encountered in double_scalars
if __name__ == '__main__':
Out[71]: nan
In [72]: n/n
C:\Anaconda3\Scripts\ipython-script.py:1: RuntimeWarning: invalid value encountered in double_scalars
if __name__ == '__main__':
Out[72]: nan
In [73]: n*n
Out[73]: inf
Though in your case , I believe you may have gotten a direct infinite value from source.
回答2:
There does not seem to be any reason a subtraction of two float64
s should raise a warning where a subtraction of two float
s doesn't.
Hence, this appears to be a bug in numpy
.
My recommendation (to myself) is to convert the float64
s to float
s at the time of the subtraction: i.e.,
return upper_int - lower_int
becomes
return float(upper_int) - float(lower_int).
This prevents the warning.
(Of course, there may be situations in which a warning for this subtraction is desired -- for these, I'd give the opposite recommendation -- i.e., keep things as is. In a sense, it's nice to have this toggle for the warning.)
来源:https://stackoverflow.com/questions/32429925/why-does-float64-produce-a-runtimewarning-where-float-produces-a-nan