Transformer革命:从序列建模到通用人工智能的架构突破

文章目录


先言

2017年,Google团队在《Attention Is All You Need》论文中提出的Transformer架构,彻底改变了自然语言处理的发展轨迹。这一革命性的模型不仅取代了RNN和LSTM在序列建模中的主导地位,更成为当今所有大语言模型(LLM)的核心基础------从BERT到GPT,从T5到ChatGPT,Transformer的身影无处不在。

本文将深入解析这一颠覆性架构:

✅ 词嵌入(Word Embedding):从符号到向量的语义革命

✅ Transformer核心设计:自注意力机制的数学之美

✅ 编码器-解码器结构:如何实现高效的序列到序列转换

✅ 多头注意力机制:并行捕捉多样化上下文依赖

✅ 完整代码实现:从零开始构建Transformer模型

无论您是NLP初学者,还是希望深入理解大模型基础的研究者,这篇文章都将带您领略Transformer架构的精妙设计!


1. 词嵌入的概念和应用

1.1从One-Hot到分布式表示:

在很久之前了,机器学习中讲到过One---Hot编码可以看一下往期文章(找找),最开始我们训练模型对数据特征提取时需要对不同信息进行都热编码,下面有例子。
One-Hot编码的局限性:

从这个稀疏矩阵来看,不是0就是1,你能看出啥,在对一段对话中或者一个句子,独热编码不具备空间意义和语义信息,且特征向量组成高维稀疏,并不适合人工智能在自然语言方面学习进化。

那咋办?

分布式假设:"词的语义由其上下文决定"

分布式语义(Distributional Semantics)是一种在自然语言处理(NLP)中用于表示和理解词汇语义的理论框架。其基本假设是:一个词的意义可以通过它在文本中的上下文来理解和表示,即"一个词的意思由它的邻居们定义"。这也被称为"分布假设"(Distributional Hypothesis),最早由 J.R. Firth 在1957年提出:"你将会知道一个词的含义,通过它所保持的公司(即上下文)"。

这个假设引导了在AI探索道路上的人朝着一个好的方向走去------词的向量化(词嵌入)

1.2向量空间中的语义几何:

语义相似的词在向量空间中距离相近 ,学了这么久对于向量这一概念应该不陌生了,我们想到将一个词用一个向量来表示可以是高纬度序列数,不同的词就用不同的序列数表示也就是不同的向量但是相同纬度,通过 向量的几何意义:向量与向量之间可以计算余弦相似度然而词与词之间可以分断语义相似度

ok,我们现在就可以通过映射思想得出结论:对于每一个词我们都用一个向量来表示,向量间的相似度就映射为词之间的相似度,记得在之前的机器学习人工智能的时候讲过类别之间的判断要根据距离,那么向量之间的距离也就代表词之间的距离,这是就对应了 "词的语义由其上下文决定"

上下文不就对应的每个词的关系,那么不同的距离和相似度就代表了不同的语义

1.3nn.Embedding词嵌入api

在 PyTorch 中,我们可以使用 nn.Embedding 词嵌入层来实现输入词的向量化:

python 复制代码
import torch
import torch.nn as nn
import jieba
# 一段文本
text = '北京冬奥的进度条已经过半,不少外国运动员在完成自己的比赛后踏上归途。'
#1.对文本进行分词
words = jieba.cut(text)
#2.创建词列表
words = list(set(words))
#3.创建ID和词的映射字典
word2id = {word:idx for idx,word in enumerate(words)}
id2word = {idx:word for idx,word in enumerate(words)}
#4.使用Embedding创建词嵌入api对象
#这里的词向量长度为5
embed = nn.Embedding(len(words),5)
for word in words:
#5.通过embed对象构建词向量
    print(embed(torch.tensor([word2id[word]])))

分词效果:

通过词嵌入文本被转为向量,那么通过构建网络结构实现对文本特征提取的模型训练,就可以实现机器对文字的学习功能。

2. Transformer架构总览

2.1诞生背景:RNN/LSTM的长期依赖问题与计算效率瓶颈

在深度学习的过程中我们知道了全连接神将网络,卷积神经网络,我们只对图像进行了特征工程的了解,其实深度学习中还有循环神经网络,该网络主要针对的是自然语言处理,通过构建循环神经网络结构,可以实现机器可以通过语言文字提取特征从而实现机器对文字的学习。

这里的教学我们浅浅的了解其中的RNN模型和LSTM模型

RNN网络

在RNN的经典架构中,网络通过一个特殊的循环结构将信息从一个处理步骤传递到下一个。这个循环结构通常被称为"隐藏层状态"或简单地称为"隐藏状态"。隐藏状态是RNN的记忆部分,它能够捕获并存储关于已处理序列元素的信息。

当RNN处理一个序列时,它会在每个时间步接受一个输入,并更新其隐藏状态。这个更新过程依赖于当前的输入和之前的隐藏状态,从而使得网络能够"记住"并利用过去的信息。这个过程可以通过以下数学公式简化表达:
s t = f ( U ⋅ x t + W ⋅ s t − 1 ) s_t=f(\mathbf{U}·x_t+\mathbf{W}·s_{t-1}) st=f(U⋅xt+W⋅st−1)

模型图像解析:

LSTM网络

LSTM的核心思想是引入了称为"细胞状态"(cell state)的概念,该状态可以在时间步长中被动态地添加或删除信息。LSTM单元由三个关键的门控机制组成 ,通过这些门控机制,LSTM可以在处理长序列数据时更有效地学习长期依赖性

图解示意图以及对应公式:

2.2循环神经网络的缺陷

在自注意力机制之前,序列建模任务主要依赖就是RNN和LSTM模型,但是两者存在一定的缺陷:

  • RNN:循环神经网络,能够处理序列数据,但存在梯度消失/爆炸问题,难以捕捉长距离依赖。
  • LSTM/GRU:通过门控机制缓解了RNN的问题,但处理长序列时难以并行化,计算效率低。

共同问题是:

  • 长距离依赖:随着序列长度增加,模型难以有效捕捉远距离元素之间的关系。
  • 计算效率:需要逐步处理序列,无法并行计算,训练速度较慢。
  • 信息瓶颈:编码器会将整个输入序列压缩为一个固定长度的向量,可能导致信息丢失,灵活度太低。

2.3核心创新:完全基于注意力机制的序列建模

CNN卷积神经网络中我们讲到过一个概念------感受野

通过卷积在整体图像进行特征提取实现获取特征图,并且在特征图再次进行卷积操作实现的远视野特征提取,多个卷积层操作得到的特征图保留了图像的整体特征,这就是感受野的概念,CNN通过层的堆叠,提高感受野,使得上层输出可以捕获长时序关系,这一思想证明了并行化在序列建模中的可行性,并为后续序列模型提供了启发------Transformer架构出现了

Transformer 的核心概念------自注意力机制(Self-Attention Mechanism):

自注意力就是受于感受野的启发,在词向量的网络结构之间加入了并行化的序列建模,通过对文本向量实现向量分解得到不同的三个新的词向量来代表文本向量的不同含义,我们可以将这三个向量归属于原文本向量的三个特征表示,但只是适用于向量分解这一个步骤(特征的分解只是为了在这里好理解但又有一点不一样)

2.3.1 深入概念

自注意力机制,就是找到当前词和所在句子的所有的词之间的关联关系。

2.3.2 核心目标

我是谁?我在哪?

自注意力的目标是让每个位置的表示能够根据整个序列中其他位置的信息进行加权融合,从而捕获实体之间的相互关系。

自注意力机制是要回答:"我(某个位置)应该关注谁(其他位置)?以及关注了之后该怎么融合信息?"

2.3.3 专业术语

为了提升表达能力和灵活度,我们不能直接使用一个词嵌入向量。

自注意力机制通过引入查询向量(Query)键向量(Key)、**值向量(Value)**概念来实现序列中各元素之间的信息交互和依赖建模。

  • Q:Query

    表示当前查询者的位置,用来发出问题:"我想知道对我来说谁重要"。

  • K:Key

    表示被查询者的身份,是所有位置给出的"介绍信"或"标签",告诉别人自己是个啥玩意。

  • V:Value

    表示被查询者实际信息,也就是一旦你决定"关注我了",我就把这份信息给你。

2.3.4 QKV的意义

序列中的每个 T o k e n Token Token 都有 Q 、 K 、 V Q、K、V Q、K、V 三个角色:

  • 所有位置之间需要【查询-响应】这样的互动,单一角色表达能力就太死板。
  • "我该关注谁"是"我"和"他们"之间的交互过程,所以需要把"我"和"他们"分别建模(Q vs K)。
  • 而最终融合的信息 V V V 可能和你打分 Q ⋅ K Q·K Q⋅K 的依据不完全相同,如:
    • K K K :强调结构特征→【位置或语法角色】
    • V V V: 强调语义内容→【单词的意义】

2. 4QKV矩阵理解:查询(Query)、键(Key)、值(Value)的角色分配

自注意力机制通过计算输入数据中每个位置与其他位置的相关性,来调整每个位置的信息表示。

2.4.1 输入序列

输入是一个序列,如词向量序列,假设:
X = ( x 1 , x 2 , ... , x n ) ∈ R n × d X = (x_1, x_2, \dots, x_n) \in \mathbb{R}^{n \times d} X=(x1,x2,...,xn)∈Rn×d

是 n n n 个输入, d d d 是输入维度,则自注意力的目的是捕获 n n n 个实体之间的关系。

2.4.2 词语关系

it代表的是animal还是street呢,对我们来说简单,但对机器来说是很难判断的。self-attention就能够让机器把it和animal联系起来。

2.4.3 线性变换

自注意力机制依赖于三个核心概念:查询向量Query、键向量Key、值向量Value。他们对输入 X X X 进行三次线性变换,得到三个矩阵。

查询向量就像便利贴;键向量是档案文件夹上贴的标签 这些百分比便是归一化之后的注意力得分
文件夹里面便是值向量 根据得分计算出查询向量和其它向量的关联关系

x向量通过词嵌入获取

python 复制代码
def test():
    embedding=nn.Embedding(10,512)#比如语料有10个单词,转换后每个单词的维度是512
    input=torch.randint(0,10,(512,),dtype=torch.int64)#随便给一个输入
    embedding_out=embedding(input)#每个数字被映射为5个数字的向量
    print(embedding_out,embedding_out.shape)

2.4.4 查询向量

Q = Query, 是自注意力机制中的"询问者"。++每个输入++都会生成一个查询向量,表示当前词的需求。

  • 作用:用于与键向量计算相似度(通过点积方式),确定当前词与其他词的相关性。
  • 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到查询空间。

Q = X W q Q=X W_q Q=XWq

W q W_q Wq 是可学习权重矩阵,维度为 d × d k d \times d_k d×dk, d k d_k dk是超参数,表示查询向量的维度。

2.4.5 键向量

**K = **Key,表示其他词的信息,供查询向量匹配。++每个输入++都会生成一个键向量,表示其能够提供的信息内容。

  • 作用:与查询向量计算点积,生成注意力权重。点积越大,表示它们之间的相关性越强。
  • 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到键空间。

K = X W k K=X W_k K=XWk

W k W_k Wk 是可学习权重矩阵,维度为 d × d k d \times d_k d×dk, d k d_k dk是超参数,表示键向量的维度。

2.4.6 值向量

V = Value, 值向量包含了++每个输入++实际的信息内容,相关性决定了信息被聚焦的程度。

  • 作用:使用值向量基于注意力得分进行加权求和,生成最终的输出表示。
  • 生成方式:通过一个权重矩阵将输入数据(如词向量)映射到值空间。

V = X W v V=X W_v V=XWv

W v W_v Wv 是可学习权重矩阵,维度为 d × d v d \times d_v d×dv, d v d_v dv是超参数,表示值向量的维度。

注: d v d_v dv 和 d k d_k dk 通常是相等的。

2.4.7 以图示意

通过线性变换得到三个向量的变化如下图所示:

2.4.8 注意力得分

使用点积来计算查询向量和键向量之间的相似度,除以缩放因子 d k \sqrt{d_k} dk 来避免数值过大,使得梯度稳定更新。得到注意力得分矩阵:
Attention ( Q , K ) = Q K T d k \text{Attention}(Q, K) = \frac{QK^T}{\sqrt{d_k}} Attention(Q,K)=dk QKT

注意力得分矩阵维度是 n × n n \times n n×n,其中 n n n 是序列的长度。每个元素 ( i , j ) (i, j) (i,j) 表示第 i i i 个元素与第 j j j 个元素之间的相似度。

参考示意图如下:

α 1 , i = q 1 ⋅ k i d k \alpha_{1,i} = \frac{q^1 \cdot k^i}{\sqrt{d_k}} α1,i=dk q1⋅ki

2.4.9 归一化

为了将注意力得分转换为概率分布,需按行对得分矩阵进行 s o f t m a x softmax softmax 操作,确保每行的和为 1,得到的矩阵表示每个元素对其他元素的注意力权重。是的,包括自己。
Attention Weight = softmax ( Q K T d k ) \text{Attention Weight} = \text{softmax} \left( \frac{QK^T}{\sqrt{d_k}} \right) Attention Weight=softmax(dk QKT)

具体到每行的公式如下:
α ^ 1 , i = exp ⁡ ( α 1 , i ) ∑ j exp ⁡ ( α 1 , j ) \hat{\alpha}{1,i} = \frac{\exp(\alpha{1,i})}{\sum_j \exp(\alpha_{1,j})} α^1,i=∑jexp(α1,j)exp(α1,i)

  • α 1 , i \alpha_{1,i} α1,i :第 1 1 1 个词语和第 i i i 个词语之间的原始注意力得分。
  • α ^ 1 , i \hat{\alpha}_{1,i} α^1,i :经过归一化后的注意力得分。

2.4.10 加权求和

通过将注意力权重矩阵与值矩阵 V V V 相乘,得到加权的值表示。
Output = Attention Weight × V = softmax ( Q K T d k ) × V \text{Output} =\text{Attention Weight} \times V = \text{softmax} \left( \frac{QK^T}{\sqrt{d_k}} \right) \times V Output=Attention Weight×V=softmax(dk QKT)×V

具体计算示意图如下:

QK 计算相似度后,经 s o f t m a x softmax softmax 得到注意力,再乘V,最后相加得到包含注意力的输出

注:通过上下文来描述每一个词

2.4.11 输出

最终得到的输出是一个维度为 n × d v n \times d_v n×dv 的新矩阵,其中每个元素的表示都被加权了。

css 复制代码
本质:将Query和Key分别计算相似性,然后经过softmax得到相似性概率权重即注意力,再乘以Value,最后相加即可得到包含注意力的输出

至此,艺术已成,"我"就是"我","我"不再是"我"。

2.5整体架构:编码器-解码器的堆叠式设计

2.5.2模型的架构

Transformer主要由编码器(Encoder)和解码器(Decoder)组成,广泛应用于自然语言处理任务,尤其是机器翻译。

Seq2Seq(Sequence-to-Sequence)是NLP中的经典框架,广泛应用于机器翻译、文本摘要等。其结构包括:

2.5.2编码器与解码器(Encoder和Decoder)

  • Encoder:编码器,将输入序列编码为一个固定长度的上下文向量。
  • Decoder:解码器,基于上下文向量生成输出序列。

应用领域:机器翻译、文本生成、图像处理等

3. 多头注意力机制深度解析

Multi-Head Attention,多头注意力机制,是对自注意力机制的扩展。

3.1 基本概念

多头注意力机制的核心思想是,将注意力机制中的 Q 、 K 、 V Q、K、V Q、K、V 分成多个头(),每个头计算出独立的注意力结果,然后将所有头的输出拼接起来,最后通过一个线性变换得到最终的输出**(分组的思想)**。

比如一个词有512维 那么可以把它分为n个组,然后每个组分别有三个w向量映射为qkv,那么qkv的结果就会得到有n组

下面以2个头为例:

q i = W q a i q i , 1 = W q , 1 q i q i , 2 = W q , 2 q i q^{i}=W^{q}a^{i} \quad \quad q^{i,1}=W^{q,1}q^{i}\quad\quad q^{i,2}=W^{q,2}q^{i} qi=Wqaiqi,1=Wq,1qiqi,2=Wq,2qi

表达能力

一个词本来是1维 就一个token id 一个数字 但是我们把它映射为了512维 也就是从512个方面(特征)来看待这个词:情感,词法,过去式,将来式,进行时,偏旁部首,名次,动词等等等我们都想不出来的一些方面

因为是n组注意力

比如第一组是512维中的64个 这64个可以表示从情感的特征

比如第二组是512维中的另外64个 这64个可以表示从词法上的特征

比如第x组...

通过多个并行的头在不同的子空间中学习上下文信息,让同一个句子在不同场景下表达不同的意思,增强模型的表达能力和灵活性。

3.2 多头机制实现

注:多头注意力机制通常先将词向量映射为Q、K、V,然后再分成多个头。

python 复制代码
import torch
import torch.nn as nn

# ======================
# 1. 词嵌入层 (Embedding)
# ======================
# 创建词嵌入层:假设10个单词,每个单词映射为512维向量
vocab_size = 10    # 词汇表大小
embed_dim = 512    # 嵌入维度
embedding = nn.Embedding(vocab_size, embed_dim)

# 生成随机输入:序列长度为512的token索引
input_seq = torch.randint(0, vocab_size, (512,), dtype=torch.long)

# 通过嵌入层:将索引转换为向量
# 输出形状: (序列长度, 嵌入维度) = (512, 512)
embedding_out = embedding(input_seq)
print("嵌入层输出形状:", embedding_out.shape)  # torch.Size([512, 512]) 有512个单词,每个单词映射为512维向量

# ==============================
# 2. 多头注意力权重矩阵初始化
# ==============================
num_heads = 8      # 注意力头数量
head_dim = embed_dim // num_heads  # 每个头的维度 512/8=64

# 初始化Q、K、V的投影矩阵 (标准Transformer实现方式)
# 注意:使用单个大矩阵而不是多个小矩阵
W_Q = torch.randn(embed_dim, embed_dim)  # (512, 512)
W_K = torch.randn(embed_dim, embed_dim)  # (512, 512)
W_V = torch.randn(embed_dim, embed_dim)  # (512, 512)
3.2.1 全部映射
python 复制代码
# =====================================
# 3. 计算Query, Key, Value (正确实现)
# =====================================
# 一次性计算所有头的投影
all_queries = torch.matmul(embedding_out, W_Q)  # (512,512) × (512,512) = (512,512)
all_keys = torch.matmul(embedding_out, W_K)    # (512,512)
all_values = torch.matmul(embedding_out, W_V)  # (512,512)
3.2.2 分割多头
python 复制代码
# 将投影结果分割成多个头
# 步骤: 
# 1. 重塑形状: (seq_len, num_heads, head_dim)
# 2. 调整维度顺序: (num_heads, seq_len, head_dim)
queries = all_queries.view(512, num_heads, head_dim).permute(1, 0, 2)
keys = all_keys.view(512, num_heads, head_dim).permute(1, 0, 2)
values = all_values.view(512, num_heads, head_dim).permute(1, 0, 2)

print("Queries形状:", queries.shape)  # torch.Size([8, 512, 64])
print("Keys形状:", keys.shape)      # torch.Size([8, 512, 64])
print("Values形状:", values.shape)  # torch.Size([8, 512, 64])
3.2.3 计算注意力分数

分别计算每一个头的注意力分数

python 复制代码
# ==============================
# 4. 计算注意力分数 (Scaled Dot-Product)
# ==============================
# 计算Q和K的点积 (每个头独立计算)
# 矩阵乘法: (8,512,64) × (8,64,512) = (8,512,512)
attention_scores = torch.matmul(queries, keys.permute(0, 2, 1))

# 缩放因子 (sqrt(d_k))
scale_factor = torch.sqrt(torch.tensor(head_dim, dtype=torch.float))
attention_scores = attention_scores / scale_factor

# 应用softmax得到注意力权重
attention_weights = torch.softmax(attention_scores, dim=-1)
print("注意力权重形状:", attention_weights.shape)  # torch.Size([8, 512, 512])
3.2.4 计算注意力输出

v的每一个权重进行加权乘v

python 复制代码
# ==============================
# 5. 计算注意力输出
# ==============================
# 注意力权重与Value相乘
# (8,512,512) × (8,512,64) = (8,512,64)
attention_output = torch.matmul(attention_weights, values)
3.2.5 合并多头
python 复制代码
# ==============================
# 6. 合并多头输出
# ==============================
# 步骤:
# 1. 调整维度顺序: (num_heads, seq_len, head_dim) -> (seq_len, num_heads, head_dim)
# 2. 重塑形状: (seq_len, embed_dim)
attention_output = attention_output.permute(1, 0, 2).contiguous()  # (512, 8, 64)
combined_output = attention_output.view(512, embed_dim)  # (512, 512)
print("合并后的注意力输出形状:", combined_output.shape)  # torch.Size([512, 512])

3.3 终极用法

实际开发中, 官方已经帮我们实现好了就一行代码

python 复制代码
# ===========================================
# 7. 使用PyTorch内置多头注意力层 (推荐方式)
# ===========================================
# 实际开发中推荐使用内置实现
multihead_attn = nn.MultiheadAttention(embed_dim, num_heads)
# 传入qkv
attn_output, attn_weights = multihead_attn(
    embedding_out,  # (512,1,512)
    embedding_out,  # (512,1,512)
    embedding_out   # (512,1,512)
)
print("内置多头注意力输出形状:", attn_output.shape)  # torch.Size([512,512])
print("内置多头注意力权重形状:", attn_weights.shape) # torch.Size([512,512])

总结

提示:这里对文章进行总结:

Transformer的核心总结

  • 目标: 让模型理解整个输入句子,并生成整个输出句子。
  • 核心: 自注意力机制 - 让句子里的每个词都能瞬间"关注"到所有其他词,理解上下文。
  • 结构:
    • 编码器(理解): 多层堆叠。每层核心:自注意力(全局交流) + 前馈网络(个体升级) + 残差&归一化(稳定训练)。
    • 解码器(生成): 多层堆叠。每层核心:掩码 自注意力(看已生成的词) + 编码器-解码器注意力(看编码器的理解) + 前馈网络 + 残差&归一化。
  • 输入输出处理: 词嵌入(单词变数字向量) + 位置编码(告诉模型单词顺序)。
  • 优势: 并行快、长距离理解强、通用灵活、可扩展成大模型。

以上就是今天要讲的内容,本文仅仅简单介绍了NLP网络Transformer整体架构构造以及自注意力机制的深入探究

🚀 动手实践:本文提供完整可运行的代码示例,你可以试着一步一步跟着解析Transformer中自注意力向量运算的过程,希望你可以在此启发下不断创新和探索人工智能的世界,欢迎在评论区留言讨论!

📌 下篇预告:Transformer还远不止这些(提示:想想前面的网络怎么优化的)

相关推荐
海兰3 小时前
【原理】OpenClaw插件系统深度解析
人工智能·插件·skill·openclaw
软件供应链安全指南3 小时前
跟随 Gartner 洞察:AIST 从单点能力到全域安全治理的蜕变
大数据·人工智能·安全·gartner·问境aist·aist
Dylan~~~3 小时前
AI Coding工具记忆功能深度解析:让AI真正“记住“你的项目
人工智能
智算菩萨3 小时前
【How Far Are We From AGI】5 AGI的“道德罗盘“——价值对齐的技术路径与伦理边界
论文阅读·人工智能·深度学习·ai·接口·agi·对齐技术
lisw053 小时前
用于实时数据处理的边缘计算!
人工智能·机器学习·边缘计算
全栈开发圈3 小时前
干货分享|R语言聚类分析2
人工智能·机器学习·r语言
Sakuraba Ema3 小时前
从零理解 MoE(Mixture of Experts)混合专家:原理、数学、稀疏性、专家数量影响与手写 PyTorch 实现
人工智能·pytorch·python·深度学习·数学·llm·latex
隔壁小邓4 小时前
SpringCloud微服务拆分原则
spring cloud·微服务·架构
shangjian0074 小时前
AI-大语言模型-模型训练-数据集1-总述
人工智能·机器学习·语言模型