精度,为什么Matlab和Python numpy的输出差异如此大?

18 投票
3 回答
4555 浏览
提问于 2025-04-17 02:39

我知道基本的数据类型,比如浮点数(float,double)不能精确表示某些数字。

在把一些代码从Matlab移植到Python(Numpy)时,我发现计算结果有很大的差异,我觉得这可能和精度有关。

举个例子,下面的代码是对一个500维的向量进行z标准化,只有前两个元素有非零值。

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代码:

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'。

为什么差别会这么大?哪个更准确呢?

3 个回答

3

根据SciPy的文档,std函数有一个叫做ddof的参数:

ddof : 整数,选填
这个参数代表“自由度的增量”。在计算时,使用的除数是 N - ddof,其中 N 是元素的数量。默认情况下,ddof 的值是零。

在 numpy 中,ddof 默认是零,而在 MATLAB 中则是一个。所以,我认为这可能会解决问题:

std(Z,ddof=1)
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))

这样在MATLAB中会得到

Za(1) = 21.1905669677

关于这两种结果哪个更适合你的需求,可以看看rockspotrocker的回答哦;-)。

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)

撰写回答