面向 AI 的转置:重新定向 token 与特征的关系
转置矩阵、预测其形状,并在按词元排列特征与按特征排列词元的视图之间安全切换,同时不丢失底层数值。
假设一个批次包含两个 token,每个 token 由三个特征表示。你把数据存储为两行三列。但之后的某个操作却要比较不同 token 之间的特征。数据变了吗,还是这个操作需要另一种方向?
答案通常是转置:同样的六个数,只是以交换行列的方式读取。在机器学习中,这个小操作是形状调试的重要工具,因为轴的含义本身就是张量契约的一部分。
学完本课后,你将能够转置矩阵、预测输出形状、解释语义上发生了什么交换,并在按词元排列特征与按特征排列词元的布局之间做出选择,同时不丢失对底层数值的追踪。
**学习成果:**转置矩阵并解释语义上的交换。
第 18 课:矩阵组织线性规则介绍了矩阵中行和列作为有意义位置的概念。本课的示例和可视化是对 Mathematics for Machine Learning 第 2.2 节中转置记号的原创应用。
矩阵沿着轴存储关系
先看一个形状为 的矩阵 :
第一个维度长度为 ,所以有两行。第二个维度长度为 ,所以有三列。形状只能告诉我们维度;标签才能告诉我们这些维度的含义。在本课中,让每一行表示一个 token,每一列表示一个特征:
| 2 | −1 | 0 | |
| 4 | 3 | 1 |
元素 的意思是“第 2 行、第 3 列”:第二个 token 的第三个特征。索引不是装饰。如果后续代码把列当作 token,数字看起来仍可能合理,但模型读取的关系已经错了。
定义:转置交换位置,而不是数值
矩阵 的转置写作 。它的定义规则是
换句话说,位于第 行、第 列的元素会移动到第 行、第 列。因此,如果 的形状是 ,那么 的形状就是 :
转置不会对任何元素取相反数、排序、缩放或重新计算。它重新定向元素与行列标签之间的关系。
X:token 按行、特征按列
两行 token,每列包含一个特征。
| 词元 | f₁ | f₂ | f₃ |
|---|---|---|---|
| t₁ | 2 | −1 | 0 |
| t₂ | 4 | 3 | 1 |
词元 → rows · 特征 → columns
Xᵀ:特征按行、token 按列
三行特征,每列包含一个 token。
| 特征 | t₁ | t₂ |
|---|---|---|
| f₁ | 2 | 4 |
| f₂ | −1 | 3 |
| f₃ | 0 | 1 |
特征 → rows · 词元 → columns
单元格对应关系:X[2, 3] = 1 变为 Xᵀ[3, 2] = 1:这个数保持自身身份不变,只是坐标发生交换。
逐步检查一个单元格
第二个 token 的第三个特征中的数值,在转置后移动到第三行第二列。
- 转置前
X[2, 3] = 1- 转置后
Xᵀ[3, 2] = 1
这个可视化以标签而不是颜色作为主要提示。它的两个语义表格也是完整的回退内容:读者无需 JavaScript,就能核对每个数值、维度和轴的含义。展开区域是原生、可用键盘操作的控件,组件也没有会干扰减少动态效果偏好的持续运动。
例题:转置一个 矩阵
按照定义逐个位置处理。 的第一行来自 的第一列:
第二行来自第二列:
第三行来自第三列:
把这些元素放在一起得到
有两个检查可以发现大多数手算错误。第一,形状从 反转为 。第二,沿着 的一列向下读取,应该能还原 的一行:它的第一列是 ,也就是 的第一行。
为什么方向对 AI 数据很重要
按行存储的批次便于执行一种常见操作。如果 存储了 个样本、每个样本有 个特征,而特征到输出的权重矩阵 ,那么通常会这样应用:
这里的转置没有改变学习到的数值。它让权重的特征轴与批次矩阵的特征列对齐。输出有 行,每行对应一个样本;有 列,每列对应一个输出特征。
同一份数据也可以按特征优先存储为 。当问题是“每个特征如何在样本之间变化”时,这种视图很有用,但它不能与按行批次的视图互换。在把数组传给要求样本位于行中的代码之前,务必先转置回来,或者按照特征优先的约定写出乘积。
与 提出不同的问题
转置常常出现在矩阵乘积旁边。它们的形状揭示了比较的对象:
因此每个元素都会比较 个样本中的两个特征。相比之下,
所以每个元素都会比较 个特征中的两个样本。两个乘积没有哪个“转置得更多”;它们回答的是不同的关系问题。
对于本课的矩阵,
第一个矩阵是 ,因为有三个特征。第二个矩阵是 ,因为有两个 token。数值彼此相关,但索引的含义不同。
在 NumPy 中实现交换
对于小型教学示例,显式循环与定义相互对应。它先分配反转后的形状,然后把 matrix[row, column] 复制到 result[column, row]:
import numpy as np
X = np.array([[2, -1, 0],
[4, 3, 1]])
def transpose_by_loops(matrix):
rows, columns = matrix.shape
result = np.empty((columns, rows), dtype=matrix.dtype)
for row in range(rows):
for column in range(columns):
result[column, row] = matrix[row, column]
return result
X_T_by_loops = transpose_by_loops(X)
X_T = X.T
np.testing.assert_array_equal(X_T_by_loops, X_T)
np.testing.assert_array_equal(X_T.T, X)
feature_relationships = X.T @ X
token_relationships = X @ X.T
print(X_T)
print(feature_relationships.shape, token_relationships.shape)
循环有助于理解,但不适合追求生产速度。NumPy 的 ndarray.T 是二维数组中 transpose 的简写,而 np.transpose 可以推广到具有更多轴的数组。NumPy 官方文档指出了一个重要边界:转置一维数组不会改变它的形状。形状为 (3,) 的向量没有可供交换的独立行轴和列轴;如果需要明确的 (3, 1) 列向量,可以使用 vector[:, np.newaxis],如果需要 (1, 3) 行向量,则可以使用 vector[np.newaxis, :]。
当下一步是矩阵乘积时,要区分运算符:@ 表示矩阵乘法,而 * 表示逐元素乘法。例如,X.T @ X 会缩并 token 轴并返回一个 (3, 3) 矩阵;X.T * X.T 只有在形状匹配时才有效,并会返回逐元素乘积。NumPy 转置参考、.T 参考和矩阵乘积参考是这些区别的实现依据。
边界情况:转置不是逆
把 称为“撤销” 的操作很诱人。但一般来说这是错误的。转置只交换轴;逆矩阵(如果存在)是另一个矩阵 ,满足
逆矩阵要求矩阵是方阵且非奇异。本课的 矩阵 不可能有普通的双侧逆,因为它的形状甚至无法与方形单位矩阵匹配。即使是方阵, 也只有在特殊情况下才是逆,例如 是正交矩阵。
代码中还有另一个边界情况。对于二维矩阵,表达式 X.T 没有歧义,但对一维 NumPy 数组来说,vector.T 什么也不会做。如果模型需要一个特征列,就要明确创建这个维度,并在矩阵乘法前检查 array.shape。形状错误通常是有用的证据,说明某个轴约定仍未明确。
可靠的调试顺序是:
- 说明每个轴的含义。
- 在转置前预测新形状。
- 手动核对一两个索引映射。
- 检查下一个运算符的形状契约。
- 确认生成的行和列仍与模型约定相符。
第 22 课将用恒等变换和逆变换讨论线性运算在什么时候确实可以被撤销。转置是其中谨慎的桥梁:它改变方向,让下一个关系可以用兼容的轴表达,但不承诺可逆性。
检查你的理解
Question 1
如果 A 的形状是 4 × 7,Aᵀ 的形状是什么?元素 A[3, 6] 会移动到哪里?
Show the step-by-step solution
第 1 步:反转维度。 转置会把 变成 ,所以 矩阵会变成 。
第 2 步:交换索引。 定义规则是 。因此,第 3 行、第 6 列的元素会移动到第 6 行、第 3 列。
第 3 步:解释结果。 数值不会改变;只有行列位置以及相应的标签发生交换。
Question 2
手算 M = [[5, −2, 1], [0, 4, 3]] 的转置,并说明结果的形状。
Show the step-by-step solution
第 1 步:数原来的轴。 有两行三列,因此它的转置必须有三行两列。
第 2 步:把列复制为行。 第一列 变成第一行;第二列 变成第二行;第三列 变成第三行。
第 3 步:写出结果。
Question 3
一个矩阵的行表示文档,列表示词汇特征。转置后,行和列分别表示什么?
Show the step-by-step solution
第 1 步:命名原来的轴。 转置前,每一行是一个文档,每一列是一个词汇特征。
第 2 步:应用索引规则。 每个文档-特征数值都会从 移动到 。
第 3 步:说明新的含义。 转置后,每一行是一个词汇特征,每一列是一个文档。数值没有改变,但按行执行的操作现在会跨文档而不是跨特征聚合。这就是为什么轴的含义必须与数组一起传递。
Question 4
为什么 (Aᵀ)ᵀ = A?这个恒等式不代表什么?
Show the step-by-step solution
第 1 步:交换一次。 第一次转置把元素 送到 。
第 2 步:再交换一次。 第二次转置把同一个元素从 送回 。每个数值都回到原来的位置。
第 3 步:保持区分。 这个恒等式说明转置是一个对合:执行两次相同的方向交换,就会回到原矩阵。它不表示 是逆矩阵,也不表示第一次操作以逆矩阵的意义撤销了一个学习到的变换。
Question 5
对于形状为 (8, 5) 的 X,XᵀX 和 XXᵀ 的形状是什么?每一对索引分别比较什么?
Show the step-by-step solution
第 1 步:转置形状。 的形状是 。
第 2 步:计算第一种乘积。 ,所以 比较八个样本中的五个特征之间的成对关系。
第 3 步:计算第二种乘积。 ,所以 比较八个样本之间、沿着它们五个特征的成对关系。反转乘积顺序改变的是问题,而不只是记号。
Question 6
在 NumPy 中,为什么 vector.T 会让形状为 (3,) 的向量保持在 (3,),而 vector[:, np.newaxis] 的形状是 (3, 1)?
Show the step-by-step solution
第 1 步:检查轴的数量。 形状 (3,) 描述了一个长度为三的轴。.T 没有独立的行轴和列轴可以交换。
第 2 步:读取 NumPy 的行为。 一维转置是一个保持不变的视图,所以 vector.T.shape 仍然是 (3,)。
第 3 步:明确添加所需的轴。 vector[:, np.newaxis] 会在三个元素之后插入第二个轴,得到 (3, 1)。这是一个明确的列向量,可以按预期形状参与矩阵乘法。
Question 7
学习者说 Xᵀ 是 X 的逆,因为两次转置会返回 X。准确的纠正是什么?
Show the step-by-step solution
第 1 步:区分两个恒等式。 表示两次交换轴会恢复原来的位置。
第 2 步:说明逆矩阵的要求。 逆矩阵必须与 相乘,在适当的一侧产生单位矩阵。
第 3 步:使用边界情况。 本课的 矩阵不是方阵,因此根本不可能有普通的双侧逆。即使是方阵,也不一定等于其转置的逆。转置是方向操作;逆是可逆性属性。
Question 8
批次 X 的形状是 (32, 768),权重矩阵 W 的形状是 (256, 768)。为什么 X @ W 无效?哪个转置能得到通常的按行批次输出?
Show the step-by-step solution
第 1 步:检查尝试的乘积。 形状是 和 。矩阵乘法要求左矩阵的列数 768 等于右矩阵的行数 256,但它们不相等,因此 X @ W 无效。
第 2 步:转置权重。 的形状是 。
第 3 步:检查修正后的乘积。 。32 行仍然表示样本,256 列表示输出特征。转置修正的是轴约定,而不是学习到的权重数值。