使用 R 的 glmnet 和 Python 的 scikit-learn 进行岭回归有什么区别?

机器算法验证 r 机器学习 scikit-学习 回归
2022-03-02 01:31:36

我正在阅读James、Witten、Hastie、Tibshirani(2013 年)所著的“R 中应用统计学习简介”一书中关于岭回归/套索的 LAB 部分§6.6。

更具体地说,我正在尝试将 scikit-learnRidge模型应用于 R 包“ISLR”中的“Hitters”数据集。我创建了与 R 代码中所示相同的一组功能。但是,我无法接近glmnet()模型的结果。我选择了一个 L2 调谐参数进行比较。(scikit-learn 中的“alpha”参数)。

Python:

regr = Ridge(alpha=11498)
regr.fit(X, y)

http://nbviewer.ipython.org/github/JWarmenhoven/ISL-python/blob/master/Notebooks/Chapter%206.ipynb

回复:

请注意,alpha=0in中的参数glmnet()意味着应该应用 L2 惩罚(岭回归)。文档警告不要为 输入单个值lambda,但结果与使用向量的 ISL 中的结果相同。

ridge.mod <- glmnet(x,y,alpha=0,lambda=11498)

是什么导致了差异?

编辑:
从 R 中的惩罚包中 使用penalized()时,系数与 scikit-learn 相同。

ridge.mod2 <- penalized(y,x,lambda2=11498)

也许问题也可能是:'进行岭回归之间glmnet()和何时有什么区别?penalized()

R包 glmnet中使用的实际 Fortran 代码的新 python 包装器
https://github.com/civisanalytics/python-glmnet

2个回答

Matthew Drury 的答案应该是 1/N。更确切地说...

glmnet文档指出,弹性网络使损失函数最小化

1NXβy22+λ(12(1α)β22+αβ1)

sklearn文档linear_model.Ridge最小化损失函数

Xβy22+αβ22

这相当于最小化

1NXβy22+αNβ22

要从 glmnet 和 sklearn 获得相同的解决方案,它们的损失函数必须相等。这意味着在 glmnet 中设置α=0λ=2Nαsklearn

library(glmnet)
X = matrix(c(1, 1, 2, 3, 4, 2, 6, 5, 2, 5, 5, 3), byrow = TRUE, ncol = 3)
y = c(1, 0, 0, 1)
reg = glmnet(X, y, alpha = 0, lambda = 2 / nrow(X))
coef(reg)

glmnet 输出:–0.03862100,–0.03997036,–0.07276511,0.42727955

import numpy as np
from sklearn.linear_model import Ridge
X = np.array([[1, 1, 2], [3, 4, 2], [6, 5, 2], [5, 5, 3]])
y = np.array([1, 0, 0, 1])
reg = Ridge(alpha = 1, fit_intercept = True, normalize = True)
reg.fit(X, y)
np.hstack((reg.intercept_, reg.coef_))

sklearn 输出:–0.03862178、–0.0399697、–0.07276535、0.42727921

我的答案缺少一个因素,请参阅下面的@visitors 答案以进行正确比较。1N


这里有两个参考资料应该澄清这种关系。

sklearn 文档linear_model.Ridge优化了以下目标函数

|Xβy|22+α|β|22

glmnet 论文说弹性网络优化了以下目标函数

|Xβy|22+λ(12(1α)|β|22+α|β|1)

请注意,这两种实现以完全不同的方式使用 alpha,sklearn 使用表示正则化的整体水平,而 glmnet 使用来达到此目的,保留用于在 ridge 和 lasso 正则化之间进行交易。 ααλα

比较公式,看起来在 glmnet 中设置应该从.α=0λ=2αsklearnlinear_model.Ridge