NumPy标准差函数的奇怪行为

3

从统计学角度来看,当所有值相等时,标准差应为0。对于arr1,结果如预期一样是0,但是对于arr2,结果是1.3877787807814457e-17 - 非常小但不是0,这会引起一些问题,例如zscore

这是正常行为还是奇怪的错误?

import numpy as np

arr1 = [20.0] * 3
#[20.0, 20.0, 20.0]

arr2 = [-0.087] * 3
#[-0.087, -0.087, -0.087]

np.std(arr1) #0.0
np.std(arr2) #1.3877787807814457e-17

4
这是一个浮点数误差。当使用std函数进行运算时,float32类型的值不足以精确表示理论值。正如你所看到的,std得出了一个非常小的数。请看 np.mean(arr2) ,它为-0.08700000000000001。 - Károly Szabó
我想不起来具体的例子,但这个问题也会出现在大数值的情况下。 - Quant Christo
2个回答

4

Numpy std 文档 中指出:

The standard deviation is the square root of the average of the squared deviations from the mean, i.e., std = sqrt(mean(abs(x - x.mean())**2)).

The average squared deviation is normally calculated as x.sum() / N, where N = len(x). If, however, ddof is specified, the divisor N - ddof is used instead. In standard statistical practice, ddof=1 provides an unbiased estimator of the variance of the infinite population. ddof=0 provides a maximum likelihood estimate of the variance for normally distributed variables. The standard deviation computed in this function is the square root of the estimated variance, so even with ddof=1, it will not be an unbiased estimate of the standard deviation per se.

Note that, for complex numbers, std takes the absolute value before squaring, so that the result is always real and nonnegative.

For floating-point input, the std is computed using the same precision the input has. Depending on the input data, this can cause the results to be inaccurate, especially for float32 (see example below). Specifying a higher-accuracy accumulator using the dtype keyword can alleviate this issue.

a = np.zeros((2, 512*512), dtype=np.float32) 
a[0, :] = 1.0 
a[1, :] = 0.1 np.std(a)
>>>0.45000005 

but for float64:

a = np.zeros((2, 512*512), dtype=np.float64) 
a[0, :] = 1.0 
a[1, :] = 0.1 
np.std(a)
>>>0.45 

np.std 在第一次计算时是否应该检查“相等”(如果为真则返回0.0)?我认为这样可以避免在这种情况下出现舍入问题。 - Quant Christo
1
@QuantChristo 是的,它似乎没有检查相等性。 - user13959036

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接