簡體   English   中英

使用Scipy vs Matlab擬合對數正態分布

[英]Fitting lognormal distribution using Scipy vs Matlab

我正在嘗試使用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

scipy 0.9.0中的fit方法中存在一個錯誤,該錯誤已在scipy的更高版本中修復。

下面腳本的輸出應該是:

Explicit formula:   mu = 4.99203450, sig = 0.81691086
Fit log(x) to norm: mu = 4.99203450, sig = 0.81691086
Fit x to lognorm:   mu = 4.99203468, sig = 0.81691081

但是scipy 0.9.0就是這樣

Explicit formula:   mu = 4.99203450, sig = 0.81691086
Fit log(x) to norm: mu = 4.99203450, sig = 0.81691086
Fit x to lognorm:   mu = 4.23197270, sig = 1.11581240

以下測試腳本顯示了獲得相同結果的三種方法:

import numpy as np
from scipy import stats


def lognfit(x, ddof=0):
    x = np.asarray(x)
    logx = np.log(x)
    mu = logx.mean()
    sig = logx.std(ddof=ddof)
    return mu, sig


# A simple data set for easy reproducibility
x = np.array([50., 50, 100, 200, 200, 300, 500])

# Explicit formula
my_mu, my_sig = lognfit(x)

# Fit a normal distribution to log(x)
norm_mu, norm_sig = stats.norm.fit(np.log(x))

# Fit the lognormal distribution
lognorm_sig, _, lognorm_expmu = stats.lognorm.fit(x, floc=0)

print "Explicit formula:   mu = %10.8f, sig = %10.8f" % (my_mu, my_sig)
print "Fit log(x) to norm: mu = %10.8f, sig = %10.8f" % (norm_mu, norm_sig)
print "Fit x to lognorm:   mu = %10.8f, sig = %10.8f" % (np.log(lognorm_expmu), lognorm_sig)

在std中使用選項ddof=1 開發。 計算使用無偏方差估計:

In [104]: x
Out[104]: array([  50.,   50.,  100.,  200.,  200.,  300.,  500.])

In [105]: lognfit(x, ddof=1)
Out[105]: (4.9920345004312647, 0.88236457185021866)

在matlab的lognfit文檔中有一條說明,即當不使用審查時,lognfit使用方差的無偏估計的平方根計算sigma。 這對應於在上面的代碼中使用ddof = 1。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM