sklearn中RidgeCV与ElasticNetCV(l1_ratio=0)最优alpha值差异问题
为什么设置l1_ratio=0时ElasticNetCV与RidgeCV的最优alpha差异显著?
当设置l1_ratio = 0时,弹性网络理论上退化为岭回归,但在sklearn中,RidgeCV与ElasticNetCV得到的最优alpha值差异显著,以下是复现代码及结果:
使用RidgeCV的代码
import numpy as np from sklearn.linear_model import ElasticNetCV, RidgeCV from sklearn.metrics import mean_squared_error import matplotlib.pyplot as plt # 数据生成 np.random.seed(123) beta = 0.35 N = 120 p = 30 X = np.random.normal(1, 2, (N, p)) y = np.random.normal(5, size=N) + beta * X[:, 0] # 候选lambda值 l = np.exp(np.linspace(-2, 8, 80)) ridge1 = RidgeCV(alphas=l, store_cv_values=True).fit(X, y) MSE_cv = np.mean(ridge1.cv_values_, axis=0) y_pred = ridge1.predict(X=X) MSE = mean_squared_error(y_true=y, y_pred=y_pred) print(f"best alpha: {np.round(ridge1.alpha_,3)}") print(f"MSE: {np.round(MSE,3)}")
结果:最优alpha: 305.368,MSE: 0.952
使用ElasticNetCV的代码
ridge2 = ElasticNetCV(cv=10, alphas=l, random_state=0, l1_ratio=0) ridge2.fit(X, y) y_pred = ridge2.predict(X=X) MSE = mean_squared_error(y_true=y, y_pred=y_pred) print(f"best alpha: {np.round(ridge2.alpha_,3)}") print(f"MSE: {np.round(MSE,3)}")
结果:最优alpha: 2.192,MSE: 0.934
差异原因分析
1. 正则化项的缩放系数不同
sklearn中Ridge和ElasticNet的损失函数定义存在本质差异:
- Ridge的损失函数:
平方误差项未做样本量归一化,正则化项为alpha * ||w||²,整体公式为:||y - Xw||² + alpha * ||w||² - l1_ratio=0时ElasticNet的损失函数:
平方误差项被样本量$n_{\text{samples}}$归一化,且正则化项多了0.5的缩放系数,整体公式为:(1/n_samples)*||y - Xw||² + 0.5*alpha*||w||²
两者要达到等价的正则化强度,需满足:alpha_Ridge = 0.5 * alpha_ElasticNet * n_samples
以你的数据为例,$n_{\text{samples}}=120$,ElasticNet的最优alpha为2.192,代入得等价的Ridge alpha为0.5*2.192*120=131.52,这和RidgeCV输出的305.368仍有差距,原因在于交叉验证策略的不同。
2. 交叉验证策略不一致
RidgeCV未指定cv参数时,默认使用留一交叉验证(LOOCV),即每次只留一个样本做测试,其余做训练- 你代码中的
ElasticNetCV设置了cv=10,使用的是10折交叉验证,将样本分成10份轮流做测试集
不同的交叉验证划分方式会导致模型在验证集上的表现波动,进而影响最优alpha的选择,尤其是样本量较小时,这种差异会更明显。
内容的提问来源于stack exchange,提问作者Markus Loecher
相关产品推荐
相关产品推荐

