☰
随机变量与概率密度函数:深度学习基石概念详解
2026/10/19 10:48:38 网站建设 项目流程

我最近在系统重读手边那本经典的深度学习教材,第三十七页,第三章第二节,整节讲的是随机变量。这个位置在目录里实在太不起眼了,夹在“概率论与信息论”那一章的前半段,很多人包括我第一次读的时候,翻一眼觉得“变量”两个字初中就见过,直接就翻到后面看卷积、看循环网络去了。结果没过多久就吃了亏——看输出层时被softmax的“概率解释”绕晕,看生成模型时被“从后验分布采样”这句话卡住,看变分推断时被一堆期望符号砸脸。这篇文章就是我回炉重读这一节时整理的笔记,把随机变量这个概念拆开揉碎,结合训练模型的真实场景,说清楚它到底是什么、离散和连续怎么区分、两套描述工具怎么读,以及新手最常掉进去的几个认知陷阱。适合正在硬啃教材但被数学符号劝退的入门读者,也适合想把自己基础补扎实的实践型开发者。

1. 一个被我翻过去的章节,后来却三次把我卡住

第一次读这一节的时候,我的真实感受是“就这?”。随机变量不就是个会变的数吗,初中就学过了。抱着这种心态,我把整本教材的第三章快速扫完,然后就冲进卷积网络、循环网络这些“看起来更刺激”的内容里去了。结果后面的日子并不好过,同一个基础概念反复把我拦在半路。这里把三次最典型的卡壳记录下来,如果你也有类似经历,说明该回头补课了。

1.1 第一次卡住:softmax的输出到底算不算概率

训练分类模型时,最后一个线性层之后通常会接一个softmax,把一堆logits压成十个加起来等于1的数。我一开始把softmax单纯理解成一个“归一化工具”,觉得它只是让分数好比较一点。直到看到交叉熵损失公式里出现log q(x),我才意识到事情没那么简单——如果模型输出的真的被定义成一个概率分布,那么训练的全部逻辑就变了:交叉熵本质上是在对“模型给出的分布”做负对数似然,优化目标就是让模型这个分布去贴近真实的类别分布。这一整段推理,全部建立在“随机变量”和“分布”的语言之上。没有这个概念,公式都只是死记硬背的符号而已。

1.2 第二次卡住:什么叫“从分布中采样”

读生成模型相关材料时,经常能看到这样的描述:“从先验分布中采样得到潜变量z,再通过解码器生成图像。”我一开始完全不理解采样这一步的意义,以为是某种工程上的随机数技巧。后来才明白,潜变量z在数学上就是一个随机变量,模型定义了它的分布,采样就是按这个分布随机取值一次。更准确地说,训练时拿到的每张图片,本质上也是“从数据分布中采样得到的一次观测”,生成时的z则是“从模型假设分布中得到的一次实现”。随机变量在这里起到了统一描述的作用:样本、采样、分布、期望,这些词最终都指向同一套数学模型。

1.3 第三次卡住:贝叶斯公式里的“分布套分布”

先验、似然、后验,三个词第一次放在一起看,简直像绕口令。直到我用随机变量的语言重新表述了一遍,才豁然开朗:把参数θ看作一个随机变量,先验p(θ)就是观察数据之前我们对参数分布的认识;数据X是另一个随机变量,似然p(X|θ)表示在某个参数取值下数据的分布;后验p(θ|X)则是看到数据之后修正过的参数分布。随机变量的核心思想就是“携带不确定性的对象”,贝叶斯视角的全部奥义,就是把参数也当作这种对象来处理。教材这一节只有两三页,却是支撑这一切的地基。地基没打牢,上面盖的楼越盖越虚。

2. 从“变量”到“随机变量”:先弄清教材在定义什么

很多读者卡在这一节,不是因为数学难,而是因为“随机变量”这个名字本身有误导性。它听起来像是一个“会随机变化的数字”,实际上它的定义要抽象得多,而且这个抽象恰恰是它能被到处使用的原因。

2.1 随机变量不是一个随机取值的数,而是一个映射

教材里的正式定义是:设样本空间为Ω,随机变量X是从Ω到实数集R(或其子集)的映射,记作X: Ω→R。你可以把它理解成一个“读值函数”:每个样本点ω对应一个实数X(ω)。掷骰子就是最直观的例子,样本空间是六个面,随机变量把每个面映射到数字1到6。样本空间里本来就有概率,这个概率被随机变量继承到了实数轴上,于是我们就能讨论P(X=3)、P(X>4)这些东西了。

为什么这个定义如此重要?因为很多复杂事件本质上是对随机变量施加条件。比如事件“X>3”,它的概率来自样本空间中所有满足X(ω)>3的样本点集合。没有映射观点,你很难解释为什么一个随机变量的函数f(X)仍然是随机变量,也很难理解为什么两个随机变量可以相加、相乘——因为函数复合之后依然是从样本空间到实数的映射。这些运算在后面积累的公式里到处都是。

2.2 离散与连续:两种世界观

随机变量按取值类型分成两大类。离散随机变量取值是可数的,比如骰子点数、分类标签、Dropout掩码;连续随机变量取值是不可数的,比如身高、图像加噪后的像素值、网络权重。这个区分不是教材为了分类而分类,而是决定了后面所有数学工具的形式。

关键差异在于:连续随机变量在某一个精确点上的概率是0。你问“一个人的身高精确等于175.0000厘米的概率是多少”,答案就是0,因为可选的精确值有无穷多个,任何一个单点都分不到正的“质量”。所以对连续变量,我们永远只能讨论区间概率,比如身高在174.5到175.5厘米之间的概率。这就是为什么后续所有连续分布的公式都是积分而不是求和。我常用一个生活类比来解释:离散分布像一盒盒分好份的零食,每份有固定重量;连续分布像一整片均匀涂抹的黄油,任何“单点”都薄到没有重量,只能讨论切下一块的面积。

2.3 符号里的潜台词:大小写与记号

教材的符号约定是:随机变量用大写X表示,具体取值用小写x表示,P(X=x)读作“随机变量X取值为x的概率”。这个记号看似只是大小写区别,读公式时却极其重要。比如p(x; θ)表示“在固定参数θ下,取值x对应的概率质量或密度”,而X~N(0,1)表示“随机变量X服从标准正态分布”。

我读论文时的第一个习惯就是给每个符号“验明正身”:哪些是随机变量,哪些是观测到的固定值,哪些是需要学习的参数,哪些是超参数。很多新手卡在公式上,根本不是数学不会,而是符号角色没分清。举个典型例子,贝叶斯公式里的p(θ|X),θ是随机变量,X是已经观测到的数据,两者角色不同,公式的含义完全不同。这一节把符号约定讲清楚,省下的时间远比你想象的要多。

3. 描述随机变量的两把尺子:概率质量函数与概率密度函数

有了随机变量这个概念,下一步就是怎么描述它。教材这一节给出了两套工具,分别对应离散和连续两种类型。这两套工具的名字非常接近,含义却天差地别,我把它们放在一起对比,你会立刻看到区别。

3.1 概率质量函数:把“重量”放在每个取值上

离散随机变量用概率质量函数(通常缩写为PMF)描述,记为P(X=x)。它的含义非常直白:每个可能取值上放了多少“概率重量”。骰子的PMF就是每个点数各占1/6,所有取值上的概率加起来等于1。分类模型输出的十个概率值,本质上也是一个定义在十个类别上的PMF。

概率质量函数有几个必须遵守的性质:每个取值上的概率都在[0,1]之间,所有取值的概率求和等于1。判断一个数列能不能当PMF用,就检查这两条。凡是看到一个输出层的数值被当作“概率”,先验证它是不是满足这两条——softmax输出天然满足,而裸的线性输出天然不满足,这就是为什么分类问题必须配softmax而不是直接拿logits当概率。

3.2 概率密度函数:连续世界里只有“面积”

连续随机变量不能用“每个值的概率”来描述,因为每个值的概率都是0,所以改用概率密度函数(通常缩写为PDF),记作f(x)。必须反复强调:f(x)本身不是概率,它描述的是“概率在这个点附近的密集程度”。事件P(a≤X≤b)等于f(x)在区间[a,b]上的积分,也就是曲线下的面积。

我用密度来类比:f(x)就像单位长度上的“质量”,而概率是长度乘以密度得到的“总质量”。正态分布曲线中间高、两边低,说的是概率在均值附近更密集,而不是“某个值有概率”。很多刚入门的人看到f(x)后面跟着一个具体数字,比如f(0)=0.4,会习惯性地读成“这个值的概率是0.4”,这是最普遍也最危险的错误理解。

对比项概率质量函数 PMF概率密度函数 PDF
适用对象离散随机变量连续随机变量
函数值含义该取值的真实概率该点附近的概率密度
函数值能否大于1不能,必须≤1可以,甚至远大于1
归一化条件所有取值求和为1全区间积分为1
区间概率算法区间内取值逐点求和区间上积分

3.3 密度值大于1不是错误:一个极其常见的认知破绽

很多读者第一次遇到密度值大于1时,会怀疑自己算错了,或者怀疑分布定义错了。实际上完全正常。举个最简单的例子:均匀分布U(0, 0.5),密度函数在[0,0.5]区间上恒为2,那么P(0≤X≤0.25)=0.25×2=0.5,结果没有任何问题。

关键就在于归一化的对象不同:PMF要求概率求和等于1,每个项都是概率,自然不能超过1;PDF要求全区间积分为1,如果支撑区间很短,密度值就必须很大才能把总面积凑到1。这就像把同样的黄油抹在更小的吐司上,单位面积上的黄油厚度自然就大。理解了这一点,后面遇到某些连续分布的似然值大于1时,你就不会大惊小怪了。

4. 深度学习里被随机变量支配的角落

基础概念讲完,我们来干点实际的事。很多人觉得概率论是“数学课上的东西”,跟训练模型是两回事。但实际上,从你写第一行初始化代码开始,你就在和随机变量打交道。下面举几个训练流程中最常见的例子,每个例子背后都是这一节的概念。

4.1 softmax输出:模型其实在定义一个离散分布

先看监督学习里最常见的场景。一个图像分类模型,最后一层输出十个logits,经过softmax之后得到十个值,加起来等于1,符合PMF的两条性质——这就是一个定义在十个类别上的概率分布q。模型预测,本质上就是给出这个分布的具体参数。

交叉熵损失公式L=-log q(y),其中y是真实类别,这个式子就是在真实类别y这一项上取预测分布的负对数。最大化似然、最小化交叉熵、最小化KL散度,在这些不同说法之间切换,背后的数学对象都是同一个分布。能从“分布拟合”的视角看训练,很多超参数选择都有了根据:为什么多分类配交叉熵而不是均方误差?因为交叉熵对应的目标是分布之间的匹配,而MSE对应的是数值回归目标的匹配——概念层面就不是一回事。

4.2 随机初始化、Dropout、数据增强:到处都是采样

再往训练过程里看。权重初始化:每个参数都是从某个分布中采样得到的随机变量初值,常见的有均匀分布U(-a,a)和正态分布N(0,σ)。Dropout:每个神经元以概率p保留、以概率1-p置零,这相当于为每个神经元采样一个伯努利随机变量作为掩码。数据增强:对图像做随机翻转、随机裁剪、随机颜色扰动,等价于从一个“图像变换分布”中采样得到不同的训练视图。mini-batch SGD:每个batch就是从训练集的经验分布中采样得到的一组样本。

这些操作在日常工程里经常被当成“技巧”或“调参项”,但底层全是随机变量与采样。理解了这层关系,你看很多实现代码时会有一种“原来如此”的通透感:Dropout的随机性来自伯努利分布,采样过程在每次前向时执行一次,所以模型等价于在多个不同的稀疏子网络上取平均。

4.3 期望视角:训练到底在优化什么

那节教材在随机变量之后紧接着就引出了期望的概念:E[X]等于所有取值按概率加权求和,或用密度做积分。这个工具一旦学会,训练目标就能一句话写清楚:最小化期望损失E_{(x,y)~p_data}[L(f(x; θ), y)]。

这里的p_data是真实的数据生成分布,它对我们来说是未知的;训练集是它的有限观测,经验分布是它的近似估计。这个视角把很多概念统一了起来:过拟合是模型在上拟合经验分布而不是真实分布,数据增强是在改变经验分布的形状让它更接近真实分布,正则化可以看作把参数分布推向某个先验。第三章开头的这些内容,几乎每一小节都能在训练循环里找到对应,差别只在于你有没有带“分布”的眼睛去看。

5. 把这一节“跑”一遍:一个最小化实验

看公式和真正动手之间隔着一条鸿沟。我建议每个读者都花十分钟跑一遍下面这个实验,它会把PMF、密度、大数定律这些概念全部落地,后面读到更复杂的采样方法时,你会有一层非常坚实的直觉。

5.1 骰子的经验分布

先用随机数生成器模拟掷骰子,估计每个点数的概率质量函数。这个实验的核心意图是:用频率估计概率,也就是蒙特卡洛方法的最原始形态。

import numpy as np rng = np.random.default_rng(42) N = 100_000 samples = rng.integers(1, 7, size=N) # 均匀采样 1~6 for v in range(1, 7): freq = (samples == v).mean() print(f"P(X={v}) ≈ {freq:.4f},理论值 1/6 ≈ {1/6:.4f}")

运行结果会让你看到,每个点数的频率都稳定在0.166附近。样本量越大,频率越接近真实概率。这就是大数定律在起作用,也是后面所有“采样估计”方法能够成立的根本原因:当我们无法解析计算某个分布的期望时,可以用采样频率去逼近。

5.2 大数定律的收敛过程

接着观察估计值的收敛速度。这里故意只打印三个阶段性结果,你可以直观感受到“越到后面,精度提升越慢”这个事实。

N_max = 200_000 samples = rng.integers(1, 7, size=N_max) empirical = np.cumsum(samples == 6) / np.arange(1, N_max + 1) print("前100次估计:", empirical[99]) print("前10000次估计:", empirical[9999]) print("前200000次估计:", empirical[-1])

经验上,前100次的结果可能偏差很大,前10000次已经比较稳定,前200000次基本贴着理论值。这个现象直接解释了为什么随机梯度下降用几千个样本的batch就能估计出全量数据的梯度方向:有限样本估计的误差随样本量下降,只要误差在可接受范围内,计算代价就大幅降低。

5.3 连续变量:密度、积分与“单点概率为零”

最后看连续变量的情况。从标准正态分布采样一百万次,估计区间(-1,1]内的概率,并与理论值0.6827对比。

z = rng.normal(loc=0.0, scale=1.0, size=1_000_000) p_between = ((z > -1) & (z <= 1)).mean() print(f"P(-1 < X <= 1) ≈ {p_between:.4f},理论值 ≈ 0.6827")

再做一件反直觉的事:检查任意精确单点值出现的频率。因为正态分布是完全连续分布,理论上P(X=1.23456789)等于0,采样时你会发现这个事件几乎不会发生。值得注意的是,如果画直方图时把分箱设得很窄,条形高度是可以大于1的,因为条形表示的是密度估计而不是概率——这正是前面3.3节讨论的密度大于1问题的直观版本。

6. 新手最常踩的几个认知陷阱(附我的答疑经验)

这些年在论坛和群里帮人看问题,关于随机变量这个知识点,翻来覆去被问到的就是下面几个问题。我把它们集中整理出来,每个都附上我惯用的解释方式,希望对你有用。

6.1 “密度值超过1,说明我分布写错了”

被问得最多的问题,几乎每个刚接触连续分布的人都问过。我的回答套路是:先分清对象,概率质量函数的值不能超过1,因为它是概率;概率密度函数的值可以超过1,因为它不是概率,只是单位区间上的“概率浓度”。判断标准就看归一化条件:求和为1还是积分为1。只要积分为1,某一点高度超过1完全正常。遇到这种情况,让对方画一个支撑区间很窄的均匀分布,比如U(0,0.1),立刻就能看到密度值等于10的画面,也就接受了。

6.2 “随机变量就是随机数”

随机数和随机变量是两回事。随机数是某一次采样得到的具体值;随机变量是描述整个取值空间和概率规则的数学对象。骰子掷出一个4,这是随机数,是X的一次实现;而“掷骰子的结果”这个随机变量,定义的是所有可能取值和每个取值对应的概率。这个区分直接影响写代码的方式:调用rng.sample()是在采样,得到一个实现;而使用分布对象的概率密度函数或累计分布函数,是在描述这个随机变量本身。两者混为一谈,就很容易在代码里搞不清“我现在在算的是概率还是在做一次抽样”。

6.3 “这个样本发生的概率是...”

对连续变量来说,单个精确值的概率是0,所以“这个样本的概率”这句话本身就是错的。准确说法是“这个样本的概率密度值”,或者“这个样本落在某个邻域区间的概率”。对离散变量才能说“这个值的概率”。这个区别在实际训练中有直接后果:计算连续数据的负对数似然时,用的必须是密度值而不是概率值,否则会得到一堆0或者无穷大。同时,也正因为密度可以大于1,连续分布的负对数似然完全可以是负值——这在离散情况下是不可能出现的现象。

6.4 “直方图就是真实分布”

直方图只是对真实分布的估计,它的形状受样本量和分箱宽度影响。同一个分布,分箱设得不同,画出来可能差别很大。真实分布是背后的理想化对象,我们永远只能通过有限的样本来近似它。这个观念的价值在于:它能解释为什么验证集评估必须独立于训练集采样,因为经验分布只是近似,用同一份数据既是训练又是验证,等于用同一个近似去验证它自己,偏差会被系统性掩盖。

7. 读完这一节,我在实际项目里养成的三个习惯

最后说说知识落地的事。重读这一节并真正理解之后,我的工作习惯发生了几个明显变化,这里挑三个最有价值的分享一下,都属于“不用额外花时间但收益立竿见影”的类型。

第一个习惯:拿到模型先回答“输出层在拟合哪个分布”。多分类问题是Categorical分布,配交叉熵;多标签问题是每个维度一个Bernoulli分布,配多个二元交叉熵;回归问题常被假设成高斯分布,配MSE本质上是固定方差下的高斯负对数似然。这个习惯帮我快速判断损失函数选得对不对,也让我在调试时能立刻发现“把概率和分数混着用”的隐蔽bug。

第二个习惯:所有概率连乘统一转到对数空间。原因是概率都在[0,1]区间,多个概率相乘很快就会下溢成0,在浮点数里变成灾难。这个习惯也让我真正理解了为什么交叉熵、KL散度里面全是log——它们本质上都在做“对数域里的分布比较”。从期望视角看,最小化负对数似然,就是在让模型分布的期望信息量最小化,一句话就能把几个公式串起来。

第三个习惯:用“分布语言”读论文和写代码注释。遇到“从先验采样z”就在旁边标注z~prior,遇到“模型输出概率”就标注p_θ(y|x),遇到“最小化期望损失”就标注E[·]。代码注释里也写清楚每个随机变量的分布假设,比如“此处对dropout掩码做Bernoulli(0.5)采样”。这个习惯极大减少了我隔一段时间回看代码时的理解成本,也让队友接手时少走很多弯路。

回头再看第三十七页第二节那两页纸,内容确实不多,但它提供了一种视角,让你能把后面几十章的公式看成同一套语言的不同句子。如果你也在啃那本经典教材,我建议别跳过这一节,可以直接拿这篇文章当导读,再动手把第五节那几个实验跑一遍。跑完你会有一个很直观的体感:概率论不是天书,它就是你每天训练模型时,那些随机性背后真正在发生的事。

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

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

立即咨询