Idea: Randomly zero parts of the network during training to prevent overfitting.
Equation
With keep mask , vanilla dropout gives , so inference must multiply by . Inverted dropout (what every framework implements) rescales at train time instead, leaving inference as the identity:
DropPath / stochastic depth samples one mask per sample and applies it to a whole residual branch, so the block becomes and sometimes reduces to :
From scratch
def dropout(x, p=0.5, training=True):
if not training or p == 0.0:
return x
mask = (torch.rand_like(x) >= p).to(x.dtype)
return x * mask / (1.0 - p) # inverted
def drop_path(x, p=0.1, training=True):
if not training or p == 0.0:
return x
shape = (x.shape[0],) + (1,) * (x.ndim - 1) # one Bernoulli per sample
mask = (torch.rand(shape, device=x.device, dtype=x.dtype) >= p)
return x * mask / (1.0 - p)
def dropout2d(x, p=0.1, training=True): # drop whole channels (N,C,H,W)
if not training or p == 0.0:
return x
mask = (torch.rand(x.shape[:2], device=x.device) >= p)[:, :, None, None]
return x * mask.to(x.dtype) / (1.0 - p)