规范化层 - 代码实现
1 课程概览
本课实现规范化层(Layer Normalization)。作用是对数据进行归一化,防止梯度消失或爆炸,加速训练。计算方式:计算每个位置所有特征维度的均值和方差,进行归一化(均值为 0,方差为 1),再进行缩放和平移。类比车辆保养、装修监工,确保数据在合理范围内。
2 核心概念与定义
- Layer Normalization(LN):层规范化,对每个位置的所有特征维度进行归一化。
- Batch Normalization(BN):批量归一化(以前学的)。
- 残差连接(Add):加法,把数据加到一起。
- 缩放因子(gamma):可学习参数,缩放。
- 平移因子(beta):可学习参数,平移。
3 模型与算法详解
规范化层的作用
对数据进行归一化,防止梯度消失或爆炸,加速训练。
- 防止梯度消失或爆炸
- 加速训练过程
- 确保网络处理数据时保持稳定的分布
类比
| 类比 | 说明 |
|---|---|
| 车辆保养 | 车开久了要保养,数据经过多层处理要规范化 |
| 装修监工 | 不管工人把砂浆调成什么样,监工让最终达到合理范围 |
计算方式
计算每个位置所有特征维度的均值和方差,进行归一化,再缩放和平移。
- 计算均值和方差
- 归一化(均值为 0,方差为 1)
- 缩放和平移(找补回一些信息)
与批量归一化的关系
公式一模一样,但计算方向不同。
| 类型 | 计算方向 | 适用 |
|---|---|---|
| LN(层规范化) | 横着算(一个样本的不同特征) | 文本 |
| BN(批量归一化) | 竖着算(同一特征的不同样本) | 图片 |
为什么要引入缩放因子和平移因子?
归一化可能丢失信息,通过两个可调节的因子找补回一些信息。
- 归一化可能压缩太多,丢失差异性
- 缩放因子(gamma)和平移因子(beta)找补回信息
- 学习不同批次的数据特征,提高泛化能力
4 数学原理与推导
归一化公式
$$\mu = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} x_i$$
$$\sigma^2 = \frac{1}{d_{model}} \sum_{i=1}^{d_{model}} (x_i - \mu)^2$$
$$\hat{x}_i = \frac{x_i - \mu}{\sqrt{\sigma^2 + \epsilon}}$$
缩放和平移
$$y_i = \gamma \hat{x}_i + \beta$$
其中:
- $\gamma$ 是缩放因子(可学习)
- $\beta$ 是平移因子(可学习)
- $\epsilon$ 是防止除以 0 的小常数
5 代码示例
import torch
import torch.nn as nn
class LayerNorm(nn.Module):
"""规范化层"""
def __init__(self, d_model=512, eps=1e-6):
"""
初始化规范化层
:param d_model: 词向量维度,例如 512
:param eps: 防止除以 0 的小常数
"""
super().__init__()
# 1. 创建缩放因子 gamma(可学习参数)
self.a_2 = nn.Parameter(torch.ones(d_model))
# 2. 创建平移因子 beta(可学习参数)
self.b_2 = nn.Parameter(torch.zeros(d_model))
# 3. 防止除以 0 的小常数
self.eps = eps
def forward(self, x):
"""
前向传播
:param x: 输入张量 (batch, seq_len, d_model)
:return: 规范化后的张量
"""
# 1. 计算均值(沿着最后一个维度)
mean = x.mean(-1, keepdim=True)
# 2. 计算方差(沿着最后一个维度)
var = x.var(-1, keepdim=True)
# 3. 归一化:(x - mean) / sqrt(var + eps)
x_hat = (x - mean) / torch.sqrt(var + self.eps)
# 4. 缩放和平移:gamma * x_hat + beta
return self.a_2 * x_hat + self.b_2
# 测试代码
def dm06_test_layer_norm():
"""测试规范化层"""
# 1. 创建规范化层对象
my_layer_norm = LayerNorm(d_model=512)
# 2. 创建输入张量 (batch=2, seq_len=4, d_model=512)
x = torch.randn(2, 4, 512)
# 3. 前向传播
output = my_layer_norm(x)
print(f"输入形状: {x.shape}")
print(f"输出形状: {output.shape}")
# 验证归一化效果
print(f"\n输出均值(应接近 0): {output.mean():.6f}")
print(f"输出方差(应接近 1): {output.var():.6f}")
return output
if __name__ == "__main__":
dm06_test_layer_norm()
代码说明
| 代码 | 说明 |
|---|---|
nn.Parameter(torch.ones(d_model)) | 缩放因子 gamma(可学习) |
nn.Parameter(torch.zeros(d_model)) | 平移因子 beta(可学习) |
x.mean(-1, keepdim=True) | 沿最后一个维度计算均值 |
x.var(-1, keepdim=True) | 沿最后一个维度计算方差 |
torch.sqrt(var + self.eps) | 防止除以 0 |
6 重难点与易错提醒
- ❗重点:规范化层对每个位置的所有特征维度进行归一化。
- ❗重点:缩放因子和平移因子是可学习参数。
- ⚠️易错:LN 和 BN 公式一样,但计算方向不同。
- 💡深入理解:归一化可能丢失信息,缩放和平移找补回信息。
- 💡深入理解:类比车辆保养、装修监工。
7 课堂问答精选
Q1:规范化层的作用是什么?
A:对数据进行归一化,防止梯度消失或爆炸,加速训练。确保网络处理数据时保持稳定的分布。
Q2:规范化层的计算方式是什么?
A:①计算每个位置所有特征维度的均值和方差;②归一化(均值为 0,方差为 1);③缩放和平移(找补回信息)。
Q3:为什么要引入缩放因子和平移因子?
A:归一化可能压缩太多,丢失差异性。通过两个可调节的缩放因子(gamma)和平移因子(beta)找补回一些信息,学习不同批次的数据特征,提高泛化能力。
Q4:LN 和 BN 的区别是什么?
A:LN(层规范化)横着算,针对一个样本的不同特征,用于文本;BN(批量归一化)竖着算,针对同一特征的不同样本,用于图片。公式一样,但计算方向不同。
8 本课小结
- 规范化层:对每个位置的所有特征维度进行归一化。
- 作用:防止梯度消失或爆炸,加速训练。
- 计算:均值 → 方差 → 归一化 → 缩放和平移。
- 缩放因子和平移因子是可学习参数。
- LN 横着算(文本),BN 竖着算(图片)。
9 延伸思考
- 如何测试规范化层?
- 规范化层如何与其他组件组合?