当前位置: 首页 > news >正文

AI-02a5a6.神经网络-与学习相关的技巧-批量归一化

批量归一化 Batch Normalization

设置合适的权重初始值,则各层的激活值分布会有适当的广度,从而可以顺利的进行学习。那么,更进一步,强制性的调整激活值的分布,是的各层拥有适当的广度呢?批量归一化(Batch Normalization)就是基于这个想法产生的。

算法介绍

有什么优点呢?

  • 可以使学习快速进行(可以增大学习率)。
  • 不那么依赖初始值(对于初始值不用那么神经质)。
  • 抑制过拟合(降低Dropout等的必要性)

向神经网络中插入对数据分布进行正规化的层,即Batch Normalization层。

在这里插入图片描述

式(6.7), μ B ← 1 m ∑ i = 1 m x i σ B 2 ← 1 m ∑ i = 1 m ( x i − μ B ) 2 x ^ i ← x i − μ B σ B 2 + ϵ \begin{aligned} \mu_B &\leftarrow \frac{1}{m}\sum^m_{i=1}x_i \\ \sigma_B^2 &\leftarrow \frac{1}{m}\sum^m_{i=1}(x_i-\mu_B)^2 \\ \hat{x}_i &\leftarrow \frac{x_i-\mu_B}{\sqrt{\sigma_B^2+\epsilon}} \end{aligned} μBσB2x^im1i=1mxim1i=1m(xiμB)2σB2+ϵ xiμB

这里对mini-batch的 m m m个输入数据的集合 B = { x 1 , x 2 , . . . , x m } B = \{x_1, x_2, ... , x_m\} B={x1,x2,...,xm}求均值 μ B \mu_B μB和方差 σ B 2 \sigma_B^2 σB2 。然后,对输入数据进行均值为0、方差为1(合适的分布)的正规化。式(6.7)中的 ϵ \epsilon ϵ是一个微小值(比如,10e-7等),它是为了防止出现除以0的情况。

式(6.7)所做的是将mini-batch的输入数据 { x ^ 1 , x ^ 2 , . . . , x ^ m } \{\hat{x}_1, \hat{x}_2, ... , \hat{x}_m\} {x^1,x^2,...,x^m}变换为均值为0、方差为1的数据。通过将这个处理插入到激活函数的前面(或者后面),可以减小数据分布的偏向。

接着,Batch Norm层会对正规化后的数据进行缩放和平移的变换,式(6.8), y i ← γ x i ^ + β y_i \leftarrow \gamma\hat{x_i} + \beta yiγxi^+β

这里, γ \gamma γ β \beta β是参数。一开始 γ = 1 , β = 0 \gamma = 1, \beta = 0 γ=1,β=0,然后再通过学习调整到合适的值。

在这里插入图片描述

几乎所有的情况下都是使用Batch Norm时学习进行得更快。同时也可以发现,实际上,在不使用Batch Norm的情况下,如果不赋予一个尺度好的初始值,学习将完全无法进行。

通过使用批量归一化,可以推动学习的进行。并且,对权重初始值变得健壮(“对初始值健壮”表示不那么依赖初始值)。

# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 为了导入父目录的文件而进行的设定
import numpy as np
import matplotlib.pyplot as plt
from dataset.mnist import load_mnist
from common.multi_layer_net_extend import MultiLayerNetExtend
from common.optimizer import SGD, Adam(x_train, t_train), (x_test, t_test) = load_mnist(normalize=True)# 减少学习数据
x_train = x_train[:1000]
t_train = t_train[:1000]max_epochs = 20
train_size = x_train.shape[0]
batch_size = 100
learning_rate = 0.01def __train(weight_init_std):bn_network = MultiLayerNetExtend(input_size=784, hidden_size_list=[100, 100, 100, 100, 100], output_size=10,weight_init_std=weight_init_std, use_batchnorm=True)network = MultiLayerNetExtend(input_size=784, hidden_size_list=[100, 100, 100, 100, 100], output_size=10,weight_init_std=weight_init_std)optimizer = SGD(lr=learning_rate)train_acc_list = []bn_train_acc_list = []iter_per_epoch = max(train_size / batch_size, 1)epoch_cnt = 0for i in range(1000000000):batch_mask = np.random.choice(train_size, batch_size)x_batch = x_train[batch_mask]t_batch = t_train[batch_mask]for _network in (bn_network, network):grads = _network.gradient(x_batch, t_batch)optimizer.update(_network.params, grads)if i % iter_per_epoch == 0:train_acc = network.accuracy(x_train, t_train)bn_train_acc = bn_network.accuracy(x_train, t_train)train_acc_list.append(train_acc)bn_train_acc_list.append(bn_train_acc)print("epoch:" + str(epoch_cnt) + " | " + str(train_acc) + " - " + str(bn_train_acc))epoch_cnt += 1if epoch_cnt >= max_epochs:breakreturn train_acc_list, bn_train_acc_list# 3.绘制图形==========
weight_scale_list = np.logspace(0, -4, num=16)
x = np.arange(max_epochs)for i, w in enumerate(weight_scale_list):print( "============== " + str(i+1) + "/16" + " ==============")train_acc_list, bn_train_acc_list = __train(w)plt.subplot(4,4,i+1)plt.title("W:" + str(w))if i == 15:plt.plot(x, bn_train_acc_list, label='Batch Normalization', markevery=2)plt.plot(x, train_acc_list, linestyle = "--", label='Normal(without BatchNorm)', markevery=2)else:plt.plot(x, bn_train_acc_list, markevery=2)plt.plot(x, train_acc_list, linestyle="--", markevery=2)plt.ylim(0, 1.0)if i % 4:plt.yticks([])else:plt.ylabel("accuracy")if i < 12:plt.xticks([])else:plt.xlabel("epochs")plt.legend(loc='lower right')
plt.show()

背景

批量归一化(Batch Normalization)与层归一化(Layer Normalization)深度解析

什么是归一化 Normalization

在深度神经网络的训练过程中,随着网络深度的增加,模型的表征能力虽然有所提升,但也带来了许多训练上的难题。其中,梯度消失梯度爆炸是最具代表性的两个问题。早期的深层网络中常使用Sigmoid或tanh等饱和激活函数,一旦输入落入函数的饱和区(梯度接近0),梯度在层间传播时会迅速衰减;另一方面,如果网络层数较多或参数初始化不当,也有可能发生梯度的指数级增长,从而使参数更新呈现“发散”现象。

与此同时,随着网络在反向传播中不断更新,前几层的参数变化会连带影响后续层的输入分布,导致高层特征分布发生非平稳性,这种现象被称为内部协变量偏移(Internal Covariate Shift)。在网络很深或数据分布复杂的情况下,这种效应会被放大,导致网络难以收敛或需要极度细心地调整超参数。

归一化(Normalization)技术正是在这样的背景下逐渐兴起的。它的核心思想是,无论网络有多深,都希望每一层的输入分布尽量稳定、可控。为此,通过对每一层的激活值进行某种形式的“标准化”处理,可以使每层输入在训练中保持较为稳定的分布,即均值和方差在较短的训练迭代内不发生剧烈波动。这种操作一方面有助于缓解梯度消失和梯度爆炸;另一方面,网络也不需要时时刻刻去适应快速变化的激活分布,从而提高了学习效率并缩短训练收敛时间。

批量归一化对批量大小的依赖

BN对批量大小较为敏感,如果批量太小(例如小于16甚至更小),当前批次的均值方差容易出现大幅波动,进而导致训练不稳定或性能下降。在一些仅能使用小批量(如显存受限或序列生成任务)的场景下,BN的效果往往不及设计专门的归一化策略(例如LN、GN等)。

优缺点

优点

  • 大幅加速收敛,允许使用更高的初始学习率。
  • 有一定正则化作用,降低对初始权重的敏感性,减少过拟合。
  • 在主流图像任务和大型批量训练的场景下表现卓越。

缺点

  • 依赖足够大的批量尺寸,否则会导致估计方差不稳定。
  • 在序列模型(如RNN、Transformer等)或者小批量场景中表现不佳。
  • 在分布式训练时,计算全局均值与方差可能比较麻烦,需要额外同步开销。

相关文章:

  • C#扩展方法的入门理解
  • 标签部件(lv_label)
  • 进阶2_1:QT5多线程与定时器共生死
  • python:一个代理流量监控的媒体文件下载脚本
  • Docker使用经验-从Image导出dockerfile并进行修改
  • Spark处理过程--案例数据清洗
  • Unity引擎源码-物理系统详解-其二
  • 智能体制作学习笔记1——智能体
  • 软件设计师-下午题-试题4(15分)
  • 深入掌握 Python 切片操作:解锁数据处理的高效密码
  • 基于 Kubernetes 部署容器平台kubesphere
  • 基于网关实现不同网段S7-1200 CPU的通信方法
  • 【Spark分析HBase数据】Spark读取并分析HBase数据
  • 互联网大厂Java求职面试:优惠券服务架构设计与AI增强实践-6
  • Python 之 selenium 打开浏览器指定端口进行接续操作
  • 机器人示教操作
  • excel使用笔记
  • 【2025版】Spring Boot面试题
  • Flutter 开发入门:从一个简单的计数器应用开始
  • Problem E: List练习
  • 遭“特朗普关税”冲击,韩国今年经济增长预期“腰斩”降至0.8%
  • 法治日报整版聚焦:儿童能否成为短视频主角?该如何监管?
  • “无锡景・江南韵”:中国评弹艺术在尼日利亚收获众多粉丝
  • 韩国总统大选候选人登记结束,共7人参选
  • 汉斯·季默:不会指挥的声音工程师终成音乐“大神”
  • 为何发胖?如何减肥?一个医学体重管理中心的探索启示