【深度学习】03-神经网络 4-1 Dropout 正则化 - 神经网络缓解过拟合的正则化方法

参数更新,只是更新一部分,剩下的部分,是进行缩放。即分数会扩大。

Dropout 正则化 是一种深度学习中常用的正则化技术,最早由 Geoffrey Hinton 等人在 2012 年提出,旨在防止神经网络的过拟合

1. 来源

Dropout 是由 Hinton 和他的团队在论文《Improving neural networks by preventing co-adaptation of feature detectors》中首次提出。该技术的灵感来自于生物学中神经元随机失活的现象,用于模拟随机神经元的失效,增强网络的鲁棒性。

2. 作用

Dropout 的核心思想是在每次训练过程中,随机"丢弃"一部分神经元(即将这些神经元的输出设为 0),使得模型不能过度依赖某些特定的神经元。这一过程可以理解为在训练过程中构建了多个不同的子模型,然后在测试时将这些子模型的输出进行平均。

  • 防止过拟合:通过随机失活神经元,减少了神经元之间的依赖,防止模型过度拟合训练数据,提高了模型的泛化能力。

  • 提高模型鲁棒性:Dropout 迫使模型中的神经元学会独立地进行工作,因为每个神经元不能保证在每次训练中都被激活。

3. 工作机制

在训练过程中,每个神经元以一定的概率(通常为 0.5)被暂时"丢弃"。在推理(即测试)阶段,不再丢弃任何神经元,而是对所有神经元的输出进行缩放,通常是将每个神经元的输出乘以丢弃概率的补值。例如,如果训练时 50% 的神经元被丢弃,测试时就将所有神经元的输出乘以 0.5,以保持训练和测试时的期望输出一致。

4. 优势

  • 简单高效:只需在前向传播时随机丢弃神经元,且不需要额外的计算资源。

  • 提升泛化能力:在深度神经网络中,Dropout 可以显著减少过拟合,尤其是在大规模数据集不足的情况下。

总结来说,Dropout 是一种简单但有效的正则化技术,通过随机丢弃神经元来减少模型的过拟合风险,并提高其泛化性能。

代码

python 复制代码
import torch
import torch.nn as nn

def test():
    # Step 1: 初始化一个Dropout层,p=0.4表示有40%的神经元在训练时会被"丢弃"
    dropout = nn.Dropout(p=0.4)
    
    # Step 2: 创建一个随机输入张量,大小为[1, 4],表示输入层的权重,随机生成0-9之间的整数,并将其转换为float类型
    inputs = torch.randint(0, 10, size=[1, 4]).float()
    
    # Step 3: 初始化一个全连接层,输入维度为4,输出维度为5
    layer = nn.Linear(4, 5)
    
    # Step 4: 对输入数据进行前向传播,通过全连接层计算输出
    y = layer(inputs)
    
    # 打印未经过Dropout层的全连接层输出结果
    print("未失活FC层的输出结果:\n", y)
    
    # Step 5: 对全连接层的输出结果应用Dropout,随机丢弃40%的神经元
    y = dropout(y)
    
    # 打印经过Dropout层后全连接层的输出结果
    print("失活后FC层的输出结果:\n", y)

# 调用函数
test()

详细讲解:

  1. Dropout层的初始化

    复制代码
    dropout = nn.Dropout(p=0.4)

    这里初始化了一个 Dropout 层 ,其中参数 p=0.4 表示在训练时,每个神经元有 40% 的概率会被随机"失活"(即丢弃),其输出值会被设置为 0。p 值的选择影响网络的正则化强度,p=0.4 说明这个网络比较倾向于在训练中通过随机丢弃一部分神经元来防止过拟合。

  2. 输入张量的初始化

    复制代码
    inputs = torch.randint(0, 10, size=[1, 4]).float()

    这一行代码生成了一个大小为 [1, 4] 的张量,表示输入层的 4 个特征,张量内的值为随机生成的 0 到 9 之间的整数,并将其转换为 float 类型(因为神经网络通常需要浮点数进行运算)。

  3. 全连接层的初始化

    复制代码
    layer = nn.Linear(4, 5)

    这里初始化了一个 线性(全连接)层,它的输入维度为 4,输出维度为 5。也就是说,这个层接收 4 个输入特征,经过权重矩阵的线性变换后输出 5 个特征。

  4. 前向传播计算输出

    复制代码
    y = layer(inputs)

    这一行代码执行了前向传播,将输入 inputs 通过全连接层计算输出 y。这个计算过程是线性变换: [ y = xW + b ] 其中,W 是权重矩阵,b 是偏置项,x 是输入。

  5. 打印未经过 Dropout 层的输出

    复制代码
    print("未失活FC层的输出结果:\n", y)

    在应用 Dropout 之前,打印未经过 Dropout 层的全连接层的输出结果 y

  6. 应用 Dropout 层

    复制代码
    y = dropout(y)

    在全连接层的输出上应用 Dropout。Dropout 通过随机丢弃 40% 的神经元(根据 p=0.4),剩下的神经元的输出会按比例缩放,以保持训练时和测试时的期望值一致。

  7. 打印经过 Dropout 层的输出

    复制代码
    print("失活后FC层的输出结果:\n", y)

    这里打印了经过 Dropout 层之后的输出结果,可以观察到部分神经元的输出会被设置为 0。

代码运行的意义:

  1. Dropout 正则化:Dropout 是一种正则化技术,旨在防止模型过拟合。它通过在训练过程中随机丢弃一部分神经元,使得网络不会过于依赖某些特定的神经元,从而提升模型的泛化能力。

  2. 全连接层与 Dropout 的结合:通过在全连接层后应用 Dropout,可以有效减少过拟合现象,尤其是在深度神经网络的训练过程中。

这个代码演示了如何在全连接层的输出上应用 Dropout,并显示了 Dropout 失活前后的输出差异。

代码2

下面是一个用 Python 实现 Dropout 正则化 的示例代码,并附有详细注释。这个代码展示了如何在前向传播中手动实现 Dropout 正则化机制,而不是使用 PyTorch 自带的 nn.Dropout。

python 复制代码
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F

# 定义一个简单的神经网络类
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        # 定义一个全连接层,输入4个特征,输出5个特征
        self.fc1 = nn.Linear(4, 5)

    def forward(self, x):
        # Step 1: 线性变换,输入经过全连接层
        x = self.fc1(x)

        # Step 2: 自定义Dropout实现:随机失活40%的神经元
        dropout_rate = 0.4  # 定义Dropout概率
        if self.training:  # 仅在训练模式下应用Dropout
            mask = (torch.rand(x.shape) > dropout_rate).float()  # 生成一个随机掩码
            x = x * mask / (1 - dropout_rate)  # 应用掩码并对剩下的神经元缩放
        # 如果不在训练模式(即推理模式),则不进行Dropout

        # Step 3: 使用激活函数(这里是ReLU)
        x = F.relu(x)
        return x

# 主函数
def main():
    # 创建一个神经网络实例
    model = SimpleNN()
    
    # 设置模型为训练模式(应用Dropout)
    model.train()
    
    # 创建一个随机输入张量,大小为 [1, 4],即1个样本有4个特征
    inputs = torch.randn(1, 4)

    # 打印输入
    print("输入数据:\n", inputs)

    # 前向传播
    outputs = model(inputs)
    
    # 打印输出
    print("经过Dropout后的输出:\n", outputs)

if __name__ == '__main__':
    main()

详细注释和讲解:

  1. 初始化神经网络类

    python 复制代码
    class SimpleNN(nn.Module):
       def __init__(self):
           super(SimpleNN, self).__init__()
           # 定义一个全连接层,输入维度为4,输出维度为5
           self.fc1 = nn.Linear(4, 5)
    • 这里我们定义了一个简单的神经网络类,包含一个全连接层。nn.Linear(4, 5) 表示输入为 4 个特征,输出为 5 个特征。
  2. 前向传播与 Dropout 实现

    python 复制代码
    def forward(self, x):
       # 线性变换,输入经过全连接层
       x = self.fc1(x)
    ​
       # 自定义Dropout实现:随机失活40%的神经元
       dropout_rate = 0.4  # 定义Dropout概率
       if self.training:  # 仅在训练模式下应用Dropout
           mask = (torch.rand(x.shape) > dropout_rate).float()  # 生成一个随机掩码
           x = x * mask / (1 - dropout_rate)  # 应用掩码并对剩下的神经元缩放
    ​
       # 使用ReLU激活函数
       x = F.relu(x)
       return x
    • 全连接层计算x = self.fc1(x) 对输入进行线性变换。

    • Dropout 实现

      • 我们生成一个与输出形状相同的随机掩码 mask,该掩码中每个元素是随机生成的 0 到 1 之间的浮点数。

      • 将这些浮点数与 dropout_rate 进行比较,大于 dropout_rate 的部分保留,其他部分被设置为 0。

      • 然后,将输出乘以掩码,并对保留的神经元进行缩放(除以 1 - dropout_rate),确保期望值不变。

    • ReLU 激活:最后,使用 ReLU 激活函数对输出进行非线性处理。

  3. 主函数

    python 复制代码
    def main():
       model = SimpleNN()
       model.train()  # 设置模型为训练模式(应用Dropout)
    ​
       inputs = torch.randn(1, 4)  # 随机生成输入数据,形状为 [1, 4]
    ​
       # 打印输入
       print("输入数据:\n", inputs)
    ​
       outputs = model(inputs)  # 前向传播
       print("经过Dropout后的输出:\n", outputs)
    • 模型训练模式 :通过 model.train() 告诉模型当前是训练模式,Dropout 将会被应用。

    • 输入数据 :随机生成大小为 [1, 4] 的输入张量,这里表示一个样本,具有 4 个特征。

    • 前向传播与输出:模型对输入进行前向传播,计算结果并打印 Dropout 后的输出。

运行结果

当你运行代码时,你会看到:

  • 输入数据是一个随机生成的 4 维向量。

  • 经过全连接层和 Dropout 操作后的输出,其中部分神经元会被丢弃,输出结果中某些值会变为 0。

总结:

  • Dropout 正则化通过随机丢弃神经元的方式防止神经网络的过拟合,尤其适合在训练深度网络时使用。

  • 在这个代码中,我们手动实现了 Dropout 的基本机制,展示了如何在前向传播中应用 Dropout,并控制训练模式和推理模式下的行为差异。

相关推荐
DisonTangor12 分钟前
Sam Altman最新博文:智能时代将带来无限的智能和丰富的能源
人工智能·aigc·能源
中智讯14 分钟前
智慧电网能源双碳实训平台
人工智能·物联网·能源
新缸中之脑21 分钟前
RPA + 计算机视觉
人工智能·计算机视觉·rpa
Trisyp23 分钟前
目标检测系列(一)什么是目标检测
人工智能·yolo·目标检测
Eric.Lee202126 分钟前
数据集-目标检测系列-海洋鱼类检测数据集 fish>> DataBall
人工智能·算法·目标检测·数据集·物体检测·鱼类检测
Eric.Lee202126 分钟前
数据集-目标检测系列-自行车检测数据集 bike>> DataBall
人工智能·python·深度学习·目标检测·数据集·物体检测·自行车检测数据集
山语山27 分钟前
目标检测DOTA数据集
javascript·人工智能·算法·目标检测·计算机视觉·github
小楼先森28 分钟前
【目标检测】隐翅虫数据集386张VOC+YOLO
人工智能·yolo·目标检测
山语山29 分钟前
机器学习与深度学习
前端·人工智能·python·深度学习·机器学习·机器人
做程序员的第一天30 分钟前
pytorch ----【输入张量.data.size()/输入张量.size()】的使用
人工智能·深度学习