sklearn中penalty仅指定正则类型,真正控制强度的是c参数:c越小正则越强;l1需配saga或liblinear求解器,l2默认用lbfgs;pytorch加正则须将惩罚项加入总loss并backward;早停需设min_delta和合理patience,保存最优而非最后模型。

sklearn LogisticRegression 的 penalty 和 C 参数怎么配才不白加正则
加了 penalty='l1' 或 penalty='l2' 却发现模型没变“更简单”,甚至准确率还掉了——大概率是 C 没调对。L1/L2 正则强度不是由 penalty 决定的,而是靠 C:它越小,惩罚越重;C=1e-4 比 C=1.0 激进得多。
-
penalty='l1'只在solver='liblinear'(旧版)或'saga'下才支持,用错 solver 会直接报ValueError: Solver lbfgs supports only 'l2' or 'none' penalties -
penalty='l2'默认搭配solver='lbfgs',速度快但不输出稀疏解;想做特征筛选,必须切到penalty='l1'+solver='saga' -
C不是越大越好。训练集准确率高、验证集掉得快,往往是C太大(正则太弱),该剪的参数没剪;反过来,系数全趋近于 0,验证集也不涨,说明C太小,欠拟合了
PyTorch 自定义 L1/L2 惩罚时,为什么 loss 不下降
手动在 loss 后加 l1_penalty = torch.sum(torch.abs(model.weight)) 很常见,但容易漏掉两个关键点:梯度没传回、权重没更新。
- 必须把正则项加进最终 loss 并反向传播,不能只算不 backward:
total_loss = criterion(y_pred, y_true) + 1e-4 * l1_penalty,然后total_loss.backward() - PyTorch 默认不会对
model.bias加正则(除非你显式写进去),但 bias 通常不该正则化;若误加了 bias 的 L1,可能导致模型无法拟合截距 - 正则系数(如
1e-4)量级要和主 loss 匹配。分类任务中 cross-entropy loss 一般在 0.1–2.0 之间,此时 L1 系数设成1e-3就可能压垮梯度;建议先从1e-5试起,观察 weight.grad.norm() 是否明显变小
早停法(EarlyStopping)触发太晚,验证损失已反复震荡
早停不是设个 patience=10 就完事。验证 loss 在最优值附近上下跳,但早停还在等“连续 10 次不降”,结果多训几十轮,过拟合已发生。
- 别只看 “loss 是否下降”,加一点容忍度:
min_delta=1e-4,避免数值抖动触发误停 -
patience要结合 epoch 数量级。如果总共只训 50 轮,patience=10就太长;200 轮以上,patience=7更稳妥 - 保存的是验证指标最好的模型,不是最后一轮。务必确认你在
torch.save()或model.save_weights()时,用的是best_model_state,而不是当前 model - 验证集太小(比如
TensorFlow/Keras 里用 kernel_regularizer 还是手动加 loss
两种都能加 L2,但行为不同:kernel_regularizer 是框架自动加到总 loss 里的,而手动 add_loss 需自己管理依赖。
立即学习“Python免费学习笔记(深入)”;
- 用
tf.keras.layers.Dense(64, kernel_regularizer=tf.keras.regularizers.l2(1e-4))最省心,Keras 会在 compile 时自动把正则项加入 total_loss,梯度、检查点、回调都兼容 - 手动
model.add_loss(1e-4 * tf.reduce_sum(tf.square(w)))虽灵活,但容易漏掉:必须在model.compile()前调用,且不能放在@tf.function里动态生成(否则图构建失败) - L2 正则系数在 Keras 里叫
l2(0.01),注意这不是乘数,而是 λ 值;它对应公式中的 λ/2 × Σw²,所以实际强度比 PyTorch 手动写的λ * sum(w**2)小一半
真正难的不是选哪个 API,而是正则强度和早停时机的配合——同一组超参,在不同数据划分下,早停轮次可能差 3 倍。跑实验时,验证集最好固定随机种子,不然连 baseline 都没法比。









