本节继续介绍Batch Normalization。
上图是对前节课所讲的小结,通过Normalize将[6, 3, 784]分为3个通道的[6, 784]数据。使得数据结果整体分布于(0~正负1)区间内。
那么在pytorch中是如何实现的呢?
代码语言:javascript复制import torch
import torch.nn as nn
import torch.nn.functional as F
x = torch.rand(100, 16, 784)
# 这里直接将28*28变为一维的784
layer = nn.BatchNorm1d(16)
# 一维直接使用.BatchNorm1d即可
# 因为Batch Norm的参数直接是由channel数量得来的,
# 因此这里直接给定了channel的数量为16,后续会输出16个channel的统计信息
out = layer(x)
# 进行前向计算
print(layer.running_mean)
# 进行权值计算并输出
输出为
代码语言:javascript复制tensor([0.0500, 0.0499, 0.0499, 0.0499, 0.0500, 0.0500, 0.0501, 0.0497, 0.0501,
0.0500, 0.0500, 0.0500, 0.0502, 0.0501, 0.0499, 0.0501])
可以自行对上述结果进行验证,该结果的平均值恰好为0.5。
Batch Normalize的规范化写法为
首先第一步先统计了当前规范化的均值和方差。接下来进行Normalize的操作,即将x值减去均值再除以根号下方差的平方与一个很小的误差。最好再进行缩放,缩放成一个适宜的分布。
再以代码示例
代码语言:javascript复制import torch
import torch.nn as nn
import torch.nn.functional as F
x = torch.rand(1, 16, 28, 28)
# 这里是28*28的数据
layer = nn.BatchNorm2d(16)
# 二维直接使用.BatchNorm2d
# 因为Batch Norm的参数直接是由channel数量得来的,
# 因此这里直接给定了channel的数量为16,后续会输出16个channel的统计信息
out = layer(x)
# 进行前向计算
print(layer.running_mean)
# 进行权值计算并输出
输出为
代码语言:javascript复制tensor([0.0514, 0.0501, 0.0520, 0.0496, 0.0498, 0.0517, 0.0510, 0.0506, 0.0517,
0.0501, 0.0509, 0.0491, 0.0486, 0.0505, 0.0516, 0.0495])
若想查看层间的参数
代码语言:javascript复制print(layer.weight)
输出为
代码语言:javascript复制tensor([0.7385, 0.5807, 0.7299, 0.6045, 0.7796, 0.5302, 0.4739, 0.2357, 0.6040,
0.7084, 0.6688, 0.7167, 0.7097, 0.6144, 0.8577, 0.0428],
requires_grad=True)
这里的weight即为σ值
这里还可以设置一些参数,如添加;training=True(表明当前的模式), affine=True(设置参数自动更新学习)。
Batch Norm同样需要手动给予参数
代码语言:javascript复制layer.eval()
# 调用不同的模式,以完成参数是否自动更新学习
BatchNorm1d(16, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
Batch Norm具有相当优异的使用效果,如下图所示
使用了Batch Norm后,收敛速度加快、精度提高。
上右图可看出尖峰的偏差对比左侧变小了很多。