目录
[2.2 编码器部分](#2.2 编码器部分)
[2.2.1Self-Attention 结构](#2.2.1Self-Attention 结构)
[2.2.2Q, K, V 的计算](#2.2.2Q, K, V 的计算)
[2.2.3 Self-Attention 的输出](#2.2.3 Self-Attention 的输出)
[2.2.4 Multi-Head Attention](#2.2.4 Multi-Head Attention)
[2.2.7Feed Forward](#2.2.7Feed Forward)
[2.3.2 Decoder注意力机制](#2.3.2 Decoder注意力机制)
[2.3.3 输出](#2.3.3 输出)
1.简介:
在深度学习的发展进程中,CNN、RNN 和 Transformer 这三种架构依次登场,不断推动着人工智能技术的进步。CNN,也就是卷积神经网络,宛如一位专注于局部细节的观察者。它借助卷积核提取局部特征,就像在图像中捕捉边缘、纹理等信息,然后通过层级的方式逐步组合出复杂的物体结构。这种架构在图像领域大显身手,像图像分类、目标检测等任务都离不开它。不过,它也有短板,缺乏对时间序列的建模能力。
而 RNN,即循环神经网络,更像是一个擅长处理时间序列的专家。它通过循环连接的方式保存历史信息,能够处理像文本、语音这类具有时间顺序的数据。然而,随着序列长度的增加,RNN 会面临梯度消失或爆炸的问题,这使得它在处理长序列时显得力不从心。
直到 Transformer 的出现,彻底改变了这一局面。它以自注意力机制为核心,就像是拥有了全局视角。这种机制能够让模型在处理序列数据时,动态地关注输入序列的不同部分,从而有效地捕捉长距离依赖关系。而且,Transformer 具有高度的并行计算能力,大大提高了训练和推理的速度。它不仅在自然语言处理领域全面超越了 RNN,还在计算机视觉等领域展现出了强大的实力,推动人工智能进入了一个新的时代。
2.模型架构

2.1输入部分
2.1.1输入部分
拿文本举例:你利用nn.Embedding()
python
nn.Embedding 主要有以下几个参数:
num_embeddings:词汇表的大小,即不同标记的数量。例如,在一个包含 10000 个不同单词的词汇表中,num_embeddings 就应该设置为 10000。
embedding_dim:嵌入向量的维度,也就是每个标记对应的向量的长度。这个维度可以根据具体任务进行调整,常见的取值有 50、100、300 等。
padding_idx(可选):指定一个填充索引,用于处理长度不一致的序列。当输入中出现该索引时,对应的嵌入向量将全为 0。
class Embeddings(nn.Module):
def __init__(self, d_model,vocab):
super(Embeddings, self).__init__()
self.embedding = nn.Embedding(vocab,d_model)
self.d_model = d_model
def forward(self,input_ids):
return self.embedding(input_ids)*math.sqrt(self.d_model)
##nn.Embedding 会创建一个大小为 (num_embeddings, 350) 的嵌入矩阵
2.1.2位置编码器
Transformer 中除了单词的Embedding,还需要使用位置Embedding 表示单词出现在句子中的位置。**因为 Transformer不采用RNN结构,而是使用全局信息,不能利用单词的顺序信息,而这部分信息对于NLP来说非常重要。**所以Transformer中使用位置Embedding保存单词在序列中的相对或绝对位置。
公式如下:

python
pe=torch.zeros(max_len, d_model)
position = torch.arange(0, max_len).unsqueeze(1)
div_term = torch.exp(torch.arange(0, d_model, 2) * -(math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
pe = pe.unsqueeze(0)#1, max_len, d_model
self.register_buffer('pe', pe)#不更新
2.2 编码器部分
2.2.1Self-Attention 结构

上图是 Self-Attention 的结构,在计算的时候需要用到矩阵Q(查询),K(键值),V(值) 。在实际中,Self-Attention 接收的是输入(单词的表示向量x组成的矩阵X) 或者上一个 Encoder block 的输出。而Q,K,V正是通过 Self-Attention 的输入进行线性变换得到的。
2.2.2Q, K, V 的计算
Self-Attention 的输入用矩阵X进行表示,则可以使用线性变阵矩阵WQ,WK,WV 计算得到Q,K,V 。计算如下图所示,注意 X, Q, K, V 的每一行都表示同一个单词。(WQ,WK,WV 在训练过程中就行更新,和其他参数一样根据梯度下降进行更新。)

2.2.3 Self-Attention 的输出

公式中计算矩阵Q 和K 每一行向量的内积,为了防止内积过大,因此除以 的平方根。Q 乘以K的转置后,得到的矩阵行列数都为 n,n 为句子单词数,这个矩阵可以表示单词之间的 attention 强度。
得到得到
之后,使用 Softmax 计算每一个单词对于其他单词的 attention 系数,公式中的 Softmax 是对矩阵的每一行进行 Softmax,即每一行的和都变为 1.

得到 Softmax 矩阵之后可以和V 相乘,得到最终的输出Z。
上图上图中 Softmax 矩阵的第 1 行表示单词 1 与其他所有单词的 attention 系数,最终单词 1 的输出
等于所有单词 i 的值 Vi 根据 attention 系数的比例加在一起得到,如下图所示:

就拿结果而言我们是不是得到了一个带有位置信息 和对所有样本有注意力系数的词向量
2.2.4 Multi-Head Attention
在上一步,我们已经知道怎么通过 Self-Attention 计算得到输出矩阵 Z,而 Multi-Head Attention 是由多个 Self-Attention 组合形成的,下图是论文中 Multi-Head Attention 的结构图。

从上图可以看到 Multi-Head Attention 包含多个 Self-Attention 层,首先将输入X 分别传递到 h 个不同的 Self-Attention 中,计算得到 h 个输出矩阵Z 。下图是 h=8 时候的情况,此时会得到 8 个输出矩阵Z 。
得到 8 个输出矩阵 Z1 到 Z8 之后,Multi-Head Attention 将它们拼接在一起 (Concat) ,然后传入一个Linear 层,得到 Multi-Head Attention 最终的输出Z。

2.2.5残差网络ADD
Add 指 X +MultiHeadAttention(X),是一种残差连接,通常用于解决多层网络训练的问题,可以让网络只关注当前差异的部分,在 ResNet 中经常用到
2.2.6Norm
Layer Normalization(常用于文本)
对于输入的一个样本(通常是一个张量),层归一化会计算该样本在特征维度上的均值和方差,然后基于这些统计量对该样本的所有特征进行归一化。假设输入是一个形状为 (batch_size, sequence_length, hidden_size)
的三维张量,层归一化会在 hidden_size
这个特征维度上计算均值和方差,对每个样本的所有特征进行归一化处理,使其均值为 0,方差为 1。
2.2.7Feed Forward
第一层是 全连接层(线性层)
第二层是 relu
第三层是 全连接层

2.2.8torch的代码实现
python
class TransformerEncoderLayer(nn.Module):
def __init__(self, d_model, nhead, dim_feedforward=2048, dropout=0.1):
super(TransformerEncoderLayer, self).__init__()
self.self_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)
self.linear1 = nn.Linear(d_model, dim_feedforward)
self.dropout = nn.Dropout(dropout)
self.linear2 = nn.Linear(dim_feedforward, d_model)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.dropout1 = nn.Dropout(dropout)
self.dropout2 = nn.Dropout(dropout)
self.activation = nn.ReLU()
def forward(self, src, src_mask=None, src_key_padding_mask=None):
src2 = self.self_attn(src, src, src, attn_mask=src_mask,
key_padding_mask=src_key_padding_mask)[0]
#src q k v attn_mask=src_mask#为掩码 decoder部分 key_padding_mask 填充
src = src + self.dropout1(src2)#add
src = self.norm1(src) #归一化
src2 = self.linear2(self.dropout(self.activation(self.linear1(src))))#forward
src = src + self.dropout2(src2)
src = self.norm2(src)
return src
#api
encoder_layer = nn.TransformerEncoderLayer(
d_model=512,
nhead=8,
dim_feedforward=2048,
dropout=0.1,
activation="relu",
layer_norm_eps=1e-5,
batch_first=False,
norm_first=False
)
encoder = nn.TransformerEncoder(encoder_layer, num_layers=num_layers)
#层 层数
nn.TransformerEncoderLaye
d_model
:模型的特征维度,也就是输入和输出张量的最后一个维度的大小。常见设置为 512 或 768。nhead
:多头注意力机制中头(head)的数量。多头注意力允许模型从不同的表示子空间并行地关注输入序列的不同部分,例如设置为 8 。dim_feedforward
:前馈神经网络中间层的维度,通常会设置得比d_model
大,如 2048。dropout
:Dropout 概率,用于防止过拟合,一般取值在 0.1 - 0.3 之间。activation
:前馈神经网络中使用的激活函数,默认是"relu"
,也可以选择"gelu"
等其他激活函数。layer_norm_eps
:层归一化中的一个小的常数,用于数值稳定性,默认值是1e - 5
。batch_first
:一个布尔值,若为True
,输入和输出张量的形状为(batch_size, seq_length, d_model)
;若为False
(默认),形状则为(seq_length, batch_size, d_model)
。norm_first
:一个布尔值,若为True
,先进行层归一化再进行多头注意力和前馈神经网络;若为False
(默认),则相反。
nn.T
2.3解码器
2.3.1掩码注意力机制
第一步**:** 是 Decoder 的输入矩阵和 Mask 矩阵,输入矩阵包含 "<Begin> I have a cat" (0, 1, 2, 3, 4) 五个单词的表示向量,Mask 是一个 5×5 的矩阵。在 Mask可以发现单词 0 只能使用单词 0 的信息,而单词 1 可以使用单词 0, 1 的信息,即只能使用之前的信息

第二步:已经算出 K Q V 得到QKT

第三步: 在得到 QKT 之后需要进行 Softmax,计算 attention score,我们在 Softmax 之前需要使用Mask 矩阵遮挡住每一个单词之后的信息,遮挡操作如下:作如
然后进行softmax

2.3.2 Decoder注意力机制
Decoder block 第二个 Multi-Head Attention 变化不大,主要的区别在于其中 Self-Attention 的 K, V 矩阵不是使用 上一个 Decoder block 的输出计算的,而是使用 Encoder 的编码信息矩阵 C计算的。
2.3.3 输出
Decoder block 最后的部分是利用 Softmax 预测下一个单词,在之前的网络层我们可以得到一个最终的输出 Z,因为 Mask 的存在,使得单词 0 的输出 Z0 只包含单词 0 的信息,如下

Softmax 根据输出矩阵的每一行预测下一个单词:

得到了最后结果 就是未来的信息不能影响你的输出
2.3.4 代码实现
python
import torch
import torch.nn as nn
# 超参数设置
d_model = 512
nhead = 8
dim_feedforward = 2048
num_layers = 6
dropout = 0.1
batch_size = 32
seq_length = 10
# 创建单个解码器层
decoder_layer = nn.TransformerDecoderLayer(d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward, dropout=dropout)
# 创建完整的解码器
decoder = nn.TransformerDecoder(decoder_layer, num_layers=num_layers)
# 生成随机输入
tgt = torch.randn(seq_length, batch_size, d_model) # 目标序列
memory = torch.randn(seq_length, batch_size, d_model) # 编码器的输出
# 前向传播
output = decoder(tgt, memory)
print("Output shape:", output.shape)
1.nn.transformerDecoderLayer
1.输入维度(词向量的维度)2.几头(就是几个叠加) 3.线形层的输入 大小4.(0-1)失活比
2.nn.TransformerDecoder(前面的解码器,层数)
3.总结
Transformer 是基于注意力机制的深度学习架构,由编码器和解码器构成,用于处理序列到序列任务。其核心组件包括多头注意力机制、前馈神经网络、层归一化和残差连接。多头注意力机制可并行计算多个注意力头,有效捕捉序列依赖;前馈网络进一步提取高级特征;层归一化和残差连接稳定训练、加速收敛。Transformer 优势显著,有并行计算能力,能捕捉长距离依赖且灵活性强,但存在计算复杂度高、缺乏位置信息的局限。在自然语言处理中,它催生了 BERT、GPT 等预训练模型,且可微调用于多种下游任务。迈向视觉语言模型学习,Transformer 可与视觉领域结合,用于视觉特征提取和多模态信息融合,典型模型如 CLIP、ViT。学习时,要巩固理论、进行代码实践、研究前沿论文并参与开源项目。