pytorch基础知识-Batch Norm(下)

2019-12-05 15:26:36 浏览数 (1)

本节继续介绍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后,收敛速度加快、精度提高。

上右图可看出尖峰的偏差对比左侧变小了很多。

0 人点赞