L1正则化通过将某些权重精确地推向零来促使稀疏性,从而有效地进行特征选择。L2正则化,通常被称为权重衰减,它总体上偏好较小的权重,并倾向于将相关特征组一起收缩,而无需将它们设为零。如果你想兼得这些效果怎么办?也许你怀疑许多特征是无关紧要的(这提示使用L1),但你也认为可能存在重要的相关特征组,并且你不希望L1随意地从组中只挑选一个(这是L2表现出色的情况)。这正是弹性网络正则化发挥作用的地方。弹性网络线性结合了L1和L2惩罚项。不仅仅是在原始损失函数 $L_{orig}(w)$ 中添加一种惩罚项,而是添加两种:$$ L_{elastic}(w) = L_{orig}(w) + \lambda_1 ||w||_1 + \lambda_2 ||w||_2^2 $$在此,$||w||_1$ 是L1范数(权重绝对值之和),$||w||_2^2$ 是L2范数的平方(权重平方和)。超参数 $\lambda_1 \ge 0$ 和 $\lambda_2 \ge 0$ 分别控制L1和L2惩罚项的强度。通常,你会在库中看到这种公式有不同的参数化方式,这样可以更容易地调整整体强度与混合比例:$$ L_{elastic}(w) = L_{orig}(w) + \alpha \left( \rho ||w||_1 + \frac{1 - \rho}{2} ||w||_2^2 \right) $$在这种常见的参数化方式中:$\alpha$(alpha)是一个非负超参数,用于控制正则化的整体强度。如果 $\alpha = 0$,则没有正则化。较大的 $\alpha$ 会增加惩罚。$\rho$(rho,在库中常被称为 l1_ratio)是一个介于0和1之间的超参数,用于控制L1和L2之间的混合。如果 $\rho = 1$,弹性网络就变为纯粹的L1正则化。如果 $\rho = 0$,弹性网络就变为纯粹的L2正则化(按 $\alpha/2$ 缩放)。如果 $0 < \rho < 1$,则是两者的混合。这种组合的益处弹性网络旨在同时获得两者的优点:稀疏性: 像L1一样,它可以通过将一些权重设为零来进行特征选择,在处理许多特征可能无关紧要的高维数据时尤其有用。处理相关特征: 像L2一样,它倾向于同时选择相关特征组。如果特征A和B高度相关且有用,L1可能会随意地将其中一个设为零,而弹性网络(当 $\rho < 1$ 时)更可能以类似方式收缩它们的权重,从而可能使两者都保持非零。稳定性: 它通常比L1正则化表现出更高的稳定性,特别是在特征数量 ($p$) 远大于训练样本数量 ($n$) 时,或者当特征高度相关时。可视化约束我们可以将正则化看作是对可能权重值的限制。L1正则化对应一个菱形约束区域(在二维空间中),而L2对应一个圆形区域。弹性网络创建的约束区域结合了这两种形状,具有圆角,但与纯L2相比,仍然偏向于沿坐标轴的解。digraph G { rankdir=LR; node [shape=plaintext]; edge [arrowhead=none]; subgraph cluster_l1 { label = "L1 (菱形)"; bgcolor="#fff0f6"; l1_node [label=""]; l1_top [pos="0,1!", label=""]; l1_right [pos="1,0!", label=""]; l1_bottom [pos="0,-1!", label=""]; l1_left [pos="-1,0!", label=""]; l1_top -> l1_right -> l1_bottom -> l1_left -> l1_top [color="#f06595"]; } subgraph cluster_l2 { label = "L2 (圆形)"; bgcolor="#e7f5ff"; l2_node [label="", shape=circle, pos="3,0!", width=2, height=2, fixedsize=true, style=filled, fillcolor="#74c0fc"]; } subgraph cluster_elastic { label = "弹性网络"; bgcolor="#f3f0ff"; el_node [label=""]; # 弹性网络近似形状点(菱形和圆形混合) el_p1 [pos="6, 0.9!", label=""]; el_p2 [pos="6.5, 0.65!", label=""]; el_p3 [pos="6.9, 0!", label=""]; el_p4 [pos="6.5, -0.65!", label=""]; el_p5 [pos="6, -0.9!", label=""]; el_p6 [pos="5.5, -0.65!", label=""]; el_p7 [pos="5.1, 0!", label=""]; el_p8 [pos="5.5, 0.65!", label=""]; el_p1 -> el_p2 -> el_p3 -> el_p4 -> el_p5 -> el_p6 -> el_p7 -> el_p8 -> el_p1 [color="#845ef7", style=dashed]; } }L1、L2和弹性网络正则化在二维空间中约束区域的比较。弹性网络将L1的锐角(促使稀疏性)与L2的圆润度结合起来。弹性网络的调整使用弹性网络会引入两个需要调整的超参数:整体强度 $\alpha$ 和混合比例 $\rho$(l1_ratio)。找到最佳组合通常需要使用网格搜索或随机搜索等方法,在两个参数的可能值范围内进行,并使用验证集来评估性能。一种常见的方法是尝试 $\rho$ 的几个离散值(例如0.1、0.5、0.9、1.0),并为每个 $\rho$ 寻找最佳的 $\alpha$。实现方面的考虑尽管L2正则化(权重衰减)通常直接内置于Adam或SGD等优化器中,但在深度学习中实现L1或弹性网络惩罚项可能需要根据框架的不同而稍加注意。层特定正则化器: 某些框架(如Keras/TensorFlow)允许你在定义层时直接指定 kernel_regularizer、bias_regularizer 等。你通常可以在这里传递L1、L2或弹性网络正则化器。手动添加到损失: 一种更通用的方法,适用于PyTorch等框架,是在训练循环中手动计算相关模型参数的L1和L2惩罚项,并在反向传播之前将它们添加到主要的计算损失中。以下是手动添加惩罚项的PyTorch示例:import torch import torch.nn as nn # 假设 'model' 是你的神经网络 # 假设 'loss' 是从你的准则(例如,交叉熵损失)计算出的损失 alpha = 0.001 # 正则化强度 l1_ratio = 0.5 # 混合参数 (rho) l1_lambda = alpha * l1_ratio l2_lambda = alpha * (1 - l1_ratio) l1_penalty = 0.0 l2_penalty = 0.0 # 遍历模型参数(权重) for param in model.parameters(): if param.requires_grad and param.dim() > 1: # 通常只应用于权重矩阵 l1_penalty += torch.linalg.norm(param, ord=1) l2_penalty += torch.linalg.norm(param, ord=2)**2 # L2 范数平方 # 将原始损失与惩罚项结合 total_loss = loss + l1_lambda * l1_penalty + (l2_lambda / 2) * l2_penalty # (L2惩罚项中的1/2因子在第二种公式中很常见) # 现在进行反向传播 # total_loss.backward() # optimizer.step()注意:这只是一个示例。高效的实现通常会与框架的梯度计算或优化器步骤挂钩。请查阅你的框架文档,了解应用L1/L2组合惩罚项的推荐方法。当你认为稀疏性和处理相关预测器都是可取的时,弹性网络提供了一种灵活的正则化选项。它需要调整一个额外的超参数,但在某些情况下,它可以使模型比仅使用L1或L2正则化训练的模型具有更好的泛化能力。