为什么LASSO在sklearn(python)和matlab统计包中有所不同?

时间:2012-10-05 12:40:49

标签: python matlab linear-regression scikit-learn statistics

我正在使用LaasoCV中的sklearn来选择通过交叉验证选择的最佳模型。我发现如果我使用sklearn或matlab统计工具箱,交叉验证会得到不同的结果。

我使用了matlab并复制了给出的示例 http://www.mathworks.se/help/stats/lasso-and-elastic-net.html 得到像这样的数字

enter image description here

然后我保存了matlab数据,并尝试使用laaso_path sklearn来复制数字,我得到了

enter image description here

虽然这两个数字之间有一些相似之处,但也存在一定的差异。据我所知,lambda中的参数matlabalpha中的sklearn相同,但在此图中似乎存在一些差异。有人可以指出哪一个是正确的,还是我错过了什么?此外,获得的系数也不同(这是我主要关心的问题)。

Matlab代码:

rng(3,'twister') % for reproducibility
X = zeros(200,5);
for ii = 1:5
      X(:,ii) = exprnd(ii,200,1);
end
r = [0;2;0;-3;0];
Y = X*r + randn(200,1)*.1;

save randomData.mat % To be used in python code

[b fitinfo] = lasso(X,Y,'cv',10);
lassoPlot(b,fitinfo,'plottype','lambda','xscale','log');

disp('Lambda with min MSE')
fitinfo.LambdaMinMSE
disp('Lambda with 1SE')
fitinfo.Lambda1SE
disp('Quality of Fit')
lambdaindex = fitinfo.Index1SE;
fitinfo.MSE(lambdaindex)
disp('Number of non zero predictos')
fitinfo.DF(lambdaindex)
disp('Coefficient of fit at that lambda')
b(:,lambdaindex)

Python代码:

import scipy.io
import numpy as np
import pylab as pl
from sklearn.linear_model import lasso_path, LassoCV

data=scipy.io.loadmat('randomData.mat')
X=data['X']
Y=data['Y'].flatten()

model = LassoCV(cv=10,max_iter=1000).fit(X, Y)
print 'alpha', model.alpha_
print 'coef', model.coef_

eps = 1e-2 # the smaller it is the longer is the path
models = lasso_path(X, Y, eps=eps)
alphas_lasso = np.array([model.alpha for model in models])
coefs_lasso = np.array([model.coef_ for model in models])

pl.figure(1)
ax = pl.gca()
ax.set_color_cycle(2 * ['b', 'r', 'g', 'c', 'k'])
l1 = pl.semilogx(alphas_lasso,coefs_lasso)
pl.gca().invert_xaxis()
pl.xlabel('alpha')
pl.show()

4 个答案:

答案 0 :(得分:3)

我没有matlab,但要注意交叉验证获得的值可能不稳定。这是因为它受细分样本的影响。

即使您在python中运行2次交叉验证,您也可以获得2个不同的结果。 考虑这个例子:

kf=sklearn.cross_validation.KFold(len(y),n_folds=10,shuffle=True)
cv=sklearn.linear_model.LassoCV(cv=kf,normalize=True).fit(x,y)
print cv.alpha_
kf=sklearn.cross_validation.KFold(len(y),n_folds=10,shuffle=True)
cv=sklearn.linear_model.LassoCV(cv=kf,normalize=True).fit(x,y)
print cv.alpha_

0.00645093258722
0.00691712356467

答案 1 :(得分:2)

有可能是alpha = lambda / n_samples
scikit-learn中的n_samples = X.shape[0]

另一个评论是你的路径不是非常线性的,因为它可能/应该是。考虑减少tol并增加max_iter。

希望这会有所帮助

答案 2 :(得分:0)

我知道这是一个旧线程,但是:

我实际上正在努力从LassoCV(在R中)转到glmnet,我发现LassoCV在规范化时并没有做得太好首先是X矩阵(即使您指定参数normalize = True)。

使用LassoCV时首先尝试规范化X矩阵。

如果是pandas对象,

(X - X.mean())/X.std()

看来你还需要多个alpha by 2

答案 3 :(得分:-1)

虽然我无法弄清楚导致问题的原因,但还是有一个合理的方向可以继续。

这些是事实:

  • Mathworks选择了一个示例并决定将其包含在文档中
  • 您的matlab代码会产生与结果完全相同的结果。
  • 替代方案与结果不符,并且过去提供的结果不准确

这是我的假设:

  • 与以不同方式复制此示例无法给出正确结果的机会相比,mathworks选择在其文档中添加错误示例的可能性是可忽略的。

逻辑结论:此示例的matlab实现是可靠的,而另一个则不是。 这可能是代码中的问题,也可能是你如何使用它,但无论哪种方式,唯一合乎逻辑的结论是你应该继续使用Matlab来选择你的模型。