Tansformer中的层归一化(Layer Normalization)

tansformer镇楼

1、内部协变量偏移问题

假设我们正在训练一个Transformer模型,用于从电影评论数据中预测情感。我们的数据集包含从2000年到2023年的评论,其中包含各种各样的评论风格和词汇。

在训练过程中,我们可能会发现一个问题:随着我们接触到的评论时间越来越近,模型的性能可能会开始下降。原因是什么呢?

原因可能是内部协变量偏移。在我们的例子中,评论的语言和风格与时间紧密相关。在2000年的评论可能会使用一些已经过时的词汇和表达方式,而2023年的评论可能会使用一些新的、流行的词汇和表达方式。

当我们的模型在处理2000年的评论时,它可能会调整其参数以适应这些评论的特点。然而,当模型开始处理2023年的评论时,由于这些评论的特点与2000年的评论不同,模型的参数可能不再适应新的评论。这就是内部协变量偏移:随着训练的进行,每一层的输入分布(即,评论的语言和风格)会随着时间的推移而变化,导致模型的性能下降。

比如说:

假设我们有以下两条电影评论:

评论1(2005年):“这个电影是个绝对的烂片,我从未看过这么无聊的电影。”

评论2(2023年):“这个电影真的太糟了,简直是睡眠药。”

在训练过程中,我们可能会发现一个问题:尽管这两条评论在语义上是相似的(都是负面的),但是由于它们使用的词汇和表达方式不同,模型可能会在处理评论2时表现得不如处理评论1时好。这是因为模型在处理评论1时,它可能会调整其参数以适应这些评论的特点。然而,当模型开始处理评论2时,由于这些评论的特点与评论1不同,模型的参数可能不再适应新的评论。这就是内部协变量偏移。

为了解决这个问题,我们可以使用一些技术,如批量归一化(Batch Normalization)或者层归一化(Layer Normalization)。这些技术可以在每一层内部对输入进行归一化,减少输入分布的变化,从而减轻内部协变量偏移的影响

2、协变量偏移引起的异常的训练指标

当内部协变量偏移发生时,一些训练指标可能会显示出异常的表现,从而帮助我们发现和诊断问题。以下是一些可能会被观察到的异常表现:

1. **训练和验证损失的差距**:如果模型在训练集上表现得越来越好,但在验证集(或测试集)上的表现却没有改善,或者甚至变得更差,这可能是一个信号,表明模型已经开始过拟合训练数据,而没有很好地泛化到新的、未见过的数据。这种现象可能是由于内部协变量偏移引起的。

2. **训练和验证准确率的差距**:同样地,如果模型在训练集上的准确率持续提高,但在验证集(或测试集)上的准确率却停滞不前或下降,这也可能是内部协变量偏移的一个信号。

3. **梯度的大小和方向**:如果模型的梯度开始变得非常大或非常小,或者经常变化方向,这可能表明模型正在努力适应不断变化的输入数据分布。这是内部协变量偏移的一个可能的迹象。

4. **模型参数的变化**:如果模型的参数开始快速变化,或者在训练过程中经常发生大的跳动,这也可能是内部协变量偏移的一个信号。

这些数据都可以通过各种可视化工具(如TensorBoard)进行可视化,以帮助我们更好地理解模型的训练过程,并识别可能存在的问题。

3、tansfomer的层归一化

ransformer架构在设计过程中采用了一种称为层归一化(Layer Normalization)的技术来解决内部协变量偏移的问题。

层归一化在每一层的神经元上都会进行操作,而不是在每个批次的数据上,这与批归一化不同。层归一化会对每一层的神经元输出进行归一化,使得这些值具有零平均值和单位方差。这样做的目的是为了消除模型训练过程中的内部协变量偏移。

(1)首先计算神经元输出的均值(μh):

μh = 1/d_model ∑(i=1 to d_model) h_i

这个公式是平均每个神经元的输出,其中d_model是神经元的数量,h_i是第i个神经元的输出。

(2)然后计算神经元输出的标准差(σh):

σh = sqrt (1/d_model ∑(i=1 to d_model) (h_i - μh)²)

这个公式是计算神经元输出的标准差,其中d_model是神经元的数量,h_i是第i个神经元的输出,μh是神经元输出的均值。

(3)最后,使用均值和标准差对神经元输出进行归一化:

ĥ_i = (h_i - μh) / σh

这个公式是将第i个神经元的输出归一化,使其具有零均值和单位方差。

通过这种方式,层归一化能使每个隐藏层的输出都具有相似的分布,从而减少模型训练过程中的内部协变量偏移。这有助于模型的训练和泛化能力。但是,尽管层归一化可以缓解内部协变量偏移,它无法解决输入数据的协变量偏移问题。对于输入数据的协变量偏移,可能需要采用其他的数据预处理或模型训练策略来解决。

4、代码实现

在实现Transformer架构的代码中,层归一化通常可以使用现有深度学习库(如PyTorch、TensorFlow)中的预定义函数或类来完成。

以下是一个使用PyTorch实现的层归一化的示例:

import torch.nn as nn

class LayerNorm(nn.Module):  # 定义LayerNorm类,继承自PyTorch的nn.Module类
    def __init__(self, features, eps=1e-6):  # 初始化函数,输入参数有特征数和一个非常小的数字eps
        super(LayerNorm, self).__init__()  # 调用父类nn.Module的初始化函数
        self.gamma = nn.Parameter(torch.ones(features))  # gamma参数,用于缩放,初始化为1
        self.beta = nn.Parameter(torch.zeros(features))  # beta参数,用于平移,初始化为0
        self.eps = eps  # 非常小的数字,用于防止除以零的情况

    def forward(self, x):  # 前向传播函数,输入是x
        mean = x.mean(-1, keepdim=True)  # 计算x沿最后一个维度的均值,保持原有的维度数量不变
        std = x.std(-1, keepdim=True)  # 计算x沿最后一个维度的标准差,保持原有的维度数量不变
        return self.gamma * (x - mean) / (std + self.eps) + self.beta  # 使用均值和标准差对x进行归一化,然后进行缩放和平移

这段代码定义了一个名为LayerNorm的类,这个类在初始化时创建了两个可学习的参数gamma和beta。在进行前向传播时,它首先计算输入x沿最后一个维度的均值和标准差,然后使用这些统计信息对输入进行归一化,并通过gamma和beta进行缩放和平移。这个eps参数是为了防止除以零的情况。

在Transformer模型中,你可以在每个子层(例如,自注意力层和前馈神经网络层)的输出后面添加这个LayerNorm模块,以进行层归一化。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

garyyu2200

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值