ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

机器学习中的数学:从线性代数到梯度下降,核心概念一次厘清

机器学习中的数学:从线性代数到梯度下降,核心概念一次厘清

很多人一提到机器学习就头大,总觉得满屏的数学概念是最大的拦路虎。我一开始也一样,看到矩阵、导数、概率密度这些名词,第一反应是“是不是得先回炉重读三年高数”。但真正做了几个项目之后才发现,机器学习里的数学并不是让你去当数学家,它更像一套工具箱:你只需要知道每个工具是解决什么问题的、什么时候该用哪一把,以及怎么把它拧到代码里去。这篇文章就是围绕机器学习涉及的数学概念做一次系统梳理,讲清楚它们到底做什么、为什么非用不可、以及新手最容易在哪个环节把概念学拧巴。不论你是准备入行的初学者,还是调过很多模型但总觉得“基础不够扎实”的实践者,这篇文章应该都能帮你把零散的知识点串成一条线。

1. 机器学习里的数学,不是门槛而是语言

先讲一个很多人没意识到的点:机器学习本质上是在“用数据做推断”。你给模型一堆例子,它要从例子里面总结出规律,再用这个规律去预测没见过的新数据。为了干这件事,你必须有办法描述数据的样子、描述规律、描述预测的好坏。数学就是这套描述语言。你不用会证明定理,但得能看懂公式在说什么、每个符号代表哪个概念。

1.1 数学在机器学习里到底承担什么角色

如果把这套语言拆开看,机器学习里反复用到的数学概念其实就四大块:线性代数、概率统计、微积分、信息论。它们分工非常明确。

线性代数管的是数据存放和变换。一张表里的每行是一个样本,每列是一个特征,这张表在数学里就是一个矩阵。你想对整批数据做同样的操作,比如缩放、旋转、投影到低维空间,用的都是矩阵运算。

概率统计管的是不确定性和推断。模型输出的很多时候不是“绝对答案”,而是“有多大的概率是A”。医学诊断、垃圾邮件过滤、语音识别,背后全是概率计算。这里还牵扯到怎么从一堆观测数据里反推模型参数,这就是统计推断要做的事。

微积分管的是模型怎么学习。学习过程本质上是“找一个参数组合,让损失函数最小”。要找到这个最小点,你得知道函数往哪个方向下降最快,这就需要梯度这个概念,而梯度就是把每个参数的偏导数拼在一起。

信息论管的是度量和判据。我们怎么量化“这个模型预测得有多差”?怎么衡量两套概率分布之间的差距?信息熵、交叉熵、KL散度这些概念就是干这个的。

把这四块放在一起看,会发现它们是配套使用的:你用线性代数把数据变成矩阵,用概率统计假设数据服从什么样的分布,用微积分去求解模型参数,用信息论评估结果靠不靠谱。每块都不需要很深,但每块都得知道它能干什么。

1.2 不同岗位方向的人,数学要学到什么程度

我经常被问到“我以后只想调参,是不是不用学数学”。我的回答是:调参也需要知道参数“参数”是什么意思。但不同路子确实深度不同,这里给一个务实的参考:

方向核心需要掌握的概念推荐深度
应用开发与调包矩阵乘法维度、梯度下降过程、训练集测试集划分、准确率与损失函数含义能看懂Loss曲线,能解释过拟合,能看懂常见报错里的维度信息
算法调参与特征工程正则化原理、交叉熵与概率输出、特征分布、降维思想能手动推导简单模型的正反向传播,能判断模型为什么训不动
模型研究与新算法复现完整线性代数、最大似然、链式法则、最优化方法能从头把一篇经典论文的公式逐步落到代码

不需要一上来就冲最难的部分,但也不能完全跳过。我见过太多人调了一年的学习率,却不知道学习率在梯度下降里到底作用在哪个位置;我也见过有人把损失函数换了好几种,却说不清交叉熵和平方误差的适用场景差异。数学概念的价值,恰恰是让你在遇到“模型不收敛”“训练集表现好测试集崩掉”这类问题时,能从原理层面定位,而不是瞎试。

2. 线性代数:一切数据表示的底层语言

线性代数大概是机器学习中出现频率最高、也最容易被忽视的数学概念。很多人以为它就是矩阵乘法的计算技巧,实际上它的核心是“用空间变换的视角看待数据”。

2.1 向量、矩阵、张量:别被名词唬住

向量就是一串有序排列的数。一个样本有若干个特征,比如房子的面积、房间数量、房龄,这三个数排成一列,就是一个三维向量。这个向量对应空间里的一个点,三维好直观,几百维也只是同一个概念的推广。

矩阵就是把多个向量堆叠起来。一个数据集有1000个样本、每个样本5个特征,那就是一个1000行5列的矩阵。你在代码里看到的 DataFrame,本质上就是在处理一个矩阵,只是包了一层更友好的外壳。

张量就是更高维的数据容器。灰度图是二维矩阵,彩色图片多了颜色通道,就变成三维张量;一批彩色图片摞在一起,就是四维张量。很多初学者被“张量”这个词吓到,其实你可以直接把它理解成“多维数组”,不用想什么玄学。

这里要强调一个容易被带偏的问题:数学里的列向量、行向量,和代码里的 shape 定义经常不一致。做矩阵运算的时候维度对齐错了,代码立刻报错。所以学线性代数,第一条就是养成“先看维度,再想含义”的习惯,每个矩阵运算前都问自己一句:这两个矩阵的 shape 分别是什么,乘出来是什么形状,每个维度代表什么意思。

2.2 矩阵乘法为什么到处可见

矩阵乘法之所以在机器学习里无处不在,是因为它能一次完成大量并行计算。传统写法用循环算1000个样本的加权和,效率低还容易出错;用矩阵乘法,一行就能表达:

import numpy as np # X: 1000个样本,每个样本5个特征 X = np.random.randn(1000, 5) # W: 5个输入特征映射到3个输出单元 W = np.random.randn(5, 3) # 一次性计算所有样本的线性变换结果 Z = X @ W # 形状是 (1000, 3)

这个操作背后就是线性代数里的“矩阵乘法”。它的规则是:两个矩阵能相乘的条件是左边矩阵的列数等于右边矩阵的行数。直觉意义是“左边矩阵提供数据,右边矩阵提供变换规则”,结果矩阵里的每个元素,是左边某一行的数据与右边某一列的参数做内积得到的。

内积就是对应位置相乘再相加。它天然适合用来表达“相似度”和“加权求和”。比如两个向量方向越接近,内积越大,这个性质被用在注意力机制里:查询向量和键向量做点积,得分高的位置就分配更多注意力权重。你表面上是在做“矩阵乘”,实际上是在做“相关性匹配”。理解这一层,再去看各种网络结构,会觉得很多设计其实都是一个套路。

矩阵另一大类用途是压缩和降维。把一个高维数据左乘一个低矩阵的投影,可以把它映射到低维空间,同时尽量保留原有差异。PCA主成分分析,本质就是找一组新坐标轴,让数据投影之后方差尽可能大。这里的坐标轴,就是协方差矩阵的特征向量,每个轴上的方差大小对应特征值。

2.3 特征值和特征向量:找数据的主要变化方向

特征值和特征向量是线性代数里最容易被当成“考试题”的概念,但在机器学习里它们有很直接的意义。特征向量描述的是一个变换下“方向不变、只被拉伸”的向量,特征值就是拉伸的倍数。

放到数据场景里,如果有一个矩阵描述数据之间的协方差关系,那么它的特征向量就是数据变化的主方向,特征值越大,说明数据在那个方向上变化越剧烈、信息量越大。PCA做的事情,就是把原始数据往这几个主方向上投影,扔掉特征值很小的方向,从而实现降维。

推荐系统里的矩阵分解,也可以用类似思路理解:用户-物品评分矩阵被分解成两个低维矩阵的乘积,低维空间里的每个维度,可以被解释成某种“潜在偏好方向”。所以线性代数的核心概念不是孤立的规则,而是让你理解“数据在空间里是怎么分布、怎么变换”的思考方式。

3. 概率论与统计:让模型学会面对不确定性

如果线性代数是骨架,概率统计就是血液。现实世界的数据不是确定性的,同一个特征组合可能对应不同结果,模型必须学会用概率的语言表达“有多大的信心”。

3.1 先验、似然、后验:三个词说清概率推断

概率论里最容易让人晕的三个概念是“先验概率”“似然”和“后验概率”。用一个例子就能说清楚:假设我们正在判断一封邮件是不是垃圾邮件。

先验概率是你在看邮件内容之前,对“这封邮件是垃圾邮件”的信念值。如果你统计过历史邮件,发现垃圾邮件占比30%,那这个先验就是0.3。

似然是“如果这封邮件真是垃圾邮件,那么它包含某些词语(比如‘免费’‘点击’)的可能性有多大”。这个值可以通过统计垃圾邮件里词频来得到。

后验概率是看到邮件内容之后,你对“这封邮件是垃圾邮件”更新后的判断。后验概率和先验概率相乘、再和证据归一化。你不需要记公式名,只要记住这个逻辑:先有初始估计,再用新证据去更新,最后得到修正后的结论。几乎所有分类模型的输出,都能从这个角度理解。

这个思路也解释了为什么朴素贝叶斯这一类算法能work:它把每个词出现的条件概率看成是相互独立的,虽然这个假设在现实里不完全成立,但它在很多场景下表现足够好,而且训练速度极快,适合做基线模型。

3.2 几类常用分布与它们出现的场景

分布描述的是“随机变量取各个值的概率规律”。机器学习里反复出现的分布其实就那么几个,每个对应一类典型场景。

伯努利分布是只有两种结果的分布,比如是否点击、是否为垃圾邮件。它只需要一个参数p,表示结果为“是”的概率。二分类模型输出层接 sigmoid,输出的就是一个伯努利分布的p值。

正态分布出现在误差分析、特征标准化、参数随机初始化等大量场景。它的形状像一口钟,大部分数据集中在均值附近,两端越来越少。很多模型假设误差服从正态分布,这个假设是“最小二乘法可以推出平方损失”的前提之一。

均匀分布是“每个值等可能”,常用于随机初始化和采样。你写代码时用 random 函数生成随机初始权重,本质上就是在均匀分布里抽样本。

除了这三个,还有指数分布用来建模等待时间、泊松分布用来建模计数,但在入门阶段用不到那么细。关键是记住:看到模型的输出层,要想一想它对应什么分布;看到损失函数,要能反向推断它隐含了什么样的概率假设。

3.3 最大似然估计:从概率反推参数

最大似然估计是连接概率论和损失函数的关键桥梁。它的思想很朴素:某个参数能让“已经观测到的数据”出现的概率最大,那这个参数就是最好的估计。

举个例子:你抛一枚硬币抛了10次,结果是7次正面3次反面。如果认为每次抛硬币正面概率是p,那么这10次结果出现的概率是 p 的7次方乘以 (1-p) 的3次方。我们把这个函数叫作似然函数,然后找来让这个函数取最大值的p,求导等于0就能解出,结果是0.7,也就是正面频率。这就是最大似然估计。

把同样的逻辑套到机器学习分类问题上:假设模型对每个样本输出一个概率预测,那么整批训练数据的似然就是所有样本预测概率的连乘积。连乘起来数值会很小,容易下溢,所以人们取对数把连乘变成连加,再取负号变成最小化问题。这一步推导下来,得到的正是交叉熵损失函数。这就是为什么很多分类模型选交叉熵而不选平方误差:它就是从“最大化观测数据概率”这个目标里自然而然地长出来的。理解这条链路,你就知道不是损失函数随便挑,而是每个损失函数背后都有一组概率假设。

3.4 过拟合的统计解释与正则化

过拟合在统计里有个很自然的解释:模型太复杂,把数据里的噪声也当成规律学进去了。从概率角度看,复杂模型有更多的自由参数,它的“先验空间”更大,更容易在有限样本上找到一套刚好拟合所有点的参数组合。

正则化就是在原来的目标函数后面加一个惩罚项,比如把权重平方和加进去,逼着权重不要长得太大。这从统计语言上讲,就是给参数增加了一个“先验约束”:我们希望参数偏好较小的取值。模型在拟合训练数据的同时,还要尽量满足这个先验,因此不那么容易钻到噪声里。很多调参经验背后的数学原理就在这里,L2正则化对应正态先验,L1正则化对应拉普拉斯先验,后者倾向于让很多权重变成零,于是起到特征选择的作用。

4. 微积分与最优化:给模型一个找最优解的方向

模型训练的本质是一次次最优化。你得有办法找到“让损失函数尽可能小”的参数组合。如果函数是简单的抛物线,初中生都知道求导找顶点;但机器学习里的损失函数是千万个参数的复杂函数,这时就需要梯度下降。

4.1 梯度不是一个神秘概念,而是下山的指南针

假设你站在一座山上的某个位置,目标是走到山谷最低点。你不需要知道整座山的地形,只需要感受脚下哪个方向是向下的、坡度最陡,然后朝那个方向迈一步,反复做。这个“当前点最陡下降的方向”就是负梯度方向,梯度本身是一个向量,它的每个分量是损失函数对某个参数的偏导数。

偏导数就是“其他参数不变时,只调整这一个参数,损失变化了多少”。把所有偏导合在一起,就得到梯度向量,它指示了上升最快的方向。我们为了找最小值,就往相反方向走,这就是梯度下降。学习率就是迈步子的幅度:步子太大会跨过山谷,步子太小则要走几万步才到底。

我学习的时候一直把“梯度”当成一个抽象符号,直到某次自己画了一个二维损失面,把梯度画成每次更新前的小箭头,才真正明白为什么参数老是被减去梯度乘以学习率。那个“减号”不是数学规定,是因为我们要逆着上升方向走。

4.2 梯度下降的三种形态与学习率选择

根据每次更新用多少数据来算梯度,梯度下降分成三种常见形态:

形态更新一次用多少样本特点
批量梯度下降全部训练样本方向稳定,但每次计算量很大,且容易卡在局部最小
随机梯度下降1个样本更新快,噪声大,容易跳出局部最小,但收敛路径很抖
小批量梯度下降一小批样本(常见32、64)实际训练基本都用这个,兼顾稳定性和速度

你以为选好优化器就完了?动手调过模型的人都知道,学习率才是最影响训练结果的那个超参数。学习率太大,损失曲线上下震荡甚至直接发散;学习率太小,损失下降慢到让人怀疑电脑坏了。常用的策略是先用默认值,再观察前几百步的损失曲线走向。

4.3 链式法则与反向传播:复杂函数求导的工程实现

神经网络是一个层层嵌套的复合函数:上一层的输出是下一层的输入。要对这种函数求导,用到的就是链式法则。公式看起来简单:复合函数导数等于外层函数导数乘以内层函数导数。但神经网络动辄上百层,逐层展开求导工作量是天文数字。

反向传播是链式法则的高效实现方式。它先做一次前向计算,把每一层的输出都存下来;再从最后一层往前,一层层计算损失对参数的偏导数。每一层只需要把误差“传回去”,不需要重复计算整条链路,因此计算量只是前向传播的常数倍。没有反向传播,深度学习不可能在现实中跑起来。可以说,神经网络工程化的起点不是某个网络结构,而是这个把一个课堂公式变成可计算程序的思想。

4.4 局部最小、鞍点与优化器为什么有意义

很多人以为梯度下降的对手是局部最小,实际更难缠的是鞍点。在高维空间里,损失函数经常出现某个方向是谷底、另一个方向是山峰的“马鞍”地形,梯度为零但并不是真正的极小值。参数走到那里就容易卡住。这就是为什么后来有动量法、自适应学习率优化器:动量让更新方向不只是当前梯度,还累积历史梯度的惯性,帮参数快速冲过平坦区域;自适应方法则给每个参数单独设置有效步长,让稀疏特征也能得到合适更新。了解这些背景后,再看各种优化器就不会一头雾水。

5. 信息论与模型评估:有度量才能判断好坏

模型训练过程依赖一个明确的问题:“这个预测到底比另一个预测好多少?”信息论提供了一套精确度量的语言。

5.1 信息熵:对“意外程度”的量化

信息熵衡量一个概率分布的不确定性。一个事件发生的概率越低,它一旦发生带来的信息量越大。你听到“太阳从东边升起”不会觉得获得了什么信息,但听到“今天股票大涨”就会很在意。如果一个系统里所有可能事件概率都很平均,它的熵就高,因为结果很难预料;如果一个系统几乎肯定总是出同一个结果,熵就接近0。

在分类问题里,如果某个类别的样本熵很高,说明类别混乱,不容易区分;如果一棵决策树切分后子节点的熵显著下降,说明这次切分带来了明确的信息增益。决策树的ID3算法核心就是选择使信息增益最大的特征来分裂,这就是信息熵在机器学习里的直接用法。

5.2 交叉熵与KL散度:预测与真实差多少

交叉熵衡量两个概率分布之间的差异程度。把它作为损失函数时,一个分布是真实标签的分布,通常是one-hot编码;另一个是模型输出的预测分布。训练过程就是不断调整模型参数,让预测分布不断接近真实分布。

KL散度是另一个常见度量,它描述“用预测分布去近似真实分布,额外需要多少信息”。从数学上看,KL散度等于交叉熵减去真实分布的熵。在模型训练时,真实分布的熵是常数,所以最小化KL散度等价于最小化交叉熵。这个等价关系解释了为什么分类模型训练时优化交叉熵就够了,不用额外计算更“复杂”的KL散度。

5.3 评估中的统计思想

很多人以为评估就是把数据随机切一刀、跑完算个准确率,但统计视角能帮你看得更远。随机切分背后的假设是训练集和测试集来自同一个数据分布,如果切分方式不对,比如按时间排序的数据里随机切,就会把未来的信息泄漏到训练集里,测试结果虚高。

方差和偏差的权衡也是评估里绕不开的统计概念。模型太简单,对训练数据都拟合不好,这是高偏差;模型太复杂,训练集表现极好但换批数据就崩,这是高方差。交叉验证能帮你估计模型在不同数据子集上的稳定性,本质上就是用多次采样来逼近“模型在所有可能数据上的表现”。

6. 学习路线与避坑心得

看了这么多概念,可能有人会焦虑:是不是得先把大学的数学课本全部啃完才能开始写模型?真不是。我见过最快入门的路径,是从一个小项目反向把需要的数学概念一个个钓出来。

6.1 别从课本啃起,用项目倒推数学需求

假设你接到一个图片分类任务,你要用到的数学概念链条大概是这样:图像是矩阵,这是线性代数;模型输出要转成概率,这是概率论;训练要最小化交叉熵,这是信息论;梯度更新要学习率,这是最优化。你不需要在第一天就学完全部,只需要顺着这条链往下追,遇到一个不会的查一个、弄懂一个。

我自己的习惯是“三遍法”:第一遍用框架把模型跑通,完全不管数学;第二遍把模型换掉几个关键组件,比如换损失函数、改优化器,观察行为变化;第三遍把某个组件自己手写一遍,比如不用框架的手动梯度计算。到了第三遍,很多之前背不下来的公式自然就内化了。

6.2 几个我踩过的坑

学习过程里最容易犯的错误,是把公式当成静态的背诵对象。比如矩阵乘法,光背“左矩阵列数等于右矩阵行数”没有用,你得真遇到过几次shape不匹配的报错,才能真正记住维度规则。我的建议是:每学一个概念,就做一个10行以内的代码验证,让数学计算落到真实数据上。

还有一个坑是忽略维度的直觉,只盯着标量公式。很多人看交叉熵损失公式时能理解每个符号,但不知道批量计算时真实标签和预测概率的shape分别是什么,结果在代码里transpose来transpose去,越搞越乱。先搞清楚数据流动时每个矩阵的形状,再回看公式,会容易得多。

我自己还踩过“只改学习率不观察曲线”的坑。学完梯度下降后,我理解学习率是步长,于是每次模型不收敛就调一次学习率,但从不画损失曲线。后来养成习惯:训练前先写一个最小循环,手动打印每一轮loss,很快就能从衰减速度判断出学习率该调大还是调小。这个习惯比任何公式都管用。

常见误区表现自查方法
只背公式不看维度代码里矩阵相乘总是报shape错动手写出每个中间张量shape,再执行乘法
只看损失不看概率含义对回归任务硬套交叉熵,结果飘了弄懂损失函数隐含的分布假设
盲目调学习率换数据集就崩打印前若干轮的loss曲线,看是发散还是收敛过慢
忽略数据泄漏测试集准确率虚高检查切分是否按时间或ID隔离,避免未来信息进入训练集

6.3 动手验证的小模板

最后分享一个我经常用来验证梯度下降理解的最小示例。用最简单的线性回归和平方误差,手动实现一轮参数更新,确认每一步都对应刚才讲的数学概念。

import numpy as np # 生成模拟数据: y ≈ 2x + 1 x = np.random.randn(100) y = 2 * x + 1 + 0.1 * np.random.randn(100) # 加上偏置项,构造 [x, 1] 的形式 X = np.stack([x, np.ones_like(x)], axis=1) # shape (100, 2) # 初始化参数 w = np.zeros(2) lr = 0.1 # 前向: 预测值 y_pred = X @ w # 损失: 均方误差 L = mean((y_pred - y)^2) loss = np.mean((y_pred - y) ** 2) # 梯度: 对w求偏导,注意这里出现X转置,是维度对齐的关键 grad = 2 / len(X) * X.T @ (y_pred - y) # 更新: 沿负梯度方向走 w_new = w - lr * grad

这个模板的每一步都能和前面章节对应上:矩阵乘法做批量预测,均方误差对应正态误差假设,转置是求梯度时维度自洽的关键,负梯度方向更新参数则是所有优化器的起点。把这段代码改一改、画一画loss曲线,比看十遍公式都管用。

学习机器学习的数学概念,最忌一口气贪多。我个人的做法是“每天早上只解决一个概念,用代码验证一遍,晚上睡前在脑子里把公式翻译成一句大白话”。比如“梯度下降”就是“朝下山最快的方向迈一小步”,“交叉熵”就是“预测分布和真实分布差多少”,“矩阵乘法”就是“一批数据同时做线性变换”。这些翻译一开始可能不够精确,但会随理解加深而逐步修正。等你能把一篇陌生论文里的数学公式,用这种“中文白话+代码形状”的方式重新讲出来,那些曾经劝退你的数学概念,就真的变成你手里的工具了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进