P2-3.6 用 NumPy 确认线性代数¶
Section ID:
P2-3.6Version:v2026.07.20
在 P2-3.1 里,我们看了标量(scalar)、向量(vector)、矩阵(matrix)的形状。在 P2-3.2 里,我们看了向量空间(vector space)与位置(position)的直觉;在 P2-3.3 里,我们把矩阵乘法(matrix multiplication)读成了加权求和(weighted sum)的复用;在 P2-3.5 里,我们又把 Python 运行环境分成了 Google Colab 与本地 PC。
现在开始用一小段一小段代码去检查同样的内容。这里我们使用 NumPy。NumPy 是 Python 里最常见的数组(array)创建与计算库之一。
- 先把它看成公式。
- 再把它做成数组。
- 然后检查
shape。 - 最后检查计算结果。
这里不要求背下很多 NumPy 语法,而是更关注:线性代数记号在代码里到底会呈现成什么样子。
这里重新整理 NumPy、数组(array)、shape、逐位置乘法(element-wise multiplication)、矩阵乘法(matrix multiplication)。如果 3.1 是在读数据形状,3.3 是在读矩阵乘法结构,那么这里就是整理“这些计算在代码和输出里长什么样”。
这里并不是要学完 NumPy 的所有功能,而是重新通过代码和 shape 去确认公式里看到的线性代数结构。只要先通过真实输出把向量、矩阵、*、@、batch 计算确认下来,后面在阅读 Pandas 数据和模型输入数组时,就更容易看出公式和代码是在说同一种结构。
从读者的角度来说,很容易出现一种感觉:代码能跑,但这一节到底在确认前面哪一个概念? 所以这里会把每个例子一起连回:它是在重新确认 P2-3.1 的形状(shape)、P2-3.2 的向量比较,还是 P2-3.3 的矩阵乘法结构。
| 这一节现在先抓住什么 | 紧接着会连到的问题 | 后面再次出现的位置 |
|---|---|---|
| 公式和 NumPy 数组是对应的 | 后面的章节里会继续看表格数据和模型输入数组如何连接。 | 在 Part 3 里按 shape 读取 X、y、train/test 分割结果时会再次出现。 |
把 * 和 @ 连同 shape 一起区分的习惯 | 在 P2-12.1、P2-12.3、P2-13.1 的数据处理和可视化练习里,也要一起确认输出形状。 | 在 Part 4 的线性层,以及 Part 5 的 embedding/logit 计算里会再次出现。 |
| 把 batch 计算读成矩阵层面的计算 | 它会继续连到 P2-4.1、P2-5.1 的变化率与概率说明,再一路连到后面的数组变换流程。 | 在跟随机器学习输入矩阵和 mini-batch 解释时会成为基础。 |
先看的概念对应表¶
这一节里的例子,会按下面这种方式重新确认前面的小节概念。
| 代码场景 | 回头确认的前文概念 | 读者第一步先看什么 |
|---|---|---|
创建向量并检查 shape | P2-3.1 的标量/向量/矩阵形状 | 是不是先看到了 shape,而不是先盯着数值 |
比较向量 a、b | P2-3.2 的位置与接近直觉 | 这些向量长度是否相同 |
a + b、2 * a | P2-3.2 的向量空间最小运算 | 加法和标量乘法在代码里怎么出现 |
区分 * 和 @ | P2-3.3 的矩阵乘法与加权求和 | 这是同位置计算,还是乘并相加的计算 |
| batch 矩阵计算 | P2-3.3 的“一次处理多个向量”视角 | 输入矩阵和输出矩阵的 shape 怎样变化 |
只要先抓住这张表,每个代码块就会更清楚地变成 重新确认前文概念的地方,而不只是语法示例。
核心判断标准:用 NumPy 确认线性代数¶
- 能用 NumPy 数组(array)创建向量和矩阵。
- 能用
.shape检查数据形状。 - 能在代码里确认向量加法与标量乘法。
- 能说明
*与@的区别。 - 能读懂把多个样本打包成矩阵,并应用同一个权重矩阵的计算。
- 能建立“公式、shape、代码结果一起读”的习惯。
三个基准¶
| 基准 | 为什么重要 | 本节所需的理解水平 |
|---|---|---|
| NumPy 把公式里的数组结构搬进代码 | 因为只有真的创建并打印向量与矩阵,才能看清 shape 与运算差异。 | 把 NumPy 理解成数组计算工具。 |
| 先看 shape,再看值 | 因为这是检查计算是否成立、输入输出结构是什么的最快方法。 | 理解要先用 .shape 读长度、行数、列数。 |
必须分清 * 和 @ | 因为一旦把逐位置乘法与矩阵乘法混淆,公式与代码都会一起读错。 | 理解 * 是逐位置计算,@ 是矩阵乘法。 |
运行环境¶
这一节的代码可以在任何安装了 NumPy 的 Python 环境里运行。
先按照 P2-3.5 的 先把运行环境分开 来确认执行位置。如果还没有安装 Python,可以在 Google Colab 代码单元里运行;如果使用本地 PC,也可以在自己的终端里运行。
在 Colab 代码单元里,可以这样准备 NumPy。
问题场景:在 Colab 中运行本节 NumPy 示例之前,先准备好包。 输入(input):笔记本代码单元里的 %pip install numpy 命令。 期望输出(output):NumPy 被安装到当前 Colab 内核。 要确认的概念:Colab 代码单元里的安装命令,与 Python 代码的执行,是两个不同阶段。
在本地 PC 终端里,则使用下面的命令。
然后,在 Python 代码里,用下面这种方式导入 NumPy。
问题场景:准备好包之后,在 Python 代码里真正导入 NumPy。 输入(input):import numpy as np 这一句。 期望输出(output):虽然不会打印结果,但后面例子里就可以使用 np 这个名字。 要确认的概念:安装命令与 import 语句的执行位置和作用不同。
这里的 np 是对 NumPy 的惯例性简写别名(alias)。
本节完整的示例代码也可以通过下面这个文件获得。
如果从项目根目录运行,可以在个人电脑终端里使用下面的命令。
这个文件会把向量加法、标量乘法、逐位置乘法、矩阵乘法、batch 计算一起打印出来。
创建向量与矩阵¶
向量(vector)可以作为值的列表来创建。
这个例子是在代码里确认 P2-3.1 提到的 向量可以读成一维数组。
问题场景:把公式里看到的向量做成 NumPy 一维数组,并检查它的形状。 输入(input):含有两个值的数组 x。 期望输出(output):打印向量值与 shape (2,)。 要确认的概念:向量在 NumPy 中表现为一维数组,可以通过 shape 检查长度。
输出可以读成:
(2,) 表示“一个含有 2 个值的一维数组”。对应到公式里就是:
矩阵(matrix)则可以创建成带有行(row)和列(column)的二维数组。
这个例子是在重新确认 P2-3.1 中“矩阵是收集多个向量的二维结构”这一说法。
问题场景:把公式中看到的权重矩阵做成 NumPy 二维数组,并检查它的形状。 输入(input):2 行 2 列 的数组 W。 期望输出(output):打印矩阵的值与 shape (2, 2)。 要确认的概念:矩阵在 NumPy 中表现为二维数组,行数和列数通过 shape 来读取。
输出可以读成:
(2, 2) 表示 2 行 2 列。
先检查 shape¶
当 AI 代码里的计算不工作时,往往应该先看 shape,再看数值。
这个习惯就是把 P2-3.2 中“只能在同一个空间里比较”的标准,搬到代码层面来。只要长度和形状不同,比较或乘法本身就可能不成立。
问题场景:先检查输入向量与权重矩阵是否具备可计算的形状。 输入(input):向量 x 和矩阵 W。 期望输出(output):打印 x 与 W 的 shape。 要确认的概念:把线性代数计算搬进代码时,先看 shape 再看值。
输出会是:x shape: (2,),W shape: (2, 2)。
这些信息能帮助我们回答:x 有多少个值、W 接收多少输入并产生多少输出、它们两者能不能相乘。
如果按 P2-3.3 的视角来读,x 是一个含有 2 个输入值的向量,而 W 是一个接收 2 个输入并产生 2 个输出的权重矩阵(weight matrix)。
确认向量加法与标量乘法¶
向量加法(vector addition)会把相同位置上的值相加。
这个例子是在代码里重新确认 P2-3.2 的向量空间最小运算。也就是说,向量不只是被比较的对象,也是可以被相加、缩放、从而做出新表示的计算对象。
问题场景:确认两个向量按相同位置相加的基础计算。 输入(input):长度为 3 的向量 a、b。 期望输出(output):打印逐位置相加结果 [5 7 9]。 要确认的概念:向量加法就是把相同位置的值相加。
输出是:
对应到公式里:
标量乘法(scalar multiplication)则是把同一个数字乘到数组的每个位置上。
问题场景:确认把一个标量乘到整个向量上的计算。 输入(input):向量 a 与标量 2。 期望输出(output):打印 [2 4 6]。 要确认的概念:标量乘法会把同一个数字应用到向量的每个位置。
输出是:
对应到公式里:
这两个计算,都直接连回了 P2-3.2 所说的向量空间最小计算。
* 表示逐位置乘法¶
在 NumPy 里,数组之间的 * 通常表示逐位置乘法(element-wise multiplication)。
这个例子也会继续连到 P2-3.4 里重新出现的比较问题。现在先熟悉“相同位置相乘”这种运算长什么样,之后再把它和点积(dot product)、相似度计算区分开来。
问题场景:确认 * 运算符不是矩阵乘法,而是逐位置乘法。 输入(input):长度为 3 的向量 a、b。 期望输出(output):打印逐位置乘积 [ 4 10 18]。 要确认的概念:NumPy 的 * 表示同位置之间的 element-wise 运算。
输出是:
对应到公式里:
这里最重要的是:* 不是矩阵乘法。它只是把相同位置的值相乘。换句话说,* 是逐位置乘法,@ 才是矩阵乘法。
@ 表示矩阵乘法¶
在 NumPy 里,@ 用来做矩阵乘法(matrix multiplication)。
这个例子是在代码里恢复 P2-3.3 的核心。@ 并不是相同位置相乘,而是一种“乘并相加”从而生成新向量的加权求和结构。
问题场景:用输入向量和权重矩阵计算基于加权求和的矩阵乘法。 输入(input):长度为 2 的向量 x 与 2 x 2 的矩阵 W。 期望输出(output):打印输出向量 y 及其 shape。 要确认的概念:@ 不是逐位置乘法,而是通过乘并相加生成新向量的矩阵乘法。
输出是:
这个计算正是 P2-3.3 里看过的加权求和结构。
第一个输出是:
第二个输出是:
所以,@ 就是 乘并相加、做出新向量的计算。
一次计算多个样本¶
如果把多个输入样本(sample)收集成一个矩阵,就可以把同一个权重矩阵一次性应用上去。
问题场景:确认把多个样本收集成矩阵,并一次性应用同一个权重矩阵的 batch 计算。 输入(input):2 x 2 的输入矩阵 X 与 2 x 2 的权重矩阵 W。 期望输出(output):打印 X、W、Y 的 shape,以及 batch 计算结果矩阵。 要确认的概念:即使是同时计算多个样本,核心仍然是矩阵形状是否兼容。
输出是:
对应到公式里:
这里,第一行是第一个样本的输出,第二行是第二个样本的输出。也就是说:有 2 个输入样本,每个样本有 2 个值,应用同一个 W 之后,得到 2 个输出样本,而每个输出也有 2 个值。
这就是 batch 计算最小的例子。
故意想一遍 shape 错误¶
下面这个计算就不能直接对上。
问题场景:确认当输入向量长度和权重矩阵输入侧大小不一致时,会出现什么问题。 输入(input):长度为 3 的向量 bad_x 和 2 x 2 的矩阵 W。 期望输出(output):尝试做矩阵乘法时出现 shape 不匹配错误。 要确认的概念:线性代数代码不是“值差不多就能跑”,而是“shape 对得上才能跑”。
bad_x 的 shape 是 (3,),而 W 的 shape 是 (2, 2)。输入有 3 个值,但权重矩阵只接收 2 个输入。也就是:bad_x shape: (3,),W shape: (2, 2)。
因此,它无法对齐到底哪些输入值该与哪些权重相乘。在真实的 NumPy 运行中,就会报出 shape 不匹配的错误。
比起死记错误消息,更重要的是问清:左边最后一个大小和右边输入侧大小是否相等、我打算做的是逐位置乘法还是矩阵乘法、输出 shape 理应是什么。
通过案例来看¶
案例 1. 为什么不先看 shape,看起来差不多的代码也会突然跑不通¶
很多学习者在跟着写 NumPy 示例时,会把 * 和 @ 混用,或者没有把向量长度和矩阵大小对齐,于是就碰到错误。即使数值看起来好像差不多,NumPy 也会先按 shape 是否匹配来决定计算能不能进行。
例如,长度为 2 的向量 x 和 2 x 2 矩阵 W 可以通过 x @ W 相乘。但如果输入向量长度变成 3,而权重矩阵保持不变,计算就会停下来,因为系统无法再决定哪些值应该和哪些权重组合。
这个案例说明了为什么我们会不断重复那句话:先看 shape,再看值。在线性代数公式里,符号看起来也许很简洁,但到了代码里,必须真正检查每个向量和矩阵到底含有多少个值,才能复现同一个计算。
所以,NumPy 实践的核心,与其说是记语法,不如说是用 shape 再次确认公式结构。* 是不是逐位置乘法、@ 是不是矩阵乘法、输入和输出维度如何连接,这些阅读标准都会直接继续连到后面的模型计算。
检查清单¶
- 能用 NumPy 数组(array)创建向量和矩阵吗?
- 能用
.shape检查向量与矩阵的形状吗? - 能把向量加法和标量乘法连回代码与公式吗?
- 能说明 NumPy 的
*是逐位置乘法(element-wise multiplication)吗? - 能说明 NumPy 的
@是矩阵乘法(matrix multiplication)吗? - 能读懂
x @ W里的输入 shape、权重 shape、输出 shape 吗? - 能说明“把多个样本收集成矩阵,再应用同一个权重矩阵”的 batch 计算吗?
- 能说明在 NumPy 里,比起单独记语法,更重要的是把公式、shape、输出一起阅读的习惯吗?
- 能区分
*和@,并应用“先看 shape、再看值”的标准吗?
来源与参考资料¶
- 本节示例代码:p2_3_6_numpy_linear_algebra.py
- NumPy Developers, NumPy documentation, 确认日期: 2026-07-19.
- NumPy Developers, NumPy quickstart, 确认日期: 2026-07-19.
- NumPy Developers,
numpy.array。可以确认数组创建 API 的参数和示例。确认日期: 2026-07-19. - NumPy Developers,
numpy.ndarray.shape。可以确认把数组维度作为元组读取的shape属性。确认日期: 2026-07-19. - NumPy Developers,
numpy.matmul。可以确认矩阵乘法以及 shape 不匹配时的错误条件。确认日期: 2026-07-19. - Charles R. Harris et al., Array Programming with NumPy, Nature, 2020, 确认日期: 2026-07-19.