☰
机器学习与深度学习实战必备数学函数:从矩阵乘法到损失函数
2026/9/26 18:24:16 网站建设 项目流程

机器学习 & 深度学习里真正会用到的全部数学函数

干了这么多年机器学习,我特别理解一个现象:很多人兴冲冲买了“工程数学”“复变函数”的教材,咬牙啃完一大堆公式,结果打开PyTorch还是不知道torch.matmul和torch.mm到底有什么区别,更搞不懂模型里那些函数究竟在做什么。这个问题我一路上见过太多次了,所以想写一篇彻底务实的总结:把机器学习、深度学习里真正会用到的数学函数挑出来,讲清楚它们解决什么问题、长什么样、怎么用,顺便排掉一些课本里根本用不上的雷区。这篇内容适合所有准备入门机器学习、正在啃《机器学习》周志华或吴恩达课程、以及被深度学习课本PDF折磨得想放弃的读者,看完你会发现——真正要用的数学函数,比你想的少得多,也远比你想的好懂。

1. 从“学了不会用”到“会用不用学”的数学地图

1.1 为什么你在课本里学的函数,一大半用不上

我当年学《工程数学》的时候,光复变函数就折腾了小半个学期,留数定理、洛朗展开、保角映射背得滚瓜烂熟。后来做第一个深度学习项目才发现,这些东西在90%的机器学习场景里压根不会遇到。真正跟ML/DL强相关的数学,其实只有三个板块:线性代数里的运算函数、概率统计里的分布与估计函数、微积分里的导数与链式法则。剩下的什么偏微分方程、特殊函数、复分析,如果你不做通信信号处理、不做流体物理模拟,基本就是路人甲。

我见过不少初学者在“数学准备阶段”浪费了几个月,刷完一堆教材发现没提升,然后开始怀疑自己智商。其实问题不在智商,在于目标错位。我们学数学是为了能看懂模型、能调参、能定位bug,不是去参加数学竞赛。我后来给学生列过一个清单,凡是不在这张清单上的数学内容,一律不优先看,除非你的课题真的踩到了那个领域。这个决定帮我省下大量精力,也让学习曲线顺滑很多。

1.2 全景图:深度学习流水线里到底碰了哪些数学函数

先把大局说清楚。一个典型的机器学习流程是这样的:拿数据 → 预处理 → 设计模型 → 定义损失函数 → 用优化器迭代训练 → 评估 → 部署。这个流程里,数学函数各司其职:

  • 数据预处理阶段:标准化、归一化,要么是线性的缩放函数,要么是概率分布函数
  • 模型结构阶段:神经网络每一层都是线性代数运算(矩阵乘法、向量点积)加激活函数
  • 损失函数阶段:回归和分类各用各的函数,核心就是距离度量和概率度量
  • 优化训练阶段:梯度下降及其变体,背后的数学是导数、偏导数、链式法则
  • 评估解释阶段:准确率、召回率、F1这些指标,本质是概率与统计的计数函数

这张图你拿到手之后,再看任何一个深度学习项目,都不会再慌。因为你知道,无论模型叫什么名字、是CNN还是Transformer,深挖下去,里面能用的数学函数永远不会离开这张图的范围。我建议你把它当作“数学寻宝图”贴在屏幕边,遇到看不懂的公式先对号入座,看它属于哪个阶段,再去针对性学。

2. 数值与张量运算:一切模型的地基

2.1 矩阵乘法:所有神经网络都在反复做的事

如果你只能记住一个数学函数,那必须是矩阵乘法。全连接层的本质就是y = Wx + b,卷积操作在底层实现里也被翻译成矩阵乘法,Transformer的注意力机制核心就是QK^T矩阵相乘。可以说,深度学习框架里最忙的函数就是矩阵乘法,没有之一。

拿PyTorch举例,你会遇到torch.mm、torch.bmm、torch.matmul、@运算符。它们之间最大的差别是维度:mm只处理二维矩阵,bmm处理带批次的三维张量,matmul更灵活,能自动处理广播。我开始写代码时用mm报了一堆维度错误,后来干脆统一用matmul或@,世界就清净了。

千万别忽视矩阵乘法的维度匹配规则:两个矩阵相乘,左边矩阵的列数必须等于右边矩阵的行数,结果的维度是“左边行数×右边列数”。我见过大量bug,比如[32, 10]和[10, 64]相乘没问题,得到[32, 64];但[32, 10]和[32, 64]直接乘就会报错。这里建议你每次构建网络结构前,先拿笔把输入维度、权重维度、输出维度手算一遍。这是我至今保留的习惯——亲手算过一遍维度,比调十次debug高效得多。

2.2 范数:距离度量与正则化的幕后功臣

范数(norm)在机器学习里的出场频率极高,但初学者经常会忽略它。L2范数就是取向量每个分量的平方和再开根号,也就是我们熟悉的欧几里得距离;L1范数则是绝对值的和。它们差异很大:L2计算平滑、处处可导,梯度大小和值的大小成正比;L1在零点不可导,却天然倾向于把稀疏项压缩成0。

实际场景中,L2正则化(也叫权重衰减)是训练神经网络时默认的策略,它把模型权重压缩到较小范围,防止过拟合。L1正则化则常用于特征选择场景,比如你要从成百上千个特征里挑出真正有用的那几个,L1会自动把无关权重压成0,省心省力。我在一个CT图像孔隙三维重构项目里就吃过亏:没有正则化时模型在训练集上漂亮得很,一到验证集就崩,后来加了一层weight_decay=1e-4,直接稳了一大截。这个参数你现在可能还不熟悉,但迟早会用到。

代码里对应的就是torch.norm(x, p=2),p=1就是L1,p=2就是L2。向量x = [3, 4]的L2范数就是5,这个勾股定理的直观理解比背公式有用得多。

2.3 广播机制:想不到的“隐式数学函数”

严格来说广播不是数学函数,但它本质上是把不同形状的张量自动补齐成相同形状再运算,效果上像一个隐式的“扩展函数”。PyTorch里你如果想对一批数据每个样本都减去均值mean,通常会写成x - mean,其中x是[B, D],mean是[D]。如果没有广播机制,你需要手写循环把mean复制B份,极其啰嗦。

但广播也是一把双刃剑。它太“智能”了,一个人初学者最容易踩的坑就是:两个张量形状明明不合适,广播机制却悄悄帮你“凑合”了一下,结果逻辑全错但程序不报错。举个例子,[B, 1]和[B, D]相加,广播会把前者复制成[B, D]。这本是好事,可如果你本意是让[B, 1]分别跟[B, D]的每一列相减,最后得到了一个你自己都解释不了的矩阵。我的经验是:在关键运算前显式打印形状、显式用unsqueeze标出意图,宁可多写两行,也别让广播替你“做主”。

3. 激活函数:神经网络的“呼吸开关”

3.1 sigmoid和tanh为什么正在被淘汰

在深度学习早期,sigmoid几乎是所有神经网络的标配激活函数,公式是1 / (1 + exp(-x)),输出范围落在(0,1)之间。它的优点是便于把输出解释成概率,但有两个致命缺点:一是饱和区梯度几乎为0,深层网络梯度信号传不回去,训练直接“卡死”;二是输出不是零中心的,这会让上层输入的分布产生偏移。tanh把输出范围搬到(-1,1),解决了零中心问题,但饱和导致的梯度消失依旧存在。

在我实际训练多层网络时,凡是用sigmoid做隐藏层激活的基本都失败了,不是不收敛,就是收敛得极其缓慢。这个教训我觉得每个做深度学习的人都应该亲手体验一次——只有自己踩过,才会理解为什么ReLU成了默认选项。

3.2 ReLU家族:现在的绝对主力

ReLU(Rectified Linear Unit)实现极其简单:max(0, x),正数原样保留,负数全部截断为0。它计算快、梯度不饱和、在实践中效果非常好,所以成了默认激活函数的第一选择。但它也有个著名的坑:神经元“坏死”。如果某个神经元的所有输入都是负数,ReLU对它输出永远是0,梯度永远是0,这个神经元就再也活不过来了。

因此在实践里,针对ReLU的问题,几乎人手一个替代方案:Leaky ReLU在负数区给一个小的斜率(比如0.01),保证梯度不死;ELU在负数区用指数曲线平滑过渡;GELU结合了ReLU和概率思维,输出按输入概率做非线性变形,现在在BERT、GPT这些Transformer模型里很常见。做CV项目我会优先试ReLU或者Leaky ReLU,做NLP相关模型则直接用GELU,省心。

3.3 Softmax:把分数变成概率的神奇函数

分类网络最后一层通常接softmax。它将一组实数(logits)映射成一组和为1的非负数,公式是exp(x_i) / sum(exp(x_j))。它的妙处在于,通过指数运算把分数差距拉大,让最大的分数获得最高的概率,形成一个“概率分布”。你拿电影分类举例:模型对《唐人街探案》输出三个判分,比如喜剧类4.2、悬疑类5.8、动作类2.1,softmax会把它们变成比如[0.18, 0.74, 0.08],加起来等于1,这时候取最大概率对应的类别,自然就是悬疑。

实际工程里有个必须提的细节:指数运算在大数值下容易溢出。exp(100)计算机表示不了,所以几乎所有框架的softmax实现都先减掉最大值再算指数,数学上结果不变,数值上稳定得多。你自己手写时也务必做这个“减最大值”操作。

3.4 激活函数选型速查表

场景推荐激活函数一句话原因
默认隐藏层ReLU / Leaky ReLU简单高效,梯度不饱和
深层网络 + 残差GELU / Swish平滑,训练更稳
二分类输出层Sigmoid输出是(0,1),可直接当概率
多分类输出层Softmax输出各类概率之和为1
回归输出层线性(无激活)直接输出实数值

这张表我自己用了很多年,遇到新项目先按表选型,再根据实验结果微调。不要一上来就花哨,稳定优先。

4. 损失函数:模型训练方向的指挥棒

4.1 回归任务:MSE、MAE与Huber的取舍

回归任务是预测连续数值,比如房价、温度。最常用的损失函数是均方误差(MSE),公式是mean((y_true - y_pred)^2)。它每个样本误差取平方,所以对大误差的惩罚更大,这既是优点也是缺点——如果数据里有个离群点,MSE会把模型拽向那个异常值,整体被带偏。

平均绝对误差(MAE)取的是mean(|y_true - y_pred|),对大误差的惩罚相对温和,对离群点没那么敏感,训练更稳,但它的梯度是常数,收敛后期可能来回震荡。我实际工作中遇到过太多次“MSE训练出来的模型被几个异常标签毁掉”的情况,后来干脆在自己项目里默认用Huber Loss:误差小于阈值δ时表现像MSE(平滑可导),大于δ时表现像MAE(对离群点鲁棒)。在PyTorch里对应torch.nn.SmoothL1Loss,做回归检测类任务时我第一优先就是它。

4.2 分类任务:为什么交叉熵是默认选择

分类任务的默认损失函数是交叉熵(Cross Entropy)。它的数学形式是-sum(y_true * log(y_pred)),实际框架里通常和softmax组合使用,比如PyTorch的nn.CrossEntropyLoss。这个函数的核心是:对于正确类别,模型给出的预测概率越接近1,损失越小;越接近0,损失爆炸式增大。

这背后的原因值得稍微展开:你如果把分类模型的输出解释成“概率分布”,那么衡量两个分布差距的经典度量就是KL散度,而交叉熵正是KL散度去掉常数项后的等价形式。换句话说,交差熵不是一个拍脑袋想出来的函数,它就是概率论里衡量“预测分布 vs 真实分布”差异的标准答案。这也解释了为什么神经网络分类问题几乎全是它在扛。

实际写代码时,有个极常见的困惑:nn.CrossEntropyLoss内部已经带softmax了,所以你的模型最后一层直接输出原始logits就行,千万别自己先softmax一遍再传入,多此一举,还会导致数值不稳定。我在帮人排查代码时,这一个问题至少遇到过十几次。

4.3 自定义损失函数的通用套路

工程到后期,大家几乎都会根据自己的任务去定义损失函数。比如在医学图像分割里,交叉熵对“前景只占1%像素”的场景极不友好,模型很快学会输出“全是背景”拿低损失。这时候就要加Dice Loss,它直接度量预测区域与真实区域的交并比,公式是2 * |A∩B| / (|A| + |B|),对类别不平衡效果好得多。

自定义损失函数的一条铁律是:只要该函数在你的后端里处处可导,或者至少能在绝大部分地方可导、梯度能回传,你就可以直接写。神经网络训练靠的是“梯度下降”,不是“精确求解”,所以哪怕函数带一点不平滑也没关系,实践里也都跑得起来。若你正在做口腔疾病图像识别这类医学影像项目,一定要多研究Dice Loss和Focal Loss,它们在病灶像素只占很小区域的任务里,能救你于水火。

5. 概率与统计:懂分布你才算真懂数据

5.1 正态分布:机器学习的默认假设

数据科学里正态分布(高斯分布)是绝对的主角,公式虽然是个带exp的函数,但你不必背诵,只需要知道它的两个参数:均值μ和标准差σ。很多预处理操作背后都在跟你数据“是不是正态的”较劲。标准化操作z = (x - μ) / σ,其实就是把一个不确定分布的数据强行对齐到标准正态分布,让不同量纲的特征可以公平参与计算。

我早年在做图像分类时发现,把像素值从[0,255]直接喂给网络,训练又慢又不稳;改成先减均值再除标准差之后,收敛速度明显变快。这个操作的数学本质就是在把数据分布“摆正”。你不妨把每个特征想象成一把尺子,有的尺子量程0~1,有的尺子量程0~100000,标准化的作用就是把它们统统换算成同一个量纲。

5.2 极大似然估计:理解损失函数的一把钥匙

极大似然估计(MLE)是统计学的核心思想,也是理解MSE和交叉熵来源的高级视角。它的逻辑是:在给定观测数据的前提下,找到一组模型参数,使得“这些数据出现的概率”最大。你把这个思想展开,对正态分布做MLE,推出来就是最小化MSE;对伯努利分布(二分类)做MLE,推出来就是二分类交叉熵。所以交叉熵和MSE并非各自独立的规定,而是同一条概率原理在不同分布下的具体化身。

如果你读文献时看到“最大化对数似然”这个说法,别慌,它表达的就是我们正在训练模型时的目标,本质和最小化损失函数是同义词,只是差个负号而已。我曾经在教程里花了整整一章节讲这个推导,但最后学生的反馈都一致说:想通MLE之后,再看所有损失函数,都有一种“原来如此”的通透感。

5.3 贝叶斯公式的实际角色

贝叶斯公式P(A|B) = P(B|A)P(A) / P(B)在教科书里地位极高,在机器学习实际工程里应用却分两个极端。一方面,朴素贝叶斯分类器直接用它做分类,尤其在文本分类、垃圾邮件过滤这类场景中简洁有效;另一方面,在深度学习大行其道的今天,贝叶斯的身影更多是“思想”而非“直接计算”——比如贝叶斯优化做超参数调参,贝叶斯深度学习做不确定性估计。

我在做工程时对贝叶斯公式的定位是:不用刻意追求深究,但一定要知道它的存在和核心含义——当你看到新证据(B)时,要对旧信念(A)做修正。这个思维方式比公式本身更有用。遇到数据不均衡问题、冷启动问题时,你会自然想到“先验概率”这个概念,这就是贝叶斯思维在起作用。

6. 优化过程背后的数学核心:导数与应用技巧

6.1 梯度、偏导数、链式法则:反向传播的三件套

神经网络训练的数学内核是反向传播,而反向传播的三件套就是梯度、偏导数和链式法则。梯度是一个向量,它的方向指向函数值上升最快的方向;所以我们做梯度下降,就是往梯度的反方向迈步,让损失变小。偏导数回答的是“如果只动某个权重,其他权重不变,损失会怎么变”。链式法则回答的是“如果误差传过很多层,怎么逐层分配责任”。这三样合起来,就是框架自动求导工具backward()背后发生的事情。

你不用自己手算链式法则,框架都帮你做了。但你必须理解一个最核心的逻辑:只有函数处处(或几乎处处)可导,梯度才有定义,参数才能更新。这解释了为什么模型里处处是光滑函数——连ReLU这种带一个尖角的函数,在0点处不可导也没关系,工程上直接指定导数为0或1就行。

我在调试自己的模型时,最常用的排查手段之一就是“检查梯度”。如果发现某一层权重梯度为nan,那几乎必然是前向计算里有数值溢出;如果梯度全为0,那可能是激活函数饱和、学习率太离谱或者网络真的没在学。理解梯度就是理解模型的命脉,这一点我怎么强调都不为过。

6.2 学习率、指数移动平均与早停的数学直觉

优化过程里,除了梯度本身,还有几个“数学函数”天天在用。学习率是每次梯度下降迈的步子大小,太大直接发散,太小半天不收敛。指数移动平均(EMA)在优化器(如Adam)里极为重要,它本质上是对历史梯度做加权平均,公式是v_t = β * v_(t-1) + (1-β) * g_t,越近的梯度影响权重越大,β通常取0.9或0.99。这也让模型在梯度噪声大时还能稳定前进,不会被单个离谱的梯度带偏。

早停(Early Stopping)则是在验证集损失连续多个epoch不下降时主动结束训练,防止过拟合。它虽然没有复杂的数学公式,但本质上是在用“验证集上的函数值”做判断。搭配学习率衰减(StepLR、CosineAnnealingLR),模型的收敛曲线会好看很多。我每次训练都喜欢打印一张“损失-epoch”曲线,观察它是不是平滑下降。如果曲线像心电图一样乱跳,我会先查学习率是不是过高,再查批次大小是不是太小。

6.3 优化器的选择思路

目前主流优化器就是SGD(加动量)和Adam两大家族。SGD简单、稳定、需要手动调学习率,但对新手不太友好;Adam自适应调整每个参数的学习率,收敛快、好上手,是绝大多数场景的默认选择。如果你想要更高的精度上限,往往套路是先Adam快速收敛,再切回SGD+Momentum精调。这个技巧我在多个图像识别项目里用效果都很好。

Adam内部还有β1、β2两个超参数,默认0.9和0.999。这几个数字背后涉及一阶矩估计和二阶梯矩估计的指数移动平均。想深入理解的,可以去看原始论文,但工程上记住“默认值在多数情况下够用,不要乱动”就够了。很多初学者喜欢调优化器参数玩,我的建议是前期不要碰,把精力放在数据质量和模型结构上,收益大得多。

7. 踩坑与排查:数学函数在实战中的事故现场

7.1 数值不稳定的四大元凶

做机器学习和深度学习,最常遇到的“数学”问题几乎都跟数值稳定性有关。我总结成四大元凶:一是log(0),交叉熵里预测概率为0时,log直接爆炸,框架一般会加一个极小的epsilon来防止;二是除零,在Focal Loss或Dice Loss里分母可能为0,务必加平滑项;三是大数溢出,softmax不先减最大值会出现inf,前面已提过;四是梯度爆炸,深层网络梯度连乘后会极大,对应策略是梯度裁剪clip_grad_norm_。

每次我遇到loss = nan,心里默念这四个字:数值溢出。绝大多数情况下,检查数据里有没有NaN、检查log的输入是不是负数、检查分母是不是0,问题就能解决。这套排查顺序,我建议你打印在工位前。

7.2 常见问题速查表

现象可能原因排查/解决方向
损失是NaN学习率过大 / log(0) / 分母为0降学习率,检查输入数据,加epsilon
损失不下降学习率过小 / 模型未收敛 / 数据没归一化调大学习率,检查数据预处理
过拟合严重模型太强 / 数据太少 / 无正则化加weight_decay,加Dropout,扩数据
梯度全为0激活函数死区 / 初始化不好换LeakyReLU,检查权重初始化
训练震荡剧烈学习率过大 / batch太小降学习率,增大batch size
验证集突然变差学习率衰减策略不佳 / 过拟合早停,降低模型复杂度

这张表是我长期调试经验的浓缩版。遇到问题先别慌,对号入座,一次只改一个变量,这是我调试的黄金法则。同时改三个参数还能定位出问题,那是奇迹,不是常规操作。

7.3 我吃过亏的三个实操教训

第一个教训是:标准化必须在划分训练集和验证集之前只统计训练集的均值和方差,然后把这个均值和方差应用到验证集上。我早期写代码图省事,整份数据一起算均值方差,结果信息泄漏,验证集指标虚高,模型上线之后彻底翻车。这个错误在Kaggle竞赛里属于“新手必踩经典坑”,但做项目时很少有人提醒。

第二个教训是:自定义损失函数时,一定要先在一个很小的batch上跑一次前向和反向,看看梯度能不能顺利回传。我做过一个Focal Loss,写完之后直接上全量训练,三个小时过去loss纹丝不动,最后发现是某个分支把梯度截断了。从此之后,任何自定义层和损失函数,我都会先拿两个样本验证一遍,再上全量数据。

第三个教训是:不要把数学“造轮子”用在工程上。能用框架内置函数就绝不手写。有一次为了让代码看起来“更厉害”,我手写了softmax,结果忘记做最大值稳定化,训练到一半全线NaN。后来我接触的几乎所有大厂代码规范都明确写着:优先使用已验证的库函数,别自己重造数学轮子。这条规范我往后一直遵守,也推荐给你。

8. 实操建议:我建议你按照这个顺序来用数学函数

给刚开始接触的朋友一条可执行路径:第一阶段,先弄懂矩阵乘法、ReLU、softmax和交叉熵这四样,配合一个图像分类小项目,比如用CNN识别手写数字。第二阶段,再补上损失函数选型和优化器的差异,跑一个回归任务,比如预测房价,练MSE和Huber之间的手感差异。第三阶段,回头学概率统计的正态分布和MLE,这时候再去看那些损失函数背后的推导,会有醍醐灌顶的感觉。第四阶段,开始研究自定义损失函数、处理不平衡数据,顺便掌握梯度裁剪和正则化。整个过程里,你不需要再去碰复变函数,也不需要死记硬背任何公式,重要的是“看到数学能联想到代码里对应的那个操作”。

我个人在实际带项目过程中的体会是:机器学习也好、深度学习也好,数学真正的作用不是让你“算出来”,而是让你“看明白”。矩阵乘法让你理解维度为什么不对,链式法则让你理解梯度为什么消失,交叉熵让你理解分类为什么这么训练。这些数学函数,就像厨师手边的油盐酱醋——用熟了自然而然,不必背配料表,但少了任何一样,菜的味道立刻不对。最后再分享一个小技巧:当你面对一篇充满公式的论文时,不要从头读,先跳到实验部分找到他们用的模型和损失函数,然后回来看公式——所有公式都是为这两个函数服务的。看懂它们,整篇论文的骨架也就立住了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询