精度问题:为什么Matlab和Python numpy输出结果如此不同?

18

我了解基本数据类型,并知道浮点数类型(float,double)不能精确地存储某些数字。

在将一些代码从Matlab移植到Python(Numpy)时,我发现计算结果存在显著差异,我认为这与精度有关。

考虑以下代码,对一个500维向量进行z-score标准化,只有前两个元素具有非零值。

Matlab代码:

Z = repmat(0,500,1); Z(1)=3;Z(2)=1;
Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z),500,1);
Za(1)
>>> 21.1694

Python:

->

Python:

from numpy import zeros,mean,std
Z = zeros((500,))
Z[0] = 3
Z[1] = 1
Za = (Z - mean(Z)) / std(Z)
print Za[0]
>>> 21.1905669677
除了Python的格式显示更多数字之外,这两者存在巨大的区别(依我看),超过0.02。
Python和Matlab都使用64位数据类型(据我所知)。Python使用“numpy.float64”,而Matlab使用“double”。
为什么差异如此之大?哪个更正确?

如果现在提问,也许应该适用于计算科学SE。 - gerrit
3个回答

27

也许差异来自于meanstd的调用。先比较一下它们。

std有几个定义,有些使用平方根。

1 / n * sum((xi - mean(x)) ** 2)

其他人使用

1 / (n - 1) * sum((xi - mean(x)) ** 2)

从数学角度来看,这些公式是正态分布随机变量方差的估计量。该分布有两个参数sigmamu。如果您确切地知道 mu,那么sigma ** 2的最优估计器是

1 / n * sum((xi - mu) ** 2)

如果你必须从数据中估算mu,使用mu = mean(xi),则sigma**2的最佳估计器为:

1 / (n - 1) * sum((xi- mean(x))**2)

14
为了回答你的问题,不是精度问题。正如@rocksportrocker所指出的那样,在标准差的估计方法中有两种流行的估计器。MATLAB的std都有可用,但作为标准使用与Python中使用的不同。
尝试使用std(Z,1)代替std(Z)
Za = (Z-repmat(mean(Z),500,1)) ./ repmat(std(Z,2),500,1);Za(1)
sprintf('%1.10f', Za(1))

导致

Za(1) = 21.1905669677

在MATLAB中。阅读rockspotrocker的答案,了解哪一个结果更适合你要做的事情;-)。


啊,我刚看到 @rocksportrocker 给你讲解了这个数学背景 :-). - Jonas Heidelberg

3
根据SciPy的std文档,在此处,它有一个叫做ddof的参数:

ddof: int, optional(可选)
意味着Delta自由度。计算中使用的除数是N-ddof,其中N表示元素数量。默认情况下,ddof为零。

在numpy中,默认情况下ddof为零,而在MATLAB中为一。因此,我认为这可能会解决问题。
std(Z,ddof=1)

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