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)