DropBlock: A regularization method for convolutional networks
DropBlock 由原本的Dropout的随机丢弃点改变为丢弃整个块,如上图所述。该论文认为随机丢弃的像素点(其实是特征图的一个点)可能会由他附近的点的关联信息所表示出来,这样就起不到原本想要的正则效果,因此直接丢弃一个块。
方法如下
输入大小为4维向量,否则会出错.
丢弃的点为随机选取。
#!/usr/bin/env python
# -*- coding:utf8 -*-
import torch
import torch.nn.functional as F
from torch import nn
class Drop(nn.Module):
def __init__(self, drop_prob=0.1, block_size=7):
super(Drop, self).__init__()
self.drop_prob = drop_prob
self.block_size = block_size
def forward(self, x):
if self.drop_prob == 0:
return x
# 设置gamma,比gamma小的设置为1,大于gamma的为0,对应第五步
# 这样计算可以得到丢弃的比率的随机点个数
gamma = self.drop_prob / (self.block_size**2)
mask = (torch.rand(x.shape[0], *x.shape[2:]) < gamma).float()
mask = mask.to(x.device)
# compute block mask
block_mask = self._compute_block_mask(mask)
# apply block mask,为算法图的第六步
out = x * block_mask[:, None, :, :]
# Normalize the features,对应第七步
out = out * block_mask.numel() / block_mask.sum()
return out
def _compute_block_mask(self, mask):
# 取最大值,这样就能够取出一个block的块大小的1作为drop,当然需要翻转大小,使得1为0,0为1
block_mask = F.max_pool2d(input=mask[:, None, :, :],
kernel_size=(self.block_size,
self.block_size),
stride=(1, 1),
padding=self.block_size // 2)
if self.block_size % 2 == 0:
# 如果block大小是2的话,会边界会多出1,要去掉才能输出与原图一样大小.
block_mask = block_mask[:, :, :-1, :-1]
block_mask = 1 - block_mask.squeeze(1)
return block_mask