1
.
Label Smoothing
原理:
就是将硬标签转换为软标签===》[0, 1] ==>[0.05, 0.95]
动机:说白了,这个平滑就是一定程度缩小label中min和max的差距,label平滑可以减小过拟合。
适当调整label,让两端的极值往中间凑凑,可以增加泛化性能
公式:同CrossEntropy计算时
![](https://i-blog.csdnimg.cn/blog_migrate/ffdead1ca53a30f0e8b28e4131b91dbd.png)
代码:
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)