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

使用L1正则化或AdamW复现scikit-learn LASSO结果遇难题

解决方案
  • 先从纯线性模型对齐LASSO本质
    要复现sklearn的LASSO结果,先跳过全连接(带非线性激活)、LSTM这类模型,先实现纯线性回归模型——sklearn的LASSO是带L1正则的线性模型,PyTorch里直接用nn.Linear(in_features, 1),不添加任何非线性激活,确保模型结构和sklearn完全一致,避免非线性带来的固有偏差。

  • 正确实现L1正则化损失
    AdamW的权重衰减是L2正则的变种,和LASSO的L1正则逻辑完全不同,必须显式计算L1惩罚项:

    def lasso_loss(outputs, targets, model, alpha):
        # 对齐sklearn的损失尺度:sklearn用(1/(2*n_samples))*MSE,PyTorch默认MSE是均值
        mse_loss = torch.sum((outputs - targets)**2) / (2 * len(targets))
        # 仅对权重施加L1惩罚,偏置项不惩罚(和sklearn默认行为一致)
        l1_penalty = alpha * sum(p.abs().sum() for name, p in model.named_parameters() if 'weight' in name)
        return mse_loss + l1_penalty
    

    如果sklearn设置了fit_intercept=False,再把偏置项也加入L1惩罚。

  • 换用凸优化专用优化器
    sklearn的LASSO用坐标下降或LBFGS这类针对凸问题的算法,AdamW这类自适应优化器不适合凸问题的精确求解,容易产生损失噪声:

    • 优先用LBFGS:这是最接近sklearn求解逻辑的优化器,训练时需要自定义闭包计算损失和梯度:
      optimizer = torch.optim.LBFGS(model.parameters(), lr=1.0, max_iter=1000, tolerance_grad=1e-7, tolerance_change=1e-9)
      for epoch in range(10):
          def closure():
              optimizer.zero_grad()
              outputs = model(X_train)
              loss = lasso_loss(outputs, y_train, model, alpha)
              loss.backward()
              return loss
          optimizer.step(closure)
      
    • 若用SGD,必须关闭动量(凸问题不需要动量),配合全量数据训练:
      optimizer = torch.optim.SGD(model.parameters(), lr=1e-2, momentum=0)
      # 训练时用全量数据,避免小批量带来的损失波动
      for epoch in range(500):
          optimizer.zero_grad()
          outputs = model(X_train)
          loss = lasso_loss(outputs, y_train, model, alpha)
          loss.backward()
          optimizer.step()
      
  • 对齐数据预处理与初始化

    • 数据标准化:sklearn的LASSO默认对特征做标准化(StandardScaler),必须确保PyTorch的训练数据和sklearn用完全相同的预处理流程——对X做均值0、方差1的标准化,y的处理逻辑也要完全对齐。
    • 模型初始化:sklearn的线性模型默认初始化权重为0,偏置为训练集y的均值(当fit_intercept=True时),PyTorch里手动对齐:
      with torch.no_grad():
          model.weight.fill_(0.0)
          model.bias.fill_(y_train.mean().item())
      
  • 消除训练损失噪声的关键操作

    • 用全量数据训练:小批量SGD会导致损失波动,直接设置batch_size=len(X_train),每一步都用全量数据计算损失和梯度,和sklearn的全量优化逻辑一致。
    • 对齐正则化强度:sklearn的alpha和PyTorch的alpha存在尺度差异,sklearn的损失是(1/(2*n_samples))*MSE + alpha*L1,如果PyTorch用默认MSE(均值),需要把PyTorch的alpha设置为sklearn_alpha * len(X_train) / 2,确保正则化强度完全匹配。
  • 非线性模型逼近线性结果的技巧
    如果必须用全连接或LSTM:

    • 全连接网络:只用一层线性层,或多层但激活函数用nn.Identity()(恒等映射),同时限制隐层神经元数量,避免模型容量过大偏离线性特性。
    • LSTM:设置num_layers=1、hidden_size=1,强制隐藏状态初始化为0,且仅取最后一步的输出,同时大幅提高L1正则化强度,用全量数据训练,避免过拟合带来的偏差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:32:49