为什么 float64 会产生一个 RuntimeWarning 而 float 会产生一个 nan?
Why does float64 produce a RuntimeWarning where float produces a nan?
我正在使用 warnings
模块将警告作为错误发出。
当我调用函数 plot_fig_4
时,出现以下错误:
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
好的。所以我在 _integrate_little_phi
里面贴了一个 pdb.set_trace
,就在出现错误的行之前,重新 运行,并检查相关变量的值:
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'>
嗯。所以出现错误是因为我从无穷大中减去无穷大。我可以复制吗?
(Pdb) upper_int - lower_int
*** RuntimeWarning: invalid value encountered in double_scalars
是的。但是等一下。让我们再尝试一件事:
(Pdb) np.inf
inf
(Pdb) type(np.inf)
<type 'float'>
(Pdb) np.inf - np.inf
nan
什么什么?当我使用 np.inf
(其中 np
是 numpy
)直接从无穷大中减去无穷大时,我得到 nan
,而不是 RuntimeWarning
.
为什么我在这个实例中得到 nan
而在另一个实例中得到 RuntimeWarning
? 我特意贴出了类型上的差异(float
与 float64
)。问题是,为什么这些(微不足道的)不同类型会产生不同的结果?
因为在 np.inf
的情况下,类型是 float
(基本数据类型),而在 upper_int
/ lower_int
的情况下,数据类型是 numpy.float64
。可以通过 -
重现类似问题
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
对于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
我想这可能是因为在正常情况下 inf
,您无法通过计算得出。示例 -
>>> 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')
相反,您总是会收到溢出错误。
而使用 np.float64
时,您可以从计算中获得无穷大值(尽管即使那样它也会发出警告)-
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
因此,由于您可以通过计算得到 np.float64
无穷大,当您尝试对其进行更多计算时,他们会发出更多警告,可能会尝试将数字从无穷大减少到更小的值,即 subtracting/dividing 乘以无穷大(无穷大的乘法或加法很好,因为将无穷大加到无穷大只会返回无穷大)。示例 -
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
虽然在你的情况下,我相信你可能已经从源代码中获得了直接的无限价值。
似乎没有任何理由减去两个 float64
应该发出警告,而减去两个 float
则不会。
因此,这似乎是 numpy
中的错误。
我(对我自己)的建议是在减法时将 float64
s 转换为 float
s:即
return upper_int - lower_int
变成
return float(upper_int) - float(lower_int).
这样可以防止警告。
(当然,在某些情况下可能需要对此减法发出警告 - 对于这些情况,我会给出相反的建议 - 即保持原样。从某种意义上说,这很好有警告开关。)
我正在使用 warnings
模块将警告作为错误发出。
当我调用函数 plot_fig_4
时,出现以下错误:
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
好的。所以我在 _integrate_little_phi
里面贴了一个 pdb.set_trace
,就在出现错误的行之前,重新 运行,并检查相关变量的值:
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'>
嗯。所以出现错误是因为我从无穷大中减去无穷大。我可以复制吗?
(Pdb) upper_int - lower_int
*** RuntimeWarning: invalid value encountered in double_scalars
是的。但是等一下。让我们再尝试一件事:
(Pdb) np.inf
inf
(Pdb) type(np.inf)
<type 'float'>
(Pdb) np.inf - np.inf
nan
什么什么?当我使用 np.inf
(其中 np
是 numpy
)直接从无穷大中减去无穷大时,我得到 nan
,而不是 RuntimeWarning
.
为什么我在这个实例中得到 nan
而在另一个实例中得到 RuntimeWarning
? 我特意贴出了类型上的差异(float
与 float64
)。问题是,为什么这些(微不足道的)不同类型会产生不同的结果?
因为在 np.inf
的情况下,类型是 float
(基本数据类型),而在 upper_int
/ lower_int
的情况下,数据类型是 numpy.float64
。可以通过 -
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
对于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
我想这可能是因为在正常情况下 inf
,您无法通过计算得出。示例 -
>>> 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')
相反,您总是会收到溢出错误。
而使用 np.float64
时,您可以从计算中获得无穷大值(尽管即使那样它也会发出警告)-
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
因此,由于您可以通过计算得到 np.float64
无穷大,当您尝试对其进行更多计算时,他们会发出更多警告,可能会尝试将数字从无穷大减少到更小的值,即 subtracting/dividing 乘以无穷大(无穷大的乘法或加法很好,因为将无穷大加到无穷大只会返回无穷大)。示例 -
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
虽然在你的情况下,我相信你可能已经从源代码中获得了直接的无限价值。
似乎没有任何理由减去两个 float64
应该发出警告,而减去两个 float
则不会。
因此,这似乎是 numpy
中的错误。
我(对我自己)的建议是在减法时将 float64
s 转换为 float
s:即
return upper_int - lower_int
变成
return float(upper_int) - float(lower_int).
这样可以防止警告。
(当然,在某些情况下可能需要对此减法发出警告 - 对于这些情况,我会给出相反的建议 - 即保持原样。从某种意义上说,这很好有警告开关。)