PyTorch使用Tricks:Dropout,R-Dropout和Multi-Sample Dropout等 !!

news2025/3/1 9:57:25

文章目录

1、为什么使用Dropout?

2、Dropout的拓展1:R-Dropout

3、Dropout的拓展2:Multi-Sample Dropout

4、Dropout的拓展3:DropConnect

5、Dropout的拓展4:Standout

6、Dropout的拓展5:Gaussian Dropout


1、为什么使用Dropout?

Dropout是一种在神经网络训练过程中用于防止过拟合的技术。在训练过程中,Dropout会随机地关闭一部分神经元,这样可以使模型更加健壮,不会过度依赖于任何一个特定的神经元,从而提高模型的泛化能力。下面是一些使用技巧:

技巧1:在输入层和隐藏层上使用Dropout。这个技巧是基于Dropout的两个作用,即增加网络的多样性和增加数据的多样性。在输入层上使用Dropout,相当于对数据进行噪声注入,可以提高数据的鲁棒性,防止网络对数据的细节过度敏感。在隐藏层上使用Dropout,相当于对网络进行子采样,可以提高网络的泛化能力,防止网络对特定的特征过度依赖。在网络的每一层都使用Dropout,可以进一步增强这两个作用,但也要注意不要过度使用,导致网络的训练不充分。

技巧2:网络中的Dropout率为0.2~0.5。这个技巧是基于经验的建议,一般来说,Dropout率太低会导致Dropout的效果不明显,Dropout率太高会导致网络的训练不充分。不过,这个技巧也不是绝对的,有些研究发现,Dropout率可以超过0.5,甚至接近1,仍然可以取得很好的效果。这可能取决于网络的复杂度,数据的规模,以及其他的正则化方法。

技巧3:在较大的网络上使用Dropout。这个技巧是基于Dropout的本质,即通过随机地删除网络中的一些连接,来防止网络的过拟合。在较大的网络上,过拟合的风险更高,因此Dropout的作用更明显。不过,这并不意味着在较小的网络上使用Dropout就没有意义,只是效果可能不如在较大的网络上显著。

技巧4:使用较高的学习率,使用学习率衰减和设置较大的动量值。这个技巧是基于Dropout的另一个作用,即增加网络的稳定性。由于Dropout会随机地改变网络的结构,导致网络的输出有较大的方差,因此需要使用较高的学习率,来加快网络的收敛速度。同时,使用学习率衰减,可以在网络接近最优解时,减小学习率,避免网络的震荡。另外,使用较大的动量值,可以增加网络的惯性,抵抗Dropout带来的扰动,保持网络的方向。这个技巧的具体参数,需要根据网络的结构和数据的特点进行调节。

技巧5:限制网络权重的大小,使用最大范数正则化。这个技巧是基于Dropout的一个局限,即Dropout不能完全防止网络的过拟合。尤其是使用较高的学习率时,网络的权重可能会变得非常大,导致网络的输出过于敏感,降低网络的泛化能力。因此,需要对网络的权重进行约束,限制其大小,防止网络的过拟合。最大范数正则化是一种常用的方法,它可以限制网络的权重的范数不超过一个给定的阈值,从而控制网络的复杂度。

下面是一个例子:

import torch
import torch.nn as nn

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.layer1 = nn.Linear(10, 20)
        self.layer2 = nn.Linear(20, 20)
        self.layer3 = nn.Linear(20, 4)
        self.dropout = nn.Dropout(p=0.5)

    def forward(self, x):
        x = F.relu(self.layer1(x))
        x = self.dropout(x)
        x = F.relu(self.layer2(x))
        x = self.dropout(x)
        return self.layer3(x)

2、Dropout的拓展1:R-Dropout

核心思想:R-Dropout的核心思想是在训练过程中通过正则化手段减少模型在同一输入数据上两次前向传播(每次都应用Dropout)结果之间的差异。这种方法强制模型在面对输入数据的不同“视角”(即,不同的Dropout掩码)时,学习到更一致的表示。通过这种方式,R-Dropout鼓励模型捕获更稳健的特征,从而提高模型的泛化能力。

实现方式:实现R-Dropout时,通常会对同一批数据进行两次独立的前向传播,每次前向传播都应用不同的Dropout模式。然后,通过比较这两次前向传播的结果(例如,使用KL散度作为两个分布之间差异的度量),将这种差异作为额外的正则化损失添加到总损失中。

下面是一个简单的例子,展示了如何在一个简单的全连接神经网络中实现R-Dropout。使用KL散度作为前两次前向传播结果之间差异的度量,并将其添加到原始损失中。

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

class RDropoutNN(nn.Module):
    def __init__(self):
        super(RDropoutNN, self).__init__()
        self.fc1 = nn.Linear(784, 256)
        self.dropout = nn.Dropout(0.5)
        self.fc2 = nn.Linear(256, 10)

    def forward(self, x, with_dropout=True):
        x = F.relu(self.fc1(x))
        if with_dropout:
            x = self.dropout(x)
        x = self.fc2(x)
        return x

def compute_kl_loss(p, q):
    p_log_q = F.kl_div(F.log_softmax(p, dim=1), F.softmax(q, dim=1), reduction='sum')
    q_log_p = F.kl_div(F.log_softmax(q, dim=1), F.softmax(p, dim=1), reduction='sum')
    return (p_log_q + q_log_p) / 2

# 假设
model = RDropoutNN()
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# 假设有一个数据加载器
# for inputs, labels in data_loader:
    # 模拟数据
inputs = torch.randn(64, 784)  # 假设的输入
labels = torch.randint(0, 10, (64,))  # 假设的标签

# 清零梯度
optimizer.zero_grad()

# 两次前向传播,每次都使用Dropout
outputs1 = model(inputs, with_dropout=True)
outputs2 = model(inputs, with_dropout=True)

# 计算原始损失
loss1 = criterion(outputs1, labels)
loss2 = criterion(outputs2, labels)
original_loss = (loss1 + loss2) / 2

# 计算R-Dropout正则化项
kl_loss = compute_kl_loss(outputs1, outputs2)

# 最终损失
lambda_kl = 0.5  # R-Dropout正则化项的权重
total_loss = original_loss + lambda_kl * kl_loss

# 反向传播和优化
total_loss.backward()
optimizer.step()

在这个例子中,对相同的输入执行两次前向传播,每次都应用Dropout。然后,分别计算这两个输出对应的交叉熵损失,并将它们的平均值作为原始损失。接着,使用KL散度计算两次输出之间的差异作为R-Dropout的正则化项,并将其加到原始损失中以得到最终的损失。最后,通过反向传播更新模型的权重。

通过引入R-Dropout正则化项,鼓励模型生成更一致的输出,即使在应用不同的Dropout掩码时也是如此。这有助于提高模型的泛化能力,并进一步减少过拟合的风险。

3、Dropout的拓展2:Multi-Sample Dropout

核心思想:Multi-Sample Dropout的核心思想是在单次前向传播过程中对同一输入应用多次Dropout,产生多个不同的掩码,并对结果进行聚合(例如,通过取平均化)。这种方法的目的是在每次训练迭代中更充分地利用Dropout,以实现更快的收敛和更好的泛化。

实现方式:在实现Multi-Sample Dropout时,会在模型的关键层中并行引入多个Dropout层,每个Dropout层对输入数据应用不同的随机掩码。然后,将这些Dropout层的输出以某种方式(通常是平均)合并,以产生最终的输出。这种方法运行模型在每次迭代中考虑多种“丢弃模式”,从而增加了训练的鲁棒性。

以下是一个使用Multi-Sample Dropout的例子:

class MultiSampleDropout(nn.Module):
    def __init__(self, dropout_rate, num_samples):
        super(MultiSampleDropout, self).__init__()
        self.dropout_rate = dropout_rate
        self.num_samples = num_samples

    def forward(self, x):
        outputs = []
        for _ in range(self.num_samples):
            output = F.dropout(x, self.dropout_rate, training=self.training)
            outputs.append(output)
        return torch.mean(torch.stack(outputs), dim=0)

在每次前向传播过程中对输入进行多次采样,然后将这些采样的结果合并,从而得到最终的输出。

以上两种拓展的区别:

目标不同:R-Dropout侧重于通过减少同一输入在不同Dropout模式下的输出差异来提高输出的一致性,而Multi-Sample Dropout侧重于在单次迭代中探索多种Dropout模式,以加速训练并提高泛化。

实现机制不同:R-Dropout通过对同一批数据进行两次前向传播并计算正则化损失来实现,而Multi-Sample Dropout在单词前向传播中应用多个Dropout掩码并聚合结果。

正则化方法不同:R-Dropout引入了一个基于两次前向传播结果差异的额外正则化项,Multi-Sample Dropout则通过聚合多个Dropout样本的结果来提高泛化能力,不需要额外的正则化项。

4、Dropout的拓展3:DropConnect

Dropout通过随机将神经元的激活输出置为零来工作,而DropConnect则是随机将网络的权重置为零。这意味着在DropConnect中,网络的连接(即权重)部分被随机“丢弃”,而不是输出。这种方法可以视为Dropout的一种泛化形式,并且理论上可以提供更强的正则化效果,因为它直接操作模型的权重。

DropConnect的工作原理:在每次训练迭代中,DropConnect随机选择一部分权重,并将这些权重暂时设置为0。这个过程减少了模型的容量,迫使网络在缺少一部分连接的情况下学习,从而有助于防止过拟合。与Dropout不同,DropoutConnect不是丢弃神经元的输出,而是直接在网络的权重上施加约束。

DropConnect的实现:在PyTorch中实现DropConnect相对简单,但需要自定义网络层,因为PyTorch的标准层不直接支持这种操作。下面是一个简单的示例,展示了如何实现一个具有DropConnect功能的全连接层:

import torch
import torch.nn as nn
import torch.nn.functional as F

class DropConnect(nn.Module):
    def __init__(self, input_dim, output_dim, drop_prob=0.5):
        super(DropConnect, self).__init__()
        self.drop_prob = drop_prob
        self.weight = nn.Parameter(torch.randn(input_dim, output_dim))
        self.bias = nn.Parameter(torch.randn(output_dim))
    
    def forward(self, x):
        if self.training:
            # 生成与权重相同形状的掩码
            mask = torch.rand(self.weight.size()) > self.drop_prob
            # 应用DropConnect:用掩码乘以权重
            drop_weight = self.weight * mask.float().to(self.weight.device)
        else:
            # 在测试时不应用DropConnect,但要调整权重以反映丢弃率
            drop_weight = self.weight * (1 - self.drop_prob)
        
        return F.linear(x, drop_weight, self.bias)

# 使用DropConnect层的示例网络
class ExampleNet(nn.Module):
    def __init__(self):
        super(ExampleNet, self).__init__()
        self.dropconnect_layer = DropConnect(20, 10, drop_prob=0.5)
        self.fc2 = nn.Linear(10, 2)
    
    def forward(self, x):
        x = F.relu(self.dropconnect_layer(x))
        x = self.fc2(x)
        return x

# 示例使用
model = ExampleNet()
input = torch.randn(5, 20)  # 假设的输入
output = model(input)
print(output)

在这个例子中,DropConnect类定义了一个自定义的全连接层,其中包含了DropConnect功能。在每次前向传播时,如果模型处于训练模式,它会随机生成一个与权重相同形状的掩码,并用这个掩码乘以权重,从而实现DropConnect效果。在评估模式下,为了保持输出的期望值不变,权重会被调整,以反映在训练时的平均丢弃率。

这种自定义层可以被嵌入到更复杂的网络结构中,以提供DropConnect正则化的效果,从而帮助减少过拟合并提高模型的泛化能力。

5、Dropout的拓展4:Standout

Standout是一种自适应的正则化方法,类似于Dropout和DropConnect,但它通过依赖于网络的激活来动态调整每个神经元被丢弃的概率。这种方法的核心思想是利用神经网络内部的状态来决定哪些神经元更可能被保留,从而使正则化过程更加依赖于模型当前的行为。这种自适应性使Standout能够在不同的训练阶段和不同的数据点上实现个性化的正则化强度。

Standout的工作原理:Standout通过一个额外的网络或层来计算每个神经元的保留概率。这个保留概率不是固定不变的,而是根据网络当前的激活动态调整的。具体来说,对于每个神经元,其保留概率是其激活的函数,这意味着网络在训练过程中自动学习每个神经元的重要性,并据此调整其被丢弃的概率。Standout是数学表达式如下:

p_i = \frac{1}{1 + \exp(-s_i)}

其中p_i是第i个神经元被丢弃的概率,是一个仿射函数,可以表示为:

s_i = a + b \cdot |w_i|

其中ab是超参数,w_i是第i个神经元的权重。可以看出,权重越大,丢弃概率越大。

Standout的PyTorch实现:在PyTorch中实现Standout需要自定义一个层,这个层能够根据输入激活动态计算每个神经元的丢弃概率。以下是一个简化的示例,说明如何实现这样的层:

import torch
import torch.nn as nn

class Standout(nn.Module):
    def __init__(self, input_dim, output_dim):
        super(Standout, self).__init__()
        self.fc = nn.Linear(input_dim, output_dim)
        # 使用一个简单的全连接层来生成保留概率
        self.prob_fc = nn.Linear(input_dim, output_dim)
    
    def forward(self, x):
        # 计算正常的前向传播
        x_out = self.fc(x)
        
        if self.training:
            # 计算每个神经元的保留概率
            probs = torch.sigmoid(self.prob_fc(x))
            # 生成与激活大小相同的二值掩码
            mask = torch.bernoulli(probs).to(x.device)
            # 应用mask
            x_out = x_out * mask
        # 注意:在评估模式下不应用Standout
        
        return x_out

在这个实现中,self.prob_fc 层输出的是每个神经元的保留概率,而不是丢弃概率,这些概率通过Sigmoid 函数进行了归一化。接着,使用这些概率生成一个二值掩码,该掩码通过伯努利采样得到,最后将这个掩码应用到 self.fc 层的输出上,以实现神经元的随机保留。

需要注意的是,由于Standout的自适应性,它的行为会比传统的Dropout或DropConnect更复杂,可能需要更细致的调参和监控以确保训练稳定性和模型性能。

6、Dropout的拓展5:Gaussian Dropout

Gaussian Dropout 是一种正则化技术,它在训练神经网络时通过引入服从高斯分布的随机噪声来防止过拟合。不同于传统 Dropout 以固定概率将激活置零,Gaussian Dropout 乘以一个随机变量 ( m ),其中 ( m ) 服从高斯分布 ( N(1, \sigma^2) )。

PyTorch 示例:

import torch
import torch.nn as nn

class GaussianDropout(nn.Module):
    def __init__(self, sigma=0.1):
        super(GaussianDropout, self).__init__()
        self.sigma = sigma

    def forward(self, x):
        if self.training:
            # 生成服从高斯分布 N(1, sigma^2) 的随机变量
            gaussian_noise = torch.normal(1.0, self.sigma, size=x.size()).to(x.device)
            # 应用高斯 dropout
            return x * gaussian_noise
        else:
            # 测试阶段不使用 dropout
            return x

# 使用示例
layer = GaussianDropout(sigma=0.1)
input_tensor = torch.randn(10, 20)  # 假设的输入
output = layer(input_tensor)

在训练阶段,forward 方法生成高斯噪声并应用于输入 x,而在测试阶段直接返回 x,不应用噪声。

参考:

Dropout和R-Dropout的使用技巧 - 知乎

深度图学习与大模型LLM

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1458098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

微信小程序开发:通过wx.login()获取用户唯一标识openid和unionid

下面代码展示了 openid 的获取过程。 想获取 unionid 需要满足条件:小程序已绑定到微信开放平台账号下,不然只会返回 openid。 【相关文档】 微信小程序开发:appid 和 secret 的获取方法 wx.login({success (res) {if (res.code) {// 发起网…

十二:枚举与注解

文章目录 01、枚举类的使用1.1、枚举类的理解1.2、自定义枚举类1.3、使用enum关键字定义枚举类1.4、Enum类中的常用方法1.5、使用enum关键字定义的枚举类实现接口 02、注解的使用2.1、注解的理解2.3、如何自定义注解2.4、jdk中4个基本的元注解的使用12.5、jdk中4个基本的元注解…

解锁创意灵感,探索FlutterExampleApps项目的奥秘

解锁创意灵感,探索FlutterExampleApps项目的奥秘 项目简介 FlutterExampleApps项目是一个包含各种示例应用链接的仓库,旨在演示Flutter应用开发中的各种功能、特性和集成。 项目包含了以下几个部分,每个部分都涵盖了不同的内容和主题&…

VO、DTO、DO、BO、PO

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 VO、DTO、DO、BO1.概念阿里Java开发手册分层领域模型: 2. VO 和 DTO 使用场景以下是一个使用VO和DTO的典型案例: 3.BO和DTO的区别 案例 VO、…

分享两个版本的数字孪生技术栈,都是AI回答的,较为精准

版本一: 数字孪生应用到的技术栈包括但不限于: 3D建模:数字孪生需要建立虚拟的三维模型,因此需要使用3D建模软件如AutoCAD、SketchUp、3ds Max等。 数据采集:数字孪生需要采集大量实时的物理数据,如传感…

为什么从没有负值的数据中绘制的小提琴图(Violin Plot)会出现负值部分?

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 小提琴图(Violin Plot) 是一种用于展示和比较数据分布的可视化工具。它结合了箱形图(Box Plot)和密度图(Kernel Density Plot)的特…

hive load data未正确读取到日期

1.源数据CSV文件日期字段值: 2.hive DDL语句: CREATE EXTERNAL TABLE test.textfile_table1(id int COMMENT ????, name string COMMENT ??, gender string COMMENT ??, birthday date COMMENT ????,.......) ROW FORMAT SERDE org.apache.…

QT中事件过滤器

Qt添加事件过滤器,设置拖放listWidget、TreeWidget、TableWidget控件。 #include "mainwindow.h" #include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this)…

UML---活动图

活动图概述 活动图(Activity Diagram)是UML(Unified Modeling Language,统一建模语言)中的一种行为建模工具,主要用于描述系统或业务流程中的一系列活动或操作。活动图通常用于描述用例中的行为&#xff0c…

SimpleDateFormat为什么是线程不安全的?

目录 在日常开发中,Date工具类使用频率相对较高,大家通常都会这样写:这很简单啊,有什么争议吗?格式化后出现的时间错乱。看看Java 8是如何解决时区问题的:在处理带时区的国际化时间问题,推荐使用…

[创业之路-88/管理者与领导者-128]:企业运行分层模型、研发管理全视野

目录 一、企业分层模型 1.1 愿景层 1.2 战略目标层 1.3 战术方法层 1.4 市场业务层 1.5 项目执行层 1.6 资源层 二、研发全视野、全流程 2.1 市场 2.2 战略规划 2.3 产品研发 2.3.1 概述 2.3.2 项目管理 2.3.3 研发业务管理(研发经理*N) – 管技术流程…

2024护眼大路灯哪个牌子好?6个挑选妙招助你选择优质落地灯!

如果大家平常关注大路灯,应该都会注意到一个情况——它确实大受众多用户的喜爱以及专业人士的认可,但是关于它的伤眼案例却从未减少。之所以如此矛盾,主要是因为市面上有太多的不专业大路灯,它们的选材用料以及品质非常糟糕&#…

Spring Boot 笔记 028 文章列表

1.1 导入中文语言包 1.2 显示文章分类 //回显文章分类 import { articleCategoryListService } from /api/article.js const articleCategoryList async () > {let result await articleCategoryListService();categorys.value result.data; }articleCategoryList() 1.3…

蓝牙BLE安全-SSP简单安全配对

SSP的配对过程由于可以根据设备的IO能力选择不同的关联模型,因此十分灵活,其提供了四种方式:Numeric Comparison、Passkey Entry、Just Works以及Out of Band (OOB) 。这里关联方式的选择实质上对后面的流程是有一定影响的,如Just…

Python实例|电商API接口数据采集的请求|爬取商品详情描述价格评论

近年来,随着互联网的发展,越来越多的数据以网页的形式存在于各个网站上。对于数据分析师、研究员或者仅仅是对数据感兴趣的人来说,如何高效地提取和分析网页数据成为了一项重要的技能。Python作为一门强大的编程语言,通过其丰富的…

【鸿蒙系统学习笔记】状态管理

一、介绍 资料来自官网:文档中心 在声明式UI编程框架中,UI是程序状态的运行结果,用户构建了一个UI模型,其中应用的运行时的状态是参数。当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状…

HTML的特殊字符

HTML的特殊字符 有些特殊的字符在 html 文件中是不能直接表示的&#xff0c;例如: 空格&#xff0c;小于号(<)&#xff0c;大于号(>)&#xff0c;按位与(&)。 空格 示例代码&#xff1a; 运行结果&#xff1a; 由于html 标签就是用 < > 表示的&#xff0…

原创个人java开源项目发布maven全球中央仓库详细过程示范和遇到的问题解决办法

文章目录 java项目上传到maven全球中央仓库&#xff08;原创个人开源项目发布maven中央仓库详细过程示范&#xff09;需求背景第一步 注册sonatype账号第二步 登录sonatype账号并申请新建项目第三步 准备个人GPG数字签名并发布到ubuntu第四步 准备maven配置第五步 修改项目配置…

java数据结构与算法刷题-----LeetCode155. 最小栈

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 1. 法一&#xff1a;使用辅助最小栈 解题思路&#xff1a;时间复杂度O(1)…

【Git】Gitbash使用ssh 上传本地项目到github

SSH Git上传项目到GitHub&#xff08;图文&#xff09;_git ssh上传github-CSDN博客 前提 ssh-keygen -t rsa -C “自己的github电子邮箱” 生成密钥&#xff0c;公钥保存到自己的github的ssh里 1.先创建一个仓库&#xff0c;复制ssh地址 git init git add . git commit -m …