两种比较重要的抗过拟合方法

1 . Label Smoothing
    原理: 就是将硬标签转换为软标签===》[0, 1]  ==>[0.05, 0.95]
    动机:说白了,这个平滑就是一定程度缩小label中min和max的差距,label平滑可以减小过拟合。
                适当调整label,让两端的极值往中间凑凑,可以增加泛化性能
    公式:同CrossEntropy计算时
代码:
def label_smoothing(inputs, epsilon=0.1):
    K = len(inputs)    # number of class
    return ((1-epsilon) * inputs) + (epsilon / K)

#同CrossEntropy损失函数计算(重点,就是在计算损失的时候用的)
import torch
import torch.nn as nn

class LabelSmoothing(nn.Module):
    """
    NLL loss with label smoothing.
    """
    def __init__(self, smoothing=0.0):
        """
        Constructor for the LabelSmoothing module.
        :param smoothing: label smoothing factor
        """
        super(LabelSmoothing, self).__init__()
        self.confidence = 1.0 - smoothing
        self.smoothing = smoothing

    def forward(self, x, target):
        logprobs = torch.nn.functional.log_softmax(x, dim=-1)

        nll_loss = -logprobs.gather(dim=-1, index=target.unsqueeze(1))
        nll_loss = nll_loss.squeeze(1)
        smooth_loss = -logprobs.mean(dim=-1)
        loss = self.confidence * nll_loss + self.smoothing * smooth_loss
        return loss.mean()

2.DropBlock

原理:在卷积层之后使用dropout,相当于对卷积层使用dropout

动机:原始dropout使用在dropout上没效果,主要是卷积操作在邻域有信息共享,要想起效果需要把邻域都drop掉

方法:

    先在特征图上随机找几个需要dropout的中心点,然后以这些点为中心将周围都dropout掉

 

gamma的计算:

    

图中黄色的是feature区域,蓝色的是drop块的大小,绿色是可以选择中心点的区域

上述公式想表达的就是:丢弃的特征数量=丢弃率*绿色框的大小*丢弃框的大小,简单来说就是在绿色框中找几个中心点,然后算一下一共要丢多少特征。

最后推出那个gamma的公式。

算法流程:

    1.随机出来一个和输入x大小一样的mask矩阵(服从正态分布)

    2.给定一个gamma,将mask<gamma的点作为中心点

    3.生成mask块,实现方法就是采用最大池化

    4.x*mask

import torch
import torch.nn as nn

class DropBlock2D(nn.Module):
    def __init__(self, drop_prob, block_size):
        super(DropBlock2D, self).__init__()
        
        self.drop_prob = drop_prob    #丢失率
        self.block_size = block_size   #drop块的大小
        
    def forward(self, x):
        assert x.dim() == 4
        if not self.training or self.drop_prob == 0:
            return x
        else:
            gamma = self._compute_gamma(x)
            mask = (torch.rand(x.shape[0], *x.shape[2:])<gamma).float()
            mask = mask.to(x.device)
            block_mask = self._compute_block_mask(mask)
            out = x*block_mask[:, None, :, :]
            out = out*block_mask.numel()/block_mask.sum()
            return out
    
    def _compute_block_mask(self, mask):
        block_mask = F.max_pool2d(input=mask[:, None, :,:],
                                 kernel_size=(self.block_size, self.block_size),
                                  stride=(1,1),
                                  padding=self.block_size//2
                                 )
        
    def _compute_gamma(self, x):
        return self.drop_prob /(self.block_size**2)

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页