Dropout与DropPath

最近在看VMamba的代码,看到了DropPath,之前没见过,这里学习一下,记录下来方便以后查阅。

Dropout

Dropout 在训练阶段会让当前层每个神经元以drop_prob ( 0 ≤ d r o p _ p r o b ≤ 1 ) (0 ≤ drop\_prob ≤ 1) (0drop_prob1) 的概率失活并停止工作,效果如下图:

在这里插入图片描述

优点:Dropout能够提高网络的泛化能力,防止过拟合。解释如下:

  1. 训练阶段每个神经元是相互独立的,仅drop_prob相同,即使是同一批次不同样本失活的神经元也是不同的。所以原文作者将Dropout的操作视为多种模型结构下结果的集成,由于集成方法能够避免过拟合,因此Dropout也能达到同样的效果。
  2. 减少神经元之间的协同性。有些神经元可能会建立与其它节点的固定联系,通过Dropout强迫神经元和随机挑选出来的其它神经元共同工作,减弱了神经元节点间的联合适应性,增强了泛化能力。

缺点:

  1. Dropout减缓了收敛的速度。训练时需要通过伯努利分布生成是否drop每一个神经元的情况,额外的乘法和缩放运算也会增加时间。
  2. Dropout一般用于全连接层,卷积层一般使用BatchNorm来防止过拟合。Dropout与BatchNorm不易兼容,Dropout导致训练过程中每一层输出的方差发生偏移,使得BatchNorm层统计的方差不准确,影响BatchNorm的正常使用。
import torch.nn as nn
import torch


class dropout(nn.Module):
    def __init__(self, drop_prob):
        super(dropout, self).__init__()
        assert 0 <= drop_prob <= 1, 'drop_prob should be [0, 1]'
        self.drop_prob = drop_prob

    def forward(self, x):
        if self.training:
            keep_prob = 1 - self.drop_prob
            mask = keep_prob + torch.rand(x.shape)
            mask.floor_()
            return x.div(keep_prob) * mask
        else:
            return x


if __name__ == '__main__':
    x = torch.randn((3, 3, 3))  # [batch_size, num_token, token_dim]
    print(x)
    drop = dropout(0.1)
    my_o = drop(x)
    print(my_o)

输出结果:

tensor([[[ 2.1157e+00, -1.8475e-01,  4.9349e-01],
         [-3.9574e-01, -3.1117e-01, -2.8903e-02],
         [-5.2807e-01,  4.9279e-01, -3.3860e-01]],

        [[-1.9957e-01, -4.1244e-01, -4.7300e-01],
         [ 4.9982e-01, -7.0539e-02, -2.4033e-03],
         [ 1.7753e-01,  6.4291e-01,  5.3292e-01]],

        [[-5.7944e-02,  3.6630e-01,  8.5649e-01],
         [-4.3081e-02, -2.6598e+00, -4.3879e-01],
         [ 2.8432e-01,  2.2989e-01,  4.9191e-02]]])
tensor([[[ 2.3508, -0.0000,  0.5483],
         [-0.4397, -0.3457, -0.0321],
         [-0.5867,  0.5475, -0.3762]],

        [[-0.2217, -0.4583, -0.5256],
         [ 0.5554, -0.0784, -0.0027],
         [ 0.1973,  0.7143,  0.5921]],

        [[-0.0644,  0.4070,  0.9517],
         [-0.0479, -0.0000, -0.4875],
         [ 0.0000,  0.2554,  0.0547]]])

DropPath/drop_path

DropPath/drop_path 是一种正则化手段,和Dropout思想类似,其效果是将深度学习模型中的多分支结构的子路径随机”删除“,可以防止过拟合,提升模型表现,而且克服了网络退化问题。

ResNet缺乏正则方法,drop-path对子路径进行随机丢弃。实验表明,残差结构对于深度网络来说不是必须的,路径长度才是训练深度网络的需要的基本组件,而不单单是残差块。

在这里插入图片描述

实验训练时,mini-batch之间交叉使用Local和Global:

  • Local:对Jion层的输入Dropout,但至少保证要有一个输入。
  • Global:对于整个网络来说,只选择一条路径,且限制为某个单独列,所以这条路径是独立的强预测路径。
    在这里插入图片描述

DropPath/drop_path的方法实际上是一个很小众的方法,使用情况如下图:

在这里插入图片描述

一般可以作为正则化手段加入网络防止过拟合,但会增加网络训练的难度。如果设置的drop_prob过高,模型甚至有可能不收敛。

import torch
import torch.nn as nn


class DropPath(nn.Module):
    """
    随机丢弃该分支上的每个样本
    """
    def __init__(self, drop_prob=None):
        super(DropPath, self).__init__()
        self.drop_prob = drop_prob

    def forward(self, x):
        if self.drop_prob == 0. or not self.training:
            return x
        keep_prob = 1 - self.drop_prob

        shape = (x.shape[0],) + (1,) * (x.ndim - 1)  # (batch_size, 1, 1, 1)维数与输入保持一致,仅需要batch_size个值
        mask = keep_prob + torch.rand(shape, dtype=x.dtype, device=x.device)
        mask.floor_()  # 二值化,向下取整用于确定保存哪些样本

        output = x.div(keep_prob) * mask
        return output


if __name__ == "__main__":
    x = torch.randn((3, 3, 3))  # [batch_size, num_token, token_dim]
    print(x)
    drop_path = DropPath(drop_prob=0.5)
    my_o = drop_path(x)
    print(my_o)

输出结果:

tensor([[[ 1.1132e+00,  4.6629e-01,  2.8472e-02],
         [-2.1804e+00, -9.5545e-01,  4.0913e-01],
         [-3.6740e-02, -5.3272e-01,  4.3683e-01]],

        [[-1.3799e-04,  7.1770e-01, -2.0838e-02],
         [ 1.7494e-01, -1.6615e+00, -6.6987e-03],
         [ 4.3963e-02, -2.9094e-01, -1.2375e+00]],

        [[-2.0168e+00, -8.4884e-01,  8.6005e-01],
         [ 7.3257e-02, -2.1834e+00, -1.4427e-01],
         [ 4.3423e-01, -1.8330e+00,  7.9087e-01]]])
tensor([[[ 0.0000,  0.0000,  0.0000],
         [-0.0000, -0.0000,  0.0000],
         [-0.0000, -0.0000,  0.0000]],

        [[-0.0000,  0.0000, -0.0000],
         [ 0.0000, -0.0000, -0.0000],
         [ 0.0000, -0.0000, -0.0000]],

        [[-4.0335, -1.6977,  1.7201],
         [ 0.1465, -4.3668, -0.2885],
         [ 0.8685, -3.6661,  1.5817]]])

参考资料

DropPath

DropPath或drop_path正则化(通俗易懂)

drop_path理解和pytorch代码

【深度学习】Dropout、DropPath

drop path与drop out

Dropout: A Simple Way to Prevent Neural Networks from Overfitting

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值