You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用enet(lambda=0)与lars(type="lasso")复现LASSO变量选择结果不一致

问题:elasticnet::enet与lars::lars实现LASSO时结果不一致的原因及解决办法

问题背景

我在研究中使用R语言elasticnet包的enet()函数,对260k个蒙特卡洛方法生成的合成数据集执行LASSO回归,并计算变量选择的性能指标。为验证结果可复现性,设置相同随机种子后改用lars包的lars(type="lasso")复现,但变量选择结果及性能指标存在明显差异——无论是"top 50"测试数据集还是大规模测试,结果均不一致。

原enet实现代码

set.seed(11)
system.time(LASSO_fits <- lapply(X = datasets, function(i) 
               elasticnet::enet(x = as.matrix(dplyr::select(i, 
                                         starts_with("X"))), 
               y = i$Y, lambda = 0, normalize = FALSE)))

提取选中变量(enet)

LASSO_Coeffs <- lapply(LASSO_fits, 
                       function(i) predict(i, 
                                           x = as.matrix(dplyr::select(i, starts_with("X"))), 
                                           s = 0.1, mode = "fraction", 
                                           type = "coefficients")[["coefficients"]])
IVs_Selected <- lapply(LASSO_Coeffs, function(i) names(i[i > 0]))

lars复现代码

set.seed(11)     # 确保可复现
system.time(LASSO.Lars.fits <- lapply(datasets, function(i) 
  lars(x = as.matrix(select(i, starts_with("X"))), 
         y = i$Y, type = "lasso")))

提取选中变量(lars)

LASSO.Lars.Coeffs <- lapply(LASSO.Lars.fits, 
                       function(i) predict(i, 
                                           x = as.matrix(dplyr::select(i, starts_with("X"))), 
                                           s = 0.1, mode = "fraction", 
                                           type = "coefficients")[["coefficients"]])
IVs.Selected.by.Lars <- lapply(LASSO.Lars.Coeffs, function(i) names(i[i > 0]))

差异原因分析

  1. 核心算法不同
    elasticnet::enet采用坐标下降法求解LASSO,而lars::lars使用**最小角回归(LARS)**算法生成正则化路径。两种算法的路径生成逻辑、变量选择顺序(尤其存在高度相关变量时)、收敛条件均有固有差异,即使目标函数一致,也会导致中间结果和最终变量选择的不同。

  2. 正则化强度的fraction定义不一致
    两个包的predict()函数中mode="fraction"的含义不同:

    • elasticnet的fraction是指从全正则化(系数全为0)到无正则化(OLS解)的路径比例;
    • lars的fraction是指LARS路径的长度比例(从原点到OLS解的路径长度占比)。
      这意味着s=0.1在两个包中对应的实际正则化强度并不相同,是结果差异的关键因素。
  3. 输入处理与参数默认值差异
    尽管都设置了normalize=FALSE,但两个包对输入矩阵的内部数值处理(如截距项计算、矩阵存储精度)、收敛阈值(如enet的maxit、lars的eps)默认值不同,进一步放大了结果差异。

解决办法

  1. 统一正则化强度的指定方式
    放弃mode="fraction",改用具体的lambda值来匹配正则化强度。例如先从其中一个拟合结果中提取对应目标fraction的lambda,再用该lambda值在另一个包中预测:

    # 从第一个lars拟合结果中获取对应fraction=0.1的lambda
    target_fraction <- 0.1
    lars_fit_example <- LASSO.Lars.fits[[1]]
    lambda_idx <- which.min(abs(lars_fit_example$fraction - target_fraction))
    matched_lambda <- lars_fit_example$lambda[lambda_idx]
    
    # 用匹配后的lambda在enet中预测
    LASSO_Coeffs_matched <- lapply(LASSO_fits, function(i) 
      predict(i, s = matched_lambda, mode = "lambda", type = "coefficients")[["coefficients"]])
    
  2. 统一使用同一算法包
    若需严格复现结果,建议全程使用同一个包的LASSO实现。同时推荐使用更主流、稳定性更好的glmnet包,其glmnet(x, y, alpha=1)对应纯LASSO,采用坐标下降法,结果一致性更强。

  3. 对齐输入处理与收敛参数

    • 确保两个拟合过程中输入的x矩阵、y向量完全一致(可通过all.equal()检查单个数据集的输入差异);
    • 手动设置相同的收敛参数,例如给enet()指定maxit=1e5,给lars()指定eps=1e-8,减少数值计算带来的误差。

内容的提问来源于stack exchange,提问作者Marlen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:41:11