论文地址:https://arxiv.org/abs/1802.02375
ShakeDrop
简介
ShakeDrop用于缓解深度神经网络过拟合的问题,受到Shake-Shake方法启发。
Shake-Shake方法有两个问题:1、只适用于ResNeXt网络, 2、Shake-Shake有效性的原理还未鉴定
ShakeDrop可以适用于 ResNet, Wide ResNet, PyramidNet
另外由于有效的正则化往往造成训练不稳定的问题,文中还提供了一种新的稳定机制用于难以训练的网络
对比Shake-Shake、 RandomDrop和ShakeDrop的架构
Shake-Shake
Shake-Shake只适用于ResNeXt。ResNeXt的基本block结构是一个三分支结构:
加上Shake-Shake之后,如上图所示:
α和β 是独立的随机的服从 [0,1]均匀分布的系数
E[α] = E[1−α] = 0.5
RandomDrop
RandomDrop最开始是在ResNet上提出来的正则化方法,不过也适用于PyramidNet。
ResNet的基本block是二分支结构:
加上RandomDrop之后如上图所示:
是0或1,服从概率为的伯努利分布。
P( = 1) = E[ ] =
论文中推荐的取值为:
是一个初始参数,论文中建议为 = 0.5
ShakeDrop
如上图所示,ShakeDrop:
是0或1,服从概率为的伯努利分布。
P( = 1) = E[ ] =
论文中推荐的取值为:
是一个初始参数,论文中建议为 = 0.5
α是服从 [-1,1]均匀分布的系数(论文中性能最佳)
β是服从[0,1]均匀分布的系数
相关代码例子如下:
pL = 0.5
pl = [(1.0 - (pL / (L)) * (i + 1)) for i in range(L)]
class ShakeDropFunction(torch.autograd.Function):
@staticmethod
def forward(ctx, x, training=True, p_drop=0.5, alpha_range=[-1, 1]):
if training:
gate = torch.cuda.FloatTensor([0]).bernoulli_(1 - p_drop)
ctx.save_for_backward(gate)
if gate.item() == 0:
alpha = torch.cuda.FloatTensor(x.size(0)).uniform_(*alpha_range)
alpha = alpha.view(alpha.size(0), 1, 1, 1).expand_as(x)
return alpha * x
else:
return x
else:
return (1 - p_drop) * x
@staticmethod
def backward(ctx, grad_output):
gate = ctx.saved_tensors[0]
if gate.item() == 0:
beta = torch.cuda.FloatTensor(grad_output.size(0)).uniform_(0, 1)
beta = beta.view(beta.size(0), 1, 1, 1).expand_as(grad_output)
beta = Variable(beta)
return beta * grad_output, None, None, None
else:
return grad_output, None, None, None
注意到:如果=1,那么shakedrop就变成了原始的网络:
如果=0,那么shakedrop变为:
相当于对F(x)进行了加干扰系数。