课程名称:神经网络与深度学习
授课教师:屈桢深老师
周次:第4周

在这里插入图片描述

图注:本周课程以 Transformer 架构为主线,重点理解输入编码、注意力机制、编码器、解码器和输出预测流程;同时结合 DeepLabV3 示例,回顾语义分割模型从图像输入到像素级预测的实践链路。

摘要

第3周课程主要围绕 Transformer 模型展开。Transformer 是现代深度学习中非常重要的基础结构,它用自注意力机制替代传统循环结构,使模型能够并行处理序列,并在自然语言处理、计算机视觉、多模态建模等方向形成广泛影响。

本周学习内容可以概括为两条线索。第一条是 Transformer 理论与代码实现:从词嵌入、位置编码开始,逐步进入 Mask、Scaled Dot-Product Attention、多头注意力、前馈网络、残差连接、LayerNorm、编码器、解码器和最终输出层。第二条是 DeepLabV3 语义分割实践:通过 deeplab.ipynb、离线预训练权重和测试图片,理解一个成熟视觉模型如何完成像素级分类。

通过本周学习,可以把“神经网络结构”从单个层的堆叠理解为完整的数据流:输入如何变成向量,向量如何通过注意力交互,编码器如何抽取上下文,解码器如何生成输出,视觉分割模型又如何把图像映射为类别掩码。

目录

  1. Transformer模型整体认识
  2. 输入部分:Embedding与位置编码
  3. 注意力机制:Mask、Scaled Dot-Product Attention与Multi-Head Attention
  4. 编码器:前馈网络、LayerNorm、残差连接与Encoder堆叠
  5. 解码器与输出部分
  6. Transformer代码实现链路
  7. DeepLabV3语义分割实践
  8. 本周知识点表格总结
  9. 本周学习收获
  10. 总结
  11. CSDN发布建议

1. Transformer模型整体认识

Transformer 最早面向序列建模任务提出。传统 RNN、LSTM、GRU 等循环神经网络按时间步顺序处理序列,天然适合表达前后依赖,但也带来两个问题:一是长距离依赖传播路径较长,二是训练时很难充分并行。CNN 虽然能够并行计算,但卷积核感受野有限,需要堆叠较多层才能覆盖远距离关系。

Transformer 的核心思想是用注意力机制直接建模序列中任意位置之间的关系。对一句话来说,某个词不必只依赖前一个词或局部窗口,而是可以通过 Attention 直接关注句子中所有相关词。这样,模型既能捕捉长距离依赖,也更适合 GPU 并行计算。

在这里插入图片描述

图注:Transformer 由 Encoder 和 Decoder 两大部分组成。输入序列先经过词嵌入和位置编码,再进入编码器;解码器结合已生成目标序列和编码器输出,最后通过 Linear 与 Softmax 得到预测分布。

从结构上看,标准 Transformer 通常包含:

  • 输入部分:词嵌入层和位置编码层。
  • 编码器部分:多头自注意力、前馈全连接网络、残差连接、LayerNorm。
  • 解码器部分:Masked 多头自注意力、编码器-解码器注意力、前馈网络、残差连接、LayerNorm。
  • 输出部分:线性映射和 Softmax,将隐藏向量映射为词表概率。

课程中的 Transformer.ipynb 按模块逐步实现了这些结构。它不是只调用现成库,而是从 EmbeddingsPositionalEncodingattentionMultiHeadedAttention 等模块开始写起,帮助我们理解 Transformer 内部每一步到底在做什么。

2. 输入部分:Embedding与位置编码

Transformer 的输入不是原始文本,而是张量。文本通常先通过词表映射为整数 token id,再通过 Embedding 层变成连续向量。

课程代码中定义了 Embeddings 类:

class Embeddings(nn.Module):
    def __init__(self, d_model, vocab):
        super(Embeddings, self).__init__()
        self.lut = nn.Embedding(vocab, d_model)
        self.d_model = d_model

    def forward(self, x):
        return self.lut(x) * math.sqrt(self.d_model)

这里有两个关键参数:

  • vocab:词表大小,表示模型可以识别多少个不同 token。
  • d_model:词向量维度,也是 Transformer 中大多数模块使用的统一隐藏维度。

代码中把 Embedding 输出乘以 sqrt(d_model)。这样做的目的,是调整词向量数值尺度,使嵌入向量与后续位置编码相加时更加稳定。

在这里插入图片描述

图注:文本输入先被映射为 token id,再通过 Embedding 矩阵得到词向量;词向量经尺度调整后与位置编码相加,形成包含词义和位置信息的序列表示。

2.1 为什么需要位置编码

Transformer 没有 RNN 的时间步顺序,也没有 CNN 的局部滑动结构。如果只输入词向量,模型能够知道“有哪些词”,却不知道“词出现在哪里”。例如“我喜欢深度学习”和“深度学习喜欢我”包含相同词,但语义完全不同。

因此,Transformer 需要显式加入位置信息。课程中实现的 PositionalEncoding 使用正弦和余弦函数构造位置编码:

PE(pos,2i)=sin⁡(pos100002i/d) PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i)=sin(100002i/dpos)

PE(pos,2i+1)=cos⁡(pos100002i/d) PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d}}\right) PE(pos,2i+1)=cos(100002i/dpos)

其中:

  • pos 表示词在序列中的位置。
  • i 表示向量维度索引。
  • d 表示词向量维度,也就是 d_model

这种设计让不同位置拥有不同编码,同时不同频率的正弦余弦函数可以表达多尺度位置信息。模型不需要额外学习位置参数,也能利用相对位置关系。

2.2 Dropout作用

位置编码层中还使用了 nn.Dropout(p=dropout)。Dropout 会在训练时随机置零部分神经元输出,降低模型对某些局部特征的过度依赖,从而缓解过拟合。课程中演示了 nn.Dropout(p=0.2) 的效果,也说明了 PyTorch 中张量维度变化和 unsqueeze 的使用方式。

3. 注意力机制:Mask、Scaled Dot-Product Attention与Multi-Head Attention

注意力机制是 Transformer 的核心。它解决的问题是:当模型处理某个位置的 token 时,应该重点关注序列中哪些位置。

3.1 Mask张量

课程中先实现了 subsequent_mask(size)。这个函数用于生成后续位置遮蔽矩阵,常用于解码器。解码时,模型只能看到当前位置及其之前的 token,不能提前看到未来答案。

例如目标序列长度为 5 时,第 1 个位置只能看第 1 个位置,第 2 个位置可以看第 1、2 个位置,第 5 个位置才能看完整前缀。这种三角 Mask 保证训练过程符合自回归生成规则。

Mask 还可以用于屏蔽 padding 位置。如果一句话被补齐到固定长度,补齐部分不应该参与注意力计算,否则模型会把无意义 token 当作上下文。

3.2 Scaled Dot-Product Attention

Scaled Dot-Product Attention 是最基础的注意力计算形式:

Attention(Q,K,V)=softmax(QKTdk)V Attention(Q, K, V) = softmax\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dk QKT)V

其中:

  • Q 是 Query,表示当前位置发出的查询。
  • K 是 Key,表示各位置可被匹配的索引特征。
  • V 是 Value,表示各位置真正要被加权汇总的信息。
  • d_k 是 Key 向量维度,用于缩放点积结果。

在这里插入图片描述

图注:Attention 先用 QK^T 计算位置相关性,再除以 sqrt(d_k) 控制数值尺度,经过 Mask 和 Softmax 得到权重,最后对 V 加权求和。

课程代码中的 attention 函数实现了这一过程:

def attention(query, key, value, mask=None, dropout=None):
    d_k = query.size(-1)
    scores = torch.matmul(query, key.transpose(-2, -1)) / math.sqrt(d_k)
    if mask is not None:
        scores = scores.masked_fill(mask == 0, -1e9)
    p_attn = F.softmax(scores, dim=-1)
    if dropout is not None:
        p_attn = dropout(p_attn)
    return torch.matmul(p_attn, value), p_attn

这里 masked_fill(mask == 0, -1e9) 很关键。它把被遮蔽位置的分数设为极小值,使这些位置经过 Softmax 后权重接近 0。

3.3 为什么要除以sqrt(d_k)

如果 QK 的维度很高,点积结果可能变得很大。Softmax 输入过大时,会让概率分布过于尖锐,梯度变小,训练不稳定。除以 sqrt(d_k) 相当于缩放分数,使注意力权重更平滑。

3.4 Multi-Head Attention

单个注意力头只能在一个表示子空间中计算关系。多头注意力把输入映射到多个子空间,让不同头分别关注不同关系。例如,一个头可能关注主谓关系,另一个头可能关注位置邻近关系,还有一个头可能关注长距离依赖。

在这里插入图片描述

图注:多头注意力将 Q、K、V 分成多个头并行计算,再拼接和线性映射。编码器中使用自注意力,解码器中既有 Masked 自注意力,也有与编码器输出交互的注意力。

课程中 MultiHeadedAttention 的实现思路可以概括为:

  1. 使用多个线性层分别生成 Q、K、V。
  2. 将张量 reshape 为多头形式。
  3. 对每个头执行 Scaled Dot-Product Attention。
  4. 将多个头的输出拼接。
  5. 再通过线性层得到最终输出。

多头注意力是 Transformer 强表达能力的重要来源。它不是简单重复计算,而是让模型从多个角度理解同一序列。

4. 编码器:前馈网络、LayerNorm、残差连接与Encoder堆叠

Transformer Encoder 由多个相同结构的 EncoderLayer 堆叠而成。每个 EncoderLayer 主要包含两个子层:

  • Multi-Head Self-Attention。
  • Position-wise Feed Forward Network。

两个子层外部都配有残差连接和 LayerNorm。

4.1 Position-wise Feed Forward Network

课程中实现了 PositionwiseFeedForward 类。它对序列中每个位置独立应用同一组全连接网络,一般形式为:

FFN(x)=max(0,xW1+b1)W2+b2 FFN(x) = max(0, xW_1 + b_1)W_2 + b_2 FFN(x)=max(0,xW1+b1)W2+b2

注意力层负责混合不同位置的信息,前馈网络负责对每个位置的表示进行非线性变换。二者组合后,模型既能进行全局关系建模,也能提升单个位置表示能力。

4.2 LayerNorm

LayerNorm 用于规范化每个样本内部的特征分布。课程代码中实现了 LayerNorm,核心思想是对最后一个维度求均值和标准差,再进行标准化:

LayerNorm(x)=a⋅x−meanstd+ϵ+b LayerNorm(x) = a \cdot \frac{x - mean}{std + \epsilon} + b LayerNorm(x)=astd+ϵxmean+b

其中 ab 是可学习参数,\epsilon 用于防止除零。

4.3 残差连接与SublayerConnection

残差连接可以写成:

x+Sublayer(x) x + Sublayer(x) x+Sublayer(x)

它让梯度更容易向前传播,也让深层模型更容易训练。课程中的 SublayerConnection 将残差连接、Dropout 和 LayerNorm 组合起来,用于包裹注意力层和前馈层。

从学习角度看,SublayerConnection 是理解 Transformer 工程实现的关键。很多模型结构图只画出 Add & Norm,但代码中需要明确处理输入、子层函数、Dropout 和规范化顺序。

4.4 EncoderLayer与Encoder

课程中的 EncoderLayer 把自注意力层和前馈层组合起来;Encoder 再通过 clones(layer, N) 复制多个 EncoderLayer,形成深层编码器。

这说明 Transformer 的深度来自模块堆叠。一个 EncoderLayer 已经具备自注意力和非线性变换能力,但多个层堆叠后,模型可以逐层形成更抽象的上下文表示。

5. 解码器与输出部分

Decoder 和 Encoder 类似,也由多个 DecoderLayer 堆叠。但 Decoder 每层通常包含三个子层:

  • Masked Multi-Head Self-Attention。
  • Encoder-Decoder Attention。
  • Position-wise Feed Forward Network。

5.1 Masked Self-Attention

解码器第一个注意力层必须使用 Mask。原因是生成任务通常从左到右预测目标序列。如果训练时允许当前位置看到未来 token,就会信息泄露,模型推理时无法复现训练条件。

例如翻译任务中,模型预测第 3 个词时,只能使用已经生成的第 1、2 个词,不能看到第 4 个词。

5.2 Encoder-Decoder Attention

Decoder 第二个注意力层使用来自 Decoder 的 Query,以及来自 Encoder 输出的 Key 和 Value。这样,解码器在生成每个目标 token 时,都可以回看源序列编码结果。

这一步可以理解为“目标端正在问问题,源端编码结果提供答案依据”。它让模型在生成过程中动态对齐输入序列不同部分。

5.3 输出层Generator

课程中定义了 Generator 类,用线性层把 d_model 维隐藏向量映射到词表大小,再通过 log_softmax 得到对数概率:

class Generator(nn.Module):
    def __init__(self, d_model, vocab):
        super(Generator, self).__init__()
        self.project = nn.Linear(d_model, vocab)

    def forward(self, x):
        return F.log_softmax(self.project(x), dim=-1)

如果词表大小为 1000,那么每个位置的输出就是 1000 个类别上的概率分布。模型会选择概率最高的 token,或在生成任务中结合搜索策略产生最终序列。

6. Transformer代码实现链路

Transformer.ipynb 的价值在于,它把 Transformer 从局部模块一直搭到完整模型。课程中涉及的主要模块如下:

模块 代码名称 作用
文本嵌入 Embeddings 将 token id 映射为 d_model 维向量,并乘以 sqrt(d_model)
位置编码 PositionalEncoding 给序列加入位置信息,弥补 Transformer 无循环结构的问题
掩码张量 subsequent_mask 屏蔽未来位置或无效位置
注意力计算 attention 实现 Scaled Dot-Product Attention
多头注意力 MultiHeadedAttention 并行计算多个注意力头并融合
前馈网络 PositionwiseFeedForward 对每个位置进行非线性变换
规范化层 LayerNorm 稳定特征分布,提升训练稳定性
子层连接 SublayerConnection 封装残差、Dropout、LayerNorm
编码器层 EncoderLayer 组合自注意力和前馈网络
编码器 Encoder 堆叠多个编码器层
解码器层 DecoderLayer 组合 Masked 自注意力、源端注意力和前馈网络
解码器 Decoder 堆叠多个解码器层
输出层 Generator 将隐藏向量映射到词表概率
完整模型 EncoderDecoder 串联编码器、解码器、嵌入层和输出层

课程后半部分还出现了 make_modeldata_generatorLabelSmoothingSimpleLossComputerun 等函数或类,用于构造完整模型、生成示例数据、定义损失和训练流程。

其中 make_model 是一个重要封装,它将编码器、解码器、嵌入层、位置编码、输出层等组装成完整模型,并使用 Xavier 初始化参数。这样可以把前面分散实现的模块合并为可训练网络。

7. DeepLabV3语义分割实践

第3周文件夹中还包含 image_segmentation 实践材料。该部分包括:

  • deeplab.ipynb:使用 DeepLabV3-ResNet101 进行语义分割的程序文件。
  • deeplabv3_resnet101_coco-586e9e4e.pth:离线预训练模型权重。
  • runner.jpgdog.jpgathletes.jpg:测试用图片。
  • readme.txt:说明模型权重需要放入 PyTorch cache 目录。

在这里插入图片描述

图注:DeepLabV3 推理流程包括输入图像、预处理归一化、模型前向传播、类别得分图、argmax 获取像素类别、调色板上色和分割结果可视化。

7.1 DeepLabV3实践流程

deeplab.ipynb 的执行流程较清晰:

  1. 导入 PyTorch。
  2. 通过 torch.hub.load 加载 deeplabv3_resnet101 预训练模型。
  3. 调用 model.eval() 进入推理模式。
  4. 使用 PIL 读取本地图像。
  5. 使用 torchvision.transforms 将图像转为张量并归一化。
  6. 使用 unsqueeze(0) 增加 batch 维度。
  7. 如果可用,将模型和输入转移到 GPU。
  8. torch.no_grad() 下执行前向传播。
  9. model(input_batch)['out'][0] 得到输出。
  10. argmax(0) 得到每个像素的预测类别。
  11. 构造调色板,将类别图转为彩色分割图。

核心推理代码如下:

with torch.no_grad():
    output = model(input_batch)['out'][0]
output_predictions = output.argmax(0)

这里 output 可以理解为类别得分图。对每个像素位置,模型都会输出多个类别的得分;argmax(0) 则选择得分最高的类别,得到最终语义分割结果。

7.2 图像预处理

DeepLabV3 使用了标准 ImageNet 归一化参数:

transforms.Normalize(
    mean=[0.485, 0.456, 0.406],
    std=[0.229, 0.224, 0.225]
)

这一步与模型预训练条件一致。如果输入图像没有按同样方式归一化,模型看到的数据分布会偏离训练分布,预测效果可能下降。

7.3 离线权重说明

readme.txt 提到,原模型约 233MB,从 PyTorch 网站下载可能较慢,因此课程材料提供了对应离线 .pth 文件。权重需要拷贝到:

C:\Users\<username>\.cache\torch\hub\checkpoints

其中 <username> 为当前 Windows 登录用户名。这样执行 torch.hub.load(..., pretrained=True) 时,PyTorch 可以直接使用本地缓存权重。

7.4 与第2周语义分割内容的衔接

第2周学习过 FCN 和语义分割基本概念,第3周的 DeepLabV3 实践相当于把概念落到代码。语义分割不是输出一个类别,也不是输出目标框,而是输出每个像素的类别。

DeepLabV3 的优势在于能够结合深层特征和多尺度上下文,对人、动物、道路、背景等区域进行像素级识别。课程示例中建议使用人、动物等模型训练过的典型目标进行测试,这也说明预训练模型的效果依赖于训练数据类别范围。

8. 本周知识点表格总结

8.1 Transformer模块功能表

模块 输入 输出 核心作用
Embedding token id 词向量 将离散文本转为连续向量
Positional Encoding 词向量 带位置的词向量 提供序列顺序信息
Scaled Dot-Product Attention Q、K、V 上下文向量 按相关性汇总序列信息
Multi-Head Attention 多组Q/K/V 融合后的表示 从多个子空间捕捉关系
Feed Forward 每个位置的表示 非线性变换后表示 提升单位置表达能力
LayerNorm 隐藏向量 规范化向量 稳定训练
Residual Connection 输入与子层输出 相加后的表示 缓解深层网络训练困难
Encoder 源序列表示 源端上下文表示 编码输入序列
Decoder 目标前缀与源端上下文 目标端隐藏表示 自回归生成输出
Generator 隐藏表示 词表概率 得到最终预测 token

8.2 Q/K/V含义表

符号 名称 直观理解 在Attention中的作用
Q Query 当前词提出的问题 与 Key 计算匹配程度
K Key 每个词提供的索引特征 被 Query 检索
V Value 每个词携带的信息内容 按注意力权重加权求和
QK^T 注意力分数 位置之间的相关性 Softmax前的原始权重
Softmax 权重归一化 把分数变为概率 决定各位置关注比例
Mask 遮蔽矩阵 禁止关注某些位置 避免看未来或看padding

8.3 Encoder与Decoder对比表

对比项 Encoder Decoder
主要目标 理解输入序列 根据输入和已生成内容产生输出
注意力类型 Self-Attention Masked Self-Attention + Encoder-Decoder Attention
是否看未来位置 可看完整源序列 不能看目标端未来位置
输入来源 源序列Embedding与位置编码 目标序列Embedding与位置编码
输出用途 提供源端上下文memory 送入Generator预测词表概率

8.4 DeepLabV3推理流程表

步骤 对应代码/文件 作用
加载模型 torch.hub.load('pytorch/vision', 'deeplabv3_resnet101', pretrained=True) 获取预训练DeepLabV3模型
设置推理模式 model.eval() 关闭训练特有行为
读取图片 Image.open(local_fn) 加载测试图像
预处理 transforms.ToTensor()Normalize(...) 转张量并匹配预训练分布
增加batch维 unsqueeze(0) 适配模型输入格式
前向传播 model(input_batch)['out'][0] 得到类别得分图
像素分类 argmax(0) 为每个像素选择最高得分类别
可视化 putpalette(colors)plt.imshow(r) 将类别图显示为彩色分割结果

8.5 本周知识点与实践收获表

学习内容 关键问题 收获
Transformer输入 模型如何接收文本 token id 需要先转为词向量,再加入位置编码
位置编码 无RNN时如何表达顺序 正弦余弦编码提供可泛化位置信息
注意力机制 模型如何找上下文重点 Q/K/V与Softmax实现动态加权
多头注意力 为什么不只用一个注意力 多个子空间能捕捉不同关系
Encoder 如何理解输入序列 自注意力和前馈网络反复提炼上下文
Decoder 如何生成目标序列 Mask保证自回归,源端注意力提供输入依据
DeepLabV3 如何做像素级分类 预训练模型输出类别得分图,argmax得到分割掩码

9. 本周学习收获

本周最重要的收获是理解 Transformer 的“整体数据流”。以前看 Transformer 结构图时,容易只记住 Encoder、Decoder、Multi-Head Attention 等名称,但通过代码逐层实现后,可以看到每个模块都有明确输入、输出和功能。

Embedding 和位置编码说明,模型输入不是自然语言本身,而是经过词表映射和向量化后的张量。位置编码解决了 Transformer 缺少天然顺序结构的问题。

Attention 机制说明,模型不必按顺序一步步传递信息,而是可以直接计算任意两个位置之间的相关性。QK^T / sqrt(d_k)、Mask、Softmax 和对 V 加权求和,是理解 Transformer 的核心公式。

多头注意力说明,模型可以并行从多个角度理解序列。残差连接和 LayerNorm 则说明,深层网络不仅要有表达能力,还要能稳定训练。

DeepLabV3 实践帮助我们把课程内容与真实视觉任务连接起来。语义分割的输出是像素级类别,而不是整图类别或目标框。模型推理流程中的预处理、GPU判断、torch.no_grad()、类别得分图和调色板可视化,都是实际使用深度学习模型时必须掌握的工程细节。

10. 总结

第3周课程以 Transformer 模型为核心,系统讲解了从输入编码到注意力机制、编码器、解码器和输出预测的完整流程。通过 Transformer.ipynb,可以看到模型不是黑箱,而是由 Embedding、PositionalEncoding、Attention、MultiHeadedAttention、FeedForward、LayerNorm、EncoderLayer、DecoderLayer 等模块一步步搭建而成。

与此同时,image_segmentation 文件夹提供了 DeepLabV3 语义分割实践材料,让本周内容不只停留在序列模型,也延伸到视觉任务。DeepLabV3 示例展示了预训练模型如何读取图像、完成归一化、输出像素类别并生成分割可视化结果。

总体来看,本周学习建立了两个重要认识:第一,Transformer 的强大来自注意力机制、并行建模和稳定的深层结构设计;第二,深度学习模型的学习不能只看理论公式,还需要结合代码、输入输出张量形状和真实推理流程进行理解。

这些内容为后续继续学习大模型、视觉Transformer、多模态模型和复杂视觉应用打下基础。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐