写点什么

Transformer 的线代基础

作者:陈一之
  • 2025-10-17
    广东
  • 本文字数:5280 字

    阅读完需:约 17 分钟

数据结构

标量 (Scalar)

  • 就是一个数字:比如3, -2.5, 0.1

  • 零维:没有方向,只有大小

  • 例子:温度、价格、单个神经元的输出

向量 (Vector)

  • 一组有序的数字:比如[1, 2, 3], [0.5, -0.2]

  • 一维:有大小和方向

  • 在 NLP 中:一个词可以表示为一个向量(嵌入,Embedding)

# “猫”的词向量可能长这样(假设是300维)猫 = [0.2, -0.5, 0.8, 0.1, ...]  
复制代码


矩阵 (Matrix)

  • 二维的数字表格:有行和列

  • 在 Transformer 中:权重参数通常都是矩阵

# 2×3矩阵的例子[1, 2, 3][4, 5, 6]
复制代码


张量 (Tensor)

  • 多维数组:标量是 0 维张量,向量是 1 维,矩阵是 2 维,更高维的就是张量

  • 深度学习中的基本数据结构

# 在Transformer中常见的数据形状输入数据: (batch_size, sequence_length, embedding_dim)# 例如: (32, 50, 512) 表示32个句子,每个句子50个词,每个词用512维向量表示
复制代码


向量点积(Dot Product)

  • 两个相同维度的向量对应元素相乘后求和

a = [1, 2, 3]b = [4, 5, 6]点积 = 1×4 + 2×5 + 3×6 = 4 + 10 + 18 = 32
复制代码


在注意力中:用点积衡量QueryKey的相似度。

  • 点积越大,表示两个向量方向越相似

  • 点积为 0,表示两个向量垂直(不相关)


几何意义

两个向量ab的点积有一个重要的几何公式:a · b = ||a|| × ||b|| × cosθ

其中:

  • ||a||是向量a的长度(模)

  • ||b||是向量b的长度(模)

  • θ是两个向量之间的夹角

a · b = 0时,有三种可能:

  1. ||a|| = 0a是零向量)

  2. ||b|| = 0b 是零向量)

  3. cosθ = 0

对于非零向量,只有第 3 种情况:cosθ = 0。在180°范围内,意味着θ = 90°θ = 270°——也就是说,两个向量的夹角是直角。

矩阵乘法(Matrix Product)

  • 两个矩阵AB可以相乘的条件:A的列数 = B的行数

  • 结果矩阵C的形状:(A的行数, B的列数)


示例

# 2×3矩阵A = [1, 2, 3]    [3, 4, 5]
# 3×2矩阵 B = [5, 6] [6, 7] [7, 8] # 计算结果C = A × B = [1*5 + 2*6 + 3*7, 1*6 + 2*7 + 3*8] [3*5 + 4*6 + 5*7, 3*6 + 4*7 + 5*8] = [38, 44] [74, 86]
复制代码


转置(Transpose)

线性代数中的“转置”

一个矩阵的转置,简单来说就是将一个矩阵的行和列进行互换。

  • 记法:矩阵A的转置记为AᵀA'

  • 数学表达:如果有一个m×n的矩阵A,那么它的转置Aᵀ是一个n×m的矩阵,并且满足Aᵀ[i, j] = A[j, i]


假设我们有一个2×3的矩阵A

A = [ 1  2  3 ]    [ 4  5  6 ]
复制代码


那么它的转置Aᵀ就是一个3×2的矩阵:

Aᵀ = [ 1  4 ]     [ 2  5 ]     [ 3  6 ]
复制代码



对于高维张量(3 维及以上),转置可以推广为对指定的两个维度进行交换。

例如,一个形状为(2, 2, 3)的张量,如果交换第一个和第三个维度,就变成(3, 2, 2)

A = [[[ 1,  2,  3]      [ 4,  5,  6]],     [[ 7,  8,  9]      [10, 11, 12]]]
Aᵀ = [[[ 1, 7] [ 4, 10]], [[ 2, 8] [ 5, 11]], [[ 3, 9], [ 6, 12]]]
复制代码


转置改变维度顺序,涉及元素位置的重新排列。如上例交换第一个和第三个维度,新张量(1, 0, 0)位置的元素与原张量(0, 0, 1)位置元素对应。



转置操作有一些非常实用的数学性质:

  1. (Aᵀ)ᵀ = A:对矩阵转置两次,会得到原矩阵。

  2. (A + B)ᵀ = Aᵀ + Bᵀ:加法转置等于转置相加。

  3. (AB)ᵀ = Bᵀ Aᵀ:乘法转置等于反向转置相乘。

Transformer 中的“转置”

自注意力机制

自注意力机制的核心目标,是让序列中的每一个元素(例如一个单词或词元)能够根据序列中所有元素的重要性进行信息聚合,从而生成一个融合了全局上下文的全新表示。


该机制通过为每个元素创建三个不同的向量来实现这一目标:

  • 查询向量Query):代表“当前元素想要寻找什么信息”。

  • 键向量Key):代表“当前元素可用于被匹配的特征”,用于和查询向量进行相似度比较。

  • 值向量Value):代表“当前元素实际需要被提取和传递的内容”。

在技术实现上,模型会维护三组共享的、可学习的权重矩阵(WQ, WK,WV)。对于输入序列中的每个元素,其对应的输入向量(如词嵌入)会分别与这三个权重矩阵相乘,从而生成该元素独有的查询(Q)、键(K)和值(V)向量。最终,通过计算所有查询向量和键向量之间的相关性,并对所有值向量进行加权求和,得到每个元素新的上下文感知表示。

转置的应用

我们想知道一个单词(Query)与序列中所有单词(Key)的关联程度。这通常通过点积来完成。


计算Q · Kᵀ

  • 假设我们的序列有n个单词,每个单词的QK向量维度是d_k。那么Q是一个n × d_k的矩阵,K也是一个n × d_k的矩阵。

  • 我们需要计算的是每一个Query和每一个Key的点积。如果直接计算Q · K,则维度不匹配。将K转置后,Kᵀ的维度是d_k × n

  • Q · Kᵀ的结果就是一个n × n的矩阵。这个矩阵的第i行、第j列的元素,就是第i个单词的Query与第j个单词的Key的点积,即相似度分数

转置的作用

在自注意力机制中,Kᵀ的操作是实现批量点积计算的关键技巧。

  • 功能上:它使我们能够在一个高效的矩阵乘法操作中,一次性计算出序列中所有单词对之间的关联强度。如果没有转置,我们就需要繁琐的循环来逐个计算点积,计算效率会极其低下。

  • 计算上:现代深度学习框架(如 PyTorch、TensorFlow)和硬件(如 GPU)都对大型矩阵乘法做了极致优化。使用Q · Kᵀ这种形式,可以充分利用硬件并行计算的能力,极大地加速模型训练和推理过程。

  • 几何上:点积可以衡量两个向量的相似度。Q · Kᵀ实质上是在计算每一个Query向量与所有Key向量在空间中的夹角余弦值,夹角越小(余弦值越大),代表相似度越高,注意力权重也就越大。

重塑(Reshape)

线性代数中的“重塑”

重塑是指改变一个张量的维度形状,而不改变其包含的原始数据的总数顺序

简单来说,就是把同样的数据元素,以不同的方式“排列”或“观看”。


关键特性

  • 数量不变:原始张量的总元素数必须等于新形状张量的总元素数。即,所有维度的乘积必须相等。

  • 数据不变:重塑操作不会增加、删除或修改任何数据元素的值。

  • 顺序不变:元素在底层内存中的线性顺序保持不变。重塑只是改变了我们“解读”这个线性序列的维度规则。


假设我们有一个包含12个元素的向量(1 维张量):

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]



我们可以将它重塑为:

  • 一个3×4的矩阵(2 维张量)

[1,  2,  3,  4][5,  6,  7,  8][9, 10, 11, 12]
复制代码



  • 一个2×3×2的张量(3 维张量)

[[[1,  2,  3],  [4,  5,  6]], [[7,  8,  9],  [10, 11, 12]]]
复制代码



所有这些形状都包含12=3×4=2×2×3个元素,并且数据的顺序从头到尾都是1, 2, 3, ..., 12

Transformer 中的“重塑”

假设我们有一个批次(batch)的句子,经过嵌入层后,输入张量的形状通常为:

(batch_size, sequence_length, embedding_dim)

例如:(batch_size=2, seq_len=5, d_model=4),表示输入是2个句子,每个句子5个词,每个词用4维向量表示。

实现多头注意力

Transformer 的核心思想是并行地计算多个“头”的注意力。每个头从不同的角度(不同的表示子空间)来关注输入序列的不同部分。重塑是实现这种并行的关键技术。


1、线性变换生成 Q, K, V

首先,我们对输入张量进行线性变换,生成查询、键、值。如果我们有h个头(例如h=2),我们不会创建h个独立的矩阵,而是一次性地生成一个更大的矩阵。

  • 原始输入X: (2, 5, 4)

  • 经过线性层WQ后,我们得到Q: (2, 5, d_k)。但为了分割成多头,我们不会输出这个形状。我们输出(2, 5, h * d_k),其中d_k = d_model / h(例如d_k = 4 / 2 = 2)。所以Q的形状是 (2, 5, 4)


2、第一次重塑:引入“头”的维度

现在,我们将最后一个维度 (h * d_k) 重塑为两个独立的维度(h, d_k)

  • 重塑前Q: (2, 5, 4)



  • 重塑后Q: (2, 5, 2, 2),含义是(batch_size, seq_len, num_heads, head_dim)


这一步在概念上等于将一个大矩阵“切割”成了h个小矩阵,每个小矩阵对应一个注意力头。


3、转置:为矩阵乘法做准备

为了便于在序列维度上计算注意力分数,我们需要将num_heads维度提前。

  • 转置Q: (2, 2, 5, 2) ,新的形状是 (batch_size, num_heads, seq_len, head_dim)


现在,我们可以把batch_sizenum_heads看作一个“批”维度,然后在这个大“批”中,并行地对每一个 (seq_len, head_dim)的矩阵计算注意力。


4、计算注意力分数

注意力分数的计算是:Softmax((Q · KT) / sqrt(d_k)) · V

由于我们的Q, K, V现在都是(2, 2, 5, 2)的形状,这个矩阵乘法可以在所有头上并行执行。计算后,输出的形状仍然是(2, 2, 5, 2)


5、第二次重塑:合并多头输出

计算完注意力后,我们需要将多个头的输出合并回一个统一的表示。

首先,将num_headsseq_len的维度顺序恢复:转置输出张量,得到 (2, 5, 2, 2)

然后,重塑这个张量,将num_headshead_dim这两个维度合并回原来的d_model维度。

  • 重塑前:(2, 5, 2, 2)

  • 重塑后:(2, 5, 4),回到了 (batch_size, seq_len, d_model),这个合并后的张量就是所有注意力头信息的聚合。

重塑的重要性

  • 计算效率:通过重塑,我们可以利用现代硬件(如 GPU)强大的并行计算能力,一次性计算所有头的注意力,而不是用循环逐个计算。

  • 模型表达力:它优雅地实现了“多头”的概念,让模型能够同时从多个角度关注信息。

  • 代码简洁性:在深度学习框架(如 PyTorch,TensorFlow)中,只需几行重塑和矩阵乘法的代码就能实现复杂的多头注意力机制。

广播 (Broadcasting)

广播机制

广播机制是一种允许不同形状的张量(多维数组)进行数学运算的规则。它的核心思想是:自动扩展较小形状的张量,使其与较大形状的张量的维度兼容,从而执行逐元素操作。


广播的规则

  1. 从尾部维度开始对齐:比较两个张量的形状时,从最右边的维度开始向左依次比较。

  2. 维度兼容的条件:两个维度在以下情况下是兼容的——它们相等、其中一个为 1、其中一个不存在(即维度缺失)。

如果所有维度都兼容,则可以广播。广播时,大小为 1 或缺失的维度会被“拉伸”或“复制”,以匹配另一个张量对应维度的大小。


广播的步骤

  1. 在所有张量的形状前面补 1,直到所有张量拥有相同的维数。

  2. 检查每个维度,对于每个维度,其大小必须相等,或者其中一个为 1,或者其中一个不存在。

  3. 执行扩展,在大小为 1 的维度上,将数据沿该维度复制,以匹配另一个张量在该维度上的大小。


广播的示例

  • 示例 1:向量 + 标量

A = [1, 2, 3]B = 2
广播发生:B被扩展为 [2, 2, 2]C = A + BC = [3, 4, 5]
复制代码


  • 示例 2:矩阵 + 行向量

A = [1, 2, 3]    [4, 5, 6]    [7, 8, 9]
B = [10, 20, 30]
广播过程:1. B的形状先被补1为(1, 3)2. 比较维度:A(3,3) vs B(1,3)。 第一个维度[3:1]:将B沿第一个维度复制3次。 第二个维度[3:3]:相等。3. B = [10, 20, 30] [10, 20, 30] [10, 20, 30] C = A + BC = [11, 22, 33] [14, 25, 36] [17, 28, 39]
复制代码

Transformer 中的“广播”

自注意力机制中的掩码

场景:在计算注意力分数后,我们需要对某些位置进行掩码(Mask)。例如,在解码器中掩码未来的词元,或者掩码填充的<pad>符号。

具体过程

  1. 我们有一个注意力分数矩阵Attn_scores,其形状为(batch_size, num_heads, seq_len, seq_len)。例如 (2, 8, 10, 10)

  2. 我们有一个掩码矩阵Mask,其形状通常为(batch_size, 1, 1, seq_len)(1, 1, seq_len, seq_len)。例如(2, 1, 1, 10)

  3. 当我们执行Attn_scores = Attn_scores + Mask时,广播机制开始工作:

  4. Mask的形状从(2, 1, 1, 10)被自动扩展(广播)到与Attn_scores的形状(2, 8, 10, 10)相匹配。

  5. Mask的第二个维度(1)被复制 8 次以匹配 8 个头,第三个维度(1)被复制 10 次以匹配seq_len(查询),而第四个维度(10)已经匹配seq_len(键)。

  6. 最终,每个批次、每个头、每个查询位置,都加上了同一个掩码向量。这样就高效地实现了对整个注意力矩阵的掩码。

位置编码与词嵌入相加

场景:将位置信息注入到输入词嵌入中。

具体过程

  1. 词嵌入矩阵Word_Embedding的形状是(batch_size, seq_len, d_model),例如 (32, 100, 512)

  2. 位置编码矩阵Pos_Encoding的形状通常是(1, seq_len, d_model)(seq_len, d_model),例如(1, 100, 512)

  3. 当我们执行Input = Word_Embedding + Pos_Encoding时:

  4. Pos_Encoding的形状被广播到(32, 100, 512)

  5. 这意味着对于批次中的每一个句子,都加上了完全相同的位置编码。我们不需要为批次中的 32 个句子分别创建一个(100, 512)的位置编码矩阵,广播机制帮我们自动完成了。

层归一化中的可学习参数

场景:对每个样本的激活值进行归一化。

具体过程

  1. 层归一化(Layer Normalization)有两个可学习的参数:缩放参数gamma和偏移参数beta,它们的形状都是(d_model,),例如(512,)

  2. 输入张量x的形状是(batch_size, seq_len, d_model),例如 (32, 100, 512)

  3. 在归一化后,我们执行y = gamma * x_norm + beta

  4. 这里,gammabeta的形状 (512,) 会被广播到与x_norm的形状(32, 100, 512)相匹配。具体来说,gammabeta会在批次维度和序列长度维度上进行复制,对批次中 32 个句子的 100 个位置上的每一个 512 维向量,都应用同一套缩放和偏移参数。

广播机制的好处

  1. 代码简洁:无需手动编写循环或使用expand/repeat函数来显式复制张量。

  2. 内存节省:我们只需要存储小尺寸的张量(如掩码、位置编码),而不是它们复制后的大尺寸版本。

  3. 计算高效:框架底层在实现广播时是高度优化的,避免了不必要的内存分配和复制,计算效率高。


发布于: 刚刚阅读数: 2
用户头像

陈一之

关注

靡不有初,鲜克有终 2017-10-19 加入

让时间流逝

评论

发布
暂无评论
Transformer的线代基础_AI技术_陈一之_InfoQ写作社区