本文仅介绍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博客