数学基础
这一课你将能做到
- 用向量和点积表达「加权求和」,并会用余弦相似度计算两道题的相似程度
- 用条件概率和贝叶斯公式解释「做对一道题之后,掌握概率怎么更新」
- 手写一个梯度下降循环,拟合一元线性回归,看着 loss 一步步下降
为什么要学
机器学习的三大支柱全是数学:线性代数负责「数据怎么表示」(一张做题记录表就是一个矩阵),概率负责「不确定性怎么量化」(掌握度本质上是个概率),导数负责「模型怎么变好」(梯度下降就是顺着导数下坡)。初学者不需要会手推公式,但必须建立这三个直觉——否则调参时不知道学习率是什么,面试时讲不清模型怎么训练。
好消息:这一课的每个概念都会立刻翻译成 Python 代码,数学在这里是工具不是考试。
先建立图像
点积 = 加权求和:
用户画像 [正确率 0.85, 用时 0.40, 题量 0.60]
权重 [0.6, 0.2, 0.2 ]
掌握分 = 0.6×0.85 + 0.2×0.40 + 0.2×0.60 = 0.71
梯度下降 = 下山:
╲
╲● ●当前损失位置
╲ ↘ 每步沿「最陡下坡方向」(负梯度)走一小步
╲_
‾‾\__ ← 山谷底部 = 最小损失
‾‾‾──__
跟着做
步骤 1:点积——把「加权求和」变成一行代码
import numpy as np
# 用户画像:[正确率, 平均用时(归一化), 做题量(归一化)]
user = np.array([0.85, 0.40, 0.60])
weights = np.array([0.6, 0.2, 0.2]) # 三项指标的重要程度
mastery_score = user @ weights # @ 就是点积
print(f"掌握度得分: {mastery_score:.2f}") # 0.71
user @ weights 等价于 np.dot(user, weights),等于 (0.6*0.85) + (0.2*0.40) + (0.2*0.60)。神经网络里每一层本质上都是一次大号点积。
步骤 2:余弦相似度——给题目找「相似题」
import numpy as np
def cos_sim(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
# 每道题用「知识点考察向量」表示:[循环, 集合, 多线程, 异常]
q1 = np.array([0.9, 0.8, 0.1, 0.2]) # 主考循环+集合
q2 = np.array([0.8, 0.7, 0.2, 0.1]) # 和 q1 很像
q3 = np.array([0.1, 0.2, 0.9, 0.8]) # 主考多线程+异常
print(f"q1-q2 相似度: {cos_sim(q1, q2):.2f}") # 0.99
print(f"q1-q3 相似度: {cos_sim(q1, q3):.2f}") # 0.27
余弦相似度只看方向不看长度,取值 -1 到 1,越接近 1 越相似。推荐系统「相似题推荐」、向量检索都是它的变体。
步骤 3:贝叶斯——做对一道题后,掌握概率怎么更新
# 先验:做题之前估计 P(掌握) = 0.5
# 条件概率:掌握了的人 P(答对|掌握) = 0.9;没掌握的人 P(答对|没掌握) = 0.3
prior = 0.5
p_c_m = 0.9 # P(答对|掌握)
p_c_n = 0.3 # P(答对|没掌握)
p_correct = prior * p_c_m + (1 - prior) * p_c_n # P(答对)
posterior = prior * p_c_m / p_correct # P(掌握|答对)
print(f"答对一道题后,掌握概率从 {prior:.2f} 更新为 {posterior:.2f}") # 0.75
这就是「知识追踪」的最简形式:每做一道题,用贝叶斯把掌握概率往真实水平修正一步。adaptive 出题系统的底层逻辑与此同源。
步骤 4:手写梯度下降——从 0 拟合 y = wx + b
import numpy as np
X = np.array([1, 2, 3, 4, 5], dtype=float)
y = np.array([3, 5, 7, 9, 11], dtype=float) # 真实规律 y = 2x + 1
w, b = 0.0, 0.0 # 从零开始猜
lr = 0.01 # 学习率:每步走多远
for epoch in range(200):
y_pred = w * X + b
error = y_pred - y
loss = np.mean(error ** 2) # 均方误差
grad_w = 2 * np.mean(error * X) # loss 对 w 的导数
grad_b = 2 * np.mean(error) # loss 对 b 的导数
w -= lr * grad_w # 顺着下坡方向更新
b -= lr * grad_b
if epoch % 40 == 0:
print(f"epoch={epoch} loss={loss:.4f} w={w:.3f} b={b:.3f}")
print(f"最终: y = {w:.3f}x + {b:.3f}") # 收敛到 y ≈ 2x + 1
运行后能看到 loss 从几百一路降到接近 0,w、b 收敛到 2 和 1。这 20 行代码就是所有模型训练的内核:算预测 → 算损失 → 算梯度 → 更新参数,循环。
讲清楚要点
- 向量和矩阵是数据的「容器语言」:一个用户画像是一行向量,一张做题记录表是一个矩阵,模型参数也是向量。把运算写成矩阵形式,代码短、底层还快(向量化)。
- 点积衡量「对齐程度」:加权求和、神经网络的线性层、相似度计算,底层全是点积。
- 条件概率 P(A|B) 有方向:P(答对|掌握) 和 P(掌握|答对) 是两个数,混用是最经典的概率错误。贝叶斯公式就是两者的换算器。
- 梯度是「多元函数的导数」:对每个参数分别求导,得到损失上升最快的方向;反方向走,损失就下降。
- 学习率决定训练成败:太大,一步迈过山谷来回震荡甚至发散(loss 变 NaN);太小,收敛极慢。0.001~0.1 是常用起点。
你可能会懵的地方
- 数学要学到什么程度才能开始机器学习? 够用就行:点积/矩阵乘法、条件概率/贝叶斯、导数和链式法则。特征值分解、协方差矩阵这些等到 ml-unsupervised 讲 PCA 时再回来补,带着问题学效率最高。
- 为什么文本相似度用余弦相似度而不用欧氏距离? 文本向量往往很长且稀疏,两篇长度差很多的文章方向可能一致(主题相同)。余弦只比方向,对向量长度不敏感;欧氏距离会被「文本长短」这种量纲差异带偏。
- 梯度下降只保证找到局部最优,为什么还敢用? 线性回归、逻辑回归的损失函数是凸的,局部最优=全局最优;深度网络虽然非凸,但实践发现局部最优通常也足够好,加上随机性和动量,效果稳定可用。
- 链式法则在机器学习里是干嘛的? 深度模型是函数套函数(一层套一层),反向传播就是用链式法则把「损失对最外层参数的导数」逐层往里传,从而算出每一层参数的梯度。ml-dl 会实际演练。
- 概率模型输出的 0.8 能当成「80% 把握」吗? 看模型。逻辑回归经良好校准后接近真实概率;树模型和未校准模型的分数只是相对排序用。涉及决策阈值时要做概率校准(如 CalibratedClassifierCV)。
错法对照
| 错法 | 问题 | 正解 |
|---|---|---|
| 上来就啃《统计学习方法》推导 | 推导脱离直觉,容易弃坑 | 先跑通代码建立直觉,再回头补推导 |
| 学习率设 1.0 还问为什么 loss 爆炸 | 步子太大直接发散 | 从 0.01 起步,看 loss 曲线调 |
| 把 P(答对|掌握) 当 P(掌握|答对) 用 | 条件方向搞反,结论完全错 | 贝叶斯换算后再用 |
| 特征量纲悬殊直接算点积 | 数值大的特征主导结果 | 先标准化(ml-preprocess 详讲) |
| 手写梯度下降忘了除以样本数 n | lr 对批量大小敏感 | 用 mean 而不是 sum |
卡点急救
- 手写梯度下降 loss 变成 NaN:学习率太大,先除以 10;还不行检查数据里有没有极端值。
- loss 下降极慢:学习率太小,或特征没归一化(X 范围 0~240 时梯度天然很小,先除以量纲)。
np.linalg.norm报错或相似度全是 1:检查输入是不是一维向量;全 1 说明向量没有区分度,看看是不是忘了减均值或特征选错了。
面试常问
- 讲一下梯度下降的原理。 目标是最小化损失函数。对参数求梯度(导数),沿负梯度方向以学习率为步长迭代更新,损失逐步下降;凸函数保证到全局最优,深度模型实践中收敛到足够好的局部最优。变体有批量/小批量/随机(SGD),深度学习默认小批量。
- 余弦相似度和欧氏距离怎么选? 关注方向/形状(文本主题、用户偏好)用余弦;关注绝对位置和尺度(地理坐标、已经归一化的特征空间)用欧氏距离。高维稀疏向量通常余弦更稳。
- 写一下贝叶斯公式并说个应用场景。 P(A|B) = P(B|A)·P(A) / P(B)。应用:自适应刷题系统,用先验掌握概率和「答对条件下各水平用户的答对率」,在每次作答后更新后验掌握概率。
自测三问
user @ weights在算什么?和神经网络哪一步对应?- 为什么 P(A|B) ≠ P(B|A)?贝叶斯公式怎么把两者联系起来?
- 学习率 0.01 时 loss 稳定下降,改成 1.0 会发生什么?
小结一句话
线性代数负责表示数据,概率负责量化不确定,梯度下降负责让模型变好——三个直觉建起来,后面的模型课就不虚。
延伸
- NumPy 官方文档
- 下一课:ml-python Python 与数据栈——numpy/pandas/matplotlib 三件套,处理真实做题记录。