PyTorch深度学习实战 |层归一化层和FeedForward

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 本文介绍了PyTorch深度学习中Add&Norm层和FeedForward层的实现原理。Add&Norm层由残差连接(Add)和层归一化(Norm)组成,能加速模型收敛并稳定训练。层归一化会对神经网络每层的输出进行归一化处理,文中详细展示了其计算方法和PyTorch实现代码。FeedForward层是一个两层的全连接网络,通过线性变换提取更深层次特征。文章还分析了Transformer模型中使用层归一化的原因,并提供了完整的代码实现,包括参数初始化和前向传播过程。

 Add & Norm

Add & Norm 层

由 Add 和 Norm 两部分组成,其计算公式如下:

image.gif 编辑

其中 X表示 Multi-Head Attention 或者 Feed Forward 的输入,MultiHeadAttention(X) 和

FeedForward(X) 表示输出 (输出与输入 X 维度是一样的,所以可以相加)。

Add

AddX+MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让

网络只关注当前差异的部分,在 ResNet 中经常用到:

image.gif

Norm 层

     Norm指 Layer Normalization(层归一化),通常用于 RNN 结构,Layer Normalization 会将

每一层神经元的输入都转成均值方差都一样的,这样可以加快收敛。下面我们将从3个方面介绍这

个模型,具体包括:

(1)层归一化的计算方法(2)如何使用层归一化(3)为什么 Transformer 使用层归一化

层归一化的计算方法

层归一化的作用很简单,就是让神经网络训练更稳定,不会出现梯度炸掉或者梯度变得特别小(梯

度爆炸和梯度消失)。 它的做法也不复杂:会对神经网络某一层里所有神经元的输出结果,统一

做“归一化”处理。 举个例子说吧:假设某一层有4个神经元,把一个样本输进去后,这一层会输出4

个结果,咱们叫它们x1、x2、x3、x4。层归一化做的事儿,就是专门针对这4个数值来计算,把它

们调整到合适的范围里。

image.gif

咱们先把层归一化的公式里各个符号说清楚,特别好理解: xi 就是神经网络某一层里第i个神经元

的输出结果,u(平均值)是这一层所有神经元输出的平均数,而xhat(带帽的x)就是经过层归

一化处理后,最终得到的结果。层归一化后的 x1 到 x4: 具有相似的尺度使得神经网络可以更快的

收敛训练过程也会变更更加稳定。

image.gif

如何使用层归一化?

    层归一化实现的还是比较简单的,我们直接调用nn.LayerNorm,然后传入当前层的输出。

import torch
from torch import nn
# 定义张量x
# x是一个2×4大小的张量,代表了2个样本,每个样本有4个特征
# 当使用层归一化对x进行计算时,会对x的每一行的4个特征进行归一化
x = torch.tensor([[1.0, 2.0, 3.0, 4.0],
                  [1.0, 1.0, 1.0, 1.0]])
# 定义层归一化实例
# 传入的参数4,表示层归一化的输入维度是4
# 也就是对应某一层的4个神经元的输出
layer_norm = nn.LayerNorm(4)
# 计算层归一化的结果
output = layer_norm(x)
print(output)

image.gif

image.gif

为啥要使用归一化?

在 Transformer 模型中,层归一化(Norm)是基于 “序列数据的特定组织形式” 设计的。

Transformer 中序列数据的尺寸为 B×Q×D,各维度定义:

B(Batch size):批量大小,即一次输入模型的样本数量;

Q(Sequence Length):序列长度,即每个样本(如句子)包含的元素(如单词)数量;

D(Features Dim):特征维度,即每个元素对应的向量维度(如词向量的维度)。

  Transformer 中,层归一化会针对 每个样本的特征维度(D维度)进行归一化(即对B×Q×D中每

个D维度的向量单独计算均值和方差),以适配序列数据的结构,稳定模型训练。

   观察结果可以发现,在做层归一化的时候,会分别对x中的每行单词对应的4个维度进行计算

在两个样本中一共有6个单词,这样就会进行6次层归一化的计算,单词和单词之间不会产出影响

总结一下:无论一组序列数据的批量 B 是多少在一组数据中,不同的序列有着不同的长度 Q不会

影响层归一化的计算。

import torch
import torch.nn as nn
# 当使用层归一化计算序列数据时,层归一化只会作用在最后的特征维度D上
# 其中批量大小B与序列长度Q,这两个维度都不会影响层归一化的计算
# 定义输入数据 x,形状为 (B, Q, D) -> (2, 3, 4)
# 2个样本,每个样本3个单词,每个单词用4个维度表示
x = torch.tensor([
    # 第1个样本:
    [
        [1.0, 2.0, 3.0, 4.0],  # 第1个单词的4个维度
        [1.0, 1.0, 1.0, 1.0],  # 第2个单词的4个维度
        [1.0, 1.0, 1.0, 1.0]   # 第3个单词的4个维度
    ],
    # 第2个样本:
    [
        [1.0, 1.0, 1.0, 1.0],  # 第1个单词的4个维度
        [1.0, 1.0, 1.0, 1.0],  # 第2个单词的4个维度
        [1.0, 1.0, 1.0, 1.0]   # 第3个单词的4个维度
    ]
])
# 初始化层归一化层
layer_norm = nn.LayerNorm(4)
# x输入至层归一化layer_norm中
output = layer_norm(x)
# 输出结果
print(output)

image.gif

image.gif


FeedForward

Feed Forward 层比较简单,是一个两层的全连接层,第一层的激活函数为 Relu,第二层不使用激

活函数,FeedForward的计算公式如下:

image.gif 编辑

X是输入,Feed Forward 最终得到的输出矩阵的维度与X一致。max相当于Relu,所以

FeedForward的作用是:通过线性变换,先将数据映射到高纬度的空间再映射到低纬度的空间,

提取了更深层次的特征。

Feed-Forward Layer就是一个全连接神经网络,通常包含两个线性变换和一个激活函数它的输入

是Multi-Head Attention的输出,这个输出首先会经过一个残差连接和Normalization,然后才会进入

Feed-Forward Layer。Feed-Forward Layer的主要任务是进一步提取和深化特征,使模型能够更

好地理解和处理输入数据。 FeedForward的输入是什么呢?是Multi-Head Attention的输出做了残

差连接和Norm之后得数据,然后FeedForward做了两次线性线性变换,为的是更加深入的提取特

代码实现:

import torch
import torch.nn as nn
import torch.nn.functional as F
class FeedForward(nn.Module):
    def __init__(self, d_model: int, d_ff: int = None, activation: str = "gelu", dropout: float = 0.1):
        """
        Args:
            d_model: 输入/输出维度(即 Transformer 的隐藏层维度)
            d_ff:    中间层维度(默认扩展为 4*d_model)
            activation: 激活函数,支持 "gelu" 或 "relu"
            dropout:  Dropout 概率
        """
        super().__init__()
        d_ff = d_ff or 4 * d_model  # 默认扩展比例为4倍
        # 定义两个线性层
        self.linear1 = nn.Linear(d_model, d_ff)  # 扩展维度
        self.linear2 = nn.Linear(d_ff, d_model)  # 压缩回原维度
        
        # 激活函数选择
        self.activation = F.gelu if activation == "gelu" else F.relu
        
        # Dropout 层(可选)
        self.dropout = nn.Dropout(dropout) if dropout > 0 else nn.Identity()
        # 参数初始化(关键!)
        self._init_weights()
    def _init_weights(self):
        # 使用 He/Kaiming 初始化(适合 ReLU)
        nn.init.kaiming_normal_(self.linear1.weight, nonlinearity='relu')
        nn.init.zeros_(self.linear1.bias)
        
        # 缩小输出层的初始化范围
        nn.init.xavier_normal_(self.linear2.weight, gain=0.02)
        nn.init.zeros_(self.linear2.bias)
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        """
        输入形状: (batch_size, seq_len, d_model)
        输出形状: (batch_size, seq_len, d_model)
        """
        x = self.linear1(x)       # (batch, seq, d_ff)
        x = self.activation(x)    # 非线性激活
        x = self.dropout(x)       # 可选 Dropout
        x = self.linear2(x)       # (batch, seq, d_model)
        return x

image.gif


目录
相关文章
|
1月前
|
机器学习/深度学习 自然语言处理 算法
PyTorch深度学习实战 | Transformer模型初识
本文介绍了Transformer模型在机器翻译任务中的工作原理。主要内容包括:1)模型分为编码器(处理英文输入)和解码器(生成中文输出)两部分;2)推理时采用自回归模式,逐步生成翻译结果;3)训练时使用教师强制模式,始终以真实标签指导模型学习。文章详细阐述了编码器-解码器结构的工作流程,包括词嵌入、多头注意力机制等核心组件,以及如何通过残差连接和层标准化优化模型性能。最后解释了编码器和解码器三个关键计算步骤的张量维度变化过程。
190 0
|
1月前
|
机器学习/深度学习 PyTorch 测试技术
PyTorch深度学习实战 |多头注意力机制
摘要:本文详细介绍了Transformer中的多头自注意力机制,从整体结构到实现细节,包括四部分内容:(1)多头自注意力的基本架构;(2)内部计算流程解析;(3)注意力计算公式详解;(4)代码实现。重点阐述了多头并行的计算方式、缩放点积注意力的计算步骤(QK转置、缩放、softmax和加权求和),以及残差连接和层归一化的作用。通过"Are you OK?"示例展示了输入张量如何经过8个64维注意力头处理后拼接成512维输出。文章最后提供了完整的PyTorch实现代码,并附测试用例验证模型
182 0
|
1月前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch深度学习实战 |手动计算 Transformer和完整的代码实现
本文介绍了基于PyTorch实现Transformer模型的完整过程。主要内容包括:1)Transformer架构的核心组件实现,如多头注意力机制、位置前馈网络、位置编码等;2)模型构建步骤,包括词嵌入层、编码器/解码器块和输出层的实现;3)完整的训练流程,包含数据处理、损失计算和参数优化;4)评估方法验证模型性能。文章通过代码示例详细展示了如何从零开始构建Transformer,并应用于机器翻译任务,同时对模型各层的输入输出维度进行了说明。该实现可作为深度学习实践者学习Transformer架构的实用指南
165 0
|
1月前
|
机器学习/深度学习 自然语言处理 PyTorch
PyTorch深度学习实战 |词嵌入和位置编码
本文介绍了PyTorch中词嵌入(Embedding)和位置编码(Positional Encoding)的实现与应用。词嵌入通过Word2Vec、GloVe等技术将单词转换为连续向量,其中使用nn.Embedding层加载预训练词向量,并展示如何可视化词向量间的语义关系(如"king-man≈queen-woman")。位置编码部分详细解释了如何通过正弦/余弦函数为词向量添加位置信息,包含公式推导和代码实现(PositionalEncoding类)。文章提供了完整的PyTorch代码示
219 0
|
1月前
|
机器学习/深度学习 编解码 算法
PyTorch深度学习实战 | 标准化和归一化
本文介绍了数据预处理中的标准化和归一化方法,包括计算过程、特性对比及实际应用。以波士顿房价数据集为例,展示了原始数据、标准化和归一化后的模型效果差异。同时讲解了深度学习中常用的层归一化(LN)和批量归一化(BN)技术,分别适用于文本和图像处理任务,并给出了PyTorch实现示例。LN通过调整词向量分布缓解梯度消失等问题,而BN则对图像各通道单独处理。两种技术都能提升模型训练效果,但适用场景不同。
171 0
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
图解人工智能的数学基础(最优化)
本文深入解析人工智能中最优化问题的核心:通过最小化损失函数来训练模型。涵盖回归(MSE)与分类(交叉熵)任务的典型损失函数,详解梯度下降原理及BGD、SGD、Mini-batch等算法差异,并介绍Momentum、Adam等现代优化技巧,辅以PyTorch代码实现。
121 0
|
1月前
|
机器学习/深度学习 数据挖掘 PyTorch
PyTorch深度学习实战 |手算​​FCN全卷积神经网络
本文介绍了FCN-8s语义分割网络的实现细节。首先解释了语义分割的概念及其与图像分类的区别,重点分析了FCN网络结构中的全卷积化、上采样和跳跃连接三个关键技术。全卷积化将传统CNN的全连接层改为卷积层,实现像素级分类;上采样通过双线性插值恢复特征图尺寸;跳跃连接则融合高低层特征以提升细节表现。文章详细推导了损失函数的计算过程,并提供了完整的PyTorch实现代码,包括双线性插值权重初始化、VGG16骨干网络和FCN-8s主体结构。最后通过测试验证了模型能正确输出与输入尺寸匹配的预测结果。
274 3
|
1月前
|
机器学习/深度学习 编解码 算法
PyTorch深度学习实战 |手算​​U-net
本文详细解析了U-Net网络架构及其在医学图像分割中的应用。重点对比了U-Net与FCN的核心区别:U-Net采用特征拼接(Concat)保留所有层级信息,而FCN使用特征相加(Add)进行融合。文章深入剖析了U-Net的编码器-瓶颈-解码器结构,解释了其独特的裁剪拼接机制和Overlap-tile策略,并提供了完整的PyTorch实现代码。现代U-Net通过SamePadding实现了输入输出尺寸一致,显著提升了分割精度。文章还探讨了弹性形变数据增强和带空间权重的损失函数设计,为医学图像分析提供了实用解决
181 2
|
1月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch深度学习实战 |Alexnet网络花分类任务项目版本
本文介绍了基于PyTorch的花卉分类实战项目,包含完整的项目架构和代码实现。项目采用AlexNet网络结构,通过YAML配置文件管理参数,实现了模块化开发。文章详细讲解了数据集处理(5类花卉)、模型训练(包含早停机制和学习率调度)、验证评估和预测功能。项目采用YOLOv5风格的目录结构,包含configs、models、utils等模块,支持命令行参数配置。实验结果显示该架构比简单实现准确率提升4%,最终预测功能可输出top-k分类结果及置信度。完整代码已开源,适合深度学习初学者进阶学习。
220 0
|
1月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch深度学习实战 |手算GCN (图神经网络)模型
本文介绍了使用PyTorch实现图神经网络(GNN)处理分子结构数据的实战方法。主要内容包括:1) GNN的基本原理,通过节点特征矩阵和邻接矩阵处理图结构数据;2) 分子图的表示方式,将SMILES字符串转换为PyTorch Geometric图对象;3) 图卷积运算过程,包括特征变换和邻接特征聚合;4) 代码实现示例,构建包含GCN层和全局池化的模型,对乙醇分子进行特征提取和分类预测。文章通过具体案例展示了GNN在化学领域的应用,为读者提供了从理论到实践的完整指导。
161 0