提问者:小点点

Numpy幂返回负值


我想画出泊松分布,得到λ的负概率

此代码为不同的lambda生成绘图:

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import factorial

for lambda_val in range(1, 12, 2):

    plt.figure()
    
    k = np.arange(0,20)
    y = np.power(lambda_val, k)*np.exp(-lambda_val)/factorial(k)

    plt.bar(k, y)
    plt.title('lambda = ' + str(lambda_val))
    plt.xlabel('k')
    plt.ylabel('probability')
    plt.ylim([-0.1, 0.4])
    plt.grid()
    plt.show()

请看这两幅图:

在我看来,Lambda=5看起来不错。

λ=9,不适用。

我很确定这和np.power有关因为

np.power(11, 9)

给我:-1937019605,而

11**9

给我:2357947691(WolframAlpha也一样)。

但是如果我避免np。权力与使用

y = (lambda_val**k)*math.exp(-lambda_val)/factorial(k)

为了计算概率,我也得到负值。我完全糊涂了。谁能解释一下效果或者我做错了什么?提前感谢。:)


共1个答案

匿名用户

您的问题是由于32位整数溢出造成的。发生这种情况是因为Numpy有时编译为32位整数,即使平台(操作系统处理器)是64位的。存在溢出,因为Numpy自动将Python解释器的无界整数转换为本机np.int_类型。您可以使用检查此类型是否为64位类型np.int_np.int64。AFAIK,Python Pip上为Windows编译的默认Numpy二进制包使用32位整数,Linux包使用64位整数(假设您在64位平台上)。

该问题可以通过以下方式轻松复制:

In [546]: np.power(np.int32(11), np.int32(9))
Out[546]: -1937019605

它也可以解决使用:

In [547]: np.power(np.int64(11), np.int64(9))
Out[547]: 2357947691

在第二个表达式中,使用类型为np的k。默认情况下,这就是为什么会出现相同问题的原因。希望您可以向Numpy指定整数应该更大。请注意,Numpy有一些隐式规则来避免溢出,但在所有情况下都很难避免它们,而不会严重影响性能。这里有一个固定的公式:

k = np.arange(0, 20, dtype=np.int64)
y = np.power(lambda_val, k) * np.exp(-lambda_val) / factorial(k)

经验法则是在得到意外结果时要非常小心隐式转换。