03.01-Agent学习记录-向量、矩阵与张量

前面的文章介绍了怎样用程序、接口和工具组织一个 Agent。继续深入模型内部,就会频繁看到向量、矩阵和张量。它们听起来像三种神秘能力,其实在机器学习入门阶段,可以先从一个很具体的问题理解:电脑需要按照什么结构,把一大批数值摆放好,才能继续计算?

舒翱移动端 / 全栈 / Agent 应用

正文

假设我们做一个整理会议资料的系统,先记录每场会议的三项信息:时长、参加人数、待办数量。某场会议持续 30 分钟,有 5 人参加,产生 2 项待办。单独的 30、5、2 都是一个数,称为标量。为了把这场会议的信息放在一起,可以按约定写成:

会议 A = [30, 5, 2]
位置含义 = [时长(分钟), 参加人数(人), 待办数量(项)]

这一组按顺序排列的数,就是我们这里使用的向量表示。它有三个位置,所以叫三维向量。这里的“三维”表示三个数值坐标,并不要求画出一个现实中的立体物体。 向量也可以有几百、几千个坐标,电脑照样能够存储和计算。向量与数值表示

顺序是这个表示的一部分。如果另一个程序把顺序约定成“人数、时长、待办数量”,同样的三个数就应该写成 [5, 30, 2]。没有说明位置含义,单看 [30, 5, 2],无法知道它描述什么。单位也一样重要:把分钟换成秒,第一项就要变成 1800。

现在再加两场会议。为了统一处理,我们让每一行表示一场会议,每一列表示一项特征:

会议 时长(分钟) 参加人数(人) 待办数量(项)
A 30 5 2
B 60 8 4
C 45 6 3

只保留数值部分,就得到一个矩阵:

X = [
  [30, 5, 2],
  [60, 8, 4],
  [45, 6, 3]
]

矩阵是按行和列排列的数值结构。这里有三行、三列,形状写成 (3, 3)。为了避免误以为矩阵必须是正方形,再加一场会议后,形状就变成 (4, 3):四场会议,每场三项特征。行数和列数可以不同。

“形状”英文是 shape,回答的是每条轴上有多少个位置。“轴”可以先理解成访问数据时要选择的方向:先选哪场会议,再选哪项特征。矩阵有两条轴。Python 常用的数值库会把形状、轴数和元素总数分开记录,这三个量要区分开。NumPy 对 shape、ndim 和 size 的说明

例如形状 (4, 3) 的矩阵,有两条轴,一共 4 × 3 = 12 个数。我们可以说它是二维数组,也可以说每行是一个三维特征向量。这两句话并不矛盾:前一句数的是整块数组有几条轴,后一句数的是一个向量有几个坐标。

接下来,假设系统每天处理四场会议,我们还想把连续七天的数据放在一起。每一天对应一个 (4, 3) 的矩阵,再按日期叠起来,整体形状就是:

(7, 4, 3)
 日期数, 每天会议数, 每场特征数

选出某一天、某场会议、某项特征,才能定位到一个数。这时需要三个索引,因此有三条轴。

机器学习程序通常把这种数值容器统称为张量,英文 Tensor。按这种编程用法,标量可以看作零条轴的张量,向量是一条轴,矩阵是两条轴,刚才的会议数据是三条轴。更高层数的数组也能用相同方式描述。这里采用的是深度学习编程中的理解;数学和物理里讨论张量,还涉及更严格的结构与变换规则。TensorFlow 对张量、轴与形状的介绍

因此,张量并不是必须“比矩阵更高级”的数据。程序里的一个普通数值矩阵,也可以作为 Tensor 对象存储。看到 Tensor 这个词,先检查形状和每条轴的含义,比先想象复杂的几何图形更有帮助。

这一点到了语言模型里尤其有用。假设教学中约定一批有两段文本,每段都整理成五个 Token,每个 Token 用四个数表示,那么对应的表示可以有形状 (2, 5, 4)。第一条轴是文本,第二条轴是文本中的位置,第三条轴是每个位置的表示。这里的数字只是为了方便展示,不是某款模型的真实设置。

实际文本长短不同,系统还要选择填充、分组或其他处理方式,并说明哪些位置有效。给短文本补齐位置,不表示它真的多了那些内容。这些规则属于输入处理,不能仅凭张量形状推断出来。

我们先前手工指定的“时长、人数、待办”有明确名称。模型学出来的 Embedding 向量则通常不同:不能随意认定第一维就是“正式程度”、第二维就是“会议主题”。学习得到的表示往往通过多个坐标的组合发挥作用,向量有多少维,也不等于模型就拥有多少种独立知识。

有了结构,还需要理解怎样进行计算。对两个形状相同的会议矩阵,可以逐个位置相加。例如把两个部门同一天的统计按相同口径合并,对应位置相加可能有意义;若两张表的列顺序不同,数值虽然能相加,业务结果却可能完全错误。

乘法更需要看清约定。假设我们人为给三项特征设置权重:

w = [0.1, 1, 2]
A 的示例分数 = 30 × 0.1 + 5 × 1 + 2 × 2 = 12

这个分数只是演示加权计算,不代表会议好坏。三项特征分别乘权重,再相加,会把三个数变成一个数。对四场会议都这样计算,就能一次得到四个分数。从矩阵角度看,是 (4, 3) 的输入与三项权重配合计算。矩阵与向量的乘积

矩阵乘法通常按“左边的一行”和“右边的一列”配对,把对应乘积相加。两个矩阵形状分别是 (4, 3) 和 (3, 2),乘积形状就是 (4, 2)。中间的两个 3 必须对得上,表示计算时有三对数参与求和;外面的 4 和 2 决定输出形状。

逐元素乘法则是对应位置分别相乘,保留那些乘积,不自动把它们相加。写程序时,有些库用 * 表示逐元素乘法,用 @ 表示矩阵乘法。运算符含义取决于对象和库,不能把普通 Python 列表的行为直接套到数值张量上。比如列表乘整数常常是在重复列表内容。

还会遇到一个操作叫转置。对矩阵而言,它把行和列交换,(4, 3) 变成 (3, 4)。原本“会议 × 特征”的排列,变成“特征 × 会议”。数值没有凭空增加,但索引解释发生了变化。转置也不是把长数组随意重新折成另一个形状;改变 shape 和交换轴是需要分别理解的操作。

另一种常见错误,是只要程序没有报错,就以为形状正确。数值库可能按照广播规则,自动让某些形状参与计算。例如给每行加同一个三项向量,可以是有意设计,也可能是本来想给每列加数却选错了轴。检查时既要看计算能否执行,也要看它是否符合原来的数据含义。

最后再补两个容易混淆的细节。形状相同的张量,元素类型可能不同,例如整数和浮点数,占用空间与数值精度也可能不同。张量还可能放在不同计算设备上;形状只能说明组织结构,不能单独说明设备、精度和计算速度。

另外,有些资料把张量的轴数称为 rank,有些资料说“矩阵的秩”也用 rank。两者不是同一概念。一个二维矩阵无论有多少条独立的列,它仍然有两条轴;矩阵秩则要分析列与列之间能否相互组合得到,03.03 会专门解释。

以后遇到一段模型代码,可以先做三个具体判断:这个张量表示什么,每条轴表示什么,经过这次运算后形状应该变成什么。这样,原本抽象的一串数字,就能和输入资料、模型计算、输出结果连起来。下一篇再继续看:两个向量怎样合成分数,又怎样比较远近。


当前学习编号:03.01 向量、矩阵与张量。
下一学习编号:03.02 点积、范数与距离。后续还有其他学习编号。

关联分支:向量运算和矩阵内部结构,对应 03.02 点积、范数与距离、03.03 矩阵秩与低秩分解;输入数字的来源,对应 04.06 特征与标签、08.03 Token Embedding、15.03 稠密向量与 Embedding 模型;一批数据进入网络,对应 07.02 前向传播、07.06 Batch 与 Mini-batch、08.07 Query、Key、Value。

系列阅读

本篇学习编号:03.01 向量、矩阵与张量。

上一篇: 02.12 单元测试与集成测试 。

下一篇: 03.02 点积、范数与距离 。

延伸阅读

返回全部文章

搜索项目和文章

输入关键词,查找项目或文章。

使用 Tab 选择结果,按 Esc 关闭。