ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Lasso回归与Elastic Net:正则化原理、区别与实战选型

2026/9/7 15:44:59 拓冰建站 浏览量
Lasso回归与Elastic Net:正则化原理、区别与实战选型 1. 内容整体设计与思路拆解1.1 从普通线性回归说起为什么需要正则化很多刚接触机器学习的朋友第一个跑的模型大概率就是线性回归。用sklearn里的LinearRegression几行代码就能在训练集上得到一个看似不错的拟合结果。但拿这套逻辑直接上真实业务数据往往会翻车——最常见的问题就是过拟合和特征共线性。我举个实际工作中经常遇到的例子。你在做用户付费预测手里有几十个特征包括用户年龄、注册天数、最近一次登录时间、历史购买次数、优惠券使用频率等等。这些特征之间天然存在相关性注册时间长的用户历史购买次数通常也多购买次数多的用户优惠券使用频率往往更高。如果你直接用普通线性回归去拟合那回归系数会因为特征间的共线性变得极其不稳定——可能某个特征系数被推到几百另一个又变成负几千纯粹在互相抵消模型换个训练集结果就面目全非。这时候就需要引入正则化。正则化的思路很直白在原始损失函数比如均方误差MSE后面加一个惩罚项限制模型系数不要太大。加惩罚项的核心目的有两个控制模型复杂度防止过拟合同时通过压缩系数来缓解共线性带来的不稳定。而Lasso回归和**弹性网络回归Elastic Net**正是沿着这条思路走出来的两个代表作。它们都通过加上惩罚项来约束系数但惩罚的形式不同导致两者在特征选择、处理相关性、稳定性上的表现差异很大。1.2 两者的核心定位差异先直接给结论这两者的本质区别可以浓缩成一句话Lasso只带L1惩罚项Elastic Net同时带了L1和L2惩罚项。这一句话引申出的实际差异非常多Lasso在特征高度相关时倾向于只随机选其中一个Elastic Net会倾向于同时保留成组的相关特征Lasso的解在特征数量超过样本量时最多只能选出n个非零特征n为样本量Elastic Net没有这个限制可以选出超过样本量的非零特征Lasso对离群点更敏感因为它的路径是分段线性的Elastic Net加了L2项之后目标函数变成强凸的整体更平滑、更稳定。这篇文章就是围绕这些差异展开的。我下面会从数学表达式、求解算法、实际案例、参数调优这几个维度逐一拆开讲手把手带你把这两个方法的区别吃透。适合的人群是已经会跑LinearRegression、想进一步搞懂正则化回归是怎么回事的同学以及在建模比赛中发现Lasso效果不稳想换Elastic Net试试的分析师。2. 核心细节解析与实操要点2.1 数学表达式的区别这一节我们直接看公式。普通线性回归的损失函数是$$\min \sum_{i1}^{n}(y_i - \hat{y}_i)^2$$最小化残差平方和本质就是最小化预测值与真实值的误差平方。这是我们熟悉的基准。Lasso回归在这个基础上加了L1惩罚项目标函数是$$\min \sum_{i1}^{n}(y_i - \hat{y}i)^2 \lambda \sum{j1}^{p} |\beta_j|$$对回归系数的绝对值求和再乘以λ加到损失函数里。λ是正则化强度的超参数越大惩罚越重系数会被压缩得更狠甚至有大量系数变成精确的零——这就实现了特征选择。Elastic Net则是同时加入L1和L2惩罚$$\min \sum_{i1}^{n}(y_i - \hat{y}i)^2 \lambda_1 \sum{j1}^{p} |\beta_j| \lambda_2 \sum_{j1}^{p} \beta_j^2$$实际操作中Elastic Net的参数通常不用λ1和λ2分开控制而是整理成两个参数alpha控制整体惩罚强度l1_ratio控制L1惩罚所占的比例。当l1_ratio1时Elastic Net就退化成Lasso当l1_ratio0时退化成岭回归。这一点在sklearn的ElasticNet接口里体现得很明显。2.2 L1惩罚和L2惩罚的几何直观L1和L2在几何上的区别是理解两者行为差异的钥匙。L1惩罚项的约束区域在参数空间里是一个以原点为顶点的菱形二维情况下。回归系数的最优解是这个菱形与误差等值线的切点。因为菱形的棱角落在坐标轴上切点很容易出现在坐标轴上——这意味着某个维度的系数正好是0特征被剔除了。L2惩罚项的约束区域则是一个圆形没有突出的棱角切点落在坐标轴上的概率几乎为零。所以岭回归能把系数压缩到接近0但很少压缩到精确的0。从这个几何视角再回头看Lasso和Elastic Net的差异就一目了然了。Lasso只有L1项所以它构成的约束区域是纯粹的菱形对应特征强制稀疏化的能力最强。Elastic Net的约束区域是菱形与椭圆的混合体棱角比纯菱形钝化了一些所以它的稀疏化能力比Lasso温和换来的是对相关特征组的保留能力。在实际应用中这个差异非常关键。比如基因表达数据里一批基因会共同调控某条通路它们之间高度相关。Lasso可能只挑了其中一个代表基因而Elastic Net会把这一组共同保留下来——从业务解释的角度看Elastic Net的结果往往更符合真实的生物学机制或业务逻辑。2.3 解路径与稳定性除了几何形状两者的解路径也有明显差异。Lasso的系数路径是分段线性的。随着λ从大到小变化每个特征的系数会沿着一条折线变化折点对应有特征进入或退出模型。这个特性带来一个好处计算效率高可以在整条路径上快速求解。但坏处也很明显——当特征间存在强相关时路径的切换点很容易受微小扰动影响训练集稍微变一点选中的特征就换了。Elastic Net因为加入了L2项目标函数变成强凸的整个解路径变得平滑得多。这带来两个实际好处预测精度更稳定对训练集的扰动不敏感在p n特征数远多于样本数的场景下依然有稳定的解。 这点是Lasso做不到的——当特征数超过样本数时Lasso最多只能选出n个非零特征这个上限在实际高维问题中往往是个硬约束。3. 实操过程与核心环节实现3.1 实验环境与数据集设计为了让大家直观看到两者的差异我用Python做了一组对比实验。环境是Python 3.10scikit-learn 1.3numpy 1.24。数据集用make_regression模拟生成在这里我特意构造了高度相关的特征组import numpy as np import pandas as pd from sklearn.datasets import make_regression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.linear_model import Lasso, ElasticNet, LinearRegression from sklearn.metrics import mean_squared_error, r2_score # 生成特征指定有效特征数量 X, y, coef make_regression( n_samples200, n_features50, n_informative10, noise20, coefTrue, random_state42 ) # 构造特征之间的强相关性 # 让第10~20个特征与第0~9个特征高度相关 for i in range(10, 20): X[:, i] X[:, i - 10] np.random.normal(0, 0.1, size200) # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 ) # 标准化 scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test)做特征标准化这一步非常重要。L1和L2惩罚都是针对系数大小的如果特征的量纲不一致惩罚项就会偏向数值大的特征导致结果失真。使用standardScaler确保所有特征处于同一量纲下再进入模型。我构造这个数据集的逻辑是50个特征中只有10个是真正有效的同时额外制造了10个与真实特征高度相关的“陪跑”特征用它们来检验两种方法对相关特征组的处理态度——是只挑一个代表还是把整组都保留。3.2 Lasso和Elastic Net的对比实现接下来分别训练两种模型并调整关键参数from sklearn.model_selection import GridSearchCV # 定义模型 lasso Lasso(max_iter100000) elastic_net ElasticNet(max_iter100000) # 为两种模型分别设置参数网格 lasso_params {alpha: np.logspace(-3, 1, 50)} en_params { alpha: np.logspace(-3, 1, 50), l1_ratio: [0.1, 0.3, 0.5, 0.7, 0.9, 1.0] } # 网格搜索 交叉验证 lasso_cv GridSearchCV(lasso, lasso_params, cv5, scoringneg_mean_squared_error) en_cv GridSearchCV(elastic_net, en_params, cv5, scoringneg_mean_squared_error) lasso_cv.fit(X_train_scaled, y_train) en_cv.fit(X_train_scaled, y_train) print(Lasso best alpha:, lasso_cv.best_params_) print(ElasticNet best params:, en_cv.best_params_) # 在测试集上评估 lasso_best lasso_cv.best_estimator_ en_best en_cv.best_estimator_ y_pred_lasso lasso_best.predict(X_test_scaled) y_pred_en en_best.predict(X_test_scaled) print(Lasso RMSE:, mean_squared_error(y_test, y_pred_lasso, squaredFalse)) print(Lasso R2:, r2_score(y_test, y_pred_lasso)) print(ElasticNet RMSE:, mean_squared_error(y_test, y_pred_en, squaredFalse)) print(ElasticNet R2:, r2_score(y_test, y_pred_en))我运行多次这类对比实验后发现在特征强相关的情况下Elastic Net的RMSE通常比Lasso低5%到15%而R²也会高一些。背后的原因就是Elastic Net不会丢掉整组相关特征的信息量而是把它们作为一个整体纳入模型预测自然更稳。3.3 观察稀疏性与特征选择结果只看预测指标还不够我们更要关注两者的稀疏性差异——也就是选出了多少特征、选了哪些特征。我加了这一段代码来检查# 提取系数 coef_lasso lasso_best.coef_ coef_en en_best.coef_ # 统计非零系数数量 n_nonzero_lasso np.sum(coef_lasso ! 0) n_nonzero_en np.sum(coef_en ! 0) print(fLasso 非零特征数量: {n_nonzero_lasso}) print(fElasticNet 非零特征数量: {n_nonzero_en}) # 查看前20个特征的系数分布 for i in range(20): print(f特征{i:02d}: Lasso{coef_lasso[i]:.3f} ElasticNet{coef_en[i]:.3f})我见过的典型输出是Lasso选出了15到18个非零特征Elastic Net选出了25到30个。关键在于看第10到19个“陪跑”特征系数的状态——Lasso往往从中挑一两个把系数分给它们而Elastic Net会把它们和对应的原始特征组一起保留系数也相对均匀。这直接回答了标题里“两者的区别”这个问题如果业务场景希望模型简洁、便于解释选Lasso如果希望预测稳健、不丢弃相关信息选Elastic Net。3.4 调试max_iter和收敛警告在实操中用Lasso或ElasticNet时会频繁遇到ConvergenceWarning。尤其是当alpha比较小、数据量大或特征量纲差异大的时候坐标下降算法迭代次数不够模型没有收敛就返回了。我的经验是先设一个比较大的max_iter比如100000。如果仍然报收敛警告优先检查数据是否需要标准化。大多数情况下做完标准化之后警告就消失了。另外一个小技巧是通过tol参数调整收敛阈值。默认是0.0001如果数据量大可以适当放宽到0.001加速收敛。但别放太宽否则模型精度会受影响。我自己常用的配置是model ElasticNet(alpha0.01, l1_ratio0.5, max_iter100000, tol0.0001)3.5 用坐标下降法理解求解差异如果你想从求解算法层面理解两者的区别sklearn里两者用的都是坐标下降法coordinate descent。核心思路是每次固定其他系数只优化其中一个系数然后轮流迭代直到收敛。Lasso的目标函数里有绝对值项它的系数更新公式里有软阈值算子soft-thresholding简单说就是如果某个系数算出来小于一个阈值就直接把它置零。这就是Lasso产生精确稀疏解的机制。Elastic Net的更新公式在软阈值基础上多了一个L2的收缩项相当于每轮更新时系数先按一个比例缩小再做软阈值处理。这个多出来的缩小动作让系数的变化路径更平滑、不会剧烈来回跳动在特征高度相关时不至于频繁出现“这边刚选中、那边又被踢掉”的抖动。4. 常见问题与排查技巧实录4.1 高频问题速查表问题可能原因排查与解决报错ConvergenceWarning数据未标准化、max_iter太小先做StandardScaler调大max_iter适当放宽tol特征系数全变成0alpha太大惩罚过重调小alpha用交叉验证GridSearchCV重搜特征系数都不为0模型不稀疏alpha太小或l1_ratio太小增大alpha检查l1_ratio越接近1稀疏性越强Lasso在不同训练集上选的特征不一样特征间强相关改用Elastic Net设置l1_ratio在0.3到0.7之间Lasso在n_samples n_features时报错或效果差高维小样本场景的天然局限优先Elastic Net它的解在高维下更稳定标准化后系数还是很大特征间共线性严重配合VIF检查或改用Elastic Net预测结果方差大数据中有离群点先处理离群值再用Elastic Net结果跟LinearRegression对比相差巨大数据量太小正则化影响过强缩小alpha确保你确实需要正则化场景4.2 特征选择结果不一致的坑我实际在业务项目里踩过最深的一个坑是用Lasso做特征筛选在训练集上选了AB两个特征换了一套交叉验证折选出来的变成AC两个特征。整个特征筛选结果不稳定导致后续建模流程里的特征列表频繁变动业务方根本没法接受。后来我把Lasso换成Elastic Netl1_ratio0.5同样的数据、同样的交叉验证筛选结果就稳定多了。不是说Elastic Net每次选的特征一定一样但整体稳定性显著提升。原因就是我们前面提到过的强凸性——Elastic Net的目标函数在参数空间里只有一个全局最优且更平滑不像Lasso在某些区域几乎是平坦的微小的数据扰动就会让最优点跳到完全不同的坐标。4.3 什么时候无脑用Lasso什么时候换Elastic Net做机器学习其实没有银弹这里我直接给几条经验规则用多了之后基本可以闭眼选特征数量中等几十到几百且相关性不高首选Lasso。它简单、稀疏性强、结果好解释一张系数表就能写进业务报告。特征存在分组相关性比如多个特征来自同一条业务链路选Elastic Net。设置l1_ratio0.5起步再往两边试探。特征数量远大于样本量比如基因数据、文本TF-IDF矩阵优先Elastic Net。Lasso最多选n个特征这个限制在这种场景下太伤。模型需要上线长期跑稳定性比解释性重要偏好Elastic Net。需要做严格的业务解释必须明确告诉老板哪些特征影响付费率偏好Lasso。4.4 调参顺序与稳定经验sklearn里Elastic Net有两个关键参数调参顺序很有讲究。我的习惯是先固定l1_ratio0.5对alpha做网格搜索或LassoCV风格的回调找到一个大致最优区间在这个区间周围对l1_ratio在[0.1, 0.3, 0.5, 0.7, 0.9, 1.0]里遍历同时微调alpha观察训练集和测试集的表现差距如果训练集远好于测试集说明alpha太小加大惩罚如果两者表现都差说明alpha太大减小惩罚。这里有个容易忽略的操作alpha与l1_ratio是相互影响的。alpha控制整体惩罚强度l1_ratio控制L1占比。当l1_ratio从0.5调到0.9时L1比例变高模型更稀疏但整体惩罚的“形状”变了最优alpha也会跟着变。所以不要只调一个参数、另一个固定不变至少要两轮交叉搜索。5. 与其他主流回归模型的横评5.1 正则化线性回归家族对比网上经常把Lasso、Elastic Net和岭回归放在一起比较。这里我补一张我平时自用的对照表模型惩罚项特征选择处理共线性高维表现模型解释性普通线性回归无无差不适用高岭回归L2无好较好中LassoL1有一般有限制高Elastic NetL1L2有好好中普通线性回归在高维或者强共线性下完全不适用系数会崩岭回归能解决共线性问题但不会丢掉任何特征解释性差一些Lasso帮你选特征但在强相关特征面前会显得武断Elastic Net合了两家之长代价是多了个l1_ratio要调。5.2 与树模型、SVR等非线性模型的边界顺带提一句热搜词里出现的随机森林回归、XGBoost回归、支持向量回归SVR、逻辑回归它们跟本文章的主角完全属于两类赛道适用场景边界要分清。随机森林回归擅长非线性关系、特征交互复杂的场景不需要对数据做标准化抗过拟合能力强但没法输出一个简洁的线性公式也不方便做精确的特征影响方向解释。XGBoost回归在结构化数据竞赛里基本是屠榜级别的存在各种复杂的非线性关系它都能拟合代价是模型规模大、调参更复杂、部署和推理成本较高。支持向量回归SVR适合中等规模、高维且样本量不夸张的场景对核函数敏感调参成本高落地不算方便。逻辑回归虽然名字里带“回归”但本质是分类模型输出概率不是用来预测连续值的别混用。我的判断标准是这样的如果你的业务方需要签合同式的结果解释比如“年龄每增加一岁付费概率变化多少个百分点”线性正则化回归是优选此时Lasso和Elastic Net都是趁手工具如果业务方只关心预测准不准不在乎中间过程那XGBoost、随机森林往往是更省事的选择。6. 我的经验总结与选型建议用到现在我个人的体会是Lasso和Elastic Net从来不是“谁替代谁”的关系而是“不同场景下谁更合适”的关系。Lasso的意义在于极致的简洁和可解释性一行系数表就能向业务方交代模型逻辑Elastic Net的意义在于稳定和稳健尤其当你面对一堆互相纠缠的特征、又必须把它们全部纳入模型时它比Lasso可靠得多。最后分享一个小技巧。在项目初期不确定选哪个模型时你完全可以用一组小实验快速验证同一份数据分别跑Lasso和Elastic Net的交叉验证比较两者的RMSE均值与方差。如果RMSE均值接近但Lasso的方差特别大果断改用Elastic Net如果Lasso的RMSE均值显著更低那就继续用Lasso。这个快速测试方法我用了很多年基本一测一个准比反复翻文档、纠结理论差异高效得多。另外一个值得扩展的方向是把Elastic Net当作特征筛选器先筛一轮特征再把这些特征喂给XGBoost或随机森林做最终建模。这种“Elastic Net筛选树模型拟合”的组合在多个项目里都帮我拿到了比单模型更好的线上表现——相当于先用线性模型砍掉无关噪音再让非线性模型专注捕捉剩下的复杂关系。如果你正在做回归建模不妨试试这条组合路径。