LayerNorm层归一化

文章介绍了LayerNorm层归一化技术在神经网络中的应用,对比了与BatchNormalization的区别,强调了其在每个样本特征维度上的归一化优势,适用于小批量和在线性时间复杂度下,以及在处理自然语言处理任务如RNN中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LayerNorm(Layer Normalization)是一种常用的归一化技术,用于神经网络模型中的层级归一化操作。它在每个样本的每个特征维度上进行归一化,使得每个特征的均值为0,方差为1,从而有助于提高模型的训练效果和泛化能力

LN是针对自然语言处理领域提出的,例如像RNN循环神经网络

与 Batch Normalization (批归一化)既有相似之处又有不同:从公式上看,都是减去均值除以标准差,也存在两个可训练的参数 gamma 和 beta

但是,BN 是对一个 batch 数据的每个 channel 进行 Norm 处理,LN是对单个数据的指定维度进行Norm处理,与batch无关。而且在BN训练时需要累计moving_mean和moving_var两个变量,LN不需要累计

所以说,,LayerNorm 是在每个样本的特征维度上进行归一化,而不是在批次维度上。这意味着在LayerNorm中,每个样本都有自己的均值和方差

用法:

torch.nn.LayerNorm(normalized_shape,eps=1e-05,elementwise_affine=True)

其中,参数normalized_shape可以指定想要Norm的维度,但是指定的维度必须是要从最后一维开始的,比如:数据的shape是[4,2,3],那么normalized_shape可以是[3](最后一维上进行Norm处理) ,也可以是[2,3](Norm最后两个维度),也可以是 [4,2,3] (对整个维度进行Norm),但是不能是[2] 或[4,2],否则会报错

实现:

import torch
import torch.nn as nn

def layer_norm_process(feature:torch.Tensor,beta=0,gamma=1,eps=1e-5):
    var_mean = torch.var_mean(feature,dim=-1,unbiased=False)
    # 均值
    mean = var_mean[1]
    # 方差
    std = var_mean[0]
    
    # layer norm process
    feature = (feature - mean[...,None]) / torch.sqrt(var[...,None] + eps)
    feature = feature * gamma + beta
    
    return feature

调用:

def main():
    t = torch.rand(4,2,3)
    # 仅在最后一个维度上做norm处理

    # 调用官方实现的layerNorm
    norm = nn.LayerNorm(normalized_shape = t.shape[-1],eps=1e-5)
    t1 = norm(t)

    # 上述自定义的LayerNorm处理
    t2 = layer_norm_process(t,eps=1e-5)
    
    print("t1:\n",t1)
    print("t2:\n",t2)

if __name__ = '__main__':
    main()

代码中的 t.shape[-1] 指的是数据的最后一个维度

注意:beta最初初始化为 0,gamma最初初始化为1,这两个参数后面通过训练慢慢学习得到

优点:

  • 不依赖于批次大小,因此在训练和推理阶段都可以使用
  • 在处理小批次数据时,相比于BN批归一化,LayerNorm 更稳定
  • 由于每个样本都有自己的均值和方差,可以更好地适应不同样本之间的差异
### Layer Normalization 的概念 Layer Normalization 是一种用于神经网络中的正则化技术,旨在解决内部协变量偏移问题并加速训练过程。与批量归一化不同的是,层归一化是在单一样本的所有特征上计算均值和方差,而不是在mini-batch维度上进行操作[^2]。 具体来说,在每一层中,对于每一个样本 \( x \),其标准化后的输出 \( y \) 可以表示为: \[y = \frac{x - E[x]}{\sqrt{Var[x]+\epsilon}} * \gamma +\beta\] 其中 \(E[x]\) 和 \( Var[x] \) 分别代表该层输入的期望和方差;\( \gamma \) 和 \( \beta \) 则是可学习参数,用来缩放和平移已规范化数据。 ### 层归一化的实现方式 下面是一个简单的PyTorch版本的层归一化实现方法: ```python import torch.nn as nn class LayerNorm(nn.Module): def __init__(self, normalized_shape, eps=1e-5, elementwise_affine=True): super(LayerNorm, self).__init__() if isinstance(normalized_shape, int): normalized_shape = (normalized_shape,) self.normalized_shape = tuple(normalized_shape) self.eps = eps self.elementwise_affine = elementwise_affine if self.elementwise_affine: self.weight = nn.Parameter(torch.ones(self.normalized_shape)) self.bias = nn.Parameter(torch.zeros(self.normalized_shape)) else: self.register_parameter('weight', None) self.register_parameter('bias', None) def forward(self, input_tensor): mean = input_tensor.mean(dim=-1, keepdim=True) std = input_tensor.std(dim=-1, keepdim=True) output = (input_tensor - mean) / (std + self.eps) if self.elementwise_affine: output = output * self.weight + self.bias return output ``` 这段代码定义了一个 `LayerNorm` 类来执行上述提到的操作,并允许通过设置 `elementwise_affine=False` 来关闭仿射变换部分。 ### 使用场景 通常情况下,当处理序列建模任务时(比如自然语言处理),由于批次大小较小或者为了保持时间步之间的依赖关系而不希望打乱顺序等原因,会选择使用层归一化而非批归一化[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值