我正在尝试使用 Scipy 拟合对数正态分布。我之前已经使用 Matlab 完成了它,但由于需要将应用程序扩展到统计分析之外,我正在尝试在 Scipy 中重现拟合值。
下面是我用来拟合数据的 Matlab 代码:
% Read input data (one value per line)
x = [];
fid = fopen(file_path, 'r'); % reading is default action for fopen
disp('Reading network degree data...');
if fid == -1
disp('[ERROR] Unable to open data file.')
else
while ~feof(fid)
[x] = [x fscanf(fid, '%f', [1])];
end
c = fclose(fid);
if c == 0
disp('File closed successfully.');
else
disp('[ERROR] There was a problem with closing the file.');
end
end
[f,xx] = ecdf(x);
y = 1-f;
parmhat = lognfit(x); % MLE estimate
mu = parmhat(1);
sigma = parmhat(2);
这是拟合图:
现在这是我的 Python 代码,目的是实现相同的目标:
import math
from scipy import stats
from statsmodels.distributions.empirical_distribution import ECDF
# The same input is read as a list in Python
ecdf_func = ECDF(degrees)
x = ecdf_func.x
ccdf = 1-ecdf_func.y
# Fit data
shape, loc, scale = stats.lognorm.fit(degrees, floc=0)
# Parameters
sigma = shape # standard deviation
mu = math.log(scale) # meanlog of the distribution
fit_ccdf = stats.lognorm.sf(x, [sigma], floc=1, scale=scale)
这是使用 Python 代码的最佳选择。
如您所见,两组代码都能够产生良好的拟合效果,至少在视觉上是这样。
问题是估计的参数 mu 和 sigma 存在巨大差异。
来自 Matlab:mu = 1.62 sigma = 1.29。来自 Python:mu = 2.78 sigma = 1.74。
为什么会有这样的差异?
注意:我已经仔细检查了两组拟合的数据是否完全相同。相同的点数,相同的分布。
非常感谢您的帮助!提前致谢。
其他信息:
import scipy
import numpy
import statsmodels
scipy.__version__
'0.9.0'
numpy.__version__
'1.6.1'
statsmodels.__version__
'0.5.0.dev-1bbd4ca'
Matlab 版本为 R2011b。
版:
如下面的答案所示,故障在于 Scipy 0.9。我能够使用 Scipy 11.0 从 Matlab 重现 mu 和 sigma 结果。
更新 Scipy 的一种简单方法是:
pip install --upgrade Scipy
如果你没有 pip(你应该!):
sudo apt-get install pip