当前位置: 首页 > article >正文

神经网络常用归一化和正则化方法解析(二)

🎀个人主页: https://zhangxiaoshu.blog.csdn.net
📢欢迎大家:关注🔍+点赞👍+评论📝+收藏⭐️,如有错误敬请指正!
💕未来很长,值得我们全力奔赴更美好的生活!

前言

神经网络中的归一化和正则化是为了提高训练稳定性、加速收敛、减少过拟合等目的而采取的一系列技术手段,本文对常见的正则化方法L1正则化、L2正则化、dropout 和 Early Stopping进行介绍。有关常见的归一化方法如,批归一化BN、层归一化LN、实例归一化IN、组归一化GN的介绍参见我写的这篇文章:神经网络常用归一化和正则化方法解析(一)


文章目录

  • 前言
  • 一、归一化和正则化
    • 1. 归一化(Normalization)
    • 2. 正则化(Regularization)
  • 二、常用正则化方法
    • 1. L1正则化
    • 2. L2正则化
    • 3. Dropout/DropPath
    • 4. Early Stopping
    • 5. PyTorch演示
  • 总结


一、归一化和正则化

1. 归一化(Normalization)

归一化是一组技术,用于调整神经网络中输入数据的分布,以帮助网络更有效地学习。主要包括批归一化、层归一化、实例归一化和组归一化等。归一化的目标是使输入数据的分布更稳定,有助于缓解梯度消失或爆炸的问题,并提高网络的训练速度和泛化性能。

  • 加速收敛: 归一化可以帮助加速神经网络的收敛过程。在训练过程中,各层输入的分布可能会发生变化,导致训练过程不稳定。通过归一化,可以保持每层输入的分布相对稳定,有助于梯度的传播和权重的更新。

  • 缓解梯度消失/爆炸问题: 在深层网络中,梯度消失或爆炸是常见的问题。通过在每层输入上进行归一化,可以避免梯度在反向传播时变得非常小或非常大。

  • 更好的泛化能力: 归一化有助于提高模型的泛化能力,使其在未见过的数据上表现更好。

常见的归一化技术包括批归一化(Batch Normalization)、层归一化(Layer Normalization)实例归一化(Instance Normalization)、组归一化(Group Normalization)。

2. 正则化(Regularization)

正则化是一种用于控制模型复杂度、防止过拟合的技术。过拟合指的是模型在训练数据上表现很好,但在测试数据上表现较差,因为模型过度适应了训练数据的噪声和细节。

  • 防止过拟合: 正则化是一种减少模型在训练数据上过拟合的技术。

  • 控制权重的大小: 正则化通过在损失函数中添加额外的惩罚项,如L1正则化和L2正则化,可以控制模型参数的大小,防止其变得过于复杂。

  • 提高泛化能力: 正则化有助于提高模型在未见过的数据上的泛化能力,使其更好地适应新的输入。

常见的正则化技术包括L1正则化、L2正则化、dropout和Early Stopping。

综合来说,归一化和正则化在神经网络中的使用可以使模型更稳定、更容易训练,同时提高其泛化能力,从而更好地适应未见过的数据。归一化是一种数据处理的方法,旨在将数据缩放到相对一致的尺度,以便更好地进行比较和分析。归一化通常用于预处理数据,使得不同特征或不同样本的数值范围相对一致。 正则化是一种用于控制模型复杂度、防止过拟合的技术。正则化通过在模型的损失函数中添加额外的项,对模型参数进行惩罚,从而限制模型的复杂性。

  • 归一化适用于数据预处理,正则化适用于模型训练。 如果你的数据具有不同的尺度,可能需要进行归一化;如果你的模型在训练集上表现良好但在测试集上泛化能力差,可能需要考虑正则化。

  • 归一化通常是标准的数据预处理步骤,而正则化是训练模型时的一种策略。 在训练模型之前,你通常会对数据进行归一化,以便更好地训练模型。正则化则是在训练过程中使用的手段,用于控制模型的复杂度。

  • 具体选择取决于任务和模型。 在实际应用中,选择归一化和正则化的方法需要考虑具体任务、数据的特性以及所使用的模型。不同的场景可能需要不同的策略。

二、常用正则化方法

1. L1正则化

L1正则化概念和思想:

L1正则化是一种用于控制模型复杂度的技术,也称为Lasso正则化。其基本思想是在模型的损失函数中添加模型权重的L1范数,通过对权重的绝对值进行惩罚,促使模型的一些权重趋向于精确为零。这导致模型的稀疏性,即模型更倾向于使用少量重要的特征,而其他特征的权重趋向于为零。

L1正则化损失函数表达式:

L1正则化的损失函数表达式为:
L o s s L 1 = λ ∑ i ∣ w i ∣ Loss_{L1}=\lambda {\textstyle \sum_{i}^{}} \left | w_i\right | LossL1=λiwi

其中:

  • λ \lambda λ 是正则化强度,控制L1正则化的影响程度。
  • w i w_i wi是模型的第 i 个权重。

L1正则化的优缺点:

优点:

  • 特征选择: L1正则化促使模型中的某些权重变为零,因此具有特征选择的效果,有助于发现对任务最重要的特征。

  • 模型解释性: 模型变得更加稀疏,模型的结构更容易解释,可以看到哪些特征对输出的影响较大。

缺点:

  • 平滑性: L1正则化对权重的惩罚不是平滑的,可能导致一些权重非常接近零,而另一些权重较大,模型参数的稀疏性可能使得模型对输入数据中的微小变化更为敏感。

  • 参数量减少: 虽然L1正则化有助于特征选择,但有时候也可能导致模型的参数量过度减少,进而导致模型的表达能力下降。

总体而言,L1正则化是一种有用的正则化技术,尤其适用于高维数据和需要特征选择的情况。在实际应用中,通常需要通过实验来调整正则化强度,以达到最佳的模型性能。

2. L2正则化

L2正则化概念和思想:

L2正则化是一种用于控制模型复杂度的技术,也称为权重衰减(weight decay)。其基本思想是在模型的损失函数中添加模型权重的L2范数,通过对权重的平方进行惩罚,促使模型的权重保持较小的值。L2正则化有助于防止模型参数过大,减少过拟合的风险。

L2正则化损失函数表达式:

L2正则化的损失函数表达式为:
L o s s L 2 = λ ∑ i ∣ w i 2 ∣ Loss_{L2}=\lambda {\textstyle \sum_{i}^{}} \left | w_{i}^{2} \right | LossL2=λi wi2
其中:

  • λ \lambda λ是正则化强度,控制L2正则化的影响程度。
  • w i w_i wi是模型的第 i 个权重。

L2正则化的优缺点:

优点:

  • 权重衰减: L2正则化通过对权重的平方进行惩罚,使得模型的权重保持较小的值,有助于防止过拟合。

  • 参数平滑性: L2正则化的平方项对权重的惩罚是平滑的,有助于权重保持在较小的范围内,减少模型对输入数据中的微小变化的敏感性。

缺点:

  • 不适用于特征选择: 与L1正则化不同,L2正则化倾向于让所有的特征都对模型有一定的影响,而不会使得某些特征的权重精确为零,因此不具有特征选择的效果。

  • 不适用于稀疏模型: L2正则化不鼓励模型参数变得稀疏,因此在需要产生稀疏模型的情况下,L2正则化可能不是最佳选择。

总体而言,L2正则化是一种常用的正则化技术,通常用于减少模型的过拟合风险。在实际应用中,通常需要通过实验来调整正则化强度,以达到最佳的模型性能。

3. Dropout/DropPath

Dropout/DropPath正则化概念和思想:

在这里插入图片描述

Dropout/DropPath:在学习深度学习模型时,由于模型的参数过多、样本数量过少,导致了模型的过度拟合。在神经网络的训练中,常常会碰到一些问题。该方法具有较低的训练数据损失,具有较高的训练准确率。但是,测试数据的损失函数比较大,导致预测的准确性不高。

Dropout能在一定程度上减轻过度拟合,并能在某种程度上实现正规化。其基本原理是:在前向传播前进的过程中,使一个神经元的激活值以 p的概率不能工作,这在上图左图中可以看到。停止工作的神经元用虚线表示,与该神经元相连的相应传播过程将不在存在。这使得模型更加一般化,因为它不会依赖于一些局部特征。

DropPath类似于Dropout,不同的是Dropout 是对神经元随机“失效”,而DropPath是随机“失效”模型中的多分支结构。例如如上图右图所示,若x为输入的张量,其通道为[B,C,H,W],那么DropPath的含义为一个Batch_size中,在经过多分支结构时,随机有drop_prob的样本,不经过主干,而直接经过分支(图中虚线)进行恒等映射。这在一定程度上使模型泛化性更强。

Dropout/DropPath正则化的优缺点:

优点:

  • 减少过拟合: Dropout通过随机地丢弃一些神经元的输出,有助于减少神经网络的过拟合风险,提高泛化性能。

  • 不依赖于数据增强: 相对于一些需要大量数据增强的方法,Dropout在训练过程中直接对模型的结构进行改变,更为直观。

缺点:

  • 增加训练时间: 在训练过程中,每个迭代都需要随机地丢弃一部分神经元,这会导致模型的训练时间略有增加。

  • 不适用于所有情况: 对于一些小型数据集或本身不容易过拟合的任务,Dropout的效果可能相对较小。

总体而言,Dropout是一种常用的正则化技术,特别适用于大型深度神经网络,可以在一定程度上提高模型的鲁棒性。在实际应用中,通常需要根据具体任务和实验结果来选择合适的Dropout比例。

4. Early Stopping

早停法是一种用于防止神经网络过拟合的正则化技术。其基本思想是在训练过程中监控模型的性能,当模型在验证集上的性能不再提升甚至开始下降时,停止训练,以防止过拟合。
在这里插入图片描述

早停法的基本思想:

  • 训练过程中监控验证集性能: 在每个训练周期或固定的训练步骤之后,使用验证集评估模型性能。

  • 比较当前性能与历史最佳性能: 记录模型在验证集上的性能,并与之前的性能进行比较。如果当前性能超过历史最佳性能,更新最佳性能记录。

  • 设定停止条件: 定义一个容忍度阈值(例如,连续几次验证集性能没有提升),如果连续几轮性能没有提升达到设定的阈值,则停止训练。

  • 使用最佳模型参数: 在停止训练后,使用具有最佳性能的模型参数。

优缺点:

优点:

  • 防止过拟合: 早停法通过在模型性能达到最优时停止训练,有效地防止了过拟合,提高了模型的泛化能力。

  • 减少计算成本: 通过避免不必要的训练步骤,早停法可以减少计算成本,特别是在大型深度神经网络的训练过程中。

  • 提高训练效率: 由于早停法使模型更早地收敛,可以提高训练效率,特别是在资源有限的情况下。

缺点:

  • 可能错过最优点: 早停法的主要缺点是,由于提前停止训练,可能会错过在更多训练步骤中找到的更优的模型参数,特别是在复杂的模型或大规模数据集上。

  • 依赖于阈值的选择: 早停法的效果受到停止条件的选择影响,选择不当的停止条件可能导致过早或过晚地停止训练。

  • 不适用于所有场景: 早停法并非适用于所有问题和场景,特别是对于训练过程中性能波动较大的情况。

在实践中,早停法通常是一种非常有效的正则化策略,但需要根据具体的问题和数据集进行调整和优化。

5. PyTorch演示

下面是使用 PyTorch 进行简单演示 L1 正则化、L2 正则化、 Dropout和Early Stopping 的代码,在这个例子中,我们定义了一个带有 L1 和 L2 正则化项、Dropout 和 Early Stopping 的神经网络模型,并在训练函数中实现了 Early Stopping。在每个训练周期中,计算 L1 和 L2 正则化项,并在损失函数中添加这些项。在验证集上监控性能,如果连续几次性能没有提升,则触发 Early Stopping。这是一个简单的演示,实际使用时可能需要更复杂的模型和更复杂的早停策略。

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
import numpy as np

# 生成示例数据
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)

# 数据标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_val = scaler.transform(X_val)

# 转换为 PyTorch 的 Tensor
X_train_tensor = torch.FloatTensor(X_train)
y_train_tensor = torch.LongTensor(y_train)
X_val_tensor = torch.FloatTensor(X_val)
y_val_tensor = torch.LongTensor(y_val)

# 创建 DataLoader
train_dataset = TensorDataset(X_train_tensor, y_train_tensor)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)

# 定义模型
class RegularizedModel(nn.Module):
    def __init__(self, input_size, hidden_size, output_size, dropout_rate=0.5, l1_strength=0.001, l2_strength=0.001):
        super(RegularizedModel, self).__init__()
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.dropout = nn.Dropout(p=dropout_rate)
        self.fc2 = nn.Linear(hidden_size, output_size)
        self.l1_strength = l1_strength
        self.l2_strength = l2_strength

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.dropout(x)
        x = self.fc2(x)
        return x

# 训练函数
def train_model(model, train_loader, val_data, criterion, optimizer, num_epochs=100, early_stopping_patience=10):
    best_val_loss = float('inf')
    patience_counter = 0

    for epoch in range(num_epochs):
        model.train()
        for inputs, labels in train_loader:
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            
            # 添加 L1 和 L2 正则化项
            l1_loss = torch.norm(model.fc1.weight, 1)
            l2_loss = torch.norm(model.fc1.weight, 2)
            loss += model.l1_strength * l1_loss + model.l2_strength * l2_loss

            loss.backward()
            optimizer.step()

        # 在验证集上计算性能
        model.eval()
        with torch.no_grad():
            val_outputs = model(val_data[0])
            val_loss = criterion(val_outputs, val_data[1])

        print(f"Epoch [{epoch+1}/{num_epochs}], Training Loss: {loss.item()}, Validation Loss: {val_loss.item()}")

        # Early Stopping
        if val_loss < best_val_loss:
            best_val_loss = val_loss
            patience_counter = 0
        else:
            patience_counter += 1
            if patience_counter >= early_stopping_patience:
                print(f"Early stopping at epoch {epoch+1}...")
                break

# 初始化模型
input_size = X_train.shape[1]
hidden_size = 64
output_size = 2
model = RegularizedModel(input_size, hidden_size, output_size)

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 训练模型
val_data = (X_val_tensor, y_val_tensor)
train_model(model, train_loader, val_data, criterion, optimizer, num_epochs=100, early_stopping_patience=10)

总结

以下是对L1正则化、L2正则化、Dropout和Early Stopping这四种正则化方法的简要总结:

L1正则化:

  • 思想: 在损失函数中加入权重的绝对值之和,鼓励模型参数稀疏化,促使一些权重趋向于零。
  • 优点: 适用于希望通过减少不相关特征的权重来进行特征选择的场景。
  • 缺点: 产生稀疏权重的特性可能不适用于所有问题,对于深度学习等复杂模型的效果可能有限。

L2正则化:

  • 思想: 在损失函数中加入权重的平方和,防止权重过大,对模型的复杂度进行惩罚。
  • 优点: 有助于防止过拟合,对于深度学习等复杂模型效果较好,保留了所有特征。
  • 缺点: 不会使权重变得稀疏,可能无法进行特征选择。

Dropout:

  • 思想: 在训练过程中,随机将部分神经元的输出置零,强制模型学习更鲁棒的特征表示。
  • 优点: 有效防止过拟合,提高模型的泛化能力,通常在深度学习中广泛使用。
  • 缺点: 可能增加训练时间,需要适当调整 dropout 概率。

Early Stopping:

  • 思想: 在训练过程中监测模型在验证集上的性能,当性能不再提升时停止训练,以防止过拟合。
  • 优点: 简单而有效,能够防止过拟合,减少计算成本。
  • 缺点: 可能错过最优点,对于某些问题和数据集可能需要调整停止条件。

这四种正则化方法在不同的情境下有各自的优势和劣势,通常需要根据具体的问题和数据集进行选择和调整。在实践中,这些方法也可以组合使用以提高模型性能。

文中图片大多来自论文和网络,如有侵权,联系删除,文中有不对的地方欢迎指正。


http://www.kler.cn/news/161978.html

相关文章:

  • axios调接口传参特殊字符丢失的问题(encodeURI 和 encodeURIComponent)
  • 【学习笔记】python仅拷贝list的值,引出浅拷贝与深拷贝
  • 在Python中,*f和**f是用于解包参数的语法
  • linux安装mysql5.7(一遍过)
  • 案例060:基于微信小程序考试系统
  • Java 简易版 UDP 多人聊天室
  • ThinkPHP插件开发实例
  • vue 使用 h函数
  • 区块链optimism主网节点搭建
  • 2024年值得关注的8个未来数据库
  • 什么是https 加密协议?
  • Javaweb之Maven仓库的详细解析
  • RPC 集群,gRPC 广播和组播
  • ELK架构监控MySQL慢日志
  • git-vscode
  • ubuntu20.04设置开机自启动jar(依赖其他服务)
  • 简单介绍一些其他的树
  • 阿里云 ACR 制品中心 AI/大数据镜像专场上新推荐榜
  • 【教程】逻辑回归怎么做多分类
  • 转转闲鱼链接后台搭建教程+完整版源码
  • 上海市青少年算法2022年10月月赛(乙组)
  • 【BUG】SpringBoot项目Long类型数据返回前端精度丢失问题
  • 论文分享 | 基于机载单目视觉的四旋翼无人机群内相对定位
  • 数据库管理-第120期 初探Halo数据库(202301201)
  • vue的props
  • git 本地有改动,远程也有改动,且文件是自动生成的配置文件
  • 【vuex】
  • 探索Vue小程序框架的底层原理
  • WPF Mvvm模式下面如何将事件映射到ViewModel层
  • lambda技巧之—如何在有多个判断分支的情况下,还能优雅的使用auto ?