机器学习AI数学基础
AI,全称人工智能(Artificial Intelligence)让机器从数据中学习规律并做出判断的技术,而数学是描述规律、刻画变化的精确语言。
AI 提出目标,数学提供实现路径——从数据表示到模型训练,每一步背后都是数学在起作用。
可以说,数学是 AI 的骨架,没有数学,AI 只是一个模糊的构想。有了数学,AI 才能被计算、被验证、被真正实现。
AI 数学基础相关内容包含以下几个板块:
- 线性代数——描述数据的语言。一张图片、一段文字、一个用户画像,在计算机里最终都变成向量或矩阵。
- 微积分——描述变化的语言。模型是怎么学会的?靠的是不断计算梯度、调整参数。
- 概率与统计——描述不确定性的语言。世界是随机的,数据有噪声,模型的输出本质上是一种概率判断。
- 信息论——描述信息量的语言。用来衡量预测和真实之间差了多少、模型学到了多少东西。
- 优化理论——描述如何找到最优解的语言。训练一个模型,本质上就是在解一个优化问题。
这五个板块不是孤立的知识点,而是环环相扣的一条链路:
数据(线性代数)→ 建模(概率统计)→ 衡量误差(信息论)→ 求解(微积分+优化)
后面每一讲的内容,都会不断回到这条链路上,帮你把抽象的公式和具体的 AI 应用对应起来。
标量、向量、矩阵、张量
在 AI 的世界里,所有数据——无论是一张图片、一段文字、还是一段音频——最终都被组织成一种统一的形式:张量(Tensor)。
张量是一个统称,按照维度的不同,它有不同的名字。用维度(Dimension)理解数据的形状
标量(0 维):就是一个数。比如气温 26°C。在 NumPy 中 shape 显示为空元组 ()。
向量(1 维):一串有序的数。比如一天中每小时的气温记录。Shape 为 (n,),n 是元素个数。
矩阵(2 维):一张表格,有行和列。比如一周七天、每天 24 小时的气温表。Shape 为 (行数, 列数)。
张量(3 维及以上):多层数据叠放。比如全国 300 个城市、每个城市一周 7 天、每天 24 小时的气温。Shape 为 (城市数, 天数, 小时数) 即 (300, 7, 24)。
维度可以简单理解为:你需要几个「坐标」才能锁定一个具体的数。
数学上的定义
标量 Scalar:标量是一个单独的数,记作 a=26,或者 x∈R(x 属于实数集)。
向量 Vector:向量是一组有序的数,通常竖着写(列向量):
表示这是一个 n 维实数向量,
是第 1 个分量,
是第 n 个分量。
矩阵 Matrix:矩阵是一个 m 行 n 列的矩形数组:
记作 m×n 矩阵(m 行 n 列), 表示第 i 行第 j 列的元素。
张量 Tensor:张量是向量和矩阵向任意维度的推广。
一个 k 维张量的形状记作 ,共
个元素。
| 名称 | 维度 | Shape 示例 | 坐标数 | 数学记号 |
|---|---|---|---|---|
| 标量 | 0 | () | 0 | x∈Rx∈R |
| 向量 | 1 | (n,) | 1 | v∈Rnv∈Rn |
| 矩阵 | 2 | (m, n) | 2 | A∈Rm×nA∈Rm×n |
| 3D 张量 | 3 | (d1, d2, d3) | 3 | T∈Rd1×d2×d3T∈Rd1×d2×d3 |
Python 动手实践
下面用 NumPy 来创建和查看这些数据结构。shape 属性 是理解数据维度的关键。
import numpy as np
# 标量(0 维张量):shape = ()
scalar = np.array(26)
# 向量(1 维张量):shape = (n,)
vector = np.array([22, 23, 24, 26, 28, 30, 31, 29])
# 矩阵(2 维张量):shape = (行数, 列数)
matrix = np.array([[1, 2, 3], [4, 5, 6]])
# 3D 张量:shape = (层数, 行数, 列数)
tensor_3d = np.array([[[1,2,3],[4,5,6]], [[7,8,9],[10,11,12]]])
# 4D 张量:模拟 3 张 2x2 像素的单通道图片
batch_images = np.array([
[[[10],[20]],[[30],[40]]],
[[[50],[60]],[[70],[80]]],
[[[90],[100]],[[110],[120]]]
])
print("标量: shape=", scalar.shape, " ndim=", scalar.ndim)
print("向量: shape=", vector.shape, " ndim=", vector.ndim)
print("矩阵: shape=", matrix.shape, " ndim=", matrix.ndim)
print("3D 张量: shape=", tensor_3d.shape, " ndim=", tensor_3d.ndim)
print("4D 张量: shape=", batch_images.shape, " ndim=", batch_images.ndim)
输出:
标量: shape= () ndim= 0
向量: shape= (8,) ndim= 1
矩阵: shape= (2, 3) ndim= 2
3D 张量: shape= (2, 2, 3) ndim= 3
4D 张量: shape= (3, 2, 2, 1) ndim= 4
Shape 属性的规律
| 属性 | 含义 | 标量 | 向量(8个元素) | 矩阵(2×3) | 3D(2×2×3) |
|---|---|---|---|---|---|
.shape |
每个维度的大小 | () | (8,) | (2, 3) | (2, 2, 3) |
.ndim |
维度数量 = len(shape) | 0 | 1 | 2 | 3 |
.size |
元素总数 | 1 | 8 | 6 | 12 |
AI 中的应用场景
图像分类:从 3D 到 4D 张量
ImageNet 分类任务中,输入图片被统一缩放到 224×224 像素。单张彩色图片是 shape 为 (224, 224, 3) 的 3D 张量。
实际训练时,GPU 一次处理一个 batch(如 32 张图片),数据变为 4D 张量 (32, 224, 224, 3)。
注意不同框架的通道位置约定不同:TensorFlow/Keras 使用 (N, H, W, C)(通道在最后),PyTorch 使用 (N, C, H, W)(通道在最前)。
当你看到报错 "shape mismatch: (32, 224, 224, 3) vs (32, 3, 224, 224)",就是通道位置不一致导致的——用 .permute() 或 .transpose() 调整即可。
自然语言处理:嵌入矩阵
BERT 模型的词表大小为 30522,隐藏维度为 768。它的词嵌入矩阵 shape 为 (30522, 768)——每行是一个词的 768 维向量。
GPT 系列也是如此:GPT-2 的词表 50257,嵌入维度 768(小模型)到 1600(大模型)。
当你输入一段文本,模型首先查表把每个词 ID 转成对应的嵌入向量,这就是「查表取行」——一个矩阵索引操作。
全连接层:矩阵乘法的核心地位
一个经典的 MNIST 手写数字识别网络:输入 784 维(28×28 像素展平),第一隐藏层 256 维。
权重矩阵 W₁ 的 shape 为 (256, 784)。每次前向传播计算 h = W₁ @ x,就是 256×784 矩阵乘 784 维向量。
整个神经网络的前向传播,本质上就是一层层的矩阵乘法和激活函数的交替。
视频数据:5D 张量
视频可以理解为多帧图片的序列。一段 16 帧的 224×224 彩色视频片段,shape 为 (16, 224, 224, 3)。
加上 batch 维度后变成 5D 张量 (8, 16, 224, 224, 3)——这就是视频分类模型(如 3D-ResNet)的标准输入。
向量的加法与数乘
向量可以理解为从原点出发的一支箭——有长度、有方向。两个向量相加,就是把两段位移「拼接」在一起。
三角形法则:把第二个向量 b 的起点接到第一个向量 a 的终点。从 a 的起点到 b 的终点的连线,就是 a + b。直觉:「先走 a,再走 b」
平行四边形法则:以 a 和 b 为两条邻边,画一个平行四边形。从起点出发的对角线,就是 a + b。

数乘:拉伸或缩短向量
用一个标量(普通数字)去乘向量,结果是 改变向量的长度,但保持它所在的直线方向不变。
数乘只改变向量的「长度」,不改变它所在直线的方向(负数反转方向但仍在同一条直线上)。
这个性质叫做 共线性——数乘前后的两个向量总是在同一条直线上。
数学定义
向量加法
两个同维度的向量相加,就是对应位置的元素分别相加。两个向量维度必须相同,否则加法无意义。
向量减法
向量减法 = 加上反方向的向量:a−b=a+(−b)
向量数乘
一个标量 c 乘以一个向量,就是把向量的每个元素都乘以 c:
运算性质速查
| 性质 | 公式 | 直觉 |
|---|---|---|
| 交换律 | a+b=b+a | 先走哪段都一样 |
| 结合律 | (a+b)+c=a+(b+c) | 怎么分组走都一样 |
| 分配律 | c(a+b)=ca+cb | 先加再拉伸 = 先拉伸再加 |
Python 动手实践
import numpy as np
# 创建两个向量
a = np.array([3, 1]) # a = (3, 1)
b = np.array([1, 2]) # b = (1, 2)
# 向量加法:对应位置相加
add = a + b
print("a + b =", add_result) # [4, 3]
# 向量减法
sub_result = a - b
print("a - b =", sub_result) # [2, -1]
# 数乘:每个元素乘以标量
c = 2.5
scale_result = c * a
print(f"{c} * a =", scale_result) # [7.5, 2.5]
# 负向量:方向完全相反
neg = -a
print("-a =", neg) # [-3, -1]
# NumPy 广播:标量与向量各元素直接运算
print("a + 10 =", a + 10) # 每个元素都加 10
print("a * 3 =", a * 3) # 每个元素都乘 3
输出:
a + b = [4 3]
a - b = [2 -1]
2.5 * a = [7.5 2.5]
-a = [-3 -1]
a + 10 = [13 11]
a * 3 = [9 3]
AI 中的应用场景
词向量的语义运算:Word2Vec 和 GloVe 等词嵌入模型最著名的发现:向量的加减法有语义含义。
vec(国王)−vec(男人)+vec(女人)≈vec(女王)
减法是去掉「男性」特征分量,加法是加上「女性」特征分量。结果向量在嵌入空间中距离「女王」最近。
这种语义运算不仅限于性别——「巴黎 - 法国 + 意大利 ≈ 罗马」也是同样的原理。向量的加法和减法在此起到了「特征编辑」的作用。(巴黎是法国的首都,罗马是意大利的首都)
神经网络中的偏置:每个神经元的计算 中,+b 就是向量加法——偏置将 wx 的结果整体平移。
如果没有偏置 b,模型在 x=0 时输出必定为 0,这严重限制了模型的表达能力。偏置相当于给每个神经元一个「默认激活值」。
梯度更新:训练时的参数更新 就是数乘(学习率 × 梯度)与向量减法的组合。
数乘控制每步更新的大小(学习率越大步长越大),减法将参数向损失减小的方向移动。
数据预处理:均值中心化:在训练神经网络之前,通常会对数据做「减均值」操作:。这就是向量减法——将数据中心平移到原点,有助于梯度下降更快收敛。
向量的点积
点积(Dot Product)是 AI 中使用频率最高的向量运算。全连接层的计算、注意力机制的相似度匹配——它们的核心都是点积。点积有两种等价的视角,理解它们之间的桥梁是本章的核心收获。
视角一,代数计算:对应位置的元素相乘,然后求和。
例如:(2,3) · (4,1) = 2×4 + 3×1 = 11
视角二,几何直觉:将一个向量投影到另一个向量上,然后两段长度相乘。
夹角 θ 越小,点积越大。
两种算法得出的是同一个值——这是数学中一个极其优雅的等式。
数学定义
代数定义:
几何定义:
两个定义的桥梁-——求夹角:
这意味着:给定两个向量的坐标,就能算出它们之间的夹角,不需要量角器。
运算性质
| 性质 | 公式 | 说明 |
|---|---|---|
| 交换律 | a⋅b=b⋅a | 顺序不影响 |
| 分配律 | a⋅(b+c)=a⋅b+a⋅c | 可先加再点积 |
| 自身点积 | a⋅a=|a|^2 | 向量与自己的点积 = 长度的平方 |
Python 动手实践
import numpy as np
a = np.array([2, 3, 1])
b = np.array([4, 1, 2])
# 方法1:np.dot()
dot1 = np.dot(a, b)
# 方法2:@ 运算符(推荐)
dot2 = a @ b
# 方法3:手写验证
dot3 = sum(a[i] * b[i] for i in range(len(a)))
print("a · b =", dot1) # 13
print("三种方法结果一致:", dot1 == dot2 == dot3)
# 用几何定义反推夹角
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
cos_theta = dot1 / (norm_a * norm_b)
theta_deg = np.degrees(np.arccos(cos_theta))
print(f"||a||={norm_a:.2f}, ||b||={norm_b:.2f}, cosθ={cos_theta:.4f}")
print(f"夹角 = {theta_deg:.1f}°")
# 验证几何公式
verify = norm_a * norm_b * cos_theta
print(f"||a||·||b||·cosθ = {verify:.4f} (与点积一致)")
# 不同夹角的演示
print("\n[1,0] · [0.8,0.6] =", np.array([1,0]) @ np.array([0.8,0.6]), " (锐角,正)")
print("[1,0] · [0,1] =", np.array([1,0]) @ np.array([0,1]), " (直角,零)")
print("[1,0] · [-1,0] =", np.array([1,0]) @ np.array([-1,0]), " (钝角,负)")
输出:
a · b = 13
三种方法结果一致: True
||a||=3.74, ||b||=4.58, cosθ=0.7582
夹角 = 40.7°
||a||·||b||·cosθ = 13.0000 (与点积一致)
[1,0] · [0.8,0.6] = 0.8 (锐角,正)
[1,0] · [0,1] = 0 (直角,零)
[1,0] · [-1,0] = -1 (钝角,负)
AI 中的应用场景
全连接层 = 点积的批量计算:一个神经元计算 。加和部分就是权重向量 w 和输入向量 x 的点积。
当你看到一个全连接层 nn.Linear(784, 256),它在数学上做的事就是:256 个神经元,每个神经元拿自己的权重向量(784 维)与输入向量做点积,再加上偏置。256 个点积并行计算 = 矩阵乘法。
注意力机制 = 点积 + Softmax:Transformer 的核心操作:Query 向量与 Key 向量做点积,结果越大表示两者越「相关」。
是 seq_len × d_k 矩阵与 d_k × seq_len 矩阵的乘法,结果矩阵中位置 (i, j) 的值 = 第 i 个 Query 与第 j 个 Key 的点积。这个值越大,表示第 i 个位置对第 j 个位置的「注意力」越高。
除以 是为了防止点积值过大导致 Softmax 梯度消失。GPT、BERT、Claude 等所有现代大语言模型都基于这个点积注意力机制。
推荐系统中的相似度计算:用户向量与物品向量做点积,得到用户对该物品的「偏好分数」。这就是矩阵分解推荐算法的核心——评分矩阵 ≈ 用户隐向量矩阵 × 物品隐向量矩阵的转置。
向量的模长与余弦相似度
模长:向量有多长?
模长就是向量从原点到终点的「直线距离」——勾股定理在高维空间的推广。
L1 范数:曼哈顿距离:。沿街道走 如:(3,4) 的 L1 = 7
L2 范数(默认):。直线距离:空中飞 (3,4) 的 L2 = 5
未特别说明时,「模长」默认指 L2 范数。
单位向量:扔掉长度,只留方向
任何非零向量除以自己的模长,得到长度为 1 的 单位向量:,归一化后向量方向不变,但模长变为 1。
余弦相似度:只看方向,不看大小
余弦相似度 = 把两个向量都归一化为单位向量后,再做点积:
(方向一致cos=1,方向垂直cos=0,方向相反cos=-1)
余弦相似度只关心方向,不关心长度。
v = (3,4) 和 w = (6,8)(w = 2v),长度差一倍,但余弦相似度 = 1——因为它们方向完全相同。
import numpy as np
v = np.array([3, 4, 0])
w = np.array([6, 8, 0]) # v 的 2 倍
# 模长
norm_v = np.linalg.norm(v) # L2 默认
norm_w = np.linalg.norm(w)
print(f"||v|| = {norm_v:.1f}, ||w|| = {norm_w:.1f}") # 5, 10
# 归一化
unit_v = v / norm_v
unit_w = w / norm_w
print("v 归一化:", unit_v) # [0.6, 0.8, 0.]
print("w 归一化:", unit_w) # [0.6, 0.8, 0.] 完全相同!
# 余弦相似度
cos_sim = np.dot(v, w) / (norm_v * norm_w)
print(f"余弦相似度 = {cos_sim:.4f}") # 1.0
输出
||v|| = 5.0, ||w|| = 10.0
v 归一化: [0.6 0.8 0. ]
w 归一化: [0.6 0.8 0. ]
余弦相似度 = 1.0000
import numpy as np
# 批量计算余弦相似度矩阵
embeddings = np.array([
[0.2, 0.5, 0.1, 0.8, 0.3],
[0.3, 0.6, 0.2, 0.7, 0.4],
[0.9, 0.1, 0.8, 0.1, 0.9],
])
norms = np.linalg.norm(embeddings, axis=1, keepdims=True)
normalized = embeddings / norms
sim_matrix = normalized @ normalized.T
print("\n余弦相似度矩阵:")
print(np.round(sim_matrix, 3))
输出:
余弦相似度矩阵:
[[1. 0.996 0.146]
[0.996 1. 0.182]
[0.146 0.182 1. ]]
解释 normalized @ normalized.T
先把所有符号简化,抛弃抽象术语,只看结构
先定义数据
normalized.shape = (3, 5)
也就是 3 行 5 列:
:第 1 个归一化向量,长度 5
:第 2 个归一化向量,长度 5
:第 3 个归一化向量,长度 5
2. normalized.T = 转置
转置之后行列互换,变成 5 行 3 列:
是行向量:
变成列向量:
3. 矩阵乘法 A @ B 规则
如果 A 是 ,B 是
结果 =
。元素
的第i行
的第j列。
现在:
输出矩阵:
展开矩阵乘法!(重点!)
4. 和余弦相似度关联
之前做过:所有 v 都是 L2 归一化向量 余弦相似度公式:
归一化后
所以矩阵里面每一格含义:
:向量 1 和 向量 1 的相似度
:向量 1 和 向量 2 的相似度
:向量 1 和 向量 3 的相似度
:向量 2 和 向量 1 的相似度 以此类推。
✅ 最终得到完整两两相似度表格(相似度矩阵)
AI 中的应用场景
语义搜索与推荐系统:将查询词和文档分别编码为向量后,用余弦相似度排序——找最相关的文档。Google 的语义搜索、RAG(检索增强生成)中的向量检索都依赖余弦相似度。
相比点积,余弦相似度不受向量模长影响——一篇长文章的向量模长可能很大,但用余弦相似度能公平地与短查询比较方向一致性。
人脸识别:余弦相似度 > 欧氏距离:FaceNet 等面部识别模型将人脸映射为 128 维嵌入向量。两个人脸是否匹配,用余弦相似度判断——它对照明条件、照片亮度(影响向量模长)不敏感。
两张同一个人不同光照下的照片,嵌入向量方向几乎一致(cos ≈ 0.95+),但模长可能差很多。
L2 正则化防止过拟合:损失函数中加入 (权重衰减),惩罚权重模长过大。权重模长大意味着模型对某些特征过度信任,泛化能力差。L2 正则化将其拉向原点附近。
Batch Normalization 中的归一化:BN 对每层激活值做归一化:减均值后除以标准差,将数据变为模长稳定的分布。这用到了 L2 范数的概念来控制各层输出的尺度。
矩阵加法与矩阵乘法
矩阵乘法是理解神经网络前向传播的关键——全连接层的本质就是矩阵乘法。
矩阵加法:对应位置相加,两个形状相同的矩阵,把对应位置的元素加起来——和向量加法一样直观。
矩阵乘法:行与列的点积,矩阵乘法没有「对应位置乘」那么简单。为什么?
矩阵的深层含义是「线性变换」——它会把一个向量映射到另一个向量。
两个矩阵相乘 AB,在几何上的意思是:先做 B 变换,再做 A 变换。所以 AB 的运算法则必须反映「复合变换」的数学结构,而不是简单的逐元素相乘。
例如:A 表示「水平拉伸 2 倍」, B 表示「逆时针旋转 90°」。AB 表示「先旋转再拉伸」——这与 BA(先拉伸再旋转)完全不同,所以矩阵乘法不满足交换律。
运算法则是:左矩阵的第 i 行与右矩阵的第 j 列做点积 → 结果矩阵的 (i, j) 位置的值。
A 的列数 必须等于 B 的行数。两个标红的 n 必须相等。
结果的形状 = (A 的行数, B 的列数)
矩阵乘法 不满足交换律:AB ≠ BA(通常情况)。甚至维度可能不匹配导致 BA 无定义——这是初学者最容易出错的地方。
矩阵乘法的本质是线性变换的复合:乘以矩阵 A → 做完一次变换;再乘以矩阵 B → 做完第二次变换。两次变换复合 = 一次 (BA) 变换。这就是矩阵乘法这样定义的原因。
小卖部收入计算:三天的销量矩阵(行=日期,列=商品):
| 可乐 | 薯片 | 泡面 | |
|---|---|---|---|
| 周一 | 10 | 5 | 3 |
| 周二 | 8 | 7 | 4 |
| 周三 | 12 | 4 | 6 |
价格矩阵(行=商品,列=店铺):
| 店铺1 | 店铺2 | |
|---|---|---|
| 可乐 | 3 | 3.5 |
| 薯片 | 5 | 5.5 |
| 泡面 | 4 | 4.0 |
销量矩阵 (3×3) × 价格矩阵 (3×2) = 收入矩阵 (3×2)。结果的每一格 = 某天在某个店铺的总收入。
数学定义
矩阵加法: 前提:A 和 B 形状完全相同。
矩阵乘法:设 A 为 m×n,B 为 n×p,则 C = AB 为 m×p:
Python 动手实践
import numpy as np
A_runoob = np.array([[10, 5, 3], [8, 7, 4], [12, 4, 6]])
price = np.array([[3, 3.5], [5, 5.5], [4, 4.0]])
# 矩阵加法(同形状)
bonus = np.array([[1, 0, 1], [0, 1, 0], [1, 1, 0]])
total = A_runoob + bonus
print("A + bonus:\n", total)
# 矩阵乘法:(3×3) @ (3×2) = (3×2)
revenue = A_runoob @ price
print("\n收入矩阵 A @ price:\n", revenue)
print("形状:", revenue.shape)
# 手动验证第(0,0)位置
manual = A_runoob[0,0]*price[0,0] + A_runoob[0,1]*price[1,0] + A_runoob[0,2]*price[2,0]
print(f"\n手动验证 [0,0]: {manual} == {revenue[0,0]}")
# 维度不匹配的陷阱
print(f"\nA 形状: {A_runoob.shape}") # (3, 3)
print(f"price.T 形状: {price.T.shape}") # (2, 3)
# A @ price.T → (3,3) @ (2,3) 不匹配!
# 正确:price.T @ A → (2,3) @ (3,3) = (2,3)
print(f"price.T @ A 形状: {(price.T @ A_runoob).shape}") # (2, 3)
输出:
收入矩阵 A @ price:
[[67. 72. ]
[75. 79.5]
[80. 88. ]]
形状: (3, 2)
A 形状: (3, 3)
price.T 形状: (2, 3)
price.T @ A 形状: (2, 3)
AI 中的应用场景
全连接层 = 矩阵乘法:nn.Linear(d_in, d_out) 的本质:权重矩阵 W(d_out × d_in)乘以输入向量 x(d_in 维),得到输出(d_out 维)。
处理 batch 数据时,输入 X 是 (batch, d_in) 矩阵,计算 Y=XWTY=XWT 或 Y=WXTY=WXT,这是一次矩阵乘法完成整个 batch 的前向计算。GPU 对矩阵乘法有专门硬件加速(Tensor Core)。
注意力机制的 :Transformer 中 Q 和 K 都是 (seq_len, d_k) 矩阵。
是 seq_len×d_k 乘 d_k×seq_len,得到 (seq_len, seq_len) 的注意力分数矩阵。
GPT-4 级别的大模型中,seq_len 可达 128K,这个矩阵乘法的计算量占整个推理成本的很大一部分。FlashAttention 算法就是专门优化这个矩阵乘法的显存访问模式。
卷积的矩阵乘法实现(im2col):卷积操作可以展开为矩阵乘法:把输入图像按滑动窗口展开为一个大矩阵(im2col),然后把卷积核也展平为矩阵,两者相乘。这让卷积能利用高度优化的 GEMM(通用矩阵乘法)库来加速。
LoRA 微调中的矩阵分解:LoRA 在预训练权重旁加两个小矩阵 A 和 B 的乘积:。这里的 AB 就是矩阵乘法——A 是 d×r,B 是 r×d,乘积是 d×d 的低秩矩阵。一个矩阵乘法实现了参数高效的微调。
矩阵的转置与逆矩阵
转置在注意力机制中频繁出现,逆矩阵帮助我们理解「可逆变换」——比如 PCA 中的坐标变换。
转置:行列互换:
| 1 | 2 | 3 |
| 4 | 5 | 6 |
| 1 | 4 |
| 2 | 5 |
| 3 | 6 |
原来 (i, j) 位置的值,经过转置后到了 (j, i) 位置。 形状从 m×n 变成 n×m。
逆矩阵:撤销变换,矩阵 A 代表一个线性变换。 代表「撤销 A 的效果」。
数学表达:(I 是单位矩阵,相当于数字 1)。
只有 方阵且满秩 的矩阵才有逆矩阵。非方阵或不满秩的方阵是「奇异矩阵」,没有逆——相当于一个不可逆的操作。
关键性质
- 乘积转置反转顺序:
- 乘积逆也反转顺序:
逆矩阵:Ctrl+Z 撤销。你做了一个旋转 + 缩放操作(矩阵 A),想还原回去()。两次操作复合 = 什么都没变(
,恒等变换)。
数学定义
转置:
逆矩阵:对于 n×n 方阵 A,如果存在 B 使得 ,则
。
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]])
print("A (2x3):\n", A)
print("A.T (3x2):\n", A.T)
print()
# 验证 (AB)^T = B^T @ A^T
B = np.array([[1,2],[3,4],[5,6]]) # 3x2
AB = A @ B # (2,3) @ (3,2) = (2,2)
print("(AB)^T:\n", AB.T)
print("B^T @ A^T:\n", B.T @ A.T)
print("相等:", np.allclose(AB.T, B.T @ A.T))
print()
# 逆矩阵
C = np.array([[2, 1], [5, 3]]) # 2x2 方阵
C_inv = np.linalg.inv(C)
print("C:\n", C)
print("C^{-1}:\n", C_inv)
print("C @ C^{-1} = I:\n", C @ C_inv)
# 奇异矩阵没有逆
D = np.array([[1, 2], [2, 4]]) # 第2行是第1行的2倍
try:
np.linalg.inv(D)
except np.linalg.LinAlgError:
print("\n奇异矩阵 D 没有逆矩阵(第2行=2×第1行)")
输出:
A (2x3):
[[1 2 3]
[4 5 6]]
A.T (3x2):
[[1 4]
[2 5]
[3 6]]
C @ C^{-1} = I:
[[1. 0.]
[0. 1.]]
奇异矩阵 D 没有逆矩阵(第2行=2×第1行)
AI 中的应用场景
注意力机制的 操作:
中 Key 矩阵的转置让 (seq_len, d_k) 的 Q 能与 (seq_len, d_k) 的 K 做矩阵乘法——转置将 K 变为 (d_k, seq_len),使内维匹配。这个 K^T 是所有 Transformer 模型注意力计算中最关键的维度变换。
线性回归的闭式解:——转置和逆矩阵同时出现。
保证结果是对称正定矩阵(可逆),然后求逆得到解析解。sklearn 的 LinearRegression 在不加正则化时底层就算这个。
梯度下降中的参数更新:在反向传播中,权重梯度矩阵的形状必须与权重矩阵匹配才能做减法更新。例如 W 是 (d_out, d_in),它的梯度 \nabla_W L 也是 (d_out, d_in)——转置在中间层帮助梯度在计算图中正确传导维度。
特殊矩阵
单位矩阵 I:主对角线全是 1,其余全是 0,乘以任何矩阵 = 不变,相当于数字中的「1」,对任意形状兼容的矩阵 A:。
对角矩阵:独立缩放每个维度,对角矩阵乘以向量 = 对向量的每个分量独立施加不同的缩放系数。
对称矩阵:转置后还是自己,对称矩阵有一个极重要的性质:特征值全是实数,特征向量相互正交。这使得对称矩阵在优化和统计中极其有用——协方差矩阵和 Hessian 矩阵都是对称矩阵。
,即
。
矩阵的迹(trace):是线性代数中的基本概念,通常记作 tr(A)。对于一个 n×n 的方阵 ,其迹定义为主对角线元素之和:
。显然,只有方阵才有迹,标量的迹就是其本身。
import numpy as np
# 单位矩阵
I = np.eye(3)
A = np.array([[4,7,2],[3,5,1],[6,8,9]])
print("I @ A == A:", np.allclose(I @ A, A))
# 对角矩阵:独立缩放
D = np.diag([2, 3, 5])
v = np.array([1, 1, 1])
print("D @ [1,1,1] =", D @ v) # [2, 3, 5]
# 对称矩阵
S = np.array([[1,4,5],[4,2,6],[5,6,3]])
print("S 对称:", np.allclose(S.T, S))
eigenvals = np.linalg.eigvals(S)
print("特征值全实数:", np.all(np.isreal(eigenvals)))
# 协方差矩阵天然对称
data = np.random.randn(100, 5)
cov = np.cov(data.T)
print("协方差矩阵对称:", np.allclose(cov, cov.T))
输出:
I @ A == A: True
D @ [1,1,1] = [2 3 5]
S 对称: True
特征值全实数: True
协方差矩阵对称: True
AI 中的应用场景
Adam 优化器 = 对角矩阵自适应缩放:Adam 为每个参数维护梯度平方的指数移动平均 v_t,更新时用 。从数学上看,
对每个参数分量独立缩放——这就是一个对角矩阵乘以梯度向量。活跃的梯度分量被缩小学习率,不活跃的梯度分量被放大。
协方差矩阵用于 PCA:PCA 降维的第一步:计算数据中心化后的协方差矩阵 。这是一个对称矩阵
,它的特征值全为实数。最大的 k 个特征值对应的特征向量就是主成分方向。sklearn 的 PCA 类底层就做这件事。
循环神经网络的恒等初始化:RNN 和 LSTM 的 recurrent 权重矩阵常初始化为单位矩阵。这确保训练初期,隐藏状态的信息能够「原封不动」地传递,避免梯度在时间步上过快衰减。这个技巧被称为 IRNN(Identity RNN)。
Xavier/Glorot 初始化:Xavier 初始化精心选择权重的方差使每层输出的方差保持一致:。这等价于从该方差的正态分布中对角矩阵(方差)的约束。
特征值、特征向量
设二阶方阵 若存在非零向量
和数
,满足:
则称
为特征值,
为对应
的特征向量。
变形:
是二阶单位矩阵。
齐次方程组有非零解 系数矩阵行列式为0:
该方程叫特征方程。
第一步:求特征多项式、解特征值
行列式:
记:
- 迹
(主对角线和)
- 行列式
特征多项式简写:
解方程 ,得到两个特征值
(实根/共轭复根/重根)。
求根公式:
判别式分类
:两个不同实特征值
:二重实特征值
:一对共轭复特征值
第二步:对每个 求特征向量
对单个特征值 ,解齐次线性方程组:
方程组有无穷多非零解,所有解都是
的特征向量;通常取一个基础解系作为代表。
实操简化(二阶专用)
矩阵,两行线性相关,只用一行列方程即可:
自由设一个变量,解出另一个。
例1:二阶实矩阵,两个不同实特征值
计算迹、行列式
特征方程
特征值:
求 的特征向量
方程: 令
,得基础特征向量:
求 的特征向量
方程:
令
:
验证:。
例2:二重特征值(亏损矩阵示例)
,特征方程
,
(二重根)
方程:
基础解系仅1个:
二重特征值只对应1个线性无关特征向量,矩阵不可对角化。
例3:共轭复特征值
对 :
取 ,复特征向量
。
几何意义:矩阵代表线性变换,特征向量是变换中 “不跑偏” 的方向,特征值是拉伸 / 压缩程度。
import numpy as np
# 输入方阵A
A = np.array([[2, 1], [1, 2]])
# eigvals:只算特征值
vals = np.linalg.eigvals(A)
# eig:同时返回特征值、特征向量矩阵
vals, vecs = np.linalg.eig(A)
print(vals)
print(vecs)
输出:
[3. 1.]
[[ 0.70710678 -0.70710678]
[ 0.70710678 0.70710678]]
vecs[:,i]:第 i 个特征向量vals[i]:对应第 i 个特征值
验证公式
v = vecs[:,0]
lam0 = vals[0]
print(A @ v)
print(lam0 * v) # 两者完全相等
代码2:
import numpy as np
A = np.array([[2, 0], [0, 1]]) # 水平拉伸2倍,垂直不变
eigenvalues, eigenvectors = np.linalg.eig(A)
print("特征值:", eigenvalues) # [2. 1.]
print("特征向量 (列):\n", eigenvectors)
# 验证 Av = λv
for i in range(2):
v = eigenvectors[:, i]
lam = eigenvalues[i]
print(f"\n验证特征向量{i+1}:")
print(f" A @ v = {A @ v}")
print(f" λ * v = {lam * v}")
print(f" 相等: {np.allclose(A @ v, lam * v)}")
# 对称矩阵的特征值全实数
S = np.array([[1, 4], [4, 2]])
print(f"\n对称矩阵 S 的特征值: {np.linalg.eigvals(S)}(全实数)")
AI 中的应用场景
PCA 降维:计算数据协方差矩阵的特征值和特征向量。最大的 k 个特征值对应的特征向量就是数据方差最大的 k 个方向(主成分)。将数据投影到这些方向上,方差小的方向被丢弃,实现降维。从 784 维的 MNIST 图像降到 50 维,仍能保留约 90% 的信息。
谱归一化(Spectral Normalization):在 GAN 训练中,判别器的权重矩阵每步做谱归一化:,其中
是最大的奇异值(方阵时 = 最大特征值的绝对值)。这确保判别器是 1-Lipschitz 的,稳定训练、减少模式崩塌。
图神经网络的谱方法:图拉普拉斯矩阵 L = D - A(D 是度对角矩阵,A 是邻接矩阵)的特征值和特征向量定义了图上的傅里叶变换。GCN(图卷积网络)就是在这个谱域上做卷积——虽然现代 GCN 更多用空间域方法,但谱方法是理论基础。
矩阵的秩
从鸡兔同笼到 AI 模型训练,线性方程组无处不在。矩阵的「秩」告诉我们方程组中真正有效的信息量有多少。
任何线性方程组都可以写成 Ax = b
A 是系数矩阵(m 个方程,n 个未知数),x 是未知数向量,b 是常数向量。例如鸡兔同笼: 写成矩阵形式:
秩:独立信息的数量:秩(Rank)= 矩阵中真正「独立」的行数(或列数)。
如果某个方程可以由其他方程乘以系数得到,它就是冗余的——不增加新信息。
鸡兔同笼:满秩,唯一解
头数 10 + 脚数 28 → 鸡 6 只、兔 4 只。两个方程提供两条独立信息,刚好解出两个未知数。
冗余信息:欠秩,无穷多解
方程一:x + y = 5。方程二:2x + 2y = 10(就是方程一的 2 倍)。两个方程其实是一条信息——有无穷多对 (x, y) 满足条件。
秩的判定
| 条件 | 解的情况 |
|---|---|
| rank(A) = rank([A|b]) = n | 唯一解 |
| rank(A) = rank([A|b]) < n | 无穷多解 |
| rank(A) < rank([A|b]) | 无解 |
其中 [A|b] 是把 b 拼在 A 右边的增广矩阵。
import numpy as np
# 鸡兔同笼:满秩
A = np.array([[1,1],[2,4]])
b = np.array([10,28])
x = np.linalg.solve(A, b)
print("解:", x, "→ 鸡=6, 兔=4")
print("秩:", np.linalg.matrix_rank(A)) # 2(满秩)
# 冗余方程
A_red = np.array([[1,2],[2,4]]) # 第2行=2×第1行
print("\n冗余矩阵的秩:", np.linalg.matrix_rank(A_red)) # 1
# 随机大矩阵的秩
big = np.random.randn(100, 50)
print("100×50 随机矩阵的秩:", np.linalg.matrix_rank(big)) # 50
输出:
解: [6. 4.] → 鸡=6, 兔=4
秩: 2(满秩)
冗余矩阵的秩: 1
100×50 随机矩阵的秩: 50
AI 中的应用场景
LoRA 微调 = 低秩假设:LoRA(Low-Rank Adaptation)的核心假设:预训练权重的微调更新量 是低秩的。因此可以用两个小矩阵 A(d×r)和 B(r×d)的乘积来近似完整更新量
,其中 r << d。
例如对 GPT-3 的 12288 维权重矩阵,r 取 8 或 16 就够了——秩从 12288 降到 8,参数量减少上千倍。这就是利用「秩」的概念做参数高效微调。
特征共线性检测:数据矩阵的秩远小于列数 → 特征之间存在高度共线性(多重共线性)→ 线性回归的 X^TX 不可逆或接近奇异 → 需要正则化(Ridge/Lasso)或降维(PCA)。在实际 ML 项目中,这表现为特征矩阵的条件数过大。
推荐系统中的矩阵补全:用户-物品评分矩阵通常只有少数评分(稀疏),但假设它是由低秩结构生成的(相似用户有相似口味)。矩阵补全(Matrix Completion)利用秩的约束,通过已知评分推断缺失评分。这是 Netflix 推荐大赛获奖算法的核心思想。
奇异值分解(SVD)
设 是
实矩阵,则奇异值分解:
各个矩阵含义
:左奇异向量矩阵,正交矩阵
:奇异值对角矩阵,只有主对角线非零
称为奇异值,
:右奇异向量矩阵,正交矩阵
import numpy as np
A = np.array([[1,0,0,0,2],[0,0,3,0,0],[0,0,0,0,0],[0,4,0,0,0]])
U, S, VT = np.linalg.svd(A)
print("奇异值:", np.round(S, 2)) # [4. 3. 2.24 0.]
print("非零奇异值个数 = 秩 =", np.sum(S > 1e-10))
# 图像压缩演示:秩为1的图像
img = np.outer(np.array([1,2,3,2,1]), np.array([2,4,6,4,2]))
U_i, S_i, VT_i = np.linalg.svd(img)
print("\n图像矩阵的奇异值:", np.round(S_i, 2))
# 只用1个奇异值完美重建(因为秩=1)
k = 1
approx = U_i[:,:k] @ np.diag(S_i[:k]) @ VT_i[:k,:]
print("k=1重建误差:", np.linalg.norm(img - approx))
代码2:
import numpy as np
A = np.array([[1,2,3],[4,5,6]])
U, s, Vt = np.linalg.svd(A)
print("U:\n",U)
print("奇异值s:",s)
print("V转置:\n",Vt)
# 构造Sigma
Sigma = np.zeros_like(A, dtype=float)
np.fill_diagonal(Sigma, s)
# 还原A
A_recon = U @ Sigma @ Vt
print("重构误差",np.linalg.norm(A - A_recon))
AI 中的应用场景
LoRA 微调的数学基础:LoRA 假设 :ΔW是低秩的——这等价于假设 ΔW 的 SVD 中只有前 r 个奇异值显著,其余可以忽略。r 取得越小,可训练参数越少,但近似精度越低。实践中 r=8 或 16 常是效果与效率的最佳平衡点,这源于对权重矩阵奇异值衰减速度的经验观察。
推荐系统:矩阵分解协同过滤:用户-物品评分矩阵 R(m×n)做截断 SVD:。U_k 的每行是用户的 k 维隐向量,V_k 的每行是物品的 k 维隐向量。用户 u 对物品 i 的预测评分 = u 的隐向量与 i 的隐向量的点积。
模型压缩与蒸馏:全连接层的权重矩阵 W 做 SVD 后,用截断 SVD 近似:。原矩阵 m×n 的参数量为 mn,分解后为 k(m+n+1)。当 k << min(m,n) 时,参数量大幅减少。这在移动端部署大模型时非常有用。
PCA 的 SVD 实现:sklearn 的 PCA 底层不用特征分解而是用 SVD——对中心化后的数据矩阵直接做 SVD,右奇异向量 V 的列就是主成分方向。SVD 数值更稳定且不需要显式计算协方差矩阵。
向量空间与基
同一个位置,在 GPS 坐标系和北斗坐标系下的经纬度数值不同——但位置本身没变。向量也一样:同一个向量在不同基下有不同坐标。理解这一点,就理解了 PCA 降维和词嵌入空间的本质。
向量空间 = 一个集合,其中的元素(向量)对加法和数乘封闭。
封闭 = 空间内任意两个向量相加、或任意向量乘标量,结果仍在空间内。
基:描述空间的坐标尺,基是一组向量,用它们的线性组合可以唯一地表示空间中任意向量。
标准基:(1,0,0)、(0,1,0)、(0,0,1)——分别代表 x、y、z 轴方向。
线性无关:没有冗余,
一组向量线性无关 = 其中没有任何向量可以由其他向量线性组合表示。
直觉:每个向量都带来真正的「新方向」,没有浪费。
import numpy as np
# 标准基
e1, e2, e3 = np.array([1,0,0]), np.array([0,1,0]), np.array([0,0,1])
v = np.array([4, 5, 6])
print("v = 4*e1 + 5*e2 + 6*e3:", 4*e1 + 5*e2 + 6*e3)
# 用秩判断线性无关
v1, v2 = np.array([1,2]), np.array([2,4]) # v2 = 2*v1
M = np.column_stack([v1, v2])
print(f"{{v1, v2}} 的秩: {np.linalg.matrix_rank(M)} (< 2 → 线性相关)")
# 换基:同一向量,不同基下的坐标不同
v_std = np.array([3.0, 2.0])
B_new = np.array([[2.0, 0], [0, 3.0]]) # 新基
v_new = np.linalg.inv(B_new) @ v_std
print(f"标准坐标: {v_std}, 新基下坐标: {v_new}")
print(f"验证 B @ 新坐标 = {B_new @ v_new}")
输出:
v = 4*e1 + 5*e2 + 6*e3: [4 5 6]
{v1, v2} 的秩: 1 (< 2 → 线性相关)
标准坐标: [3. 2.], 新基下坐标: [1.5 0.67]
验证 B @ 新坐标 = [3. 2.]
AI 中的应用场景
PCA 降维 = 换基:PCA 找到一组新的标准正交基(主成分方向),使数据在新基的前 k 个坐标上方差最大。降维 = 只保留前 k 个新基坐标,扔掉后方差小的方向。这本质上是坐标系变换——从一个 784 维的像素空间换到 50 维的主成分空间。
词嵌入空间:Word2Vec 和 GloVe 将每个词映射到 300 维向量空间中的一个点。这个空间不是随意构造的——词与词之间的几何关系反映了语义关系。同义词距离近,反义词在某些方向上正好相反。向量空间中的线性运算(加减)对应语义操作。
特征空间变换:神经网络的每一层都可以看作将输入映射到一个新的向量空间。原始空间中线性不可分的数据(如 XOR 问题),经过隐藏层变换到特征空间后变得线性可分。这就是深度学习的核心直觉——逐层变换,最终在特征空间中用简单分类器即可分开。
导数/微分

设函数 在
邻域有定义,自变量增量
,函数增量:
若极限存在(函数连续不断裂),则称
在
可导,导数记作
:
等价写法:
微分 dy
,代表函数微小变化量,用直线(切线)近似一小段曲线,即以直代曲。
平时大家说 “求微分”“求导” 经常混用,做题时不严格区分;
导数几何意义 = 函数在该点切线斜率。
物理意义:瞬时变化率:速度、变化快慢。
|
分类 |
原函数 |
导数结果 |
示例 |
|---|---|---|---|
|
常数 |
|
0 |
|
|
幂函数 |
|
|
|
|
一次函数 |
|
|
|
|
自然指数 |
|
|
|
|
指数函数 |
|
|
|
|
自然对数 |
|
|
|
|
对数函数 |
|
|
|
|
正弦 |
|
|
|
|
余弦 |
|
|
|
导数的四则运算
| 公式 | 示例 |
|---|---|
练习1:
,求
答案:
练习2:已知函数 ,求
。
答案:
练习3:求函数 的导数。
答案:
练习4:已知 ,求
代码1:
import numpy as np
def f(x):
return (x**2 - 1) / (x - 1)
print("=== lim_{x->1} (x^2-1)/(x-1) = 2 ===")
# 从左右两边逼近
for delta in [0.1, 0.01, 0.001, 0.0001]:
print(f"x = {1-delta:.4f}, f(x) = {f(1-delta):.6f}")
print(f"x = {1+delta:.4f}, f(x) = {f(1+delta):.6f}")
print("→ 无论从哪边逼近,f(x)都趋近于 2")
输出:
=== lim_{x->1} (x^2-1)/(x-1) = 2 ===
x = 0.9000, f(x) = 1.900000
x = 1.1000, f(x) = 2.100000
x = 0.9900, f(x) = 1.990000
x = 1.0100, f(x) = 2.010000
→ 无论从哪边逼近,f(x)都趋近于 2
代码2:
import numpy as np
def numerical_derivative(f, x, h=1e-5):
return (f(x + h) - f(x - h)) / (2 * h)
f = lambda x: x**2
# f'(2) = 2*2 = 4
print(f"f'(2) 数值={numerical_derivative(f, 2):.6f}, 理论=4")
# 各点的导数
for x in [-2, -1, 0, 1, 2]:
d = numerical_derivative(f, x)
dir = "下降" if d < 0 else ("上升" if d > 0 else "水平")
print(f"x={x:2d}, f'(x)={d:5.1f}, {dir}")
输出:
f'(2) 数值=4.000000, 理论=4
x=-2, f'(x)= -4.0, 下降
x=-1, f'(x)= -2.0, 下降
x= 0, f'(x)= 0.0, 水平
x= 1, f'(x)= 2.0, 上升
x= 2, f'(x)= 4.0, 上升
代码3
import sympy as sp
x = sp.Symbol('x')
funcs = {'x^3': x**3, 'e^x': sp.exp(x), 'ln(x)': sp.log(x),
'x^2 + 3x + 5': x**2 + 3*x + 5}
print("=== 符号求导验证 ===")
for name, f in funcs.items():
print(f"f(x)={name:15s} → f'(x)={sp.diff(f, x)}")
# 乘积法则
f = x**2 * sp.exp(x)
print(f"\n(x^2 · e^x)' = {sp.diff(f, x)}")
# 链式法则:(2x+1)^3 的导数
g = (2*x + 1)**3
print(f"((2x+1)^3)' = {sp.diff(g, x)}")
AI 中的应用场景
梯度下降的一维原型:对于单变量函数,梯度下降退化为 。导数告诉你「往哪边走函数值会减小」——导数正就向左走,导数负就向右走。
激活函数的导数决定反向传播效率:ReLU 的导数:x>0 时为 1,x≤0 时为 0。计算极快,且正半区梯度不衰减——这是 ReLU 比 Sigmoid 更适合深层网络的关键原因。Sigmoid 的导数最大只有 0.25,多层相乘后梯度指数级衰减(梯度消失)。
损失函数在最优解处的导数为零:当模型收敛到局部最优时,损失函数关于所有参数的偏导都接近 0——梯度下降自然停止。这是训练收敛的信号:梯度范数 。
积分
积分的核心思想:无限分割、微小量累加,求一段区间内的总累积量;微分是细分看变化率,积分是汇总算总量,二者互为逆运算。
若函数 的导数等于
:即
则称 是
的一个原函数。
例:,所以
是
的一个原函数。
不定积分: (求导逆运算,求解原函数)
定积分: (区间[a,b]内曲线围成的净面积)
牛顿-莱布尼兹公式
例题1:计算
求解原函数
例题2:计算
求解原函 ,取
例题:用定积分求 在
与 x 轴围成的面积。
时
,面积等于定积分:
原函数:
牛顿–莱布尼茨公式代入上下限
结论: 在 0 到
之间与 x 轴围成的面积为 2。
例题3:球的表面积公式为 S = 4πr²,体积公式为 V = (4/3)πr³。体积求导就是表面积。
公式说明
- 半径 r:球心到球面任意一点的距离
- 直径 D:球的最大距离,D = 2r
- 表面积 S:球表面所占的面积,S = 4πr² = πD²
- 体积 V:球内部空间的大小,V = (4/3)πr³
公式推导概述
微积分法:将球体沿半径方向分割成无数个薄壳层,每层厚度趋近于零时,薄壳体积除以厚度即为表面积,积分求和得到体积公式。
梯度
一元函数一阶导数就是该函数的梯度
自动微分(Automatic Differentiation)TensorFlow 使用 GradientTape 来记录运算并自动计算梯度:函数: 解析导数:
,验证 x=2 时导数 = 14
x = tf.Variable(2.0)
with tf.GradientTape() as tape:
y = 3 * x**2 + 2 * x + 1
# 求dy/dx
dy_dx = tape.gradient(y, x)
print(f"计算导数:{dy_dx.numpy()}") # 输出14.0
print(f"解析解验证:6*2+2 = {6*2+2}")
多元函数梯度是各偏导组成的梯度向量
二元函数:
偏导数:
梯度为[]
取 x=1, y=2
x = tf.Variable(1.0)
y = tf.Variable(2.0)
with tf.GradientTape() as tape:
f = x**2 + 3*x*y + y**3
# 一次性求多个梯度
df_dx, df_dy = tape.gradient(f, [x, y])
print(f"df/dx = {df_dx.numpy()}") # 2*1+3*2=8
print(f"df/dy = {df_dy.numpy()}") # 3*1+3*(2^2)=15
# 梯度向量 [8,15]
import numpy as np
def f(x, y):
return x**2 + y**2 # 碗形函数
def grad(x, y):
return np.array([2*x, 2*y])
pt = np.array([1.5, 1.0])
g = grad(*pt)
print(f"在 (1.5, 1.0): 梯度 = {g}")
print(f"梯度模长 = {np.linalg.norm(g):.2f}")
print(f"梯度指向远离原点(上升),负梯度指向原点(下降)")
多元函数:,参数向量
梯度 是损失函数对所有参数的偏导数构成的向量:
代码:
import sympy as sp
x, y = sp.symbols('x y')
f = x**2 + x*y + y**2
print(f"f(x,y) = {f}")
print(f"∂f/∂x = {sp.diff(f, x)}") # 2x + y
print(f"∂f/∂y = {sp.diff(f, y)}") # x + 2y
# 二阶偏导
print(f"∂²f/∂x² = {sp.diff(f, x, 2)}") # 2
print(f"∂²f/∂x∂y = {sp.diff(f, x, y)}") # 1
# 线性模型损失对参数的偏导
w, b, xi, yi = sp.symbols('w b x_i y_i')
loss = (w*xi + b - yi)**2
print(f"\nloss=(w·xi+b-yi)^2")
print(f"∂L/∂w = {sp.diff(loss, w)}")
print(f"∂L/∂b = {sp.diff(loss, b)}")
输出:
f(x,y) = x**2 + x*y + y**2
∂f/∂x = 2*x + y
∂f/∂y = x + 2*y
∂²f/∂x² = 2
∂²f/∂x∂y = 1
loss=(w·xi+b-yi)^2
∂L/∂w = 2*x_i*(b + w*x_i - y_i)
∂L/∂b = 2*b + 2*w*x_i - 2*y_i
AI 中的应用场景
神经网络训练 = 百万次偏导计算:一个百万参数的模型,损失是关于百万个变量的多元函数。每轮训练,自动微分引擎对每一个参数求偏导,得到百万个偏导数值拼成梯度向量,沿负梯度方向更新所有参数。
冻结参数的迁移学习:迁移学习中常「冻结」预训练层——这些层的参数不求偏导、不更新。PyTorch 中设置 requires_grad=False,对应参数的偏导计算被跳过,大幅节省显存和计算量。
梯度下降算法
梯度下降是最小化损失函数的迭代优化算法,广泛用于线性回归、逻辑回归、神经网络。
一句话:沿着损失函数梯度的反方向,一步步更新参数,直到损失最小。
梯度方向 = 函数上升最快的方向,在一维平面函数中即为函数的导数,在二维或多维函数中为每个参数的偏导数所构成的向量。
目标:找到损失函数 最小值。它的函数图像如下:

损失函数对应的导数为
,当然只需要调用 gradient 方法即可得到。
通用梯度下降迭代公式: ,
:学习率(learning rate),控制每一步走多大。(梯度/导数越大,说明此时前进的步子越大,为了防止迭代步子太大超过极值使用
控制,梯度前加⼀个负号,就意味着朝着梯度相反的⽅向前进!我们在前⽂提到,梯度的⽅向实际就是函数在此点上升最快的⽅向!⽽我们需要朝着下降最快的⽅向⾛,⾃然就是负的梯度的⽅向,所以此处需要加上负号)
学习率 效果
太小 收敛极慢,需要很多步
适中 平稳快速收敛
太大 震荡甚至发散
极小值点 x=2 手动利用梯度迭代更新参数
x = tf.Variable(0.0) #从0开始找
lr = 0.2 # 学习率
epochs = 30 #迭代30次
for i in range(epochs):
with tf.GradientTape() as tape:
y = x**2 - 4*x +5
grad = tape.gradient(y, x)
# 梯度下降更新:x = x - lr * grad
x.assign_sub(lr * grad)
if i % 5 == 0:
print(f"迭代{i}, x={x.numpy():.3f}, loss={y.numpy():.3f}")
输出会逐步收敛到 x≈2,loss≈1。
迭代0, x=0.800, loss=5.000 迭代5, x=1.907, loss=1.024 迭代10, x=1.993, loss=1.000 迭代15, x=1.999, loss=1.000 迭代20, x=2.000, loss=1.000 迭代25, x=2.000, loss=1.000
import numpy as np
# 生成数据 y = 3x + 2 + noise
np.random.seed(42)
X = np.linspace(0, 10, 100)
y = 3 * X + 2 + np.random.normal(0, 2, 100)
# 从零实现梯度下降
w, b = 0.0, 0.0
lr, n_iter = 0.01, 200
losses = []
for i in range(n_iter):
y_pred = w * X + b
loss = np.mean((y_pred - y) ** 2)
losses.append(loss)
# 梯度
dw = 2 * np.mean((y_pred - y) * X)
db = 2 * np.mean(y_pred - y)
# 更新
w -= lr * dw
b -= lr * db
print(f"RUNOOB 梯度下降结果:")
print(f"真实: w=3.0, b=2.0")
print(f"拟合: w={w:.4f}, b={b:.4f}")
print(f"初始损失: {losses[0]:.2f} → 最终损失: {losses[-1]:.2f}")
RUNOOB 梯度下降结果:
真实: w=3.0, b=2.0
拟合: w=2.9874, b=2.2835
初始损失: 79.69 → 最终损失: 3.91

链式法则
2.复数乘法与欧拉公式
虚数单位
规定:,i 叫虚数单位。 实数范围内负数不能开平方,引入 i 后可以计算
。
复数标准形式
任意复数写成:
- a:实部,记作
- b:虚部,记作
都是实数
举例:
:实部 3,虚部 4
:实部 5,虚部 - 2
- 纯实数
,虚部为 0
- 纯虚数
,实部为 0
复平面(几何意义)
每个复数 对应平面上一个点
:
- 横轴:实轴(实数)
- 纵轴:虚轴(虚部) 这个平面叫复平面。
复数的模(到原点距离):

复数乘法(代数形式)
设两个复数:
乘法直接按多项式展开,再代入
化简:
例题 1:计算
例题 2 :纯虚数相乘
复数乘法的几何意义,极坐标形式
复数写成极坐标:
:模长
:辐角(与实轴夹角)

乘法几何法则
若
则
.....用到公式:两角和差:sin(A±B)=sinAcosB±cosAsinB,cos(A±B)=cosAcosB∓sinAsinB。
一句话总结几何意义:
- 模相乘:新模长 = 两个模长相乘
- 辐角相加:新角度 = 两个辐角相加
直观例子
乘以 i: 任意复数乘 i:模不变,辐角加
,相当于复平面上逆时针旋转 90°。
指数形式(欧拉公式)
由于导数节我们对函数 求导
,
导数恒为 0,说明 是常数。代入
:
,因此
,整理:
左边
:虚指数,不能用实数指数思维硬理解,它只是一个简写记号,等价于右边的三角函数复数。
- e:自然常数,约 2.71828,和实数指数
是同一个底数;
- i:虚数单位,
;
:弧度制角度(复数的辐角),实数;
举几个直观例子:
1.
2.(180°)
这就是著名的欧拉恒等式:(统一:
五大基础常数。)
3.(90°)
4.(270°)
欧拉公式验证代码
import os
import tensorflow as tf
# 统一 float64 精度
pi = tf.math.acos(tf.constant(-1.0, dtype=tf.float64))
x = pi
# 实部、虚部全部强制 float64
z = tf.complex(tf.constant(0.0, dtype=tf.float64), x)
# e^(ix)
left = tf.exp(z)
# cosx + i sinx
right = tf.complex(tf.cos(x), tf.sin(x))
print("e^(iπ) =", left.numpy())
print("cosπ + i sinπ =", right.numpy())
复数的指数形式
之前讲过复数三角形式: 根据欧拉公式
,直接替换括号里的部分:
- r:复数的模(长度,实数≥0);
:只负责描述方向(旋转角度),模永远等于 1;
举例: 复数 模
,辐角
指数形式:
指数形式下复数乘法
公式: 计算过程如下:
设两个复数:
第一步:分开实数部分和指数部分
实数 可以交换位置,先相乘;指数项放一起:
第二步:虚指数运算法则(和实数指数一样)
实数指数公式: 虚指数完全沿用这条规则:
第三步:合并得到乘法公式
文字翻译(对应之前几何意义)
- 新模长 = 两个复数模相乘:
- 新辐角 = 两个复数角度相加:
实操例题:设 求
。
再转回代数形式:
乘法核心性质
复数乘法五条性质与实数完全相同,有兴趣同学自行证明其过程。
- 交换律:
- 结合律:
- 分配律:
- 零元:
- 单位元:
补充一个关键用处:复数乘方(指数形式秒杀)
模取 n 次方,角度乘 n,也就是棣莫弗公式,比三角函数展开简单很多。 例:
余弦、正弦复指数展开
欧拉公式:
对任意实数 :
(式一)
将 替换为
,利用奇偶性:
(式二)
式一 与 式二 相加/相减即可推出:余弦、正弦复指数展开(积分 / 傅里叶变换必备)
欧拉分解:令余弦、正弦复指数展开中的x为
为虚数单位,时域三角函数等价正负频率复指数叠加。
基频
的含义
T:信号周期,完成一次完整波形所需要的时间(单位:秒 s)如:T=0.5 s 则对应频率 2 Hz
:频率,1 秒内完整波形重复多少次,
,单位 Hz
三角函数 里的
叫角频率,表示每秒转过多少弧度。一圈圆周是
弧度,所以:
。如:每秒转2圈说明频率 f =2 Hz,
对于周期为 T 的周期信号:
是这个周期信号自身最慢、最基础的振荡频率,对应完整波形转一圈的角速度。
傅里叶级数层面(最关键) 任何周期信号,都可以拆成:直流 + 基波 + 2 次谐波 + 3 次谐波 + …
- 基波:频率 =
,和原信号周期完全相同的正弦 / 余弦波;
- n 次谐波:频率
,速度是基波的 n 倍,周期
。
举例:
- 基波:
,周期
- 2 次谐波:
,周期
- 3 次谐波:
,周期
频谱层面 傅里叶级数的所有谱线频率只能是 ,
是频谱上两根相邻谱线之间的间隔,所以叫 “基频”。
实周期函数三角形式
周期 T,基频
含义:周期信号 = 直流 + 无数倍频正余弦叠加。
代入复指数展开,转复数傅里叶级数把 全部换成
:
合并同指数项:是复傅里叶系数,对应频率
的幅值相位,这就是复数形式傅里叶级数。
周期延拓间隔无限大 → 傅里叶变换(连续频谱)
傅里叶级数针对周期信号,频谱是一根根离散谱线; 令周期 ,信号变为非周期信号,离散谱线间距
,离散频谱变成连续曲线,就推导出傅里叶变换。
从级数系数过渡到傅里叶变换定义
傅里叶级数系数:
定义 ,替换
:
这就是连续时间傅里叶变换 CTFT。
逆变换(还原时域信号)
物理意义: 任意时域非周期信号,等价无穷多不同频率复指数
加权叠加,权重就是频谱
。
更多推荐



所有评论(0)