从 Bit 到 AGI第二章:数学(Math)

矩阵是什么

从 Bit 到 AGI · 第二章:数学(Math) · 矩阵是什么

作者 David更新于 第 22 篇(共 186 篇)

上一篇说:一个样本是一个向量。实际训练时,我们同时处理 32、256 甚至 4096 个样本——这就需要把向量按行或按列排成表格。这个表格就是矩阵。本篇讲清矩阵的定义、在内存里的布局,以及它与神经网络权重的一一对应关系。学会用 (m,n)(m,n) 两个整数描述一层线性变换,是读任何 modeling_*.py 的基本功。后续矩阵乘、注意力、FFN 的 shape 推导,全部建立在「矩阵 = 二维浮点表」这一共识上。

直觉:向量组成的 spreadsheet

Excel 里一张表:每行是一个用户,每列是一个特征。机器学习里的矩阵完全一样——行 = 样本(或 token),列 = 特征(或神经元)。

神经网络的权重本质上就是矩阵:全连接层 W∈Rm×n\mathbf{W} \in \mathbb{R}^{m \times n} 把 nn 维输入变成 mm 维输出。Transformer 的 Q/K/V 投影、FFN 的两层线性变换,全是矩阵乘法。

定义

矩阵是 m×nm \times n 个实数排成的矩形数组:

A=[a11a12⋯a1na21a22⋯a2n⋮⋮⋱⋮am1am2⋯amn]∈Rm×n\mathbf{A} = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{bmatrix} \in \mathbb{R}^{m \times n}
  • aija_{ij}:第 ii 行、第 jj 列的元素。
  • 行向量:A\mathbf{A} 的第 ii 行,1×n1 \times n。
  • 列向量:A\mathbf{A} 的第 jj 列,m×1m \times 1。

转置 A⊤\mathbf{A}^\top 交换行列:(m×n)→(n×m)(m \times n) \to (n \times m)。

例子

例 1:batch 输入矩阵

X∈RB×dX \in \mathbb{R}^{B \times d}:BB 个样本,每个 dd 维。

import numpy as np

B, d = 32, 768
X = np.random.randn(B, d)   # shape (32, 768)
print(X.shape)              # 32 行 = 32 个向量
print(X[0])                   # 第 0 个样本,768 维向量

例 2:线性层权重

PyTorch 中 nn.Linear(in_features=768, out_features=3072) 的权重 weight.shape == (3072, 768)——即 W∈R3072×768\mathbf{W} \in \mathbb{R}^{3072 \times 768}。前向计算:Y=XW⊤\mathbf{Y} = \mathbf{X}\mathbf{W}^\top,输出 Y∈RB×3072\mathbf{Y} \in \mathbb{R}^{B \times 3072}。

对象形状含义
X\mathbf{X}(B,din)(B, d_{in})batch 输入
W\mathbf{W}(dout,din)(d_{out}, d_{in})可学习权重
Y\mathbf{Y}(B,dout)(B, d_{out})batch 输出

量化:内存与参数量

矩阵 A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n} 的存储(float32):

bytes=m×n×4\text{bytes} = m \times n \times 4
矩阵形状float32 参数量显存
小线性层768×768768 \times 768589,824≈ 2.25 MiB
FFN 第一层4096×110084096 \times 1100845,088,768≈ 172 MiB
LLaMA-7B 全部权重—≈ 7B≈ 14 GiB (fp16)

矩阵-向量乘 y=Ax\mathbf{y} = \mathbf{A}\mathbf{x}(A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n})的 FLOPs:2mn2mn(每个输出元素 nn 次乘加)。

NumPy 默认 row-major(C 序):同一行元素在内存中连续。第一章讲过 contiguous 数组对 GPU 很重要——非连续矩阵乘会触发隐式拷贝,拖慢训练。

工程视角:权重即矩阵

打开 model.state_dict(),你会看到成百上千个 key,每个 value 几乎都是二维或更高维张量。layers.0.self_attn.q_proj.weight 形状 (4096, 4096)——这就是一个方阵,4096×4096 = 16,777,216 个参数,bf16 下约 32 MiB 单层单投影。

7B 模型 ≈ 32 层 Transformer,每层含 Q/K/V/O 四个 d×dd \times d 投影、FFN 两个 d×4dd \times 4d 矩阵——参数量主要来自这些重复堆叠的矩阵。读 config.json 时:hidden_size、num_hidden_layers、intermediate_size 三个数乘乘除除,就能粗算总参数。

稀疏矩阵在经典 ML 里常见(词袋 TF-IDF);深度 LLM 权重是稠密的,每个元素都可训练。量化(INT8/INT4)不改变「逻辑上是矩阵」,只是把每个 wijw_{ij} 用更少 bit 存储——第四章以后推理章节会详讲。

矩阵转置在 API 设计里处处可见:NumPy A.T、PyTorch W.t()。Attention 里 QK⊤\mathbf{QK}^\top 故意把 key 转置,使 (i,j)(i,j) 元素变成 query ii 与 key jj 的点积——shape 对不上时,90% 是转置写错。

# 检查 Linear 层参数量
import torch.nn as nn
layer = nn.Linear(768, 3072)
params = layer.weight.numel() + layer.bias.numel()
print(f"params={params:,}, mem_bf16={params*2/1024**2:.2f} MiB")

常见误区

  1. (m,n)(m,n) 与 (n,m)(n,m) 不是一回事:转置改变形状;矩阵乘法 AB\mathbf{AB} 要求 A\mathbf{A} 的列数 = B\mathbf{B} 的行数。
  2. PyTorch Linear 的 weight 是 (dout,din)(d_{out}, d_{in}),不是 (din,dout)(d_{in}, d_{out})。读 shape 时别凭直觉。
  3. 「大矩阵 = 大模型」:7B 参数 ≈ 70 亿个 float,主要是大量 d×dd \times d 和 d×4dd \times 4d 的权重矩阵堆叠。

动手试一试

def matrix_stats(m: int, n: int, bytes_per_elem: int = 2) -> dict:
    params = m * n
    mem_mib = params * bytes_per_elem / (1024 ** 2)
    flops_mv = 2 * m * n  # matrix-vector multiply
    return {"params": params, "mem_MiB": mem_mib, "flops_mv": flops_mv}

# Transformer FFN: 4096 -> 11008 -> 4096
w1 = matrix_stats(11008, 4096)
w2 = matrix_stats(4096, 11008)
print(f"FFN 两层权重合计 ≈ {(w1['mem_MiB'] + w2['mem_MiB']):.0f} MiB (bf16)")

深入一层:分块与视图

大矩阵不必一次载入 GPU:按行块(数据并行)或列块(模型并行)切分。Megatron tensor parallel 把 W\mathbf{W} 列切到 8 卡,每卡算局部 GEMM 再 all-reduce——逻辑仍是一个矩阵乘,物理是分块。

视图(view)不拷贝:X.view(B, -1) 把图片 batch 展平为 (B,150528)(B, 150528)。transpose 可能不连续,.contiguous() 才保证 row-major——第一章与本章衔接。

单位矩阵 II:对角 1、其余 0,Ix=x\mathbf{I}\mathbf{x}=\mathbf{x}。残差连接 y=x+F(x)\mathbf{y}=\mathbf{x}+\mathbf{F}(\mathbf{x}) 在 Jacobian 层面加 II,特征值谱整体右移——训练更稳。

低秩分解:W≈UV\mathbf{W} \approx \mathbf{U}\mathbf{V},U∈Rm×r\mathbf{U}\in\mathbb{R}^{m\times r},V∈Rr×n\mathbf{V}\in\mathbb{R}^{r\times n},r≪min⁡(m,n)r \ll \min(m,n)。LoRA 即此思路;全秩 W\mathbf{W} 是工业默认,微调时用低秩增量省显存。

条件数(下节特征值详讲):A\mathbf{A} 求逆时,κ(A)=∥A∥∥A−1∥\kappa(\mathbf{A})=\|\mathbf{A}\|\|\mathbf{A}^{-1}\| 大 → 数值解敏感。线性方程 Ax=b\mathbf{A}\mathbf{x}=\mathbf{b} 的 solver 与神经网络无关,但Hessian 条件数影响优化——同一套矩阵分析语言。

与第一章的衔接

第一章:float 数组在内存 row-major 连续存放。矩阵即「mm 行向量首尾相接」——reshape(m, n) 不改变底层 bytes,只改解释。GPU kernel 要求 leading dimension 连续;transpose 后 GEMM 前常 .contiguous(),否则隐式拷贝拖慢数倍。

Batch 维 BB 是「第三维」:逻辑上 BB 个矩阵,物理上常 (B, m, n) 一块分配——与 SIMD、CUDA grid 的 batch 并行一致。

读者备忘

矩阵 = 二维权重表 = Rm×n\mathbb{R}^{m \times n}。 PyTorch Linear 的 weight.shape 是 (out_features, in_features)。参数量 = 行 × 列;一次前向该层 GEMM FLOPs ≈ 2×B×m×n2 \times B \times m \times n。读 checkpoint 时 state_dict 里二维 tensor 几乎都是权重矩阵;一维是 bias 或 norm 的 γ,β\gamma,\beta。

本章内容面向程序员:公式可手推,数字可心算,代码可运行。遇到符号不熟时,先查本篇定义表,再查总结篇速查表,不必一次背熟全部细节。

复习建议:先通读直觉与定义,再跑代码块验证数字,最后看读者备忘与小结。与第一章的 float 数组、SIMD、GPU 并行对照阅读,印象更深。后续章节会在 Transformer、训练、推理中反复调用本章符号,值得在笔记里自建一张 shape/FLOPs 速查表。

小结

矩阵是向量的二维排列,A∈Rm×n\mathbf{A} \in \mathbb{R}^{m \times n} 有 mnmn 个元素。在 AI 里:batch 输入、权重、注意力得分表都是矩阵。参数量 = 元素个数;显存 ≈ 参数量 × 每元素字节数。下一篇讲为什么矩阵乘法是神经网络和 GPU 的核心运算——矩阵定义了「存什么」,GEMM 定义了「怎么算」。

→ 下一篇:为什么矩阵乘法这么重要

本页目录