本文仅介绍BatchNormalization的理解,对于原理部分,网上博客资料很详细.
1 什么是BatchNormalization
在做图像的神经网络训练时,我们往往每次给神经网络喂食一个batch的数据,当然这些数据指的是一个个的image或者feature map.比如我们batch_size=32,即每次处理32张image或者 feature map.而这一个batch的数据的不能反映出该batch的分布情况,需要将其映射到某个区间上,以反映样本集的分布,这时候就需要使用normalization对数据进行处理.可以参考下面图片理解.使用了Normalizatio之后,它可以一直保持数据分布基本不变.而Batch_normallization就是对每个batch做处理.
2 有什么作用
其作用可以加快模型训练时的收敛速度,使得模型训练过程更加稳定,避免梯度爆炸或者梯度消失。并且起到一定的正则化作用,几乎代替了Dropout。
3 怎么理解BatchNormalization的过程
我们使用一张图来描述Batch_normalization,
在做图像卷积操作或者其他操作时,输入是一个(batch_size,channel,height,width)4D 形状的tensor数据.我们把它变成(batch_size,channel,height*width)3D的shape.其中C表示channel ,N表示batch,H,w可以把他理解成将一个二维(H,W)的图像矩阵拉成一维的(H*W).
batch_size : 一个批次的样本数量
channel : 通道的数量
height : 一张image 或者是 feature map的高度
width : 一张image 或者是 feature map的宽度
从上图可以看出它是对同一个channel ,不同的batch,不同的image信息进行做normalizaton.你可以直接看出,图中蓝色的部分就是从channel的角度切割的.
举个例子
比如一个彩色Image的大小是32*32大小,我们一个batch有8个Images, channel是3(即RGB三个通道),tensor 的shape 就是:(8,3,32,32). 对这样的tensor数据进行normalization.
其实就是分别对image的R通道,G通道,B通道分别做normalization.
公式:
对每个颜色通道做一个Normalization.
4 代码实现
#!/usr/bin/env python # coding:utf-8 # image = (N,C,H,W) import torch import torch.nn as nn batch_size = 2 channel = 3 height = 32 width = 32 eps = 1e-5 # ======== officcal API ============= # 通道级别 def get_Batch_norm_API(x) : bn = nn.BatchNorm1d(channel,affine=True) y = bn(x) return y,y.shape # ======= 手动计算batch_norm =========== def get_Batch_norm(x): # 求均值 bn_mean = x.mean(dim=(0,2) ,keepdim=True) # 求标准差 bn_std = x.std(dim=(0,2) ,unbiased=False,keepdim=True ) y = (x-bn_mean) /(bn_std + eps) return y,y.shape x = torch.randn((batch_size ,channel ,height*width )) # 官方的api bn_api,bn_api_size = get_Batch_norm_API(x) # 自己的 bn,bn_size = get_Batch_norm(x) print(bn_api) print('=================') print(bn) print(bn_size)
构建一个网络,使用写的batch_normalization
#!/usr/bin/env python # Author: zhanghansen # Created Time: 2023年03月28日 星期二 14时28分42秒 # coding:utf-8 # import cv2 import torch import torch.nn as nn import numpy as np import random seed = 42 torch.cuda.manual_seed(seed) # 为GPU设置种子 torch.cuda.manual_seed_all(seed) # 当有多张GPU时,为所有GPU设置种子 np.random.seed(seed) # 为Numpy设置随机种子 random.seed(seed) # class Net1(nn.Module): def __init__(self,shape): super().__init__() self.shape = shape self.in_channel = self.shape[1] self.out_channel = 16 self.conv1 = nn.Conv2d(self.in_channel,self.out_channel,kernel_size=3) def forward(self,x) : x = self.conv1(x) x = self.batch_norm2(x,x.shape[1]) return x # normalization def batch_norm(self,x,channel): bn = nn.BatchNorm2d(channel,affine=True) return bn(x) def batch_norm2(self,x,channel) : eps = 1e-5 # 均值 bn_mean = x.mean(dim=(0,2,3),keepdim=True) bn_std = x.std(dim=(0,2,3),unbiased=False ,keepdim=True) bn = ( x- bn_mean) /( bn_std+eps) return bn # 方差 batch_size = 4 in_channel = 3 height = 32 width = 32 input_ = torch.rand((batch_size ,in_channel,height,width)) X = Net1([batch_size,in_channel,height,width]) y = X(input_) print(y.shape)
参考 :
深入解读Batch Normalization_batchnorm 维度_我太难了...的博客-CSDN博客深度学习之图像分类(八)--Batch Normalization_batch 图像_木卯_THU的博客-CSDN博客
Batch Normalization详解以及pytorch实验_太阳花的小绿豆的博客-CSDN博客
【基础算法】六问透彻理解BN(Batch Normalization) - 知乎
https://www.cnblogs.com/wevolf/p/15195143.html