岭回归:Scikit-learn 与直接计算不匹配 alpha > 0
Posted
技术标签:
【中文标题】岭回归:Scikit-learn 与直接计算不匹配 alpha > 0【英文标题】:Ridge Regression: Scikit-learn vs. direct calculation does not match for alpha > 0 【发布时间】:2016-11-28 11:56:23 【问题描述】:在岭回归中,我们使用L2
正则化解决Ax=b
。直接计算如下:
x = (ATA + alpha * I)-1ATb
我查看了 scikit-learn 代码,它们确实实现了相同的计算。但是,对于alpha > 0
,我似乎无法得到相同的结果
重现这一点的最少代码。
import numpy as np
A = np.asmatrix(np.c_[np.ones((10,1)),np.random.rand(10,3)])
b = np.asmatrix(np.random.rand(10,1))
I = np.identity(A.shape[1])
alpha = 1
x = np.linalg.inv(A.T*A + alpha * I)*A.T*b
print(x.T)
>>> [[ 0.37371021 0.19558433 0.06065241 0.17030177]]
from sklearn.linear_model import Ridge
model = Ridge(alpha = alpha).fit(A[:,1:],b)
print(np.c_[model.intercept_, model.coef_])
>>> [[ 0.61241566 0.02727579 -0.06363385 0.05303027]]
有什么建议可以解决这个差异吗?
【问题讨论】:
【参考方案1】:这种修改似乎对直接版本和 numpy 版本产生了相同的结果:
import numpy as np
A = np.asmatrix(np.random.rand(10,3))
b = np.asmatrix(np.random.rand(10,1))
I = np.identity(A.shape[1])
alpha = 1
x = np.linalg.inv(A.T*A + alpha * I)*A.T*b
print (x.T)
from sklearn.linear_model import Ridge
model = Ridge(alpha = alpha, tol=0.1, fit_intercept=False).fit(A ,b)
print model.coef_
print model.intercept_
似乎造成差异的主要原因是Ridge
类具有参数fit_intercept=True
(通过从_BaseRidge
类继承)(source)
这是在将矩阵传递给_solve_cholesky
函数之前应用数据中心化过程。
这是 ridge.py 中的代码
X, y, X_mean, y_mean, X_std = self._center_data(
X, y, self.fit_intercept, self.normalize, self.copy_X,
sample_weight=sample_weight)
此外,您似乎试图通过添加 1 的列来隐式解释截距。如您所见,如果您指定 fit_intercept=False
附录:Ridge 类是否真的实现了直接公式?
这取决于solver
参数的选择。
实际上,如果您没有在Ridge
中指定solver
参数,则默认采用solver='auto'
(内部采用solver='cholesky'
)。这应该相当于直接计算。
严格来说,_solve_cholesky
使用numpy.linalg.solve
而不是numpy.inv
。但是可以很容易地检查出来
np.linalg.solve(A.T*A + alpha * I, A.T*b)
与
产生相同的结果np.linalg.inv(A.T*A + alpha * I)*A.T*b
【讨论】:
感谢您的详细回复。这确实解决了fit_intercept = False
。但是,在我的示例中,我确实想要intercept
,因此我在直接计算中将 1 的列添加到我的A
矩阵中。当我使用A[:,1:]
传递给Ridge
时,我删除了1 的列。因此,即使我运行model = Ridge(alpha = alpha, normalize = False, fit_intercept = True, solver = "cholesky").fit(A[:,1:],b)
- 我也无法获得相同的结果。当你想要fit_intercept = True
时有任何澄清吗?
我相信你仍然可以保持A = np.asmatrix(np.c_[np.ones((10,1)),np.random.rand(10,3)])
这一行并设置fit_intercept=False
。第一个系数不应该是截距吗?
是的 - 就是这样!应该考虑一下。仍然想知道为什么normalize = False, fit_intercept=True
不这样做。感谢您的所有帮助。以上是关于岭回归:Scikit-learn 与直接计算不匹配 alpha > 0的主要内容,如果未能解决你的问题,请参考以下文章
线性回归 scikit-learn LinearRegression最小二乘法梯度下降SDG多项式回归学习曲线岭回归Lasso回归