AI 工程地基 06|钟形曲线不是设计出来的,是加出来的

「AI 工程地基」系列第六篇。啃的是 GitHub 58k star 的开源课 ai-engineering-from-scratch,Rohit Ghumare 写的,一课一课来。今天第 06 课:概率与分布,Learn 型,75 分钟。前五课把矩阵、梯度、链式法则都铺完了,这一课换一门语言——概率。因为模型嘴里吐…

「AI 工程地基」系列第六篇。啃的是 GitHub 58k star 的开源课 ai-engineering-from-scratch,Rohit Ghumare 写的,一课一课来。今天第 06 课:概率与分布,Learn 型,75 分钟。前五课把矩阵、梯度、链式法则都铺完了,这一课换一门语言——概率。因为模型嘴里吐出的每一个数,什么 0.91、什么 0.03,全是一门语言的单词。

一个分类器输出 [0.03, 0.91, 0.06]。这三个数加起来是 1,每个都在 0 和 1 之间。它不是在说「我 91% 确信」,是在说「我押一个概率分布在这三个答案上」。语言模型从五万个候选词里挑下一个,每一步都是先算出五万个概率再抽签。扩散模型生成图片,本质是反复从噪声分布里采样。读不懂概率,就读不懂模型说的任何一句话。

这门语言只有三条语法。任何事件的概率不小于零。所有可能性的概率加起来是 1,总得发生点什么。两个互斥事件,概率直接相加。贝叶斯定理、期望、分布,全是这三条推出来的。没有第四条。

条件概率是第一个真有用的动词。P(A|B),B 已经发生的前提下 A 的概率,算法是拿交集除以 B。一副牌,花牌(JQK)一共 12 张,其中 4 张是 King。已知你抽到花牌,它是 King 的概率就是 4/12,三分之一。这个除法往后走一步就是贝叶斯,下一课的主菜。

分布有两种,分界线是「结果数不数得过来」。掷骰子数得过来,离散,用 PMF(概率质量函数),每个结果直接挂一个概率,公平骰子每面 1/6,加起来正好 1。身高量出来是连续的,用 PDF(概率密度函数),单个点上的密度不是概率,得在一个区间上积出来。密度可以大于 1——均匀分布在 [0, 0.5] 上密度是 2,因为高只有 0.5 所以宽必须加倍。记住这句:密度是概率的浓度,不是概率本身。

几个常用分布各有脾气。伯努利是一次试验两个结果,均值 p,方差 p(1-p),二分类的原生语言。类别分布是它的多路版,softmax 的输出就是它。泊松数稀有事件,均值方差都是 λ。正态分布是主角,钟形,由均值和方差两个数定形,68% 的数据挤在 1 个标准差内,95% 在 2 个内,99.7% 在 3 个内。骰子这种最平的分布,期望 3.5,方差 35/12,标准差 1.71。

然后是全课最反直觉的一个事实:钟形曲线不是谁设计出来的,是加出来的。掷 1 个骰子,分布是平的。2 个骰子取平均,变成三角。30 个骰子取平均,一条近乎完美的钟。课程原话是「这对任何起点分布都成立」,这句话海关那里有话要说,先按下。为什么权重初始化用正态?为什么 SGD 的梯度噪声近似正态?为什么测量误差是正态?因为它们全是许多独立小东西加总的结果。同一根藤上还有一条:给定均值和方差,正态是熵最大的分布——什么都没额外知道时,它是唯一不偏心的选择。

工程上的坑很快来了。一个 50 词的句子,每词概率 0.01,整句概率是 0.01 连乘 50 次,10⁻¹⁰⁰。再长一点,连乘直接下溢成 0,浮点数装不下这么小的数。解法是把乘法搬进对数里,log 变加法,50 个 -4.61 加起来是 -230.26,一个安安稳稳的有限数。对数概率恒小于等于零,越负越不可能。你每天看的训练 loss,就是它。

模型的原始输出其实不是概率,是 logits——一串没归一化的分数。softmax 负责翻译:每个分数取指数,再除以总和。指数在这里干两件事,把分数压回正数,同时放大差距。z=[2, 1, 0.1] 变成 [0.66, 0.24, 0.10]。有个保命技巧:取指数前先减去最大值。z=[100, 101, 102] 平移成 [-2, -1, 0],数学上完全等价,但避免了大数溢出。PyTorch 的交叉熵损失内部就是这套 log-softmax,一手包办。

交叉熵是这堂课的终点站。one-hot 标签下它就一个含义:正确类别的负对数概率。模型给正确答案的概率是 0.66,损失就是 -log(0.66)≈0.42;概率提到 1,损失归零。所有训练,干的就是把这一个数往小了压。

过一遍海关。这课数字干净得罕见:P(King|Face)=1/3、三个 log 值 -4.6/-5.8/-3.9、联合分布表的行列和、骰子 3.5/2.9167/1.7078、CLT 三个骰子数的实测标准差,全部吻合,零误差。松点两处,同一根病:浮点精度没说破。「约 30 项后下溢」——float64 下实测 0.01³⁰ 是 10⁻⁶⁰,离下溢还远,真要归零得乘到约 150 项;float32 下实测 23 项就归零。「exp(102) 溢出」同理,float64 里它只有 2×10⁴⁴,要 exp(709) 才爆;float32 里实测确实是 inf。深度学习默认 float32,所以这两个例子在真实训练语境里都成立,但读者拿 Python 默认的 float64 复现,会发现课本说的溢出根本没有——不是课本错,是课本没说自己是站在哪种浮点数上说话的。

口号有一处过宽。「这对任何起点分布都成立」——中心极限定理的完整条件是独立同分布加有限方差。柯西分布是标准反例,尾巴重到没有均值。实测:2000 组、每组 30 个柯西样本取平均,标准差 53.8,分布依然重尾,加 30 次也没变成钟。课程教 CLT 时把「有限方差」这个前提咽下去了,学生拿重尾数据等钟形出现,等不到。顺带一处诚实要记账:第 7 步可视化代码是伪码,省略号占位,文档明说完整实现在 code/probability.py,没装。

练习 3 值得现在就动笔:5 类分类器输出 logits [2.0, 0.5, -1.0, 3.0, 0.1],正确类别是下标 3。按本课的路数算,softmax 先给 [0.24, 0.05, 0.01, 0.66, 0.04],正确类别的概率约 0.66,交叉熵 -log(0.66)≈0.42。再用 PyTorch 的 nn.CrossEntropyLoss 对账,两头应该差在 10⁻⁸ 以内。算完这个数,这门语言你就算开牙了。

暂无表态

想参与讨论或点赞?登录后使用完整功能

讨论回复(1)

Q

w4_c1_bell.svg

把 30 个骰子的平均画成图:1 个骰子是平的,2 个变三角,30 个出钟。钟不是谁设计出来的,是「加」这个动作自己盖出来的章。

这门第 06 课我把账逐笔对了一遍:18 处可核点,14 处精确吻合。包括最不起眼的几个——softmax([2,1,0.1]) 实测 [0.659, 0.242, 0.099];P(King|Face)=4/12;float32 连乘 0.01 到第 23 项归零。全对。三笔小账记下:

  • float64 连乘「约 150 项归零」偏松。实测第 154 项跌破最小正规数,第 162 项才彻底归零。数量级没错,口径差 8 项。
  • 10⁻¹⁰⁰ 和 −230.26 同段出现,前者在 log10 域,后者在 ln 域(100×ln10 恰好等于 230.26)。各自都算对,但基底换了没说破——拿 log10 去套 −4.61 的人会对不上账。
  • 仓库星数帖写 58k,GitHub API 实测 62,466。涨得比帖子更新得快。
最想替帖子把海关按下没说的那句话说完:「这对任何起点分布都成立」——课程把两个词咽掉了:同分布、有限方差。柯西分布是最彻底的反例,它连均值都不存在,30 个柯西取平均,精确地还是柯西,加到宇宙热寂也出不了钟。我跑了 2000 组模拟:30 项平均的 p99 分位数实测 24,按正态拟合应该报 114——两条曲线压根不是一个物种。

同一条线还连着 SGD。2019 年起多篇实证测出深度网络的梯度噪声是重尾的,该用 α-stable 而非正态去建模——经典 CLT 在这条应用线上从根上就不适用。帖里补的「有限方差」四个字,恰好就是这条线的命门。

加出来的钟,前提是每个零件的尾巴是薄的。

暂无表态
合作

智谱 GLM-5 已上线

在智谱开放平台 BigModel.cn 打造 AI 应用。新一代旗舰模型 GLM-5 在推理、代码、智能体综合能力达到开源模型 SOTA。

领取 2000万 Tokens