28 批量归一化 [动手学深度学习v2]

  1. 为什么需要批量归一化?

    • 损失出现在最后,后面的层训练比较快 【梯度大】;
    • 数据在最底部,底部的层训练较慢 【梯度小】;
    • 底部层一变化,所有都得跟着变,最后的那些层需要重新学习很多次,导致收敛变慢【底层尝试抽取一些很底层的特征,比如局部、边缘、很简单的纹理信息】。
    • 我们可以再学习底部层的时候避免变化顶部层吗?这就是批量归一化要考虑的问题。
  2. 批量归一化

    固定小批量里面的均值和方差
    μ B = 1 ∣ B ∣ ∑ i ∈ B x i  and  σ B 2 = 1 ∣ B ∣ ∑ i ∈ B ( x i − μ B ) 2 + ϵ \mu_{B}=\frac{1}{|B|} \sum_{i \in B} x_{i} \text { and } \sigma_{B}^{2}=\frac{1}{|B|} \sum_{i \in B}\left(x_{i}-\mu_{B}\right)^{2}+\epsilon μB=B1iBxi and σB2=B1iB(xiμB)2+ϵ

    然后再做额外的调整(可学习的参数)
    x i + 1 = γ x i − μ B σ B + β x_{i+1}=\gamma \frac{x_{i}-\mu_{B}}{\sigma_{B}}+\beta xi+1=γσBxiμB+β

  3. 批量归一化层

    1. 可学习的参数为 γ \gamma γ(方差)和 β \beta β(均值);
    2. 作用在:全连接层和卷积层输出上,激活函数前;全连接层和卷积层输入上;
    3. 对全连接层,作用在特征维;对于卷积层,作用在通道维。
  4. 批量归一化在做什么?

    • 最初论文是想用它来减少内部协变量转移

    • 后续有论文指出它可能就是通过在每个小批量里加入噪音( μ ^ B , σ ^ B \hat{\mu}_B, \hat{\sigma}_B μ^B,σ^B)来控制模型复杂度
      x i + 1 = γ x i − μ ^ B σ ^ B + β x_{i+1}=\gamma \frac{x_{i}-\hat{\mu}_{B}}{\hat{\sigma}_{B}}+\beta xi+1=γσ^Bxiμ^B+β
      因此没必要跟丢弃法混合使用

  5. 批量归一化可以加快收敛速度【可以调大学习率】,但一般不改变模型精度。

  6. 代码实现

    import torch
    from torch import nn
    
    def batch_norm(X, gamma, beta, moving_mean, moving_var, eps, momentum):
        if not torch.is_grad_enabled():
            X_hat = (X - moving_mean) / torch.sqrt(moving_var + eps)
        else:
            assert len(X.shape) in (2, 4)
            if len(X.shape) == 2:
                mean = X.mean(dim=0)
                var = ((X - mean)**2).mean(dim=0)
            else:
                mean = X.mean(dim=(0, 2, 3), keepdim=True) # 1xBx1x1的tensor,按通道数求均值
                var = ((X - mean)**2).mean(dim=(0, 2, 3), keepdim=True)
            X_hat = (X - mean) / torch.sqrt(var + eps)
            moving_mean = momentum * moving_mean +(1.0 - momentum) * mean
            moving_var = momentum * moving_var + (1.0 - momentum) * var
        Y = gamma * X_hat + beta
        return Y, moving_mean.data, moving_var.data
    
    
    class BatchNorm(nn.Module)def __init__(self, num_features, num_dims):
            super().__init__()
            if num_dims == 2:
                shape = (1, num_features)
            else:
                shape = (1, num_features, 1, 1)
            self.gamma = nn.Parameter(torch.ones(shape))
            self.beta = nn.Parameter(torch.zeros(shape))
            self.moving_mean = torch.zeros(shape)
            self.moving_var = torch.ones(shape)
        
        def forward(self, X):
            if self.moving_mean.device != X.device:
                self.moving_mean = self.moving_mean.to(X.device)
                self.moving_var = self.moving_var.to(X.device)
            Y, self.moving_mean, self.moving_var = batch_norm(X, self.gamma, self.beta, self.moving_mean, self.moving_var, eps=1e-5, momentum=0.9)
            return Y
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值