说实话当我在学习笔记目录里看到deeplearningbook_002-2这个编号时第一反应是有点头皮发麻的。002 指的是那本经典深度学习教材的第二章而 -2 则意味着这一章被我拆成了两个部分来处理。前半部分线性代数还能靠矩阵乘法硬撑下去但到了概率论和数值计算这一段身边一起自学的人几乎走丢了一半。这个编号背后的内容本质上是在解决一个很现实的问题怎么把数学公式和深度学习模型真正对应起来。如果你能看懂我下面写的这些内容那你大概率能救回不少卡在第二章的朋友也能让自己从“背公式”切换到“用公式”的状态。这篇笔记适合正在系统读深度学习教材、却被第二章劝退的同学也适合想补一下概率论和数值计算底子的初学开发者。1. 002-2 是道坎概率论和数值计算为什么总在第二章卡人1.1 这篇笔记到底在聊什么先把这个编号翻译成人话。deeplearningbook_002-2在我这套笔记命名规则里002表示某本深度学习经典教材的第二章-2表示这一章的第二个学习包。第二个学习包的典型范围就是概率论的基础概念、常见分布、贝叶斯公式再加上数值计算里的溢出、梯度问题、条件数。很多人会觉得这部分跟“深度学习”关系不大因为翻开书全是公式看起来跟神经网络八竿子打不着。但恰恰是这些数学工具决定了后面几乎所有模型公式的来路。拿交叉熵损失来说它本质上就是极大似然估计取负对数拿 Dropout 来说它就是给神经网络的隐藏层注入随机性拿梯度消失来说它和反向传播里连乘的数值稳定性直接相关。所以这一包内容不是“背景知识”而是后面每一章的“弹药库”。我在整理这一包笔记时给自己定了一个原则每一个数学概念必须找到它在深度学习里的一个落点。如果找不到落点就先标记为“待应用”不强行背。这个原则帮我省下了很多无效记忆。1.2 为什么数学基础越急越学不进去第二章劝退不是因为内容有多难而是因为它和“训练模型”这个目标之间隔着一层窗户纸。你刚学会 sigmoid 和梯度下降满怀期待想看卷积神经网络结果翻开第二章全是随机变量、概率密度、期望、协方差大脑直接宕机。更麻烦的是很多人一上来就试图把每个公式从头推导一遍。推导本身没错但如果你连“概率分布到底在描述什么”这种直觉都没有推三步就会卡住卡住就会烦躁烦躁就会跳过跳过就会心虚最后变成“好像看完了又好像啥也没学会”。这是典型的完美主义反噬。我的破法是先鸟瞰再细读。鸟瞰的意思是先把这一章的大纲画出来搞清楚每一节在回答什么问题。概率论在回答“数据是怎么产生的”数值计算在回答“计算机算这些数学时为什么出错”。有了这个地图再往下走每一步都知道自己在哪里、要去哪里心态就稳很多。1.3 我采用的三条腿走路方案针对这一包内容我给自己搭了个学习方案核心是三条腿同时走路教材原文作为主线按顺序阅读但每天只看一到两个小节不贪多。建模视角每学一个公式立刻追问“深度学习里哪里用到了它”哪怕答案暂时模糊也要写下来。比如学到期望时就联想“损失函数在样本分布上的平均”。最小代码实验用 Python 把公式跑一遍哪怕只是一段十几行的 Numpy 脚本也能让公式从纸面上活过来。这三条腿缺一不可。只读教材容易走神只做实验容易丢了理论根基只追求建模关联容易消化不良。我会在后面第 4 章给出几个可以直接跑的最小实验现在先回到数学本身把概率论这块硬骨头嚼碎。2. 概率论深度学习中“不确定”的数学翻译2.1 随机变量和概率分布模型眼中的世界概率论一开始就讲随机变量很多人被这个名字唬住以为“随机变量”是什么高深的东西。其实它就是一个取值带有不确定性的变量。扔硬币的结果是随机的所以它是一个取值“正面/反面”的随机变量明天是否下雨是随机的它也是一个随机变量图像里的某个像素点、某个词在文本里是否出现同样可以建模成随机变量。在深度学习中随机变量最常出现的地方是数据生成过程。我们假设训练数据是从某个未知的真实分布里采样出来的。比如手写数字图像就可以看成从一个 28x28 像素空间上的分布里抽出来的样本。模型的训练目标就是逼近这个分布或者说学会这个分布的模式。你可能会问那神经网络输出的那个概率值是什么意思举个手写数字识别的例子模型对一张图片输出“是数字 7 的概率是 0.92”这个 0.92 本质上就是在条件分布 P(y|x) 上的一个估计。y 是类别标签x 是输入的图像条件概率描述的是“已知图像 x 时标签取某个值的概率分布”。所以随机变量和分布这两个概念是理解分类、生成模型、强化学习所有后续内容的地基。2.2 联合概率、条件概率和贝叶斯公式掌握推理的杠杆这三个概念在一起构成了概率推理的核心骨架。联合概率 P(A,B) 说的是 A 和 B 同时发生的概率条件概率 P(A|B) 说的是在 B 已发生的前提下 A 发生的概率。两者之间有一个简单的换算关系P(A,B) P(A|B)P(B)也可以写成 P(A,B) P(B|A)P(A)。这两个表达一结合就得到了贝叶斯公式P(A|B) P(B|A)P(A) / P(B)很多初学者把贝叶斯公式当成一个需要死记的公式其实它说的是一件非常自然的事用新的证据去更新你对一件事的原有看法。P(A) 是你看到证据前对 A 的信念叫先验P(A|B) 是你看到证据后对 A 的信念叫后验P(B|A) 是“如果 A 是真的那么 B 有多可能出现”的解释力。写到这里必须插一句我自己的体会贝叶斯公式一开始记混是正常的。我当时是画了一棵事件树才把它彻底搞明白的。先画 A 的两个分支A 发生和 A 不发生再在每条分支下画 B 发生和不发生然后去看 B 发生的那一列你会发现 P(A|B) 的分子正好是“B 发生时且 A 发生”的那一条路径而分母是所有“B 发生”的路径总和。对照树图一目了然比干记公式牢得多。在深度学习里贝叶斯视角最直接的应用是贝叶斯神经网络和模型不确定性估计。不过在入门阶段你只要把“先验-似然-后验”这个结构记在心里就够了后面学到正则化时你会再遇到它。2.3 期望和方差模型评估的度量标准期望和方差这两个词在概率论里出现得极早也极容易被一笔带过。但它们是理解“模型好不好”的核心。期望在离散情形下就是加权平均E[X] Σ x P(x)。它描述的是一个随机变量“平均来看”会取什么值。放到深度学习里损失函数在数据分布上的期望就是所谓的期望风险。我们训练模型时做的本质上就是希望找到一组参数让这个期望风险尽量小。当然现实中拿不到真实分布只能用训练数据上的经验分布去近似所以有了经验风险最小化也就是大家常说的把训练集上的平均损失降下去。方差描述的则是随机变量的离散程度Var[X] E[(X - E[X])^2]。它回答的是“这个随机变量的取值稳定不稳定”。在模型训练里方差对应的是“模型在不同数据子集上表现一致不一致”。一个模型在训练集上表现很好、在验证集上一塌糊涂从概率视角看可以理解为它把训练集的噪声也学进去了导致在新样本上的随机误差很大。这个问题后面会用一个更具体的词来描述过拟合。我自己理解期望和方差时用过一轮骰子模拟实验跑了 100 万次掷骰子然后计算均值和方差看到它接近理论值的那一刻才真正意识到“概率论说的不是某一个具体结果而是大量重复后的统计规律”。这个直觉特别重要因为深度学习中几乎处处都在和“统计规律”打交道。3. 数值计算学习算法稳定的隐形地基3.1 溢出与下溢为什么深度学习模型经常 NaN这一节的内容常常被初学者跳过但训练过模型的人基本都遇到过这种场景loss 突然变成 nan前几分钟还好好的突然整个训练崩了。很多时候问题就出在数值溢出上。计算机里的浮点数是有上限的单精度 float32 的最大值大约是 3.4e38超过这个范围就会变成 inf再做运算就可能变成 nan。深度学习模型里最常见的溢出场景是 softmax。softmax 的公式是 e^{x_i} / Σ_j e^{x_j}如果输入里有几个数是 1000那 e^{1000} 直接超出表示范围算出来就是 inf / inf结果是 nan整个损失函数直接炸掉。解决办法并不复杂而且是有严谨数学依据的。softmax 对输入同时减去一个常数结果不变因为分子分母同时缩小了同样的倍数。实际实现里通常减去输入的最大值这样最大指数就变成 e^0 1所有指数项都在一个安全的范围内。这个技巧叫 log-sum-exp 的偏移实现是模型稳定训练的标配。我第一次在自定义网络里跑 softmax 时没做这个处理loss 在第几千步突然变成 nan排查了一个下午。后来把所有中间结果打印出来才发现是 logits 里出现了几个上千的极端值。这个坑踩过之后我写任何带 softmax 的模块第一行都会习惯性地先减 max已经成了肌肉记忆。3.2 梯度消失与梯度爆炸训练不动的元凶梯度问题在深度学习教材的数值计算章节里会有一个数学层面的解释通常和矩阵的特征值有关。反向传播的本质是把损失函数对每一层参数的导数通过链式法则一层一层传回去。这个过程里会出现很多矩阵乘法。如果这些矩阵的特征值普遍大于 1乘的次数多了梯度就会指数级放大变成梯度爆炸如果特征值普遍小于 1梯度就会指数级衰减变成梯度消失。这个“指数级”三个字是关键。深度网络的层数只要到了几十层哪怕每一层只乘一个 0.950 层之后就是 0.9 的 50 次方大约是 0.005梯度已经小得几乎不更新反过来如果每层乘 1.150 层后就是 117 倍直接爆炸。之前看到很多初学者在这块的反应是“那我不用深层网络不就行了”。说的没错但你迟早要面对 transformer、残差网络这些深层结构所以这个知识点跑不掉。后面你会学到 ResNet 的残差连接、注意力机制里的缩放点乘、各种归一化层它们本质上都在和“让梯度在深层网络中保持稳定”这个问题搏斗。现在在数值计算这一节理解了这个根子后面看到那些结构时会有一种“原来你是在解决这个问题”的感觉。3.3 条件数与病态问题优化器在这里“晕头”条件数是数值计算里一个重要但容易被忽略的概念。它描述的是一个函数对输入变化的敏感程度。条件数太大的问题被称为病态问题意思是输入稍微变化一点输出就会产生巨大的波动。放到深度学习里条件数大对应的是**优化曲面特别“狭长”**的情况。你可以想象一个碗正常碗是圆的梯度方向四面八方都一样病态问题的碗是一个特别扁的椭圆沿着长轴方向梯度很小沿着短轴方向梯度很大。梯度下降在这个椭圆上会来回震荡更新路径像在走“之”字形明明看着在下降速度却慢得离谱。这就解释了为什么后来需要引入动量、自适应学习率这类优化器。它们本质上就是在“不同方向的梯度尺度差异很大”的场景下做一种补偿和平衡。AdaGrad、RMSProp、Adam 这些名字后面藏的其实是同一个问题。所以你在数值计算这一章里提前知道了病态条件这个概念后面读优化器章节会轻松很多否则你会觉得 Adam 那套方均值更新规则像是在变魔术。4. 实操用代码和笔记把数学“焊接”到模型上4.1 从理论到代码最小概率模型模拟这一节我会给你几个可以直接跑的实验脚本配上对应概念。第一个实验用来建立“期望和方差”的直觉。你可以用 Numpy 模拟掷骰子看看实际统计值和大数定律的关系。import numpy as np np.random.seed(42) samples np.random.randint(1, 7, size100000) theoretical_mean 3.5 theoretical_var 35 / 12 # 均匀分布离散情形的方差公式 empirical_mean samples.mean() empirical_var samples.var() print(f理论期望: {theoretical_mean:.4f} 实际均值: {empirical_mean:.4f}) print(f理论方差: {theoretical_var:.4f} 实际方差: {empirical_var:.4f})跑完你会发现实际均值和方差非常接近理论值但不会完全相等。这就是统计规律的本质样本量越大越接近但单次采样永远有随机性。我把这个脚本跑过很多次每次看到结果都在提醒自己深度学习里用一批数据去估计梯度本身就是一个带随机性的估计所以训练过程的 loss 曲线有波动是正常的不用一看到波动就慌。第二个实验模拟条件概率和贝叶斯。我之前写过一个极简的“人群患病检测”模拟器用来理解“检查阳性不代表一定患病”这件事。这个经典例子比任何公式都更能帮你记住贝叶斯公式的分母在做什么。import numpy as np population 100000 disease_rate 0.01 false_positive_rate 0.05 true_positive_rate 0.99 has_disease np.random.rand(population) disease_rate test_positive np.zeros(population, dtypebool) # 患病且检测阳性 test_positive[has_disease] np.random.rand(has_disease.sum()) true_positive_rate # 未患病但误报阳性 test_positive[~has_disease] np.random.rand((~has_disease).sum()) false_positive_rate positive test_positive.sum() positive_and_disease (test_positive has_disease).sum() print(f检测阳性人数: {positive}) print(f阳性确实患病比例后验: {positive_and_disease / positive:.4f})这个结果通常会让你吃惊即使检测准确率高达 99%真正阳性的概率也可能不到 20%。原因就是人群里患病的人本来就少误报基数太大。跑完这个实验P(A|B) 的分子是“真阳性”分母是“所有阳性”这个结构就再也忘不掉了。4.2 数值计算演示稳定 softmax 的实现第三个实验复现 softmax 下溢问题然后验证减最大值这个技巧。import numpy as np def softmax_bad(logits): exp np.exp(logits) return exp / exp.sum() def softmax_stable(logits): shifted logits - np.max(logits) exp np.exp(shifted) return exp / exp.sum() logits np.array([1000, 900, 800, 990]) print(不稳定版本:, softmax_bad(logits)) print(稳定版本:, softmax_stable(logits))不稳定版本一跑就是nan或者inf/inf的警告稳定版本则输出一个概率向量。你可能会想减掉最大值后结果真的和原来一样吗数学上确实是恒等的因为分子分母同时除以了 e^{max}。但代码上这一个小改动决定了训练会不会突然崩溃。我强烈建议你在自己的项目里主动写一次这种“出问题版本”的代码亲眼目睹 nan 是怎么来的。有过一次触发 nan 的完整经历你对“数值稳定性”五个字的理解会超过看十遍书。这也是我把这个实验放进笔记里的原因。4.3 我的笔记模板和复习节奏代码实验做完之后还有一个很重要的问题数学知识太多怎么记笔记才能不变成抄书我的做法是给每个概念建一张“概念卡”每张卡固定四个区块一句话直觉、数学表达、深度学习落点、易错点。一张典型的概念卡长这样一句话直觉牛顿第二定律有很多近似期望就是大量随机实验结果的平均中心。数学表达E[X] Σ x P(x)深度学习落点交叉熵损失可以被理解为模型在真实数据分布上的负对数似然的期望近似。易错点期望的线性性 E[aXb]aE[X]b 永远成立但方差没有线性性Var[aXb]a²Var[X]很多人把系数直接提出来导致算错。四块写完这一张卡就算过关。如果哪一个区块写不出来说明这个知识点还没被消化我会重新回去看书而不是硬着头皮往后面翻。复习节奏我采用的是间隔重复大致节奏是当天学完复习一次第二天复习一次三天后复习一次一周后再复习一次。听起来占时间但每次复习只需要 10 到 15 分钟而且因为笔记里写的是“自己脑子里的话”复习效率比重新翻书高得多。这套方法帮我扛过了整本教材前面最枯燥的章节。5. 自学者最常踩的五个坑及排除方法5.1 背公式不等于理解数学三种记忆方式对比我在带人自学的时候发现一个特别普遍的做法把公式抄下来然后反复默写。这种纯机械记忆在数学学习里几乎毫无用处因为公式是用来推导和应用的不是用来默写的。我自己的对比经验是默写公式一周后基本就忘了但用“一句话直觉几何图像代码实验”三合一记忆三个月后还能给别人讲明白。举一个典型例子很多人背过方差的公式 Var[X] E[X²] - (E[X])²。如果你只是默写考试时很可能会把符号记反。但如果你知道它的直觉含义——方差是“偏离均值的平均平方”——你马上就能从定义式 Var[X] E[(X-E[X])²] 一步一步推到这个简写形式。所以我给自己定的规矩是教材里的每一个公式先看它从哪里来、代表什么直觉再谈记忆。5.2 矩阵和概率对不上模型尺寸标注法另一个高频问题是符号和模型对不上。书上用大写的 X 表示随机变量用粗体 W 表示权重矩阵初学者经常搞混。我用了一个笨但有效的办法在笔记里给每个符号标注尺寸和含义。比如权重矩阵 W 就写清楚“W 形状是 [输出维度, 输入维度]”样本 X 就写清楚“X 形状是 [批量大小, 特征维度]”。这样在学线性层时你会直接写下 y Wx b 然后标尺寸x 是 [D_in]W 是 [D_out, D_in]y 是 [D_out]一看就知道矩阵乘法为什么是 W 在前。概率符号同理P(y|x) 就写上“给定 x 时 y 的概率x 是条件y 是随机变量”。养成这个习惯之后你再看到任何公式第一反应都是“它输入什么形状、输出什么形状、形状怎么变”数学公式就不再是一堆风干符号了。5.3 完美主义拖延用九十一原则在啃这一章时我还遇到过一个问题总想把每个定理的证明都看懂再往下走。结果经常是看一个证明用了两小时看完还不确定自己有没有看懂第二天就放弃了。后来我给自己定下一个“九十一原则”90% 的精力放在理解核心概念和直觉上10% 的精力放在推导细节上。如果一个证明暂时看不明白就先用红笔标注“此处待回补”跳到后面的应用小节。这个原则帮我绕开了很多无意义的卡死。等到后面在实际模型里用到某个定理时再回头去看会突然觉得自己能看懂了。这是因为数学证明只有在你知道结论有什么用之后它的每个步骤才有意义。我之前在贝叶斯公式的证明上卡了两天后来在概率模拟实验里用了三分钟就再也不想纠结那个证明了。5.4 如何判断自己真的学会了费曼测试学完一个概念最有效的自测方法不是我上一节说的默写公式而是费曼测试能不能用大白话把“期望是什么”讲给一个完全没学过概率论的人听并且让他听懂如果能说明你真的懂了如果不能说明你还在靠术语填窟窿。我每次学完一小节都会在手机备忘录里用语音给自己录一段 60 秒以内的解释然后重新听一遍。这个习惯听起来有点傻但它非常管用。当你发现自己在解释里频繁用到“就是那个……你懂吧”这种话时其实就已经暴露了理解漏洞。这时候不要急着往下学回去把漏洞补上效果远好于刷十遍笔记。5.5 多线作战策略教材、课程、代码怎么安排最后一个坑是学习资源太多反而造成瘫痪。有人既买了教材又收藏了一堆视频课还同时想上 Kaggle 刷比赛结果哪条线都没走完。我自己的经验是以教材为主线视频只用来消化学不懂的特定章节代码实验作为课后作业。这三个角色不能反过来。具体到第二章我的节奏是早晨看教材一小节并做笔记下午写 20 分钟的 Numpy 小实验验证公式晚上用十分钟做费曼测试。一周大概推进两个小节听起来慢但因为我中途没有反复“推翻重来”实际两个月后已经能把“概率论和数值计算”相关的数学基础讲得明明白白。这个速度反而比那些一周硬啃五章的人快得多。写在最后这一章之后你会获得什么如果只看教材的目录002-2 这个编号覆盖的内容就是概率论基础和数值计算听起来平平无奇。但等你真正把这一包内容消化完再回到深度学习的主线会发现到处都是熟悉的影子softmax 不会让你觉得只是查表用的函数交叉熵不再是天外飞仙Adam 优化器也不再是黑洞一样的黑盒。你会开始理解模型训练过程中各种 nan、震荡、不收敛的现象背后的数学来源。我个人把这一段经历总结成一句口诀不确定的世界用概率描述不稳定的计算用数值方法稳住。概率论帮你建模问题、评估效果数值计算帮你把模型真正跑起来。两者一起才是深度学习中“做实验”和“调 bug”的共同地基。如果你也正在啃这一章我给你一个最踏实的建议别急着看完。谁先在后边代码里碰到了 nan谁再来读这一章最合适。现在没遇到也没关系先扎扎实实把一张张概念卡做出来等到采坑那天你会感谢自己当时多花的那一周。