我在探索山脊回归。在比较statsmodels和sklearn时,我发现这两个库产生了不同的岭回归输出。下面是区别的一个简单例子
import numpy as np
import pandas as pd
import statsmodels.api as sm
from sklearn.linear_model import Lasso, Ridge
np.random.seed(142131)
n = 500
d = pd.DataFrame()
d['A'] = np.random.normal(size=n)
d['B'] = d['A'] + np.random.normal(scale=0.25, size=n)
d['C'] = np.random.normal(size=n)
d['D'] = np.random.normal(size=n)
d['intercept'] = 1
d['Y'] = 5 - 2*d['A'] + 1*d['D'] + np.random.normal(size=n)
y = np.asarray(d['Y'])
X = np.asarray(d[['intercept', 'A', 'B', 'C', 'D']])首先,使用sklearn和Ridge
ridge = Ridge(alpha=1, fit_intercept=True)
ridge.fit(X=np.asarray(d[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']]), y=y)
ridge.intercept_, ridge.coef_输出4.99721, -2.00968, 0.03363, -0.02145, 1.02895]。
接下来,statsmodels和OLS.fit_regularized
penalty = np.array([0, 1., 1., 1., 1.])
ols = sm.OLS(y, X).fit_regularized(L1_wt=0., alpha=penalty)
ols.params输出[5.01623, -0.69164, -0.63901, 0.00156, 0.55158]。然而,由于这两者都在实施岭回归,我希望它们是一样的。
请注意,这两种方法都不能惩罚拦截术语(已经检查过了,因为这是一个可能的潜在差异)。我也不认为这是我的错误。具体来说,我发现这两种实现为LASSO提供了相同的输出。下面是前面数据的演示
# sklearn LASSO
lasso = Lasso(alpha=0.5, fit_intercept=True)
lasso.fit(X=np.asarray(d[['A', 'B', 'C', 'D']]), y=y)
lasso.intercept_, lasso.coef_
# statsmodels LASSO
penalty = np.array([0, 0.5, 0.5, 0.5, 0.5])
ols = sm.OLS(y, X).fit_regularized(L1_wt=1., alpha=penalty)
ols.params两者都输出[5.01465, -1.51832, 0., 0., 0.57799]。
因此,我的问题是为什么岭回归的估计系数在sklearn和statsmodels的实现中有所不同?
发布于 2022-05-16 14:25:45
在仔细研究了一下之后,我发现了为什么他们会有不同的答案。不同之处在于,sklearn的Ridge将惩罚项定级为alpha / n,其中n是观察的数量。statsmodels不适用这种调优参数的缩放。如果您重新调整statsmodels的惩罚级别,则可以使岭实现匹配。
使用我发布的示例,下面是如何在这两者之间进行输出匹配:
# sklearn
# NOTE: there is no difference from above
ridge = Ridge(alpha=1, fit_intercept=True)
ridge.fit(X=np.asarray(d[['A', 'B', 'C', 'D']]), y=y)
ridge.intercept_, ridge.coef_
# statsmodels
# NOTE: going to re-scale the penalties based on n observations
n = X.shape[0]
penalty = np.array([0, 1., 1., 1., 1.]) / n # scaling penalties
ols = sm.OLS(y, X).fit_regularized(L1_wt=0., alpha=penalty)
ols.params现在,两者都输出[ 4.99721, -2.00968, 0.03363, -0.02145, 1.02895]。
我发布了这篇文章,所以如果其他人在我的情况下发现了他们,他们可以更容易地找到答案(因为我以前从未见过任何关于这种差异的讨论)。我不确定重新调整的理由。同样奇怪的是,Ridge重新调整了调优参数,但Lasso没有。看起来是很重要的行为。阅读sklearn 山脊和套索的文档后,我没有看到讨论过的Ridge的重新缩放行为有什么不同。
https://stackoverflow.com/questions/72260808
复制相似问题