提升模型泛化能力:PyTorch的L1、L2、ElasticNet正则化技术深度解析与代码实现

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 本文将深入探讨L1、L2和ElasticNet正则化技术,重点关注其在PyTorch框架中的具体实现。关于这些技术的理论基础,建议读者参考相关理论文献以获得更深入的理解。

神经网络训练过程中,模型优化与过拟合防控之间的平衡是一个核心挑战。过拟合的模型虽然在训练数据上表现优异,但由于其复杂性导致模型将训练数据集的特定特征作为映射函数的组成部分,在实际部署环境中往往表现不佳,甚至出现性能急剧下降的问题。
正则化技术是解决此类问题的有效方法。本文将深入探讨L1、L2和ElasticNet正则化技术,重点关注其在PyTorch框架中的具体实现。关于这些技术的理论基础,建议读者参考相关理论文献以获得更深入的理解。通过本文的学习,您将掌握神经网络正则化的必要性、L1、L2和ElasticNet正则化的理论工作机制,以及在PyTorch中实现这些正则化技术的具体方法。

正则化技术的必要性

神经网络的训练目标是建立输入变量向量x与目标变量y之间的映射关系。这种映射关系可以用数学函数f表示,即y = f(x)。

映射函数的特性取决于模型的设计和拟合方式。如下图所示,使用相同的输入数据点集合,我们构建了两种不同的映射函数。第一种是具有三个自由度的多项式拟合(黄线),第二种是具有十个自由度的多项式拟合(蓝线)。

在评估哪种映射更接近真实情况时,具有较少自由度的黄线映射通常更为合理。蓝线所示的极端拟合情况在实际应用中极不可能成立,这种过度拟合现象往往源于模型对数据集中异常值的过度敏感性。

神经网络的训练过程需要使用输入数据(x集合)为每个样本生成预测结果(对应的y集合)。网络中的可训练参数协同工作以逼近真实的映射关系y = f(x),生成的逼近函数记为ŷ = f(x)。

在前向传播和模型优化过程中,我们无法预知模型将学习到类似黄线的合理映射还是类似蓝线的过拟合映射。模型仅基于损失函数的最小化进行学习,这可能导致学习到不理想的过拟合映射。

除了Dropout这一常用的正则化机制外,主要的正则化方法包括三种类型:L1正则化(也称为Lasso正则化)通过将所有权重的绝对值添加到损失函数中实现;L2正则化(也称为Ridge正则化)通过将所有权重的平方值添加到损失函数中实现;ElasticNet正则化则以加权方式组合L1和L2正则化。

接下来我们将详细研究每种正则化方法,并提供在PyTorch中的具体实现示例。

PyTorch中L1正则化的实现

在使用基于PyTorch的分类器进行二元交叉熵损失计算时,实现L1正则化需要将以下数值添加到损失函数中:

其中n表示权重参数的总数,通过遍历所有权重参数,计算每个权重值w_i的绝对值并求和得到L1正则化项。

L1正则化损失的计算公式为:

这里的

original_loss

表示原始的二元交叉熵损失,但该方法几乎适用于任何损失函数。

以下是PyTorch中L1正则化的完整实现方案。我们定义了一个继承自PyTorch

nn.Module

类的

MLP

类,并在该类中添加了

compute_l1_loss

函数,用于计算特定可训练参数的绝对值之和。在训练循环中,我们指定L1权重系数,收集所有参数,计算L1损失,并在误差反向传播之前将其添加到损失函数中。同时,在输出统计信息时显示损失的L1分量。

 importos  
importtorch  
fromtorchimportnn  
fromtorchvision.datasetsimportMNIST  
fromtorch.utils.dataimportDataLoader  
fromtorchvisionimporttransforms  

classMLP(nn.Module):  
  '''  
    多层感知器。  
  '''  
  def__init__(self):  
    super().__init__()  
    self.layers=nn.Sequential(  
      nn.Flatten(),  
      nn.Linear(28*28*1, 64),  
      nn.ReLU(),  
      nn.Linear(64, 32),  
      nn.ReLU(),  
      nn.Linear(32, 10)  
    )  

  defforward(self, x):  
    '''前向传播'''  
    returnself.layers(x)  

  defcompute_l1_loss(self, w):  
      returntorch.abs(w).sum()  


if__name__=='__main__':  

  # 设置固定的随机数种子  
  torch.manual_seed(42)  

  # 准备MNIST数据集  
  dataset=MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())  
  trainloader=torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)  

  # 初始化MLP  
  mlp=MLP()  

  # 定义损失函数和优化器  
  loss_function=nn.CrossEntropyLoss()  
  optimizer=torch.optim.Adam(mlp.parameters(), lr=1e-4)  

  # 运行训练循环  
  forepochinrange(0, 5): # 训练5个epoch  

    # 打印当前epoch  
    print(f'Starting epoch {epoch+1}')  

    # 遍历DataLoader获取训练数据  
    fori, datainenumerate(trainloader, 0):  

      # 获取输入数据和标签  
      inputs, targets=data  

      # 梯度清零  
      optimizer.zero_grad()  

      # 执行前向传播  
      outputs=mlp(inputs)  

      # 计算原始损失  
      loss=loss_function(outputs, targets)  

      # 计算L1正则化损失分量  
      l1_weight=1.0  
      l1_parameters= []  
      forparameterinmlp.parameters():  
          l1_parameters.append(parameter.view(-1))  
      l1=l1_weight*mlp.compute_l1_loss(torch.cat(l1_parameters))  

      # 将L1损失分量添加到总损失中  
      loss+=l1  

      # 执行反向传播  
      loss.backward()  

      # 执行优化步骤  
      optimizer.step()  

      # 打印训练统计信息  
      minibatch_loss=loss.item()  
      ifi%500==499:  
          print('Loss after mini-batch %5d: %.5f (of which %.5f L1 loss)'%  
                (i+1, minibatch_loss, l1))  
          current_loss=0.0  

  # 训练完成  
   print('Training process has finished.')

PyTorch中L2正则化的实现

L2正则化在PyTorch中同样可以便捷地实现。与L1正则化不同,L2正则化计算权重值的平方而非绝对值。具体而言,我们将\sum_{i=1}^{n} w_i^2添加到损失函数中。以下示例展示了在PyTorch中应用L2正则化的具体方法:

 importos  
importtorch  
fromtorchimportnn  
fromtorchvision.datasetsimportMNIST  
fromtorch.utils.dataimportDataLoader  
fromtorchvisionimporttransforms  

classMLP(nn.Module):  
  '''  
    多层感知器。  
  '''  
  def__init__(self):  
    super().__init__()  
    self.layers=nn.Sequential(  
      nn.Flatten(),  
      nn.Linear(28*28*1, 64),  
      nn.ReLU(),  
      nn.Linear(64, 32),  
      nn.ReLU(),  
      nn.Linear(32, 10)  
    )  

  defforward(self, x):  
    '''前向传播'''  
    returnself.layers(x)  

  defcompute_l2_loss(self, w):  
      returntorch.square(w).sum()  


if__name__=='__main__':  

  # 设置固定的随机数种子  
  torch.manual_seed(42)  

  # 准备MNIST数据集  
  dataset=MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())  
  trainloader=torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)  

  # 初始化MLP  
  mlp=MLP()  

  # 定义损失函数和优化器  
  loss_function=nn.CrossEntropyLoss()  
  optimizer=torch.optim.Adam(mlp.parameters(), lr=1e-4)  

  # 运行训练循环  
  forepochinrange(0, 5): # 训练5个epoch  

    # 打印当前epoch  
    print(f'Starting epoch {epoch+1}')  

    # 遍历DataLoader获取训练数据  
    fori, datainenumerate(trainloader, 0):  

      # 获取输入数据和标签  
      inputs, targets=data  

      # 梯度清零  
      optimizer.zero_grad()  

      # 执行前向传播  
      outputs=mlp(inputs)  

      # 计算原始损失  
      loss=loss_function(outputs, targets)  

      # 计算L2正则化损失分量  
      l2_weight=1.0  
      l2_parameters= []  
      forparameterinmlp.parameters():  
          l2_parameters.append(parameter.view(-1))  
      l2=l2_weight*mlp.compute_l2_loss(torch.cat(l2_parameters))  

      # 将L2损失分量添加到总损失中  
      loss+=l2  

      # 执行反向传播  
      loss.backward()  

      # 执行优化步骤  
      optimizer.step()  

      # 打印训练统计信息  
      minibatch_loss=loss.item()  
      ifi%500==499:  
          print('Loss after mini-batch %5d: %.5f (of which %.5f l2 loss)'%  
                (i+1, minibatch_loss, l2))  
          current_loss=0.0  

  # 训练完成  
   print('Training process has finished.')

L2损失的替代实现方法

基于L2的权重衰减也可以通过在优化器中设置

weight_decay

参数来实现。

weight_decay (float**, 可选) — 权重衰减 (L2惩罚) (默认值: 0)

PyTorch 文档

实现示例:

 optimizer=torch.optim.Adam(mlp.parameters(), lr=1e-4, weight_decay=1.0)

PyTorch中ElasticNet正则化的实现

ElasticNet正则化可以通过PyTorch高效实现。该正则化方法本质上是L1和L2损失的加权组合,权重之和为1.0。具体而言,我们将以下表达式添加到损失函数中:

其数学表达式为:

以下示例展示了在PyTorch中实现ElasticNet(L1+L2)正则化的具体方法。在这个实现中,MLP类提供了计算L1和L2损失的独立函数。在训练循环中,这两种损失以加权方式应用(权重分别为0.3和0.7)。在输出统计信息时,各损失分量也会显示在控制台中。

 importos  
importtorch  
fromtorchimportnn  
fromtorchvision.datasetsimportMNIST  
fromtorch.utils.dataimportDataLoader  
fromtorchvisionimporttransforms  

classMLP(nn.Module):  
  '''  
    多层感知器。  
  '''  
  def__init__(self):  
    super().__init__()  
    self.layers=nn.Sequential(  
      nn.Flatten(),  
      nn.Linear(28*28*1, 64),  
      nn.ReLU(),  
      nn.Linear(64, 32),  
      nn.ReLU(),  
      nn.Linear(32, 10)  
    )  

  defforward(self, x):  
    '''前向传播'''  
    returnself.layers(x)  

  defcompute_l1_loss(self, w):  
      returntorch.abs(w).sum()  

  defcompute_l2_loss(self, w):  
      returntorch.square(w).sum()  


if__name__=='__main__':  

  # 设置固定的随机数种子  
  torch.manual_seed(42)  

  # 准备MNIST数据集  
  dataset=MNIST(os.getcwd(), download=True, transform=transforms.ToTensor())  
  trainloader=torch.utils.data.DataLoader(dataset, batch_size=10, shuffle=True, num_workers=1)  

  # 初始化MLP  
  mlp=MLP()  

  # 定义损失函数和优化器  
  loss_function=nn.CrossEntropyLoss()  
  optimizer=torch.optim.Adam(mlp.parameters(), lr=1e-4)  

  # 运行训练循环  
  forepochinrange(0, 5): # 训练5个epoch  

    # 打印当前epoch  
    print(f'Starting epoch {epoch+1}')  

    # 遍历DataLoader获取训练数据  
    fori, datainenumerate(trainloader, 0):  

      # 获取输入数据和标签  
      inputs, targets=data  

      # 梯度清零  
      optimizer.zero_grad()  

      # 执行前向传播  
      outputs=mlp(inputs)  

      # 计算原始损失  
      loss=loss_function(outputs, targets)  

      # 指定L1和L2权重系数  
      l1_weight=0.3  
      l2_weight=0.7  

      # 计算L1和L2正则化损失分量  
      parameters= []  
      forparameterinmlp.parameters():  
          parameters.append(parameter.view(-1))  
      l1=l1_weight*mlp.compute_l1_loss(torch.cat(parameters))  
      l2=l2_weight*mlp.compute_l2_loss(torch.cat(parameters))  

      # 将L1和L2损失分量添加到总损失中  
      loss+=l1  
      loss+=l2  

      # 执行反向传播  
      loss.backward()  

      # 执行优化步骤  
      optimizer.step()  

      # 打印训练统计信息  
      minibatch_loss=loss.item()  
      ifi%500==499:  
          print('Loss after mini-batch %5d: %.5f (of which %.5f L1 loss; %0.5f L2 loss)'%  
                (i+1, minibatch_loss, l1, l2))  
          current_loss=0.0  

  # 训练完成  
   print('Training process has finished.')

总结

本文深入探讨了神经网络正则化的重要性,详细分析了L1、L2和ElasticNet正则化的理论机制,并通过具体示例演示了这些技术在PyTorch中的实现方法。正则化技术是防止模型过拟合的关键手段,通过在损失函数中添加权重惩罚项,能够有效提升模型的泛化能力。

L1正则化通过权重的绝对值惩罚促进稀疏性,L2正则化通过权重的平方惩罚控制模型复杂度,而ElasticNet正则化则结合两者的优势,提供了更灵活的正则化策略。在实际应用中,选择合适的正则化方法和权重系数对于获得最佳的模型性能至关重要。

希望通过本文的学习,读者能够掌握在深度学习项目中应用正则化技术的方法,并理解其在提升模型性能中的重要作用。

https://avoid.overfit.cn/post/9848d169f0a74458b8dbec5591e8885e

作者:Francesco Franco

目录
相关文章
|
2月前
|
机器学习/深度学习 搜索推荐 PyTorch
基于昇腾用PyTorch实现CTR模型DIN(Deep interest Netwok)网络
本文详细讲解了如何在昇腾平台上使用PyTorch训练推荐系统中的经典模型DIN(Deep Interest Network)。主要内容包括:DIN网络的创新点与架构剖析、Activation Unit和Attention模块的实现、Amazon-book数据集的介绍与预处理、模型训练过程定义及性能评估。通过实战演示,利用Amazon-book数据集训练DIN模型,最终评估其点击率预测性能。文中还提供了代码示例,帮助读者更好地理解每个步骤的实现细节。
|
2月前
|
机器学习/深度学习 PyTorch 编译器
深入解析torch.compile:提升PyTorch模型性能、高效解决常见问题
PyTorch 2.0推出的`torch.compile`功能为深度学习模型带来了显著的性能优化能力。本文从实用角度出发,详细介绍了`torch.compile`的核心技巧与应用场景,涵盖模型复杂度评估、可编译组件分析、系统化调试策略及性能优化高级技巧等内容。通过解决图断裂、重编译频繁等问题,并结合分布式训练和NCCL通信优化,开发者可以有效提升日常开发效率与模型性能。文章为PyTorch用户提供了全面的指导,助力充分挖掘`torch.compile`的潜力。
171 17
|
2月前
|
机器学习/深度学习 PyTorch API
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
本文深入探讨神经网络模型量化技术,重点讲解训练后量化(PTQ)与量化感知训练(QAT)两种主流方法。PTQ通过校准数据集确定量化参数,快速实现模型压缩,但精度损失较大;QAT在训练中引入伪量化操作,使模型适应低精度环境,显著提升量化后性能。文章结合PyTorch实现细节,介绍Eager模式、FX图模式及PyTorch 2导出量化等工具,并分享大语言模型Int4/Int8混合精度实践。最后总结量化最佳策略,包括逐通道量化、混合精度设置及目标硬件适配,助力高效部署深度学习模型。
240 21
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
|
2月前
|
机器学习/深度学习 算法 PyTorch
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
深度学习近年来在多个领域取得了显著进展,但其核心组件——人工神经元和反向传播算法自提出以来鲜有根本性突破。穿孔反向传播(Perforated Backpropagation)技术通过引入“树突”机制,模仿生物神经元的计算能力,实现了对传统神经元的增强。该技术利用基于协方差的损失函数训练树突节点,使其能够识别神经元分类中的异常模式,从而提升整体网络性能。实验表明,该方法不仅可提高模型精度(如BERT模型准确率提升3%-17%),还能实现高效模型压缩(参数减少44%而无性能损失)。这一革新为深度学习的基础构建模块带来了新的可能性,尤其适用于边缘设备和大规模模型优化场景。
84 16
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
|
3月前
|
机器学习/深度学习 存储 缓存
加速LLM大模型推理,KV缓存技术详解与PyTorch实现
大型语言模型(LLM)的推理效率是AI领域的重要挑战。本文聚焦KV缓存技术,通过存储复用注意力机制中的Key和Value张量,减少冗余计算,显著提升推理效率。文章从理论到实践,详细解析KV缓存原理、实现与性能优势,并提供PyTorch代码示例。实验表明,该技术在长序列生成中可将推理时间降低近60%,为大模型优化提供了有效方案。
306 15
加速LLM大模型推理,KV缓存技术详解与PyTorch实现
|
3月前
|
存储 自然语言处理 PyTorch
从零开始用Pytorch实现LLaMA 4的混合专家(MoE)模型
近期发布的LLaMA 4模型引入混合专家(MoE)架构,以提升效率与性能。尽管社区对其实际表现存在讨论,但MoE作为重要设计范式再次受到关注。本文通过Pytorch从零实现简化版LLaMA 4 MoE模型,涵盖数据准备、分词、模型构建(含词元嵌入、RoPE、RMSNorm、多头注意力及MoE层)到训练与文本生成全流程。关键点包括MoE层实现(路由器、专家与共享专家)、RoPE处理位置信息及RMSNorm归一化。虽规模小于实际LLaMA 4,但清晰展示MoE核心机制:动态路由与稀疏激活专家,在控制计算成本的同时提升性能。完整代码见链接,基于FareedKhan-dev的Github代码修改而成。
98 9
从零开始用Pytorch实现LLaMA 4的混合专家(MoE)模型
|
3月前
|
机器学习/深度学习 数据可视化 机器人
比扩散策略更高效的生成模型:流匹配的理论基础与Pytorch代码实现
扩散模型和流匹配是生成高分辨率数据(如图像和机器人轨迹)的先进技术。扩散模型通过逐步去噪生成数据,其代表应用Stable Diffusion已扩展至机器人学领域形成“扩散策略”。流匹配作为更通用的方法,通过学习时间依赖的速度场将噪声转化为目标分布,适用于图像生成和机器人轨迹生成,且通常以较少资源实现更快生成。 本文深入解析流匹配在图像生成中的应用,核心思想是将图像视为随机变量的实现,并通过速度场将源分布转换为目标分布。文中提供了一维模型训练实例,展示了如何用神经网络学习速度场,以及使用最大均值差异(MMD)改进训练效果。与扩散模型相比,流匹配结构简单,资源需求低,适合多模态分布生成。
165 13
比扩散策略更高效的生成模型:流匹配的理论基础与Pytorch代码实现
|
3月前
|
机器学习/深度学习 编解码 PyTorch
从零实现基于扩散模型的文本到视频生成系统:技术详解与Pytorch代码实现
本文介绍了一种基于扩散模型的文本到视频生成系统,详细展示了模型架构、训练流程及生成效果。通过3D U-Net结构和多头注意力机制,模型能够根据文本提示生成高质量视频。
121 1
从零实现基于扩散模型的文本到视频生成系统:技术详解与Pytorch代码实现
|
4月前
|
机器学习/深度学习 JavaScript PyTorch
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
生成对抗网络(GAN)的训练效果高度依赖于损失函数的选择。本文介绍了经典GAN损失函数理论,并用PyTorch实现多种变体,包括原始GAN、LS-GAN、WGAN及WGAN-GP等。通过分析其原理与优劣,如LS-GAN提升训练稳定性、WGAN-GP改善图像质量,展示了不同场景下损失函数的设计思路。代码实现覆盖生成器与判别器的核心逻辑,为实际应用提供了重要参考。未来可探索组合优化与自适应设计以提升性能。
263 7
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
|
5月前
|
机器学习/深度学习 算法 安全
用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解
本文详细介绍了DeepSeek R1模型的构建过程,涵盖从基础模型选型到多阶段训练流程,再到关键技术如强化学习、拒绝采样和知识蒸馏的应用。
549 3
用PyTorch从零构建 DeepSeek R1:模型架构和分步训练详解

推荐镜像

更多