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

batchnorm和layernorm的理解

batchnorm和layernorm原理和区别

batchnorm

原理

  对于一个特征tensor

x ∈ R b × c × f 1 × f 2 × … x \in \mathbb{R}^{b \times c \times f_1 \times f_2 \times \dots} xRb×c×f1×f2×

  其中, c c c是通道, f f f是通道中各种特征,batchnorm是对所有batch的每个通道特征分别进行归一化,即对于第 i i i个通道,选出他的所有batch的第 i i i个通道的所有特征 x [ : , i , : , : , . . . ] x[:,i,:,:,...] x[:,i,:,:,...]进行归一化:

μ = 1 m ∑ i = 1 m x i σ 2 = 1 m ∑ i = 1 m ( x i − μ ) 2 x ^ i = x i − μ σ 2 + ϵ y i = γ x ^ i + β \mu = \frac{1}{m} \sum_{i=1}^{m} x_i \\ \sigma^2 = \frac{1}{m} \sum_{i=1}^{m} (x_i - \mu)^2 \\ \hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}} \\ y_i = \gamma \hat{x}_i + \beta μ=m1i=1mxiσ2=m1i=1m(xiμ)2x^i=σ2+ϵ xiμyi=γx^i+β
  其中, ϵ \epsilon ϵ是较小的数,为了防止分母为0, γ \gamma γ β \beta β是可训练参数,用于仿射变换
  因此,输出向量形状不发生改变,可训练参数取决于通道 c c c的个数

代码

import torch
import torch.nn as nn## BatchNorm1d
batchnorm1d = nn.BatchNorm1d(num_features=10)  # 输入特征数为 10
# 构造输入张量 (N, C)
x_1d = torch.randn(16, 10)  # 模拟训练数据 (batch_size=16, num_features=10)
y = batchnorm1d(x)
# 打印结果
print("Output shape :", y.shape)  # (N, C)## BatchNorm2d
batchnorm2d = nn.BatchNorm2d(num_features=16)  # 输入通道数为 16
# 构造输入张量 (N, C, H, W)
x = torch.randn(8, 16, 32, 32)  # 模拟训练数据
y = batchnorm2d(x)
# 打印结果
print("Output shape :", y.shape)  # (N, C, H, W)## BatchNorm3d
batchnorm3d = nn.BatchNorm3d(num_features=8)  # 输入通道数为 8
# 构造输入张量 (N, C, D, H, W)
x = torch.randn(4, 8, 16, 32, 32)  # 模拟训练数据
y = batchnorm3d(x)
# 打印结果
print("Output shape :", y.shape)  # (N, C, D, H, W)

作用

  • 加速模型收敛
  • 缓解梯度消失或爆炸问题
  • 降低对初始化的敏感性
  • 一定程度上防止过拟合

通俗理解

    从图片数据 x ∈ R b × c × h × w x \in \mathbb{R}^{b \times c \times h \times w} xRb×c×h×w来理解:对于不同通道的特征,我们经过batchnorm以后,不同通道的特征便失去了可比性或者相对性(通道一:9,8,7,6;通道二:8,7,6,5经过归一化后都一样),但是从人的视角来区分一张图像不是靠不同通道之间的差异性,换句话说RGB稍微变一下变成RRR一样可以区分出图片中物体、属于哪一类。因此我们使用batchnorm相当于告诉模型你应该从同一通道内的数据差异来得到结果,而不是通道间。
    其实你不告诉模型(不用batchnorm),模型在多次训练后也可以发现相同的规律,只是模型训练就慢了,因此我们说batchnorm可以加速收敛

注意点

    模型训练阶段,我们存在batch维度,使用batchnorm时模型的正向计算会受到batch大小影响。那么我们在推理阶段通常只有一个batch,怎么办呢?
    解决方法:在pytorch中,模型训练时,调用 m o d e l . t r a i n ( ) model.train() model.train(),当创建一个 BatchNorm 层时,PyTorch 会自动初始化 r u n n i n g m e a n running_{mean} runningmean r u n n i n g v a r running_{var} runningvar,并将它们存储为模型的缓冲区(buffers)。
    在训练阶段:训练模式下( m o d e l . t r a i n ( ) model.train() model.train()),每次对 mini-batch 进行前向传播时:

r u n n i n g m e a n = m o m e n t u m ⋅ r u n n i n g m e a n + ( 1 − m o m e n t u m ) ⋅ μ b a t c h r u n n i n g v a r = m o m e n t u m ⋅ r u n n i n g v a r + ( 1 − m o m e n t u m ) ⋅ σ b a t c h 2 r u n n i n g v a r = m o m e n t u m ⋅ r u n n i n g v a r + ( 1 − m o m e n t u m ) ⋅ σ b a t c h 2 running_{mean}=momentum⋅running_mean+(1−momentum)⋅μ_{batch} \\ running_{var}=momentum⋅running_var+(1−momentum)⋅σ_{batch}^2 \\ running_{var}=momentum⋅running_var+(1−momentum)⋅σ_{batch}^2 runningmean=momentumrunningmean+(1momentum)μbatchrunningvar=momentumrunningvar+(1momentum)σbatch2runningvar=momentumrunningvar+(1momentum)σbatch2
    在推理阶段:推理模型下( m o d e l . e v a l ( ) model.eval() model.eval()),模型会使用 r u n n i n g m e a n running_{mean} runningmean r u n n i n g v a r running_{var} runningvar进行归一化,从而避免上述问题

layernorm

原理

    对于一个时序特征tensor

x ∈ R b × t × d x \in \mathbb{R}^{b \times t \times d} xRb×t×d

  其中, t t t是时序, d d d是某一时间点的各种特征,layernorm是对某一时间点的特征进行归一化,即对于第 i i i个时间点,分别在各个batch上选出他的所有特征 x [ k , i , : ] x[k,i,:] x[k,i,:]进行归一化:
μ = 1 d ∑ i = 1 d x i σ 2 = 1 d ∑ i = 1 d ( x i − μ ) 2 x ^ i = x i − μ σ 2 + ϵ y i = γ d x ^ i + β d \mu = \frac{1}{d} \sum_{i=1}^d x_i \\ \sigma^2 = \frac{1}{d} \sum_{i=1}^d (x_i - \mu)^2 \\ \hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}} \\ y_i = \gamma_{d} \hat{x}_i + \beta_{d} μ=d1i=1dxiσ2=d1i=1d(xiμ)2x^i=σ2+ϵ xiμyi=γdx^i+βd
  其中, ϵ \epsilon ϵ是较小的数,为了防止分母为0, γ d \gamma_{d} γd β d \beta_{d} βd是可训练参数,用于仿射变换
  因此,输出向量形状不发生改变,可训练参数取决于特征维度$d$的个数

代码

import torch
import torch.nn as nn
# 特征维度 d=16,归一化最后一个维度
layernorm = nn.LayerNorm(normalized_shape=16)# 打印可训练参数
print("Trainable parameters (gamma):", layernorm.weight.shape)  # gamma (scale) (16)
print("Trainable parameters (beta):", layernorm.bias.shape)    # beta (shift) (16)# 构造输入张量 (b, t, d)
x = torch.randn(32, 10, 16) # 前向传播
output = layernorm(x)# 打印结果
print("Input shape:", x.shape)       # [32, 10, 16]
print("Output shape:", output.shape) # [32, 10, 16]

作用

  • 加速模型收敛
  • 缓解梯度消失或爆炸问题
  • 降低对初始化的敏感性
  • 一定程度上防止过拟合

通俗理解

  从时序数据(或者一段话)数据 x ∈ R b × t × d x \in \mathbb{R}^{b \times t \times d} xRb×t×d来理解:对于不同时间点的特征,我们经过layernorm以后,不同时间点的特征便失去了可比性或者相对性(时间点1:9,8,7,6;时间点2:8,7,6,5经过归一化后都一样),。。。目前我也不知道怎么直观理解(后续有新的理解持续更新。。)

注意点

和batchnorm一样,在pytorch中,训练和推理时,一定要指定模型当前状态

总结

BatchNorm适用于CV,LayerNorm适用于NLP

本文是我学习过程中的个人理解,有不对的地方希望大家帮忙指出。希望可以抛砖引玉,欢迎大家在评论区和我交流。

http://www.lryc.cn/news/510474.html

相关文章:

  • 在git commit之前让其自动执行一次git pull命令
  • 【Rust自学】6.3. 控制流运算符-match
  • 大模型应用技术系列(三): 深入理解大模型应用中的Cache:GPTCache
  • 『大模型笔记』评估大型语言模型的指标:ELO评分,BLEU,困惑度和交叉熵介绍以及举例解释
  • 深度解析:Maven 和 Gradle 的使用比较及常见仓库推荐
  • SQLite本地数据库的简介和适用场景——集成SpringBoot的图文说明
  • 管理面板Ajenti的在Windows10下Ubuntu24.04/Ubuntu22.04里的安装
  • 在Python如何用Type创建类
  • Android学习19 -- NDK4--共享内存(TODO)
  • 《Cocos Creator游戏实战》非固定摇杆实现原理
  • RabbitMQ工作模式(详解 工作模式:简单队列、工作队列、公平分发以及消息应答和消息持久化)
  • 【VScode】第三方GPT编程工具-CodeMoss安装教程
  • 在JavaScript中,let 和 const有什么不同
  • Mysq学习-Mysql查询(4)
  • 安装torch-geometric库
  • Java数组深入解析:定义、操作、常见问题与高频练习
  • Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde
  • 【C语言练习(17)—输出杨辉三角形】
  • SpringMVC学习(二)——RESTful API、拦截器、异常处理、数据类型转换
  • React 第二十节 useRef 用途使用技巧注意事项详解
  • VIVO Java开发面试题及参考答案
  • C# Winfrom chart图 实例练习
  • iOS从Matter的设备认证证书中获取VID和PID
  • 带着国标充电器出国怎么办? 适配器模式(Adapter Pattern)
  • 破解海外业务困局:新加坡服务器托管与跨境组网策略
  • Mybatis-Plus快速入门
  • Chrome被360导航篡改了怎么改回来?
  • Coding(Jenkinsfile)+ Docker 自动化部署 Springboot —— 图文细节和一些注意事项说明
  • docker django uwsgi 报错记录
  • 数据分析思维(五):分析方法——假设检验分析方法