如何在glmnet绘制的Lasso系数路径图中添加最优lambda竖线?
在Lasso系数路径图中添加LOOCV最优Lambda竖线
嘿,刚好做过类似的操作,我来一步步教你怎么实现!核心思路是先通过留一交叉验证(LOOCV)找到最小MSE对应的最优lambda,再把这个lambda的位置作为竖线叠加到你已经画好的系数路径图上。下面我用Python的scikit-learn为例,给你具体的代码和解释:
步骤1:用LassoCV完成LOOCV并获取最优Lambda
首先我们需要用LassoCV来执行留一交叉验证,它会自动帮我们遍历lambda序列、计算每个lambda对应的交叉验证MSE,最后返回最优的lambda值:
import numpy as np import matplotlib.pyplot as plt from sklearn.linear_model import LassoCV, Lasso from sklearn.datasets import make_regression # 替换成你自己的真实数据 X, y = make_regression(n_samples=50, n_features=10, noise=10, random_state=42) # 初始化LassoCV,设置cv=len(X)就是留一交叉验证(每个样本单独作为测试集) lasso_cv = LassoCV(cv=len(X), random_state=42) lasso_cv.fit(X, y) # 获取LOOCV得到的最优lambda,以及对应的最小MSE best_lambda = lasso_cv.alpha_ # 如果你需要看最小MSE的值,可以用下面这行 min_mse = lasso_cv.mse_path_.mean(axis=1)[np.argmin(lasso_cv.mse_path_.mean(axis=1))]
步骤2:绘制系数路径图并添加最优Lambda竖线
接下来我们先画出不同lambda下的beta系数路径,然后用axvline添加最优lambda对应的竖线。注意如果你的x轴是对数转换后的lambda(通常系数路径图会这么做,因为lambda范围很大),竖线的x坐标也要对应转换:
# 用LassoCV自带的lambda序列(你也可以自己定义序列) alphas = lasso_cv.alphas_ # 计算每个lambda对应的beta系数 coefs = [] for alpha in alphas: lasso = Lasso(alpha=alpha, random_state=42) lasso.fit(X, y) coefs.append(lasso.coef_) coefs = np.array(coefs) # 绘制系数路径图 plt.figure(figsize=(10, 6)) # 这里用log10转换lambda,让坐标轴更易读 plt.plot(np.log10(alphas), coefs, linewidth=0.8) plt.xlabel(r'$\log_{10}(\lambda)$') plt.ylabel('Beta Coefficients') plt.title('Lasso Coefficient Path with LOOCV Optimal Lambda') # 添加最优lambda的竖线,颜色用红色虚线,加上图例 plt.axvline( x=np.log10(best_lambda), color='red', linestyle='--', linewidth=1.5, label=f'Optimal λ (log10): {np.log10(best_lambda):.2f}\nMin MSE: {min_mse:.2f}' ) plt.legend() plt.grid(alpha=0.3) plt.show()
关键细节和注意事项
- LOOCV的设置:
cv=len(X)是scikit-learn中实现留一交叉验证的方式,因为它会把数据集拆分成len(X)个折叠,每个折叠只包含一个测试样本。 - 1SE规则的可选方案:如果你不想用最小MSE对应的lambda,而是想选择更简洁的模型(系数更少),可以用
lasso_cv.alpha_1se_,这个lambda对应MSE在最小MSE加1个标准差范围内的最大lambda,只需要把上面代码中的best_lambda替换成这个值就行。 - 坐标轴匹配:如果你的系数路径图没有做对数转换,那竖线的x坐标直接用
best_lambda就行,不用转成log10。 - R语言用户的参考:如果你用R的
glmnet包,思路是一样的:先用cv.glmnet(X, y, type.measure="mse", nfolds=nrow(X))做LOOCV,然后用abline(v=log10(cv_fit$lambda.min))添加竖线(同样注意对数转换的问题)。
内容的提问来源于stack exchange,提问作者Ville
相关产品推荐
相关产品推荐

