【问题标题】:Why are LASSO in sklearn (python) and matlab statistical package different?为什么sklearn(python)和matlab统计包中的LASSO不一样?
【发布时间】:2012-09-26 14:57:31
【问题描述】:

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

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

然后我保存了matlab的数据,并尝试从sklearn复制带有laaso_path的图形,我得到了

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

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()

【问题讨论】:

  • 我只能说我在处理真实数据时记得类似的发现。 Matlab 结果不同并且明显更好。不过,我并没有深入探讨这个问题的根源。

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


【解决方案1】:

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

另一句话是,您的路径不是非常分段线性的,因为它可能/应该是。考虑减少 tol 并增加 max_iter。

希望对你有帮助

【讨论】:

  • 我想问题不仅仅是标准化。我尝试了上述一个,但仍然得到不同的曲线。此外,交叉验证得到的系数差异很大。
  • 这对我来说仍然像是一个参数化问题:两条曲线看起来很相似,但在 X 轴上发生了偏移。在日志空间中对 scikit-learn 中的 alpha 进行重新缩放可能会导致这种情况。 scikit-learn 中使用的参数化在documentation 中给出。您还可以从相同的分布中生成更多数据并计算回归分数(例如确定系数 r^2 或 RMSE),并检查是否发现 alpha 的最佳值接近 alpha 的交叉验证值。
  • @imsc 你试过alpha = lambda / (2 * X.shape[0])吗?
【解决方案2】:

虽然我无法找出导致问题的原因,但有一个合乎逻辑的方向可以继续。

这些是事实:

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

这是我的假设:

  • 与以替代方式复制此示例未给出正确结果的可能性相比,mathworks 选择在其文档中放置错误示例的可能性可以忽略不计。

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

【讨论】:

  • 这是一个非常薄弱的​​论点来宣传一种技术而不是另一种技术。 sklearn 也提供了例子。 matlab代码可以重现吗?实际上,LASSO 更像是一类求解器,而不是精确定义的算法。因此,算法稍有不同的可能性更大。根据您的论点说 scikit-learn 不可靠是相当苛刻的。
  • 我不想暗示这一点,我已经稍微改写了我的答案以更清楚。
  • 感谢您的回答。 scikit-learn 确实是一个很好实现的模块。但是,仍然缺乏导致上述问题的文档和示例。我可以通过适当的标准化来解决这个问题。
【解决方案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

【讨论】:

    【解决方案4】:

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

    我实际上正在处理从glmnet(在R中)到LassoCV的管道,我发现LassoCV首先对X矩阵进行归一化并做得不太好(即使你指定了参数normalize = True)。

    在使用 LassoCV 时先尝试对 X 矩阵进行归一化。

    如果是pandas对象,

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

    看来你还需要将 alpha 乘以 2

    【讨论】:

      猜你喜欢
      • 2021-06-03
      • 2019-07-24
      • 1970-01-01
      • 2019-05-13
      • 2021-02-18
      • 2015-08-01
      • 2014-07-28
      • 2021-01-16
      • 1970-01-01
      相关资源
      最近更新 更多