Batch Normalization

Concept and Principle

  • 问题
    • 损失出现在最后,由BP算法和梯度消失,后面的层训练的会更快
    • 数据在最前面,前面的层训练的慢且前面的层变化后面的层也要跟着变(抽取的底层信息变化让后面的层要重新学),所以后面的层要重新学习很多次,导致收敛变慢
    • 考虑在学习底部层时避免变化顶部层
  • 批量归一化
    • 固定小批量里面的均值和方差,然后再做额外的调整(可学习的参数gama和beta)
    • 是线性变换
    • 作用在
      • 全连接层和卷积层输出后,激活函数前
      • 全连接层和卷积层输入前
    • 对于全连接层作用于特征维
    • 对于卷积层作用于通道维(将每一个像素都当作一个样本,通道数就是一个样本的特征数)
  • 批量归一化在做什么?
    • 最初的论文是想用它来减少内部协变量转移(使每一层的输出分布变化不那么剧烈)
    • 后续有论文指出,批量归一化可能只是在小批量中加入噪声控制模型复杂度
  • 总结
    • 批量归一化固定小批量中的均值和方差,然后学习出适合的偏移和缩放
    • 批量归一化可以加速收敛(可以设置更大的学习率),一般不改变模型精度

Implementation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from torch import nn,optim
import torch
import torch

net=nn.Sequential(
nn.Conv2d(1,6,kernel_size=5,padding=2),nn.BatchNorm2d(6),
nn.AvgPool2d(2),nn.Sigmoid(),
nn.Conv2d(6,16,5),nn.BatchNorm2d(16),
nn.AvgPool2d(2,2),nn.Sigmoid(),nn.Flatten(),
nn.Linear(16*5*5,120),nn.BatchNorm1d(120),
nn.Sigmoid(),
nn.Linear(120,84),nn.BatchNorm1d(84),
nn.Sigmoid(),
nn.Linear(84,10)
)
loss_f=nn.CrossEntropyLoss()
opt=optim.Adam(net.parameters(),lr=1.0)

import d2l


train_iter,test_iter=d2l.load_data_fashion_mnist(256)

# d2l.train(
# 10,nn.CrossEntropyLoss(),
# optim.Adam(net.parameters()),
# net,train_iter,save_name="LeNet_bn",
# device=torch.device("cuda:0"))
d2l.evaluate(
net,test_iter,nn.CrossEntropyLoss(),
param_path="D:/code/machine_learning/limu_d2l/params/LeNet_bn_10",
device=torch.device("cuda:0")
)