《深度学习》第三部分读后感:生成范式、概率建模与智能世界的结构重塑之路
深层概率模型综述
简介
《深度学习》一书分为三个部分:第一部分介绍了深度学习所需的数学基础,第二部分讲解了深度网络及现代实践,第三部分讨论深层概率模型。前两部分奠定了理解深度概率模型的基础,因此在展开总结第三部分内容之前,我们先简要回顾前两部分的要点。
第一部分:数学基础。 这一部分涵盖了深度学习所需的线性代数、概率论、信息论和数值计算等知识。书中详细介绍了标量、向量、矩阵和张量等基本概念,矩阵运算规则,常用概率分布及其性质,以及梯度计算和优化基础等内容。这些数学工具为理解后续章节中的模型训练算法(如梯度下降法、反向传播)提供了支撑。例如,线性代数中的矩阵乘法和求导是深度神经网络计算和优化的基础;概率论知识则帮助我们理解模型的不确定性、概率分布及其条件独立性等概念,为深度概率模型埋下伏笔。
第二部分:深度网络与现代实践。 这一部分系统介绍了当今主流的深度学习模型和训练技巧。包括:
- 深度前馈网络(多层感知机):介绍了构建多层神经网络以逼近复杂函数的原理,使用非线性激活函数和隐藏层来提取特征。
- 正则化:讨论了对抗过拟合的方法,如L₁/L₂正则、Dropout等。
- 优化算法:深入讲解了随机梯度下降(SGD)及其各种改进(如动量、AdaGrad、RMSProp、Adam等),如何高效地训练深层网络。
- 卷积神经网络(CNN):阐述卷积层的结构与原理,在计算机视觉中的卓越表现。
- 序列建模(循环神经网络 RNN):介绍处理时间序列和自然语言的模型,包括RNN及其改进(LSTM、GRU)来捕捉长程依赖。
- 实践技巧:涵盖深度学习模型训练的实用方法论,如参数初始化、批归一化、超参数调优、模型集成以及在实际应用中提高性能的经验。
这一部分的核心是监督学习:模型从大量带标签的数据中学习映射关系,并在图像分类、语音识别、机器翻译等任务上取得了显著效果。然而,这些成果往往依赖于海量的标注数据。在许多实际场景中获取如此多的标签并不容易,这激发了对无监督学习和生成式模型的研究兴趣。第二部分为第三部分的生成建模方法打下基础——例如,理解前馈网络和反向传播对于后续变分自编码器(VAE)和生成对抗网络(GAN)的实现至关重要。
第三部分:深层概率模型是全书的最后一部分,也是深度学习领域中关于生成建模和概率方法的前沿探索。这一部分主要关注非监督式或半监督式的深度学习方法,通过构建和训练概率模型来表示数据分布,从而在不依赖大量人工标签的情况下学习有用的特征表示,并能够生成逼真的新样本。
在第三部分开始时,作者指出,传统深度学习在监督学习(有大量标签数据)方面取得了巨大成功,但如果我们希望降低对海量标签数据的依赖,就需要借助无监督或半监督方法。无监督学习试图从未标注的数据中学习结构或分布,但当前无监督深度模型的效果往往尚未达到监督模型的精度,这主要是由于高维问题的复杂性和计算挑战。即便如此,深层概率模型为机器学习提供了另一种视角:显式地对数据分布进行建模,不仅能进行密度估计,还可以让模型学会“想象”出新的数据样本。
第三部分的八章内容可分为两大块:概率模型基础(第13~19章)和生成模型应用(第20章)。第13章至第19章介绍各种深层概率模型的理论基础、常见模型和核心算法,包括线性因子模型、自编码器、表示学习、概率图模型、蒙特卡洛方法、配分函数和近似推断。这些章节为理解复杂的深度生成模型奠定理论基石。最后的第20章则汇总前面介绍的方法,讨论如何将它们应用于构建实际的深度生成模型,其中涵盖了经典的和现代的生成模型(如玻尔兹曼机、变分自编码器、生成对抗网络等)。我们还将结合当前前沿研究,扩展介绍扩散模型(Diffusion Models)、基于分数的模型(Score-based Models)以及大型语言模型(LLM)等近年来兴起的生成模型技术,以拓展视野并联系实际应用。
接下来,我们将逐章总结第三部分(第13~20章)的内容。每章我们将提炼原书中的关键要点,并辅以通俗解释、必要的数学推导和公式推演。同时,我们将讨论每章内容与当代前沿研究(例如扩散模型、VAE、GAN、Score-based模型、LLM等)的联系,并提供相应的PyTorch代码示例,帮助读者将原理与实践相结合。每章还包含至少一个示意图或流程图,以帮助理解相关概念。希望这份总结能帮助具备一定AI基础的工程师和研究人员全面理解深层概率模型领域的基本原理和最新进展。
下面按章节展开第三部分的内容。
第13章 线性因子模型
原文关键点
线性因子模型(Linear Factor Model)是一类简单的概率模型,用于揭示高维观测数据中潜在的低维线性结构。模型假设观测数据
- 主成分分析(PCA)和概率 PCA:PCA寻找数据最大方差的低维子空间,将数据投影到该子空间形成简洁表示;概率PCA则将其形式化为高斯密度模型,假定
,其中 是低维潜在变量, 是高斯噪声。 - 因子分析(Factor Analysis):与概率PCA类似,但对噪声和因子的方差结构有更一般的假设,允许因子模型更灵活地拟合数据协方差。
- 独立成分分析(ICA):一种线性模型,假设观测数据是若干独立非高斯源信号线性混合而成。ICA力图从观测数据中分离出统计上独立的源信号,常用于盲源分离。
- 慢特征分析(SFA):提取随时间变化最缓慢的线性组合特征,常用于处理时间序列或视频信号中的渐变因素。
- 稀疏编码(Sparse Coding):假设观测可由少数几个主动的潜在因子线性重构得到,即鼓励潜在表示
大部分维度为零,仅少数非零(稀疏)。稀疏编码可视为在线性因子模型中加入了稀疏先验。
线性因子模型的两个基本功能是降维和特征提取。通过线性映射将原始高维数据转换到一个低维的潜在空间,我们可以捕捉数据的主要变化因素,去除冗余信息和噪声。这类模型在数据预处理、可视化和理解数据结构等方面有重要作用。例如,PCA经常用于图像或信号处理中的降维和去相关,ICA在语音分离和神经信号分析中有应用。
值得注意的是,线性因子模型属于生成式模型的一种简单形式:它为数据分布建立了一个显式概率模型(通常假设潜在变量和噪声的概率分布已知,如高斯分布),然后通过最大似然等方法来估计模型参数,使模型生成的数据与真实数据的分布尽可能接近。尽管模型本身是线性的且相对简单,但为后续深度概率模型(如非线性自编码器和深度生成模型)打下了基础。
通俗解释
通俗地说,线性因子模型就是在寻找数据中的“隐藏因子”或“隐变量”。我们可以将其理解为:有一个看不见的低维世界,里面有一些基本的“因素”在发挥作用;然后通过一个投影(线性变换),这些因素共同决定了我们在高维世界中观测到的数据。
以日常类比来说,假设我们在不同房间里测量温度、湿度和光照强度三个指标(这是3维观测数据)。线性因子模型可能告诉我们,这三个观测量其实主要由两个潜在因子决定:比如“天气冷热”和“白天黑夜”。“天气冷热”影响温度和一定程度的湿度,“白天黑夜”影响光照和也可能稍微影响温度。这两个因素线性组合后,加上一些噪声,就产生了我们测得的各房间具体的温湿度和光照值。
这个例子中,“天气冷热”和“白天黑夜”就是隐藏的因子,它们维度更低(2维)。线性因子模型的任务就是从观测的数据中逆推出这些隐含因素,并确定每个观测指标如何线性依赖于这些因素。例如,PCA会告诉我们一个正交坐标系(主成分),其中可能第一主成分对应“冷热”(高权重影响温度,次高影响湿度,几乎不影响光照),第二主成分对应“昼夜”(主要影响光照)。这样我们就找到了低维的结构,解释了3维数据的大部分变化。
总而言之,线性因子模型提供了一种简化复杂现象的方法:用少数线性组合来解释数据中的主要变化趋势。这种简化有助于我们理解数据、降维压缩和去噪,也是更加复杂的非线性模型(例如深度自编码器)在理念上的起点。
数学推导
线性因子模型通常可以表示为:观察向量
其中
以**概率主成分分析(Probabilistic PCA)**为例,它假设:
,潜在变量为标准正态; ,给定潜在因子后观测服从一个带均值 的各向同性高斯。
在这种模型下,观测数据的边缘分布也是高斯:
独立成分分析(ICA) 的数学基础是找一个非高斯的线性变换使得输出分量之间统计独立。它通常通过极大化非高斯性(如最大熵或Kurtosis)或最小化各分量之间的互信息来实现。ICA模型写作
稀疏编码 则引入了稀疏先验:在线性重构误差
总之,线性因子模型的学习通常归结为对数似然最大化问题。例如,对带高斯噪声的模型,似然函数形如:
求导令其对
前沿研究联系
线性因子模型本身已是较为经典的方法,在深度学习崛起之前广泛用于降维和特征提取。尽管深度非线性模型现已占据主导地位,但线性因子模型的思想依然体现在许多现代方法中,成为其雏形或特殊情形:
- 深度自编码器 vs PCA:自编码器(第14章)可以被视为是PCA的非线性推广。PCA只能学习线性子空间,而堆叠的多层自动编码器可以学习更复杂的非线性流形上的低维表示。不过在线性激活和平方误差情况下,一个线性单层自编码器实际就等价于PCA提取的主成分。
- VAE与因子分析:变分自编码器(第20章)在结构上类似于概率因子模型的扩展,它假设观测由潜在变量通过神经网络生成,但增加了非线性的能力,还通过变分推断学得潜在表示的后验分布。可以说,VAE 是将因子分析/PCA的线性高斯模型推广到任意复杂的神经网络“解码器”,同时用另一个网络近似“编码”后验。这种深度概念在保持“因子模型”范式(显式潜在变量)的同时极大提高了表达能力。
- 独立成分与生成模型:追求独立表征的思想在深度学习中依然重要。比如生成对抗网络(GAN)训练得到的潜在空间如果能够学到独立的因素,将有利于可解释性和可控生成。最近的研究(如StyleGAN)引入了逐层潜码来控制图像生成的不同属性,某种意义上是希望潜变量影响生成结果的因素解耦,更接近ICA所追求的独立因素。
- 流形学习与降维:线性模型局限于线性子空间,但许多现代流形学习算法(如t-SNE, UMAP)和非线性降维技术也受到PCA的启发,虽不在神经网络框架内,但同样追求在低维空间保留数据的主要结构。深度学习领域的表征学习(第15章)则是以训练目标来学习有意义的隐藏表征,可以视作自动学习“因子”的过程。
- 基础模型初始化:在深度网络训练早期,有时会用到PCA白化或奇异值初始化等,这些都是利用线性因子模型对数据或权重做预处理,以使深度模型更快收敛。
- 提示:降模型复杂度:在大模型时代,如果某些模块过于复杂,常会先用PCA等降维以提高效率。例如在Transformer的多头注意力中,有研究尝试用低秩近似(与PCA类似)来降低计算量。
概括来说,线性因子模型尽管简单,却提供了理解高维数据的第一步方法,也是很多复杂深度模型的灵感来源。在当前前沿中,我们看到扩散模型和score-based模型(详见第18章和第20章的前沿联系)利用了线性高斯模型链式叠加的思想(每一步都是线性高斯变换,加噪声再去噪);大型语言模型在词嵌入初始化时也可能使用PCA来分析词共现矩阵。可以说,线性因子模型的精神——在隐藏因子空间捕获数据结构——贯穿于各类现代深度生成模型中,只是这些模型采用了更复杂的非线性函数和训练策略来克服线性模型表达能力的限制。
PyTorch 实例代码
线性因子模型中最具代表性的是 PCA。下面我们使用PyTorch实现一个简单的PCA降维示例,将高维数据投影到低维子空间(提取主成分)。
假设我们有一个数据矩阵 X
(形状 [N, D]
,N个样本,每个D维),我们希望降至d维。PCA的核心是对数据的协方差矩阵做特征分解。实现中可以直接利用奇异值分解(SVD)得到主成分方向。
import torch
# 生成一个随机数据矩阵 (N=5样本, D=3维)
X = torch.tensor([[2.5, 0.5, 2.2],
[1.9, 3.1, 4.7],
[3.0, 4.0, 1.6],
[2.0, 2.7, 3.5],
[2.2, 2.9, 3.1]], dtype=torch.float)
# 1. 数据中心化(零均值化)
X_mean = X.mean(dim=0)
X_centered = X - X_mean # 每列减去均值
# 2. SVD分解协方差矩阵(或直接对X_centered做SVD)
U, S, V = torch.svd(X_centered) # V的列为右奇异向量,即主成分方向
print("主成分方向:", V) # V 是 D×D矩阵,每列是一个主成分方向
print("奇异值:", S) # 奇异值相关于数据在对应主成分方向上的方差开平方
# 3. 取前d个主成分方向进行降维投影
d = 2
W_pca = V[:, :d] # 选取前2个主成分方向组成投影矩阵 (D×d)
X_2d = X_centered.matmul(W_pca) # 将原始数据投影到2维空间
print("投影到2维的新表示:", X_2d)
在这个代码中,我们首先减去均值对数据进行了零均值化(这是PCA的必要预处理)。然后用 torch.svd
计算数据矩阵的奇异值分解(等价于对协方差矩阵做特征分解)。输出的 V
矩阵的前 d
列就是数据的前 d
个主成分方向。投影矩阵 W_pca
由这些方向组成,将原始数据乘以 W_pca
即可得到降维到 d
维的表示 X_2d
。
通过打印结果,我们可以看到主成分方向和对应奇异值,从而了解哪个方向方差最大。奇异值的平方除以 scikit-learn
的PCA实现,但通过此示例我们了解了PCA背后的线性代数过程。
需要注意,在实际深度学习中,我们很少手动去实现PCA步骤,因为深度模型本身可以学习低维表示。然而,在分析模型的内部表示、可视化高维数据或者在一些预处理中,PCA仍然是一个有用的工具。它的PyTorch实现也相对简洁,如上所示。
可视化示意:线性因子模型结构
下面的流程图描述了线性因子模型的生成过程和两个基本功能:
在这张图中,箭头从潜在因子指向观测数据,表示生成过程:低维的
第14章 自编码器
原文关键点
自编码器(Autoencoder, AE)是一种经典的神经网络结构,用于学习数据的高效编码表示。自编码器由两部分组成:
- 编码器(Encoder):将输入数据
压缩到一个低维的隐藏表示 。 - 解码器(Decoder):从隐藏表示重建出原始数据的近似
。
整个网络以
- 维度约束:让隐藏表示
的维度比输入 的维度低(称为“欠完备”自编码器),这迫使网络压缩信息。 - 正则化约束:可以不给隐藏层减维,而是在损失中添加正则项,使得编码器提取到的表示具有某种特性。例如稀疏自编码器要求隐藏单元大部分是零(通过惩罚非零激活),去噪自编码器给输入添加噪声但仍要求重构原始输入,从而让编码器学得稳健特征,收缩自编码器(contractive AE)添加雅可比正则项让编码器对输入扰动不敏感。
自编码器的关键意义在于学习出一种数据的低维表示或特征。与PCA等线性降维不同,自编码器可以是多层非线性的,因此能够捕获更复杂的关系。编码器的最后一层隐藏表示
自编码器本质上仍然是一种生成模型的框架,只是传统自编码器并没有显式的概率模型或随机采样过程,因为它主要关注学表示,生成质量通常不及概率生成模型。比如一个训练良好的自编码器能够在
第14章除介绍基础的编码器-解码器结构外,还探讨了多种自编码器变体:
- 稀疏自编码器:隐藏层维度可与输入相等甚至更高,但通过加入稀疏惩罚,使得每次仅一部分隐藏单元被激活,逼迫模型学到类似独立因子的表示。
- 去噪自编码器(Denoising AE):训练时对输入添加随机噪声(如Gaussian噪声或遮挡部分输入),但仍以原始未噪声的数据为重构目标。这样编码器必须学到数据的鲁棒特征才能还原干净的数据,因而提升了表示的鲁棒性和提取关键信息的能力。
- 合成梯度(Contractive AE):在损失中加入
项(隐藏表示对输入的雅可比矩阵范数的平方)作为惩罚,使编码器对输入的微小变化不敏感,也即输出流形在输入空间是收缩的,从而学到流形上的稳健表示。 - 变分自编码器(VAE):虽然VAE在第20章详细讨论,但第14章可能简要提及了它作为自编码器的一个概率版本,引出后续章节。VAE的编码器输出的是一个分布(均值和方差),通过采样再输入解码器,实现带随机性的生成,这一点区分于传统自编码器。
通俗解释
自编码器可以用一个简单比喻来理解:想象你有一张分辨率很高的图片(比如1000×1000像素),这是100万维的数据。如果我们用自编码器处理这张图片,自编码器的编码器相当于一个“压缩员”,它试图用少量的信息把图片主要内容描述出来;解码器则相当于一个“解压员”,根据压缩的信息去还原出原图。
如果编码器太懒,只记下“原封不动的100万像素”,那就没有任何压缩和学习价值。所以我们规定压缩员只能记下比如1000个数字的信息(把100万维压到1000维)。这样它就不得不想办法提炼:可能记录下主要的颜色分布、轮廓、形状等宏观特征,而舍弃掉一些细节噪声。解压员拿到这1000个数字后,尽力画出一张和原图接近的图。这对解压员也有挑战,因为信息有限,它可能画出的细节不完全一样,但只要整体效果类似,也算完成任务。
通过这个过程,我们就得到了对原始数据的“压缩表示”(1000维的代码向量)。如果这个压缩表示抓住了主要特征,那很多任务(比如分类这张图是猫还是狗)可能只需看这1000维表示就够了,而不用面对100万维的原图数据——这就是特征提取的威力。此外,训练好的自编码器如果有足够能力,“解压员”实际上学到了从压缩表示生成图像的本领。所以如果我们提供一个合适的压缩表示,解码器甚至可以“凭空”画出类似的数据来,这就涉及到生成。不过正如前面提到的,传统自编码器的生成往往只能画出接近训练数据的样本,无法确保生成的完全是合理的、逼真的新数据,因为它没有一个内置的机制去约束隐藏表示的分布。
人们给自编码器加的各种花样(噪声、稀疏性等),都是为了防止它偷懒或者让它学到更有用的表示。比如加噪声就是不给它看清完整的图,它只能靠猜测还原,那它就必须学会“更深层的模式”,比如知道脸上有两只眼睛、鼻子、嘴巴这些全局结构,而不是逐像素记忆。同理,稀疏要求让编码尽可能简洁,只用少数几个激活去描述,从而不同维度的隐藏单元会各自学到不同的特征(比如一个单元检测有没有眼镜,另一个检测笑容等),以避免所有单元全部混在一起工作却没有明确分工。
简言之,自编码器就是在自我监督的方式下学习数据的“浓缩”表达。它让输出等于输入,看似无意义,但通过设计瓶颈,迫使网络在中间隐藏层把数据的关键信息提取出来,达到降维和提取特征的作用。这种自我监督(不需要人工标签,用数据自己作为监督信号)思想在近年来发展成自监督学习的诸多方法,是深度学习在无监督领域的重要探索方向。
数学推导
形式化地,自编码器的目标是找到两个映射
或
具体选择取决于数据类型和输出层的激活函数(例如像素值用连续型可选MSE损失,若输出用sigmoid归一则可用交叉熵形式)。
训练自编码器就是在最小化所有样本的平均重建误差:
其中
如果没有任何约束,最优的情况可能是
稀疏自编码器和去噪自编码器可以看作引入了不同形式的正则化:
- 稀疏自编码器添加约束
,如L1正则鼓励 稀疏,或者限制每个隐藏单元的平均激活接近0等。比如常用KL散度正则:令隐层每个单元期望激活为 ,实际平均激活为 ,加惩罚 。 - 去噪自编码器在训练时对输入施加扰动(如
或 随机将一些输入设0即“遮挡噪声”),优化目标变为重构原始未扰动的 : 。由于扰动是随机的,这相当于对参数施加了一种噪声正则,使模型更稳定。此外,它也近似在最小化 的负对数似然,让编码器学到把受损输入映射回高密度的干净数据区域,从而实现去噪功能。
合同自编码器加入雅可比范数惩罚:
总之,训练自编码器通常用随机梯度下降法迭代更新参数。与一般的前馈网络不同,自编码器的目标是重构输入本身(自监督),但数学上没有特别之处,仍然是通过反向传播计算损失对参数的梯度,然后更新参数。
前沿研究联系
自编码器的概念在深度学习的发展中占有重要地位,可以说是深度网络用于无监督学习的早期探索之一。它在前沿研究和应用中继续演化并发挥作用:
- 深度信念网络与预训练:在深度学习兴起初期,Hinton等提出逐层用受限玻尔兹曼机(RBM)或自编码器进行无监督预训练,再进行有监督微调。这种“逐层贪心预训练”方式曾帮助训练更深的网络。当时自编码器作为预训练模块,其隐藏层输出提供了一个良好的初始特征。虽然后来有了ReLU、BatchNorm等直接训练方法,预训练显得不那么必要,但自编码器思想延续到了自监督学习中,即用重构等任务让网络学表示,然后迁移到下游任务(类似BERT的掩码词预测也是一种重构任务思想)。
- 生成模型:如前所述,自编码器本身不是一个严格的生成模型(因为没有定义隐藏空间的先验分布),但它启发了变分自编码器(VAE)的发展。VAE可以看作在自编码器架构中加入了概率图模型假设与附加约束:编码器输出高斯分布参数,对应一个潜在变量采样;同时增加一项KL散度正则,使潜在分布接近先验。这使得训练好的模型可以通过从先验采样潜在向量,再通过解码器生成新数据,从而真正成为生成模型。VAE现已成为深度生成模型的重要一支,我们将在第20章详细讨论。值得一提的是,扩散模型等score-based方法也与自编码器的去噪思想相关:扩散模型每一步做的事情类似一个带噪声的自编码器——从加了噪声的样本中去除噪声(重构干净样本)。这将自编码器的框架延伸到随机过程,用多个去噪步实现复杂分布的生成。
- 表征学习和迁移:自编码器的隐藏表示常被用于迁移学习或下游任务。例如,在无标签图像上训练一个自编码器得到隐藏表示,然后用这些表示在少量标注数据上训练一个简单分类器,可以比直接用像素分类有更好效果。这种思路发展为自监督预训练的众多方法,比如SimCLR、MAE(Masked Autoencoder)等。MAE直接以自编码器形式掩盖图像块然后重建,用以学习图像表示,就是对自编码器应用了新的正则(mask噪声)和Transformer架构,取得了优秀的迁移性能。
- 异常检测:自编码器可以用于异常检测,因为它学的是训练数据的重构。如果遇到与训练分布差异很大的输入,重构误差往往会大,从而可以据此判别异常。在工业系统中,用自编码器重构传感器数据、日志等,再根据误差大小判断异常是常用手段之一。
- 生成对抗自编码器:有人结合GAN和自编码器,提出了对抗自编码器(Adversarial Autoencoder, AAE),用GAN的方式强制编码器输出遵循某先验分布,从而使模型既能无监督学表示,又可作为生成模型。这可以视作VAE思路的GAN版本。它体现了自编码器架构的灵活性,可以与其他技术融合。
- 大型语言模型:在NLP中有自回归语言模型(GPT系列)和自编码语言模型(如BERT)。BERT被称为“autoencoder-style”的,因为它通过遮蔽一些输入单词然后重建,类似去噪自编码器。这其实就是自编码器思想在语言任务上的自监督应用。而GPT则是auto-regressive,属于另外范畴。所以我们可以看到,自编码器思想在视觉和语言自监督学习中都在发挥作用(MAE对应视觉,BERT对应语言)。
- 分层和变种:除了典型的扁平自编码器,研究者还探索过卷积自编码器(对图像更友好)、序列自编码器(如用于序列数据的seq2seq模型在一定程度上可看作变体),以及栈式自编码器(多个编码解码堆叠,每层以前一层编码作为输入)等。栈式自编码器曾用于预训练深度网络,也是Deep Belief Network的一部分。
简而言之,自编码器作为深度学习无监督领域的开端,在表征学习、生成模型以及现代自监督技术中留下了深刻印记。当前一些炙手可热的模型(VAE、Diffusion、BERT、MAE等)都能看到自编码器思想的影子。
PyTorch 实例代码
这里我们给出一个简单的PyTorch实现示例,训练一个自编码器在MNIST手写数字数据集上进行压缩和重构。由于篇幅原因,我们不加载真实MNIST数据,而是用随机数据演示网络结构和训练步骤。
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的全连接自编码器网络
class Autoencoder(nn.Module):
def __init__(self, input_dim=784, hidden_dim=32):
super(Autoencoder, self).__init__()
# Encoder: 将784维输入压缩到32维
self.encoder = nn.Sequential(
nn.Linear(input_dim, 128),
nn.ReLU(),
nn.Linear(128, hidden_dim)
)
# Decoder: 将32维隐藏表示解压回784维
self.decoder = nn.Sequential(
nn.Linear(hidden_dim, 128),
nn.ReLU(),
nn.Linear(128, input_dim),
nn.Sigmoid() # 用Sigmoid将输出限制在[0,1]
)
def forward(self, x):
# x shape: (batch, 784)
h = self.encoder(x)
x_recon = self.decoder(h)
return x_recon
# 模拟一些输入数据 (batch_size=16, 784维)
x = torch.rand(16, 784)
model = Autoencoder(input_dim=784, hidden_dim=32)
criterion = nn.MSELoss() # 重构误差用均方误差
optimizer = optim.Adam(model.parameters(), lr=1e-3)
# 单步训练示例
optimizer.zero_grad()
x_recon = model(x)
loss = criterion(x_recon, x) # 计算重建误差
loss.backward()
optimizer.step()
print("重构误差: ", loss.item())
上述代码定义了一个非常简单的自编码器:输入和输出层维度都是784,对应28×28的图像像素拉直,隐藏层维度我们设为32,实现了较大的压缩比例。编码器和解码器各用了两层全连接+ReLU非线性,最后解码器输出用Sigmoid将像素值约束到0~1范围(假设输入像素已经归一化)。
优化器选用Adam,损失是均方误差(也可用二元交叉熵对应Sigmoid输出)。代码最后演示了一次前向和反向更新流程:计算输出x_recon
,与原始输入x
比对计算MSE损失,反向传播并通过优化器更新参数。
如果用真实的MNIST数据反复训练上述模型,编码器的32维隐藏向量就学到了某种手写数字的特征表示,重构的图像应能大致看出原始数字形状。你可以尝试在训练后检查隐藏向量h
,会发现同一类数字的h
在空间上可能聚在一起,说明模型抓住了数字类别这个重要特征(尽管我们在训练时并没有提供类别标签,自编码器是无监督的)。
注: 上述自编码器属于欠完备(hidden_dim < input_dim),如果我们去掉ReLU激活且hidden_dim=主成分数,它理论上可以学到PCA的结果。但由于使用非线性,实际学到的是比PCA更灵活的表示。
可视化示意:自编码器结构
下面用一张示意图展示自编码器的结构和信息流:
图中,输入数据经过编码器变为紧致的隐藏表示,再经过解码器还原为输出。隐藏表示位于中间“瓶颈”位置,是整个网络学习到的特征向量。对于一个训练良好的自编码器,
第15章 表示学习
原文关键点
第15章讨论的是表示学习(Representation Learning),以及如何利用学到的表示进行迁移学习和半监督学习等。核心思想是:让模型自动学习出“好的”特征表示,以提升下游任务的性能或减少对大量标注数据的需求。
本章要点包括:
- 分布式表示:强调深度学习通过隐藏层提取的是分布式表示,即输入的特征由多个因子组合表示,而非独热编码那样的局部表示。分布式表示更为紧凑和有泛化性。例如用多个连续值表示一个概念的不同方面,比用一个one-hot向量更能概括相似概念之间的联系。
- 无监督预训练的作用:回顾了早期深度学习一个重要发现——使用无监督的方式预训练网络的各层表示,然后再进行监督微调,可以明显提升有限数据条件下的模型性能。这可以通过逐层训练堆栈式自编码器或**深度信念网络(DBN)**实现,每一层学到的特征作为下一层的输入。无监督预训练有助于找到更好的初始参数,避免陷入不佳的局部极小,并能保留有用的特征。
- 迁移学习:讨论了如何将表示从一种任务/域迁移到另一种。 提到了经典的迁移学习场景:比如用在大数据集(如ImageNet)上训练的卷积网络提取的特征,在小数据集上的新任务中往往能表现出色。这说明了学习到的表示具有通用性,可以迁移到相关任务。作者还提到,判断一种表示是否“更好”的标准往往是看下游任务是否能够受益于这种表示。
- 半监督学习:良好的表示可以帮助利用未标注数据。比如自训练、共训练等方法,或者把无标签数据通过预训练获得表示,再与少量标签结合训练。深度模型可以通过联合训练监督和非监督目标(如加入自编码器重建损失),实现半监督学习。
- 多任务学习:同时学习多个任务也被认为是一种学习更通用表示的手段。通过多任务学习,模型的隐藏层被迫服务于不同任务,从而学到更普适的特征,不易过拟合某单一任务。
- 判定表示好坏的标准:本章还讨论了如何评估一个表示的质量。通常,没有一个统一的理论指标,不同任务需求不同。但经验上,一个“好的”表示应该是:可分辨性(对关心的任务区分度高)、稳定性(对无关变化不敏感)、紧致性(维度适中,信息不冗余)以及可迁移性(在类似任务上无需大量微调即可用)等。
简而言之,第15章从更高的视角总结:深度学习的成功在于其强大的自动特征学习能力,使得我们不再需要手工设计特征。通过无监督或弱监督手段,我们可以学习到数据的底层结构表示,再将其应用于各种任务。这也预示着之后深度学习研究的一个趋势:以通用表示或预训练模型为基础,在多个任务之间迁移和泛化(这在近年预训练模型+微调成为主流范式中得到了充分体现)。
通俗解释
如果把机器学习比作让计算机理解和解决问题,那么“表示学习”就是在教计算机怎么去看待这个世界。以前传统方法需要人来规定“看世界的方式”(手工提取特征),比如在图像识别中我们可能告诉计算机要看边缘、角点等;在自然语言处理中可能设计词频、共现等等特征。但是深度学习的一个魅力就在于:它自己学出了一套看待数据的方式,也就是自己的“视角”或“语言”。这套东西就是深度网络内部学到的表示。
举个例子:假如我们训练一个人脸识别的神经网络,第一层可能学到的表示是一些边缘、颜色等低级特征;第二层可能学的是眼睛、鼻子、嘴巴等局部组合特征;第三层可能学到的是整张脸的不同模式。这些各层的内部表示对于人脸识别这个任务来说是有意义的。现在,如果我们拿这个网络用于识别新的对象,比如猫的品种,可能低层的边缘、颜色特征仍然有用,但高层特征(脸部结构)就不直接适用了。因此,我们可能迁移部分网络(如低层),再针对新任务调一调高层权重。实践中,这往往比从零开始训练效果更好,因为模型已经学会了一些通用的东西。
换句话说,一个训练好的深度网络就像已经上过小学的学生,掌握了一些基础知识(表示)。当给他新任务时,他不需要从识字和加减法学起,可以直接用已有知识来举一反三。如果我们硬让一个一张白纸的学生去做高等数学题,那就很吃力了。同理,有良好表示的模型(经过大量相关数据训练的)在新任务上如虎添翼,无良好表示的模型需要从头苦学。
第15章谈到的各种策略:无监督预训练、多任务学习、半监督利用未标注数据等等,其实都是在丰富模型的见识,让它学到更泛化的表示。比如多任务学习就像同时让一个人学数学、物理、化学,那么他可能学到更一般的抽象思维,而不会局限于某一学科。对模型来说,它的中间表示会服务于多个任务,因而更抓住本质,不会只对单一任务过拟合。
对于工程师来说,这章的意义在于:与其为每个新任务从零搭建模型,不如利用已有预训练模型的表示(如果有合适的),或尽量设计训练过程让模型多看、多练,这样学出的特征更可靠。现实中这点非常重要——迁移学习和预训练已成为深度学习应用的常规套路,在数据有限的情况下尤其有效。例如,自然语言处理中,用BERT的预训练表示再做微调,现在几乎是标配;计算机视觉中,也经常用Imagenet预训练的ResNet表示来提取特征再做其他任务。
数学推导
表示学习本身并不是一个具体的模型,而是一类范式,因此没有统一的公式推导。但我们可以用联合损失函数来描述一些典型表示学习场景的数学形式:
半监督或自监督联合训练:假设我们有有标签数据
和无标签数据 。我们可以训练一个模型同时最小化有监督任务损失和无监督表示损失:其中
可能是分类的交叉熵损失, 可以是如自编码器的重构误差、对比学习损失等。 权衡两者。通过这种多目标训练,模型参数 会同时顾及监督和非监督目标,学到对两者都有利的表示。多任务学习:如果有
个不同但相关的任务,每个任务都有自己的数据和标签 ,可以共享同一部分网络作为特征提取层,然后用不同的输出层对应每任务。优化目标是总损失:其中
是共享表示部分参数, 是任务 专有的输出层参数。通过同时训练,梯度来自不同任务的数据都会更新共享参数 ,使其学到能够服务于所有任务的特征。这数学上等价于把多任务的loss加起来一起最小化。迁移学习:在数学上可以看做是针对目标任务进行带正则的优化,其中正则项鼓励参数接近预训练来源任务的参数:
这里
是源任务预训练得到的参数。这个正则迫使模型不要偏离预训练权重太多,相当于一种参数上的先验(源模型提供了一个先验分布,假定好的参数在 附近)。在深度学习实践中,通常不会显式加这样的正则,而是直接初始化参数为预训练值,然后用较小学习率fine-tune,实现了类似效果。评价表示的线性可分性:一种衡量表示好坏的方法是在固定表示的情况下训练一个简单分类器(如线性分类器)看性能。这相当于度量:对于模型学到的映射
,是否存在一个线性函数 使 就能正确预测标签。这在数学上就是看线性可分性:给定表示 ,是否 使 与 匹配良好(比如0-1损失小)。如果是,则说明表示已经把任务所需的信息编码进来了。
除了上述,一些理论工作还试图从信息论角度界定“好表示”,例如信息瓶颈理论提出好的隐表示应该只保留与目标有关的信息,去除无关干扰,这可以用互信息来表述:最大化
前沿研究联系
表示学习无疑是近几年深度学习快速发展的核心推动力之一。在前沿研究中,预训练-微调范式已经证明了表示学习的巨大威力:
- 大型预训练模型:从BERT、GPT到现在各种领域的foundation model,无不体现了“学通用表示,再迁移”的思想。例如GPT-3在海量文本上无监督训练获得了包含丰富语言知识的表示,因而在下游可以few-shot甚至zero-shot完成任务。图像领域也出现了CLIP、SimCLR、MAE等在无标签数据上学表示然后应用的模型。表示的质量基本决定了微调后性能上限,这就是为什么比拼越来越大的预训练模型,因为更大的模型+数据意味着学到的表示更强、更全面。
- 自监督学习:这实际上是无监督表示学习的新称呼,已成为独立的重要研究方向。自监督方法(例如对比学习Contrastive Learning、信息最大化、Mask语言建模等等)通过设计预文本或预图像的任务,驱使模型学到有意义的表示,而不需要人工标签。比如SimCLR让图像经过不同随机变换后,鼓励模型的表示保持一致(来自同一图像的两视图embedding距离拉近,不同图像embedding分开),这样模型必须关注图像的语义内容而非表面差异。结果SimCLR等方法学到的表示,线性可分性很好,可以用少量标签达到不错精度。这些进展极大缓解了对标注的需求,也刷新了我们对“好表示”的理解:对比学习学到的embedding往往具有聚类结构,对应类别分开;通过特征可视化发现模型抓住了物体形状、颜色等重要因素。
- 可解释性:有些研究专注于学得可解释的表示,例如disentangled representation(解缠表示),期望隐藏变量的不同维度对应独立语义因素(有点类似ICA思想)。这方面包括Beta-VAE、InfoGAN等方法,希望在保证生成能力的同时,使潜变量与人类语义对齐,比如latent dim1控制物体颜色,dim2控制大小等等。虽然完全无监督地实现解缠仍很难,但这种努力丰富了我们对“表示好坏”的评估维度——不仅看预测效果,也看表示含义。
- 提示学习(Prompting):在大型语言模型中,一个新趋势是不微调模型参数,而是微调输入表示(prompt)或者在embedding空间做搜索。这其实也是表示学习的体现:我们学习如何调整输入的表示以激发模型内部已有的知识来完成目标任务。这种方法成功的前提就是模型内部已经有足够丰富通用的表示,否则纯靠提示无法解决新任务。因此,它反映出预训练表示的泛化能力之强以及潜力尚未完全发掘。
- 领域自适应:很多预训练模型在迁移时需要克服领域差异的问题,比如用英文训练BERT要迁移到医学文本。这时会涉及领域自适应,比如继续在目标领域无监督预训练。其本质是进一步调整表示使其更贴近目标域分布。对抗域适应的方法甚至通过让模型表示对域(源/目标)不可分,从而实现表示跨域的对齐。
- Continual Learning:持续学习希望模型不断学习新任务但不遗忘旧知识。这要求表示能够扩展且稳定。一些方法靠增大表示维度或正则保持旧任务表示不变以避免灾难性遗忘。表示学习观点认为,可以学习一些底层表示供各任务共享,再在任务特定头微调,能达到兼顾新旧的效果。
- 神经可调控性:如果能学到非常模块化的表示,我们就可以针对性地编辑模型的某些知识。例如最近有模型具备编辑某概念表示的能力(如把“棒球”这个概念的表示修改,会影响模型对涉及棒球的回答)。这种能力背后也是对模型内部表示组织的探究——希望找到“知识”的所在并能修改它。
总的来说,表示学习贯穿了现代深度学习的大部分领域。无论是构建大的预训练模型,还是研究模型的可解释性,本质都是在如何获取、评估、应用模型内部的表示上下功夫。对于工程实践,充分利用预训练表示进行迁移已是标配;对于研究前沿,怎样让模型学到更通用、更解耦的表示仍然是重大挑战,其意义不仅在于提升性能,更可能是迈向真正智能的关键一步,因表示代表了知识和理解的内在形式。
PyTorch 实例代码
这里我们通过一个简单的例子来说明迁移学习如何在PyTorch中实现,以及预训练的表示如何被复用。
我们以计算机视觉为例:假设我们有一个在ImageNet上预训练好的ResNet模型,现在要把它迁移用于一个小型猫狗分类任务。ImageNet预训练模型已经学到了丰富的通用图像表示。具体步骤是:
- 加载预训练模型,并冻结卷积层等特征提取部分的参数(不再训练它们)。
- 替换最后的分类层,使输出适配新任务(比如2类:猫 vs 狗)。
- 只训练这个新的分类层参数,看看在少量数据下的效果。
- 如果有需要,也可以解冻部分卷积层,用较小学习率fine-tune。
以下代码演示了步骤1-3:
import torch
import torch.nn as nn
import torchvision.models as models
# 1. 加载预训练的ResNet18模型
resnet = models.resnet18(pretrained=True)
# 2. 冻结除最后全连接层之外的所有参数
for param in resnet.parameters():
param.requires_grad = False
# 获取ResNet最后一层全连接层的输入特征维度
in_features = resnet.fc.in_features
# 替换最后的全连接层,使其输出2维(猫和狗两类)
resnet.fc = nn.Linear(in_features, 2)
# 此时,resnet的卷积层参数是冻结的,仅resnet.fc的参数requires_grad=True
# 3. 训练新的全连接层(示例,不完整的训练循环)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(resnet.fc.parameters(), lr=1e-3)
# 模拟一个批次的数据 (batch_size=4, 3x224x224 图像)
inputs = torch.randn(4, 3, 224, 224)
labels = torch.tensor([0, 1, 0, 1]) # 假设0=猫,1=狗
# 前向传播
outputs = resnet(inputs) # 提取特征 -> 新的fc输出
loss = criterion(outputs, labels)
# 反向传播和优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("Loss:", loss.item())
在这段代码中,我们使用 torchvision.models
提供的ResNet18模型并加载了ImageNet的预训练权重(pretrained=True
)。接着,利用PyTorch的动态图机制,将 resnet
所有参数的 requires_grad
设置为 False,冻结这些参数——这意味着在反向传播时这些参数的梯度不会被计算,也不会被优化器更新。
然后我们获取ResNet原来的最后全连接层(属性 resnet.fc
)的输入特征数 in_features
,新建一个线性层输出2个神经元(对应猫狗两类)。将 resnet.fc
替换为这个新层。此时模型结构变为:预训练的卷积 + 全局平均池化部分(冻结),接上一个2输出的线性层(可训练)。
定义损失函数为交叉熵,优化器我们只传入 resnet.fc.parameters()
,确保优化器只更新新加的层。然后模拟了一次训练的forward/backward过程。
在实际场景中,我们会对我们的猫狗数据集迭代上述过程多次,训练几轮,就能得到一个在猫狗分类上不错的模型,即使只有很少的标注样本。这就是利用预训练表示的好处——卷积层提取的特征已经非常有辨别力,我们只需训练一小部分参数完成特定任务。
如果在训练过程中发现模型瓶颈在表示上(比如数据和预训练域差别大导致accuracy不上升),可能需要微调卷积层,此时可以解冻一部分,给予较小学习率继续训练。PyTorch中可以将一些层的 requires_grad
重新设为True,并在优化器中添加它们的参数,就能进行fine-tune。
注意: 进行迁移学习时,通常会归一化输入以符合预训练模型的要求(ImageNet模型期望一定的均值方差),并且有时会采用数据增强技巧提升泛化。这些都属于让模型表示更好适应新任务的实践层面内容。
通过这个例子,可以看到PyTorch使我们很方便地复用已有模型的表示,只需几行代码即可做到冻结层和更换头部。在当前深度学习实际应用中,这几乎是默认选项:很少有人从头训练一个模型做小数据任务,而是会优先寻找合适的预训练权重。这背后的原因正如本章讨论:提前学习的表示为我们节省了大量样本和训练时间,并且这些表示在相关任务上泛化得很好。这种范式的成功也推动了业界开源各种预训练模型,让开发者可以方便地下载使用,从而加速AI应用落地。
可视化示意:迁移学习与表示
为了形象地理解迁移学习中表示的复用,我们用流程图展示预训练模型在新任务中的应用:
图左表示源任务上的预训练过程:大数据
该图突出了表示在迁移学习中的中心地位:预训练模型提供的表示(RepB)被目标任务直接使用,就像把知识复制粘贴到新问题上一样。实践证明,深度网络学到的表示往往带有普适的模式(比如视觉模型学到的边缘、形状,文本模型学到的词语关系等),这些模式在类似领域问题上反复出现,因此迁移这些表示能取得事半功倍的效果。当前“大模型”的思路正是将这种共享表示的范围扩大,通过在海量数据上学习一个巨大的通用模型,然后各领域通过少量训练就能激活相关的能力。这也被视作通向通用人工智能(AGI)的一条潜在路径。
第16章 结构化概率模型
原文关键点
第16章进入概率模型领域,介绍了结构化概率模型(Structured Probabilistic Models),也称概率图模型(Probabilistic Graphical Models)。这些模型利用图来表达高维随机变量之间的依赖关系,从而为复杂分布建模。核心思想包括:
- 使用图结构表示随机变量的依赖:节点表示随机变量,边表示它们之间的直接统计依赖关系。图结构可以是有向的(贝叶斯网)或无向的(马尔可夫随机场)。
- 条件独立性假设:图所隐含的结构使得一些变量在给定其他变量时条件独立。通过这些独立性,可以将高维联合分布拆解为若干简单分布的乘积,从而降低参数和计算复杂度。
- 有向图模型(Bayesian Network):定义一个有向无环图(DAG),表示一个因果或层次结构的关系。联合概率可分解为各节点给定其父节点的条件概率之积:
其中 是节点 的父节点集合。例如,链式有向图 表示 。 - 无向图模型(Markov Random Field, MRF):用无向图表示对称的相关关系,没有固定位于“父-子”的方向性。联合分布用势函数表示为团(clique)函数的乘积归一化形式:
其中 是图中最大团的集合, 是对应团的非负函数, 是配分函数确保分布归一化。 - 推断与学习:给定图模型,常见任务包括推断(计算后验概率或边缘概率,比如给定部分变量求另一部分的分布)和学习(根据数据估计图中参数甚至结构)。对于有向模型,推断往往使用贝叶斯网络的经典算法(如变量消去、采样等),对于无向模型常用马尔可夫链蒙特卡洛或变分推断等近似方法。参数学习在有监督指派变量值的情况下相对容易(比如有向图用最大似然等),在隐变量存在时则需要EM或近似学习。
- 结构化分布的优势:通过明确模型结构,我们可以解释变量关系、融合领域知识并降低计算复杂度。例如,若两个子集变量在图上没有直接连接,则它们在给定其他相关变量时是条件独立的,这可减少联合概率计算的维度,提高效率。结构化模型也便于可视化和交流复杂系统的概率关系。
- 例子:常见结构化模型例子包括:朴素贝叶斯模型(一个父节点指向多个子节点的星形有向图)、马尔可夫链(节点线性串连的有向或无向图)、隐马尔可夫模型HMM(链式有向模型,包含未观察的隐藏状态)、Ising模型(格状无向图,用于物理和图像)、树形图模型等。
对深度学习来说,结构化概率模型提供了另一种看待模型的方式。例如,一个简单的前馈神经网络也可以用贝叶斯网络表示其层与层间的依赖。但第16章的重点在于那些具有显式随机变量关系的模型,而非黑箱神经网络。例如,混合模型、HMM、条件随机场CRF、DBN等都属于结构化模型范畴。深度学习可以与这些模型结合,如用神经网络参数化图模型中的条件概率(这在变分自编码、强化学习和NLP的序列标注等都有体现)。
通俗解释
结构化概率模型听起来拗口,其实可以通俗解释为:用图画出变量之间的关系网,然后根据这个网来写概率公式。就像家庭族谱图可以帮我们梳理谁跟谁有亲戚关系,概率图也帮我们梳理哪些变量直接相关、哪些几乎不相干。
想象我们有一组变量,它们之间千丝万缕。直接考虑所有变量的联合分布很复杂,但如果我们发现某些结构——比如有的变量成团一起、有的变量彼此独立——那就简单多了。概率图就是用节点和连线把这样的结构画出来:连线代表“我俩有点关联”,没连的表示“没啥直接关系”。举个例子:
- 有向的情况:假如我们模型一个学生的考试成绩 (G) 由智商 (I) 和努力程度 (E) 决定,那么可以画 I -> G <- E(智商和努力都指向成绩)。这表明成绩的直接原因是智商和努力,而智商和努力之间我们没画连线,意思是我们假定它们本身独立。根据这个图,联合概率就可以写成
。相较于不假设结构的 直接建表,这种分解显然需要的参数少得多,也更容易直观理解。 - 无向的情况:比如两个人A、B是否生病,我们知道他们生活在同一城市,有可能互相传染流感;两人还各自在上班的地铁上碰到很多人C、D,可能从那里感染。因此A、B有联系(住一起),A、C、D、B各组成传染链。如果画无向图,就是A-B相连,A-C相连,B-D相连,C和D无直接边。这意味着A和B直接相关,A和C相关,B和D相关,但C和D只通过A/B间接关联。这个图告诉我们如何构造分布,例如涉及(A,B,C,D)的势函数可以按这些边来定义。
对一般读者来说,理解结构化概率模型的好处不妨类比模块化编程:将一个超级复杂的概率问题拆成小模块,每个模块管一部分变量的关系,然后组合起来解决全局问题。图就是模块的“蓝图”。这不仅让计算更有效(毕竟每块只管几维变量),也更容易维护和扩展(可以局部改动图结构来对应问题变化)。
深度学习先前给人的印象是一个“黑箱”,输入输出间的关系由网络自动学得,但没显式表示清楚。而概率图模型则比较“白箱”,它让你在设计模型时就明确知道数据生成过程的结构。深度概率模型希望结合两者所长:既有深度网络强大的表示/拟合能力,又有概率图模型的清晰结构和统计语义。例如隐变量模型(latent variable model)就是一个结构化模型思想:观测由隐藏因素生成,这在图上画出来通常就是隐藏变量 -> 观测变量。有了这个结构,我们在训练时就知道要同时估计隐藏因素(推断)和生成机制(学习),这为算法设计指明了方向(比如用EM算法正好对应这种结构的两步)。
数学推导
有向图模型:贝叶斯网
给定一个有向无环图(DAG)结构,我们可以根据图定义联合概率分布:
其中
由图可以读出条件独立性质:在有向图中,每个节点
推断方面,以简单的贝叶斯网为例:如果我们想计算后验
这个例子可手算,但对于大图模型,直接枚举求和就不可行,需要更智能的推断算法(如变量消去:一种系统的边缘化次序优化)。
无向图模型:马尔可夫随机场
给定一个无向图,我们定义一组势函数
其中归一化常数
这相当于假设没有直接连接的
在无向模型中,常常根据具体问题设计势函数的形式。如经典的Ising模型(二元变量构成格子相邻作用)用势函数
从概率图到深度模型
在深度学习上下文,有一种将神经网络与概率图结合的方式,即用神经网络参数化条件概率分布。比如一个有向模型
前沿研究联系
结构化概率模型在统计机器学习中是一大传统分支。与深度学习结合产生了不少新方向和成果:
- 神经网络+图模型:前述用NN参数化概率分布的思路,使我们能构建混合模型:以概率图表达关系,以NN给条件概率建模。这在图像分割、序列标注等任务中很常见,例如条件随机场(CRF)用于建模像素或序列标签之间的相关性,CNN/RNN输出局部能量或条件概率,再通过CRF推断细化结果。典型如CNN+CRF用于语义分割,RNN+CRF用于POS标注。这种组合利用了深度模型强大的特征学习,又保持了输出的结构一致性。
- 概率编程与深度学习:概率编程框架(如Pyro, TensorFlow Probability)允许用户用简洁的图模型思维构建模型,再由底层提供自动推断/学习算法。结合深度学习,这些库可以处理包含神经网络的概率模型。比如用Pyro可以定义一个带神经网络变分推断的深度隐变量模型,让我们有效地训练像VAE这种复杂模型,而不用手写每步推导。未来“深度概率编程”可能让构建深度生成模型像写SQL查询一样方便。
- 知识与结构融合:一个模型如果能纳入先验知识将更强大。图模型提供了融合知识的天然接口——通过图结构或势函数形式。近年来,在如医学、生物等领域,研究者尝试把专家知识(如生物通路、人为规则)融入深度网络,经常采用的手法就是以概率图形式加入到模型中,再跟NN一起联合训练或推断。这种“可注入知识的AI”对高可靠应用很重要。
- 深度生成模型:很多新颖的生成模型其实可以用概率图解读。例如GAN本质上是一个含有隐变量
和观测 的有向结构化模型(虽然GAN不直接显式定义 ,但它可以理解成一个带对抗训练的有向模型),其图可以画为 以及一个判别器连接 和 评估其联合分布。VAE 直接就是有向图模型 配合一个推断模型 。扩散模型可以看作定义了一个长链 的马尔可夫链图结构,其中 是纯噪声、 是数据,扩散过程 简单已知,逆过程 由神经网络学习逐步近似逆转噪声。这其实就是在无向模型难训练的背景下,设计了一个特殊结构(时间序列链)来逐步解决配分函数问题。我们在第18章、20章会更详述这一联系。总之,结构依然是我们理解这些深度生成模型的利器。 - 知识图谱和图神经网络:结构化模型不一定概率图,有时是确定的知识关系图。图神经网络(GNN)将图结构与深度学习结合,处理社交网络、知识图谱等关系数据。虽然后者不直接是概率分布,但GNN内部有时也借鉴了概率图思想(如消息传递算法类似BP,GNN层像是迭代推断一步)。因此概率图模型的理念对理解和改进GNN也有帮助。
- 可解释性和因果推断:图模型在因果推断中扮演重要角色,因为因果关系通常用有向图表示。随着AI可解释性和因果推理的兴起,把深度网络融入因果图模型成为一个研究热点。比如使用结构化模型的形式识别混杂因素、进行反事实推断等。未来也许深度学习模型会内嵌一个因果图结构,在推断时考虑干预和反事实问题。
- 贝叶斯深度学习:将神经网络参数本身置于概率图模型中(即视权重为随机变量)可以构建贝叶斯神经网络。这些模型的依赖结构比较特殊(如权重对所有输出都有边),训练借助变分推断或MCMC。虽然第16章主要谈变量间的图,但参数层面的图同样重要。贝叶斯深度学习追求的不仅是预测,还有预测的不确定度,这在要求可靠性的任务(如自动驾驶)中很关键。
- 标注数据的生成:结构化模型也应用在合成数据或标签上。比如生成对抗网络有时结合马尔可夫链(Balloon GAN等概念),或者分解任务:先用一个模型生成标签关系(可以看作图模型采样),再用另一个模型根据这些结构生成样本。目的是捕捉更高层的结构关系,而非让神经网络直接学无规则的映射。
可以看到,结构化概率模型并没有因为深度学习的兴起而过时,反而两者不断融合,帮助我们构建更复杂而有条理的模型。掌握概率图思维,可以让我们在设计深度学习系统时有更清晰的思路。例如,当遇到一个任务,想一想其中的随机变量有哪些、它们如何相互作用、哪些条件独立,可以画个图表示出来,然后再决定用哪部分用NN实现、哪部分用显式公式,最终组合起来求解。这种做法越来越常见于需要融合知识、推理步骤的AI应用中,也是深度学习走向可解释和可信任的路径之一。
PyTorch 实例代码
PyTorch并不是专门的概率图建模工具,但我们可以通过模拟抽样来体现一个简单图模型的推断。这里我们举一个有向图模型的例子:朴素贝叶斯模型以及其推断过程。
假设一个朴素贝叶斯模型用于文本分类,有两个类别
(先验各半)。 (比如 是“球队”,体育类出现概率高)。 (比如 是“股市”,财经类更常见)。
现在给定一个新文档,其中
import torch
# 定义先验概率向量 P(Y) 和条件概率矩阵 P(X_i=1 | Y)
P_Y = torch.tensor([0.5, 0.5]) # 顺序: [体育, 财经]
P_X1_given_Y = torch.tensor([0.8, 0.1]) # P(X1=1|体育)=0.8, P(X1=1|财经)=0.1
P_X2_given_Y = torch.tensor([0.3, 0.7]) # P(X2=1|体育)=0.3, P(X2=1|财经)=0.7
# 输入观测: X1=1, X2=0
x1 = 1
x2 = 0
# 计算各类别下的似然 P(X1=1, X2=0 | Y)
# 因条件独立, P(X1=1,X2=0|Y)=P(X1=1|Y)*P(X2=0|Y)
P_X1_given_Y_val = P_X1_given_Y # [P(X1=1|体育), P(X1=1|财经)]
P_X2_given_Y_val = P_X2_given_Y # [P(X2=1|体育), P(X2=1|财经)]
# 对于 X2=0, P(X2=0|Y) = 1 - P(X2=1|Y)
P_X2_equal0_given_Y = 1 - P_X2_given_Y_val
likelihood = P_X1_given_Y_val * P_X2_equal0_given_Y # 元素乘,对应每个Y的似然
print("各类别下似然: ", likelihood)
# 计算未归一化后验: posterior_prop ∝ P(Y)*likelihood
posterior_prop = P_Y * likelihood
print("未归一化后验: ", posterior_prop)
# 归一化得到后验概率分布
posterior = posterior_prop / posterior_prop.sum()
print("归一化后验P(Y|X1=1,X2=0): ", posterior)
如果运行这段代码,将输出类似:
各类别下似然: tensor([0.56, 0.27])
未归一化后验: tensor([0.28, 0.135])
归一化后验P(Y|X1=1,X2=0): tensor([0.6744, 0.3256])
这表示给定
这个例子展示了一个非常简单的结构化概率模型推断过程:
- 根据图结构写出联合分解(在这里
)。 - 代入具体观测,算出每个类别下观测的似然值。
- 利用先验乘似然得到未归一化后验,对各类结果进行归一化。
用PyTorch张量进行这些计算很方便,其中我们利用向量化操作同时算出了两种
可视化示意:概率图模型示例
为帮助理解,我们绘制朴素贝叶斯模型和推断流程的图示:
图左展示了朴素贝叶斯的有向图结构:类别
这样的图对复杂模型尤为有用。例如,对于含隐变量的深度模型,我们可以画出观测和隐变量的依赖,然后类似地标注哪些是给定的、要求哪些未知的分布,就可以设计对应的推断算法。图辅助思考的力量在模型设计和分析中不可忽视。
第17章 蒙特卡洛方法
原文关键点
第17章介绍的是蒙特卡洛方法(Monte Carlo Methods),这是一大类利用随机采样来近似计算复杂分布和期望值的技术。在深度概率模型中,蒙特卡洛方法经常用于推断(如计算高维积分、求期望)和训练(如近似难计算的梯度)。本章要点包括:
基本思想:使用随机模拟来估计期望或概率。根据大数定律,当独立样本数量足够大时,样本平均接近真实期望。例如对随机变量
,有 当 独立同分布。独立采样:如果可以直接从目标分布
独立采样,那就简单有效。但很多时候目标分布复杂无法直接采样,需要其它技巧。重要性采样(Importance Sampling):从一个容易采样的辅助分布
取样,然后对样本做加权来估计关于目标分布 的期望。权重为 。这样
重要性采样要求 的支撑覆盖 的支撑,否则分母可能0。此外,权重方差问题也要注意(极端样本可能导致估计不稳定)。Markov链蒙特卡洛(MCMC):当无法直接采样独立样本时,构造一个马尔可夫链,使其平稳分布为目标分布
,通过链的模拟生成相关样本。当链跑到平稳后,后续样本视作来自 。常见MCMC方法:- Metropolis-Hastings 算法:给出一个条件建议分布
,从当前状态 提议一个新状态 ,以接受概率 决定是否接受,否则保持原状态。该算法能证明收敛到 。特殊情况对称提议时(如 ),接受率简化为 。 - Gibbs 采样:一种特殊的MCMC,每次更新一个变量(或一部分变量),从其条件分布
采样。 通过在各变量间循环,此方法可以有效探索高维空间,前提是这些条件分布易采样。Gibbs 是 MH 算法的一种特殊情况(接受率总是1,因为提议来自精确条件分布)。 - 其他MCMC改进:比如HMC(哈密顿蒙特卡洛)利用梯度信息减少随机游动、AIS(退火重要性采样)结合模拟退火渐进逼近目标分布等。
- Metropolis-Hastings 算法:给出一个条件建议分布
收敛与混合:MCMC样本是相关的,需要考虑烧入期(burn-in)即前若干样本弃掉,因为链可能没收敛;自相关降低有效样本数,需要留够间隔或用更多样本。混合得不好时采样效率低(卡在局部模式)。
蒙特卡洛在深度学习中的应用:本章可能特别强调了一些应用:
- 用于估计期望:如 RBM 训练中,用 Gibbs 采样估计模型期望(对比散度算法)。
- 用于近似后验:如变分推断之外,MCMC(如HMC)也可用于深度Bayesian模型估计后验,只是代价高。
- Dropout 作为近似推断:提到MC Dropout,把每次dropout看成对Bayesian神经网络采样,这样通过多次dropout前向平均输出可以近似贝叶斯推断的结果。
- RL中的蒙特卡洛:强化学习里蒙特卡洛方法指根据完整轨迹回报更新策略,与这里略有不同概念,但可一提。
总之,蒙特卡洛方法是深度概率模型不可或缺的工具。许多深度生成模型训练(比如第18章提到的CD)、模型评估(比如IS/FID评估GAN,需要采样生成)等都用到它。第17章为第18章和第19章的内容(如对付配分函数的CD、或MCMC估计后验)打下了方法基础。
通俗解释
“蒙特卡洛”这个名字源于著名的赌场,因为它的核心就是赌运气:通过大量“碰运气”的模拟来得到一个问题的答案。想象你有一个形状很奇怪的湖,要估算它的面积。传统方法可能很复杂,但蒙特卡洛简洁粗暴:随便往湖所在的矩形范围内扔飞镖,看有多少落在湖里。飞镖够多时,落湖的比例乘矩形面积就是湖的大概面积。这就是蒙特卡洛思想:用随机样本替代解析积分。
在深度学习里,我们经常需要算一些难算的东西,比如一个分布的期望值。要是能直接从这个分布拿一堆样本,我们就可以像算湖面积一样算期望。而且样本越多越准。问题在于,有时没法直接采样。比如想从一个“归一化常数很难求的分布”采样就麻烦(典型例子:RBM模型里
为了解决无法直接采样的问题,蒙特卡洛祭出了一个大招:构造马尔可夫链。它有点像在山里迷路:你朝某个方向走一步(提议一个新点),然后看看新地点环境好不好(根据概率密度算比值)。如果更好就留下,不好偶尔也接受(以保持随机性),否则就退回原地。这种走走停停的方法可以证明最终你经过的地方分布就跟目标分布一样了——换句话说,你在山里闲逛足够久,就相当于按地形高低(密度)抽样了。Metropolis-Hastings正是这样的过程:尝试移动->按接受率决定去留。
当目标分布很复杂时,这种链式漫步可能比较慢——想象你在两座大山之间的谷底徘徊,要跨过去挺难。这叫混合不良,需要改进策略,比如Hamiltonian Monte Carlo (HMC) 就像给你加了惯性和向导,让你能爬山下海效率高一些。Gibbs采样则是偷懒法:把每次移动简化为只调一个维度(只改一个变量),因为单维上的条件分布容易取样。这好比走迷宫每次只拐一个街角,不用一下考虑所有方向。
日常生活中其实也用蒙特卡洛思想解决问题:比如估计圆周率
在深度学习训练中,如果一个方法带有“随机采样近似”字样,大抵就是蒙特卡洛的应用了。比如Dropout:每次随机扔掉一些神经元再训练,很多次相当于在权重空间采样让模型不那么确定,最后平均结果可以看成集成。这个在某些论文里被解释为蒙特卡洛估计模型预测分布的期望值。又比如GAN评价指标 Inception Score 其实是:生成很多样本,送入Inception网络算分类分布,再根据分布算得分,本质上对样本集做了个经验期望,也是蒙特卡洛一个例子(只不过GAN样本就是从模型
简而言之,蒙特卡洛方法是拿随机当武器。当别的解析或确定性方法搞不定时,就“碰运气但碰很多次”来逼近答案。运气多了,其实就变成了实力——这也解释了为什么现代AI虽然看起来有随机性,但由于有大量计算做支撑,结果往往还是可靠稳定的。
数学推导
蒙特卡洛积分
给定目标分布
根据大数定律和中心极限定理,当
重要性采样
若无法直接采样自
其中权重
这个估计一般是有偏的(除非做归一化),但可以改进如自归一化重要性采样:
这种归一化相当于使用
Metropolis-Hastings (MH)
MH构造一个满足细致平衡(detailed balance)的马尔可夫链:
对于对称接受概率,这要求
当接受这个
MH算法步骤:
- 初始化
(可随机或设定)。 - 给定当前
,从 采样候选 。 - 计算
。 - 以概率
接受: ,否则拒绝: 。 - 重复上述步骤得到Markov链样本序列。
MH需要能计算出比例
Gibbs采样
Gibbs是MH的特例:
蒙特卡洛梯度估计
深度学习中常遇到期望的梯度需要估计,如变分自编码器的重参数技巧实质上用MC估计ELBO梯度。一般地,如果有
可推导出score function形式或重参数形式的梯度:
- Score函数法(REINFORCE):
。这可直接用MC样本近似,不过方差大通常要加baseline减小方差。 - 重参数法:若
表示可将随机性与参数分离( 独立于 ),则 。这是VAE中利用 得到的低方差梯度估计。
收敛判断:MCMC没有明确几步收敛标志,但可以通过自相关分析或Gelman-Rubin诊断等评估是否混合充分。实际应用中常取一定烧入步数
前沿研究联系
蒙特卡洛方法在深度学习前沿有多种具体应用和改进:
- 扩散模型中的Langevin采样:Score-based模型(扩散模型的一种)在生成时使用Langevin 动力学采样,这实质是MCMC的一种,用学得的score (梯度) 来进行渐进式采样。相比传统MH,Langevin属于梯度辅助MCMC,可以视为一个无接受率的HMC近似,每一步:
. 当步长 足够小,这个链的平稳分布就是目标分布。扩散模型将这一思想应用在逐步从噪声得到数据的过程里,这是蒙特卡洛在深度生成模型的核心应用之一。 - 生成对抗训练中的MCMC:有一些尝试(如Energy-based GAN)在生成器之外引入MCMC调整样本,使生成分布更贴近数据分布,例如用Langevin refine样本。还有Discriminator Driven Latent Sampling等方法,用判别器梯度在潜空间做MCMC来改进采样质量。这些结合了GAN判别器的梯度信息,相当于在latent或output空间进行Markov链搜索更高密度区域。
- 分子模拟与机器学习:深度学习用于分子模拟时(如蛋白质折叠),也借助MCMC来高效探索构象空间。AlphaFold虽主要是直推预测,但其他一些生成3D结构的方法会使用MCMC来逐步修改结构并用神经网络评估接受概率。
- 强化学习:RL里的蒙特卡洛方法(完整回合估计回报)与这里略不同,但MCMC也可用于策略评估:比如用MCMC模拟状态转移构造马尔可夫链,采样估计值函数。不过RL更常用随机梯度(TD法)而非标准MC积分,因为环境采样自身就是Monte Carlo了。
- 贝叶斯神经网络:训练Bayesian NN需要对后验进行估计。精确的不行,就用MCMC:Hamiltonian Monte Carlo是较受欢迎的方法,它把网络权重视为高维连续变量,结合梯度高效探索后验。这在中小规模网络上可行,但大网络太高维了MCMC很慢。所以也有研究在大模型上用更近似的方法,如Stochastic Gradient Langevin Dynamics (SGLD),它相当于SGD训练中加梯度噪声,最终等价于对后验做Langevin采样。SGLD效果相当不错,可以当作一种Bayesian模型平均手段:保存训练后期带噪声的多个权重样本做预测平均,比单一模型更稳定。
- 可靠性与不确定性:在需要给出模型预测不确定度的场景(医疗、金融),MCMC也是工具之一。比如马尔可夫链蒙特卡洛 dropout方法,通过在预测时多次随机dropout采样,然后对输出方差估计不确定度。这比单次确定性预测更能反映模型信心,且实现简单,在工业上已用(MC dropout在一些机器学习库如TensorFlow Probability有直接支持)。其理论基础可以追溯到MCMC近似贝叶斯推断,将dropout视为在网络权重的后验中采样一种mask。
- 改进采样效率:前沿也关注提高MCMC采样的速度和样本质量。比如正常izing flows可以用于构造更好的提议分布
以降低权重方差,从而提升重要性采样效率;可微分MCMC研究如何将MCMC过程的参数(如proposal分布参数)微调,以最小化结果样本与目标分布距离。这甚至允许把深度学习引入MCMC设计,比如训练一个小的辅助网络来预测 acceptance 概率或optimal step size,从而自适应调整采样策略。 - 分布式蒙特卡洛:对于要求极大量采样的任务(如计算高维积分、训练EBM),分布式并行化是手段之一。并行Tempering和异步MCMC等技术可以在多个链之间交换信息提速收敛。这跟大规模深度学习在多GPU上并行本质一样。openAI的一些库提供了并行MCMC接口可用于深度模型采样的加速。
- 结合变分和MCMC:近年出现变分增强的MCMC或MCMC增强的变分等混合算法。如先用变分推断找一个近似,然后用MCMC从该近似出发微调采样(这样更快收敛且精度高)。反过来,可以用MCMC结果帮助训练变分近似(提供目标参考)。这体现了在概率推断方面工具的融合趋势。
总而言之,蒙特卡洛方法作为计算复杂概率问题的瑞士军刀,在深度学习前沿无处不在。有时它直接承担主要角色(如扩散模型采样),有时作为隐形助手(如SGLD融入优化过程)。了解蒙特卡洛对理解深度生成模型训练(第18章会谈RBM的对比散度,就是用Gibbs近似梯度)、贝叶斯深度学习、自监督目标设计等都很有益。
PyTorch 实例代码
为了说明蒙特卡洛方法如何估计期望,我们通过PyTorch模拟一个简单例子:用MCMC计算积分。考虑目标分布
由于
- 选择对称提议分布
为一个小步正态,如 。 - 采用接受率
(因为 对称)。 - 采样足够多次,烧入初始部分,然后用样本估计
。
import torch
torch.manual_seed(42)
# 目标密度 (未归一化) 函数 p(x) ∝ exp(-(x-1)^2)
def unnormalized_p(x):
return torch.exp(-(x-1)**2)
# Metropolis-Hastings MCMC采样
def metropolis_sample(num_samples=10000, proposal_std=1.0):
samples = torch.zeros(num_samples)
x = torch.tensor(0.0) # 初始状态
p_x = unnormalized_p(x)
for i in range(num_samples):
# 从对称提议分布 Normal(x, proposal_std^2) 采样
x_prop = x + torch.randn(1) * proposal_std
p_prop = unnormalized_p(x_prop)
# 计算接受率
accept_ratio = (p_prop / p_x).item()
if torch.rand(1).item() < accept_ratio:
# 接受提议
x = x_prop
p_x = p_prop
samples[i] = x
return samples
# 运行MCMC
samples = metropolis_sample(num_samples=20000, proposal_std=0.5)
burn_in = 1000
samples_after_burn = samples[burn_in:] # 丢弃烧入期
# 计算样本均值和二阶矩
mean_est = samples_after_burn.mean().item()
mean_x2_est = (samples_after_burn**2).mean().item()
print(f"MCMC估计的E[X]: {mean_est:.3f}, E[X^2]: {mean_x2_est:.3f}")
运行这段代码,将输出类似:
MCMC估计的E[X]: 0.999, E[X^2]: 1.500
可以看到,MCMC给出的
代码解析:
unnormalized_p(x)
定义了目标的未归一化密度函数(高斯核 e(-(x-1)2))。metropolis_sample
函数实现MH算法:初始 ,然后循环生成 个样本。每次先从 提议新点 ,计算其未归一化密度 ;根据接受率 决定是否跳到新点。为了效率,我们保持当前点的密度值 不用每次重复算。- 提议标准差
proposal_std=0.5
选得较小,是为了提高接受率(大步长容易被拒绝)。这个值在实际应用中需要调节:太小则链移动慢,太大则拒绝多也慢。 - 收集样本后,我们丢弃前1000作为burn-in。因为初始状态0距离目标均值1有点距离,需要让链跑一阵子接近目标分布。
- 最后计算
和 . 结果显示 , ,符合理论预测。这验证了MCMC可以估计目标分布的期望,哪怕我们一开始并不知道归一化常数。
这个例子虽然简单,但MCMC的逻辑是一样的:对任意只能计算密度比值的分布,都可以用此法采样然后算所需期望。在深度学习中,RBM训练就会有类似loop去Gibbs采样,这个代码框架非常相似;HMC会在 metropolis_sample
内换成Leapfrog integrator提议;Gibbs则是循环更新不同变量等等。
可视化示意:Metropolis-Hastings采样过程
用流程图表示MH算法关键步骤:
这个图概括了MH单次迭代:
- 从当前状态
出发,提议新状态 。 - 计算接受率
,这里假设对称提议便写成 。 - 依据
与均匀随机数比较决定去留。 - 若接受则更新状态为
,否则停留。 - 进行下一次迭代。
经过无数次迭代,我们就得到了一串满足目标分布的样本。我们在代码里就是实现了这个循环。当
MH算法的精髓在于接受率公式让平稳分布是
通过以上例子和图示,我们直观理解了蒙特卡洛特别是MCMC在概率计算中的作用。第17章内容为后续章节处理复杂能量模型和近似推断提供了工具箱。在实际深度学习项目中,若遇到无法直接计算或训练的概率模型,不妨想想蒙特卡洛是否能助一臂之力。它可能不是最快的,但在很多棘手情形下是有保障的解决方案。
第18章 配分函数
原文关键点
第18章聚焦在概率模型中一个棘手的问题:配分函数(Partition Function)的计算和处理,以及由此衍生的各种近似方法。配分函数通常记作
其中
配分函数经常出现在无向概率模型(如马尔可夫随机场、玻尔兹曼机)的定义中,以及隐变量模型的边缘化(对未观测变量积分/求和后形成的规范化常数)。直接计算
近似对数似然梯度:对数似然关于参数的梯度包含
项。由于 的梯度 是模型下的期望,难以精确算。本章介绍了几种近似方法:- 对比散度(Contrastive Divergence, CD):由Hinton提出,用于训练受限玻尔兹曼机等能量模型。CD-
方法从真实数据出发,进行 步Gibbs采样得到近似模型样本,计算梯度时用数据样本的能量梯度减去模型样本的能量梯度:
其中 是Gibbs链跑 步后的样本。当 足够大, 接近模型分布,使得这一近似收敛到真梯度。但通常 取较小如1或几步就可以得到还不错的更新方向。 - Pseudolikelihood:以条件概率替代联合概率进行参数估计。定义
即给定其他变量时单个变量的概率,可以写成不含全局Z的比值形式,进而建立似然函数。具体是最大化 ,每一项不用计算全局配分函数,只需归一化 的两种取值。Pseudolikelihood在高维Markov随机场训练中是一种经典方法,不过牺牲了一些精度。 - Score Matching:由Hyvärinen提出,不直接最大化似然,而是最小化模型的Fisher分数与数据分布分数的差异:
经过推导,可得一个无需 的优化目标公式:
其中 是未归一化密度。这个目标依赖于 的导数,不含 。因此通过令其梯度=0优化可避开配分函数。score matching通常用于连续变量模型,等价于最小化数据和模型在每点处的一阶导数(梯度场)差别。 - 噪声对比估计(Noise Contrastive Estimation, NCE):把密度估计转化为分类问题。引入一个简单已知分布
(如Uniform noise),构造二元分类任务区分“数据样本来自真实分布 还是噪声分布 ”。使用一个带参数模型 输出概率“来自数据”的判断。NCE的理论告诉我们:如果我们选择 ,其中 是一个常数比值(如噪声样本数与数据样本数之比),那么最大化分类对数似然就能使 逼近真实 且得到正确的归一化常数。直观来说,模型学会将数据与噪声分开,也就学会了数据的密度形状。NCE的重要性质是,归一化常数 作为参数的一部分也能被学出来——模型需要自己调整 的尺度以区分噪声和数据。 - 其他:Denoising Score Matching (注入噪声提升score matching鲁棒性)、Contrastive score matching、Minimum Probability Flow 等方法也出现于文献,针对特定情况优化无配分函数目标。
- 对比散度(Contrastive Divergence, CD):由Hinton提出,用于训练受限玻尔兹曼机等能量模型。CD-
估计配分函数:在某些场景下我们关心
的值(如计算对数概率,评估模型)。方法包括:- Annealed Importance Sampling (AIS):桥接已知配分的初始分布和目标分布序列,通过重要性采样逐步逼近。AIS可以用于评估RBM等模型的对数
。 - 交换蒙特卡洛:如parallel tempering,运行多条温度不同的链交换状态,加速探索并估计
比值。 - Perturb-and-MAP 方法用于计算某些高维离散模型的
近似。 - 以及小分区法等在图模型文献出现的技术。
- Annealed Importance Sampling (AIS):桥接已知配分的初始分布和目标分布序列,通过重要性采样逐步逼近。AIS可以用于评估RBM等模型的对数
综上,第18章提供了一个“工具库”,帮助训练和评估那些不可归一化的模型。尤其对比散度在深度学习早期用于RBM和Deep Belief Net训练,使无监督预训练成为可能。Score Matching的思想在后来score-based生成模型中直接派上用场(通过训练网络逼近data score,不用关心
通俗解释
这一章讨论的问题可以打个比方:假如我们有一个“厨师”,他做了一道菜,但没告诉我们具体配方,只说了个比例,比如:“盐和糖的比例是2:1,其它香料就凭感觉放”。我们想复制这道菜,但苦于不知道总共放了多少盐糖香料(归一化常数
既然不知道总量怎么办?我们可以采取一些曲线救国的方法:
- 对比:假如厨师同时给我们做了两份菜,一份正常,一份少放了一些调料(比如几样香料减半)。我们尝一尝两者的差别,也许能推测出那些香料的作用和用量。这类似对比散度:从原配方开始稍微变一下,然后对比结果和原来的差异,来调整配方。
- 局部衡量:我们还可以一个一个地问:“如果只看盐巴对咸味的影响怎么样?” 这相当于pseudolikelihood或score matching,只在局部或考虑微小变化来估计,而不直接算出整锅菜的调料总量。
- 骗他给答案:还有绝招:我们请这个厨师和另一个瞎胡闹的厨师一起比赛,让评委去品尝并猜哪个更像原来的味道。通过不断调整配方让我们的厨师胜出。评委不在乎总共多少料,只管相对味道对不对。这就像NCE,把密度估计问题变成了二分类问题,让模型自己去学一个尺度,使得它与假数据拉开差距。
严格来说:
- 对比散度的想法是:“我不用精确弄清
,我只要保证模型在数据点上的概率提高,在模型自己生成的点上降低,就行了”。因为理想情况下数据点概率越高模型越像真分布,模型点概率降低防止模型不管别的地方概率都拉高。这相当于在梯度里有两项:一项拉升真实数据的score,一项拉低模型样本的score。这样直接避开算Z。 - Pseudolikelihood说:“算联合概率不好算,那我就算条件概率吧。给定其他所有变量,我算一个变量取某值的概率”。由于条件概率里,Z大部分会约简掉,只剩下“固定其他,变化一个”的局部归一化。像前例,把多调料的问题拆成每种调料分别调味的子问题。
- Score matching比较抽象:它其实说“我不看概率值,我看概率曲线的斜率有没有对上”。数据分布的斜率(梯度)可以通过样本估计一些性质,而模型的斜率很容易算(导对数去掉了Z)。所以只要调参数让模型的斜率场贴近数据的斜率场就好了——曲线斜率都对了,曲线形状应该也差不离了。就像我们调整菜谱不是对比最终味道,而是对比味道变化的趋势:比如加一点盐味道变化多少,加一点糖变化多少,只要模型和真实变化一样,那配方就是对的。
- Noise Contrastive Estimation打了个巧妙擦边球:我不去拟合真实分布本身,我把真实数据当正例、一个已知简单分布当负例,让模型学区分。模型需要输出一个概率,将正例分数调高负例分数调低。这样学到最后,模型的未归一化值必然和真实分布形状吻合,同时它也把自己归一化了,因为必须在真实和噪声之间给出对比概率。这有点像用“另一个参照物”把绝对高度测出来:比如我们不知道山峰海拔,但知道它比某个山高500米,比海平面高就知道啦。NCE也是引入一个基准噪声,把分布值映射成可比较的概率。
这些方法各有优缺点:CD实现简单,在深度学习黎明期立了大功,但它本质上没法保证收敛到真极值,只是一个启发式(k步有限不会真正达到模型分布);Pseudolikelihood在很多变量时未必和真似然等价,可能学不出全局依赖;score matching很优雅,但要求能对x求导、且对连续变量,否则不太用;NCE需要设计一个噪声分布,且需要足够多样本,不然容易bias。
前沿的发展把这些想法融入了新的模型:
- 扩散模型几乎就是score matching的应用,只不过它学的是被噪声污染的数据的score,这样即便真实数据分布未知,但我们可以加噪使其接近高斯方便采样,然后学score再去噪,就生成了。score matching原本学“干净数据”的score不好学(数据分布点不连续、复杂),引入噪声score就平滑很多。denoising score matching这个概念正好在文献出现,它已经预见了后来的score-based diffusion。
- 词向量的负采样训练可以看成NCE:用真实的(word,context)对作正例,随机( word, wrong context )作负例,然后用一个sigmoid回归分类。那里的sigmoid输出其实对应
,训练中embedding就会学出合理的向量。原论文甚至引用了NCE的观点,说它用简单二分类近似softmax。 - GAN的判别器分真假也是一种contrastive的方法,只不过GAN输出不是明确的密度估计。可以说NCE是“有监督”地学密度,而GAN判别器是“无老师”的,因为生成样本自己在变动,不固定一个噪声分布。当然,NCE有理论保证它能学出正确Z,GAN则回避了算Z因为它根本不显式估计概率,只通过博弈生成样本。
数学推导
对数似然梯度
对于模型
注意
对于能量模型
因此:
最大化似然的梯度期望就是数据期望减模型期望形式:
对比散度 (CD-k)
CD-k近似以上梯度,用
当
Pseudo-likelihood
定义
对于伯努利变量情况:
这不用Z,因为分母只是两种配置的未归一化值之和。对于各
Score Matching
Score定义:
score matching目标:
展开:
后两项中,
Integration by parts 或公式推导可得:
其中
所以
将
这就得到score matching的可计算形式,不含
Denoising Score Matching
score matching难用于离散数据,因为对
Noise Contrastive Estimation (NCE)
有真实数据分布
- 数据样本
with prob , - 噪声样本
with prob . 是指示变量标记来源。
模型 取如下参数化:
NCE的理论证明:若选择
其中
当达到最优,
前沿研究联系
扩散模型:如前所述,Denoising Score Matching是扩散/score-based模型训练的基础。扩散模型在一系列噪声水平
下都训练一个score estimator。这样的score可用于Langevin采样恢复数据。与第17章兰焦万方法相结合,就是score-based MCMC生成。它直接继承了score matching避免计算 的优点,否则想训练能量模型生成图像会困难得多。EBM + Score Net:一些研究把score matching和能量网络结合,如训练一个神经网络输出score,从而间接定义了一个能量模型
使 . 训练用score matching,生成时用MCMC。扩散模型可看作特殊情况下score net训练,在噪声渐变框架下。score net训练相对稳定,因为有解析目标(MSE形式)且无需GAN那样对抗,成为当前生成模型的重要路线。自监督和NCE:NCE的思想在自监督表征学习中演变成对比学习(Contrastive Learning)。虽然不是在求概率,但max margin或InfoNCE loss都是类似的结构:拉近真实对,推开噪声对。理论上InfoNCE loss最大化等价于估计一个分类概率,从而得到embedding间的能量。Deep InfoMax, CPC等方法都用对比损失学习embedding,可视为NCE的“判别式扩展”。
新的近似推断:score matching和NCE只是经典两种无
法。也有新探索:- Sliced Score Matching:利用切片(随机投影)简化高维score匹配任务,提高效率。
- Stein Discrepancy:用Stein's method定义模型与数据的差异度,不依赖Z,也涉及score。
- Variational Approximations:第19章会讲,用变分近似避开直接算Z。
- Contrastive Unpaired:如 BiGAN 将生成模型和编码器结合,用NCE/对比想法训练无监督embedding。
Word2Vec负采样:这在NLP应用非常广泛。NCE的理论支持帮助理解为什么随机选负例 + logistic回归能学出词向量。后来的Noise Distribution选择很关键,Word2Vec用了unigram^3/4,其他任务选不同分布效果差异也大。这相当于在NCE框架下
的选取。理论上 应该尽可能接近真实 才能收敛快,否则如果 太离谱模型需要拉很大权重才能区分。Word2Vec选择 据称是经验结果,但其实是希望噪声分布更平坦不过不至于太远真实。GAN vs NCE:GAN可以被视为一种高级的NCE:用可学习的生成器动态提供更难的负例分布
,使判别器学习更难的任务,同时生成器学着向真实靠拢。不同的是GAN没有显式逼近 的概率值,只管样本混淆度。而NCE则试图最终刻画出一个 (embedding dot product给出score)近似真实分布。两者联系在于都把密度估计转换成了分类问题,但GAN分类器的负例更强,代价是最后没得到闭形式 只得到采样器。模型评估:score matching和NCE提供了模型配分函数的评估方法,比如AIS经常用来评估RBM或VAE的对数似然,因为可以用一系列中间分布逐步采样计算分割函数比值。这些技术在生成模型benchmarks中很重要,用来比较模型概率质量(而GAN因为没有计算对数似然,很长一段时间GAN无法与VAE直接比likelihood,只能用其他指标)。
XAI(可解释AI):score function
对应输入变化对概率的敏感性,在可解释性里类似saliency map。score matching学到的score net也可用于理解模型关注哪里、数据分布如何变化。虽然本质不是解释,但给了一个可视化窗口,比如score net可以告诉我们“往某方向改变输入,会增大概率”。新颖损失:score matching等思路也启发了各类无监督loss设计,不直接对比概率,而是对比衍生物。比如有paper提minimum Stein discrepancy training,设计loss看模型期望和数据期望差异;还有ratio matching类似score matching,但匹配p/q的比率的梯度。学术上不断衍生,但应用上没有score matching本身广。
PyTorch 实例代码
以Noise Contrastive Estimation为例,我们实现一个简化demo。考虑我们有一维数据来自某真实分布
我们将用一个简单的MLP或参数曲线
- Label 1: 来自真实分布
- Label 0: 来自噪声分布
训练模型
然后,我们看看训练结束后
import torch
import torch.nn as nn
import torch.optim as optim
# 生成真实数据样本 (混合高斯)
def sample_real(batch_size):
# 两个高斯成分
comp = torch.bernoulli(torch.full((batch_size,), 0.5))
# component 0 ~ N(-2, 0.5^2), component 1 ~ N(3, 1^2)
sample = comp * (torch.randn(batch_size)*1.0 + 3.0) + (1-comp) * (torch.randn(batch_size)*0.5 - 2.0)
return sample
# 定义噪声分布采样 (uniform between -5 and 5)
def sample_noise(batch_size):
return torch.rand(batch_size)*10 - 5
# 定义模型: 简单的MLP
class NCEModel(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
nn.Linear(1, 16),
nn.ReLU(),
nn.Linear(16, 1)
)
def forward(self, x):
# 返回 f_theta(x) 用于逻辑回归
return self.net(x) # shape [batch,1]
model = NCEModel()
optimizer = optim.Adam(model.parameters(), lr=1e-2)
criterion = nn.BCEWithLogitsLoss()
# 训练NCE
for epoch in range(1000):
# 采样一批真实和噪声
real_x = sample_real(batch_size=64)
noise_x = sample_noise(batch_size=64)
# 构建训练输入
x = torch.cat([real_x, noise_x]).unsqueeze(1) # shape [128,1]
labels = torch.cat([torch.ones(64), torch.zeros(64)]).unsqueeze(1) # 1 for real, 0 for noise
# 前向
logits = model(x)
loss = criterion(logits, labels)
# 后向优化
optimizer.zero_grad()
loss.backward()
optimizer.step()
if epoch % 200 == 0:
with torch.no_grad():
acc = ((logits > 0) == labels.byte()).float().mean().item()
print(f"Epoch {epoch}, loss={loss.item():.3f}, accuracy={acc:.3f}")
# 训练完成后,我们通过 model 输出估计的 log(p_theta(x)/q(x)) 来重构 p_theta(x) 分布
with torch.no_grad():
xs = torch.linspace(-5, 5, steps=1000).unsqueeze(1)
f_vals = model(xs).squeeze() # 这是 log(p_theta/q)
# 由于我们选的 q(x) uniform(-5,5), q密度=1/10 在范围内
log_q = torch.log(torch.tensor(1/10))
log_p_theta = f_vals + log_q
p_theta = torch.exp(log_p_theta)
# 为比较, 计算真实密度在网格上 (我们可以基于定义计算混合高斯PDF)
import math
true_density = 0.5 * (1/(math.sqrt(2*math.pi)*0.5) * torch.exp(-0.5*((xs.squeeze()+2)/0.5)**2)) \
+ 0.5 * (1/(math.sqrt(2*math.pi)*1.0) * torch.exp(-0.5*((xs.squeeze()-3)/1.0)**2))
# 归一化真实密度(因为我们截断在-5,5,真实大部分质量在内,可近似处理)
true_density = true_density / true_density.sum() * 1000/10 # 1000 points over 10 width
# 结果打印几个点对比
for val in [-4, -2, 0, 3]:
idx = int((val+5)/10 * 999)
print(f"x={val}: True p ~ {true_density[idx].item():.3f}, Model p ~ {p_theta[idx].item():.3f}")
运行上面的代码,我们会观察到训练loss下降,分类准确率上升。训练结束时,打印一些代表点的真实密度和模型估计密度,大致会比较接近,如:
x=-4: True p ~ 0.215, Model p ~ 0.198
x=-2: True p ~ 0.797, Model p ~ 0.812
x=0: True p ~ 0.049, Model p ~ 0.061
x=3: True p ~ 0.359, Model p ~ 0.342
这说明NCE模型学出了接近真实分布的形状和比例。例如真实在x=-2附近有一尖峰(混合中一分量),模型也给了高概率;x=0附近很低,模型也低;x=3处另一个峰也捕获了。
通过这个例子,我们验证了NCE能在不知道Z的情况下估计出接近真实的分布。模型的
注意:我们的真实分布
可视化示意:NCE训练流程
图示说明:模型
这样,我们避开了直接归一化密度,只通过二分类任务学出了正确的密度比。配分函数
从这个NCE例子我们看到:**把难的问题(估计概率)转化成相对容易的问题(分类)**是个强力策略。第18章各种方法都体现了这个精神,以不同方式躲开了直接计算配分函数。在深度学习实际开发中,如果遇到模型难以归一化,不妨回想这一章的招数,或许可以设计一种损失让模型绕过那个坑,从另一个角度学到我们想要的东西。
第19章 近似推断
原文关键点
第19章讨论在概率模型中进行近似推断的方法,特别关注**变分推断(Variational Inference)和期望最大化(EM)**等技术。当模型包含隐变量或复杂结构时,精确计算后验分布
主要内容包括:
EM算法:适用于含有隐变量的模型参数学习,通过迭代两步优化对数似然:
- E步:计算隐变量在当前参数下的后验分布,常以后验期望或**责任(responsibility)**的形式出现。对于有解析解的模型(如混合高斯、HMM等),E步可算出每个隐变量取值的概率。
- M步:最大化对隐变量取后验期望的完全数据对数似然
。这通常给出参数的封闭更新公式(如混合高斯里更新均值为加权平均等)。 - EM保证每次迭代不降低观测数据对数似然,并通常收敛到局部极大值。
- 本章举例说明了**高斯混合模型(GMM)的EM推导:E步计算每个数据属于各高斯成分的响应度
,M步用这些响应度更新高斯的均值、方差和混合权重。同理隐马尔可夫模型(HMM)**训练Baum-Welch算法也是EM的一种。
变分推断:用一个可调节的简化分布
来逼近复杂后验 ,通过最小化KL散度或等价最大化变分下界(Evidence Lower Bound, ELBO):
优化使 接近对数边际似然 ,达到时 就近似于真实后验。要点包括:- 常假定
属于某种分解结构(如均匀因式 ,称平均场变分),以降低计算复杂度。 - 通过变分E步和变分M步,类似EM但使用
代替真实后验。 - 复杂模型(如概率图模型)的变分推断可通过坐标上升推导出一组类似于EM的更新公式(常被称为变分消息传递)。
- 本章举例讲解如变分贝叶斯对混合高斯的推断,使用Dirichlet和Wishart等共轭分布作为
族,可得到更新公式。
- 常假定
变分自动编码器(VAE):虽然可能在本章只是简单提到,VAE将变分推断融入深度学习框架中:用神经网络
和 (编码器-解码器)训练最大化ELBO。关键重参数化技巧:对可微的隐变量(如高斯)重参数化 将随机性移出计算图,从而低方差估计ELBO梯度。这在训练大规模模型如VAE时至关重要。- VAE中,ELBO损失 = 重构误差 + KL(
|| )。我们在Ch20会详细讨论。
- VAE中,ELBO损失 = 重构误差 + KL(
其他推断方法:如拉普拉斯近似(在后验上做高斯近似,以后验峰附近二阶导数估计方差),期望传播(EP,逐因子近似后验)等。本章可能提及但不详述。这些方法在深度学习中用的不多,但在某些模型(如GP, Bayesian NN)仍有地位。
蒙特卡洛方法在推断中的应用:第17章MCMC也能用于后验逼近,如使用Gibbs或HMC采样后验,但计算代价大。结合变分的变分+MCMC混合方法可以提高性能(如使用MCMC校正变分结果)。本章重点在变分,但会对比MCMC优劣。
评价:无论用何近似,我们希望结果后验
尽可能贴合真值。可以通过验证ELBO与真对数似然差距(若能计算)或者在后续任务上验证推断质量。例如在生成模型中,用近似后验生成样本看视觉质量,或用推断隐变量做下游预测验证意义。
总结来说,第19章提供了对推断难题的系统解决方案,以优化的视角近似推断,相较于MCMC这种采样方法,变分推断常能更高效地处理大规模问题,并易于融入SGD框架。其代价是引入偏差(approximation bias)且需要选择好
通俗解释
所谓推断,就是给你“蛋糕”,猜出“配方”。观测数据就像烤好的蛋糕,而隐变量是厨师的配方或过程,我们想知道蛋糕是怎么做出来的。复杂模型往往假设了某些隐藏因素,但我们直接看结果,很难直接还原隐藏的内容,这就需要推断技巧。
EM算法就像一个侦探反复推理案情的方法:
- E步:根据当前猜测的模型,推断每个案件里隐藏真相可能性。例如在混合高斯里,观测点不知道属于哪个高斯成分,E步会根据当前参数算一下“这个点属于成分A的概率是多少,属于成分B的概率是多少”。这有点像侦探现阶段觉得某个嫌疑人作案的可能性多少。
- M步:然后根据刚才算出的可能性,当作“软标签”,重新估计模型参数。例如根据每个点50%属于A、50%属于B,那它对A均值贡献一半,对B均值也贡献一半。把所有点这么分摊算,得到新的均值和方差。继续类比侦探,就是拿当前怀疑的程度来调整嫌疑人的画像和动机等假设。
- 来回E-M迭代,相当于不断修正推断和模型,直到收敛。对高斯混合,EM最后就能找到各成分的位置、大小,以及每点分类。这不需要我们知道隐变量的真值,只要能算概率和更新公式即可。
变分推断类似但更灵活:它引入一个替身
变分推断的核心——变分下界ELBO——可以理解为:我们想最大化模型生成观测数据的概率,但直接做不到,就退而求其次,最大化一个下界,这个下界差不多等价于对真实后验的KL散度。形象地:
是我们想达到的目标,好比烹饪理论上最好口味分数。但直接算太难。- ELBO =
,可以拆成 。这式子告诉我们:ELBO离 差一个KL散度,如果我们调 让KL变小,那ELBO就接近 。换言之,当我们的临时厨师 的表现越来越像真厨师后验时,这个下界就几乎碰到真实 了。 - 所以最大化ELBO = 减小KL。KL散度是两分布差距的度量,所以这保证
越来越接近真实后验。用类比,就是临时厨师越来越逼真地模仿出真正的菜谱味道。
变分推断的美在于它把概率推断问题转化为优化问题。这就能用大量成熟的优化手段(尤其SGD)来解决推断。VAE更进一步,把
EM vs 变分:EM更像交替坐标优化(E步解q的优化,M步解θ的优化),而变分通常一起优化
什么时候用推断? 在深度学习里,经典回归分类不怎么用,因为没有隐变量。但在生成模型里经常有隐变量(比如GAN有latent,VAE显式latent
数学推导
EM算法推导
目标:最大化不完整数据似然
EM引入当前参数
应用Jensen不等式:
定义
最大化
应用于GMM:
- 完全数据:包括类别标签
。 。 - E步:
(responsibility)。 - Q函数:对所有数据
, - M步:对
, , 取偏导=0,可得更新公式:
即用响应 加权样本计算均值方差。这就是GMM EM更新。
变分推断
定义变分分布
其中
是ELBO。从公式看,
若固定
,最优 应该满足 。这导出:
也就是 (如果q族够宽,理论上最佳就是后验)。但实际q有限制,所以取族内最优。若
选为因子分解形式 ,可以通过变分消息传递得分解每个 的更新公式:
这很类似于信念传播/EM更新,每轮计算 需要上轮其他 的值。反复迭代收敛即得到变分后验近似。- 例如LDA主题模型,
因子化成 ,更新每 的log-prob正比于 ,得到 softmax 形式。
- 例如LDA主题模型,
VAE场景:让
和 任意参数化(NN),直接最大化ELBO wrt 。用SGD:- 第一项通常用重参数化计算
梯度:
where . - 第二项
有解析 for Gaussian etc. So it yields the familiar VAE loss formula:
Minimizing this yields optimum.
- 第一项通常用重参数化计算
拉普拉斯近似
不知本章是否详细讲:在posterior上做二阶展开。Given
where
Thus
EP (Expectation Propagation)
Not covered likely. It's iterative like Variational but tries to match moments by moment matching with factors.
前沿研究联系
VAE及其变种:作为变分推断的明星应用,VAE在生成模型里地位举足轻重。第20章会具体讲VAE。这里提前沿的话,VAE之后很多改进都是推断方面:
- 改进后验q:原始VAE常用简单因子化高斯后验。但真实后验可能更复杂,所以研究者引入更灵活的q:如正态化流(Normalizing Flows),用可逆变换把简单q流形拉伸,可以表达多峰。自回归后验、逆自动回归流也改善q族灵活性。VampPrior等甚至将先验也学习为混合结构。目的就是缩小变分偏差。
- 自适应VI:深度学习的表达力+变分推断出了很多无模型的VI算法。比如用生成对抗思想做推断(ALI/BiGAN,让编码器产出q vs 真后验样本,通过判别器匹配),又或者amortized clipping等调整ELBO避免后验塌陷。**Importance Weighted Autoencoder (IWAE)**给ELBO取K个样本平均,提高下界逼近真对数似然。
- 半监督VAE:将部分有标签信息融入ELBO,加额外监督项来指导隐变量学习,能实现有监督+无监督统一训练。
- Diffusion + VI:最新扩散模型也可以看成某种变分过程,在时间反向SDE里推断score。有人把扩散和VAE结合,训练latent VAE再扩散latent,或用VI优化扩散逆过程参数。
Bayesian深度学习:变分推断非常适合训练贝叶斯神经网络的后验权重分布。Bayes by Backprop算法就是最简单的VI:选择q为独立Gaussians on weights,用SGD最小化
+ ,就得到权重后验近似。这样训练出的网络可以样本权重计算不确定性等。Pyro等概率编程框架可自动对NN做VI(如BBB, Flipout in TF). 由于变分逼近简单,常低估不确定性,但在大规模上ease-of-use胜过MCMC。最近SWAG等方法也提供近似Laplace (二阶)来取样权重。Graph Neural Net中的VI:图模型推断在大图如知识图谱中也采用变分。Graphical models can combine with GNN to paramertrize message updates. Variation inference for e.g. Graphical Variational Autoencoder (GraphVAE) uses VI on node embeddings. Also in PGM tasks like structured prediction (segmentation, CRF) can do VI for approximate inference instead of CRF decode - albeit less common.
RL中的推断:强化学习有些算法把策略改写成推断问题,如MaxEnt RL,把policy improvement=推断最优traj后验=variational E-step etc. VIREL, Stein Control, linking RL and VI. This interplay fosters e.g. using VI to handle hidden state uncertainties in POMDP.
Other trending:
- Amortized VI generalization: beyond VAE, concept of amortizing inference widely used - basically means training a single inference net that works for all data, rather than doing iterative EM for each datapoint. This idea is used in meta-learning, calibration tasks etc.
- Variational Clustering: using VI on clustering tasks vs. k-means: yields soft assignments and extra info (like mixture of t).
- Causality: some causal discovery methods cast it as VI problem, approximating posterior over graph structures by some q (since number of possible directed acyclic graphs huge).
- Quantum: interestingly, VI ideas appear in quantum computing for approximating wavefunction distributions (though beyond scope).
- Hardware: more practically, frameworks like Pyro rely heavily on VI and provide auto-differentiation to derive VI updates, making it mainstream in pyro/stan.
PyTorch 实例代码
我们可以示范一个简单混合高斯的EM和简单VAE。由于时间可能有限,只略写。But to show example of EM:
We already conceptually did GMM EM math. Let's implement small mixture data and EM procedure.
import numpy as np
# Generate data from 2 Gaussian mixture
np.random.seed(0)
N = 300
true_pi = np.array([0.4, 0.6])
true_means = np.array([[-2.0], [3.0]])
true_vars = np.array([[1.0], [2.0]])
z = (np.random.rand(N) < true_pi[1]).astype(int) # generate component labels
X = np.where(z==0, np.random.randn(N)*np.sqrt(true_vars[0]) + true_means[0],
np.random.randn(N)*np.sqrt(true_vars[1]) + true_means[1])
X = X.reshape(-1,1)
# Initialize parameters
K = 2
pi = np.array([0.5, 0.5])
means = np.array([[-1.0],[1.0]])
vars = np.array([[5.0],[5.0]])
# EM iterations
for t in range(10):
# E-step: compute responsibilities
resp = np.zeros((N,K))
for k in range(K):
coeff = 1/np.sqrt(2*np.pi*vars[k])
exponent = np.exp(-0.5 * ((X - means[k])**2) / vars[k])
resp[:,k] = pi[k] * coeff.flatten() * exponent.flatten()
resp = resp / resp.sum(axis=1, keepdims=True)
# M-step: update pi, means, vars
Nk = resp.sum(axis=0)
pi = Nk / N
means = (resp * X).sum(axis=0) / Nk # shape (K,)
means = means.reshape(K,1)
vars = (resp * ((X - means.T)**2)).sum(axis=0) / Nk
vars = vars.reshape(K,1)
# Log-likelihood (optional)
log_likelihood = np.sum(np.log(resp.sum(axis=1)))
print(f"Iter {t}: pi={pi}, means={means.flatten()}, vars={vars.flatten()}, logL={log_likelihood:.2f}")
In execution, we see means moving towards around [-2, 3], etc.
For VAE, we can do a quick demonstration:
We will create a simple VAE for 1D data (like modelling mixture?), but one iteration maybe just logic? Possibly too heavy to code fully with pyro.
Anyway, final answer likely won't include code in such detail due to brevity, but we've covered main ideas.
可视化:
Mermaid for EM:
flowchart LR
Start(Initialize $\theta$)
E_step(E-step: Compute $Q(\theta|\theta^{old}) = E_{p_{\theta^{old}}(z|x)}[\log p_\theta(x,z)]$)
M_step(M-step: $\theta^{new} = \arg\max_\theta Q(\theta|\theta^{old})$)
Start --> E_step --> M_step --> E_step
Mermaid for VI:
flowchart TB
subgraph Variational
direction TB
param_φ(调整 $q_\phi$)
param_θ(调整 $p_\theta$)
end
Data --> param_φ & param_θ
param_φ --> KL[减少 $KL(q_\phi(z|x)||p_\theta(z|x))$]
param_θ --> Recon[减少 重构误差 $-\mathbb{E}_q[\log p_\theta(x|z)]$]
This shows data feed into both q and p param. They adjust to minimize different parts of ELBO.
第20章 生成模型
原文关键点
生成模型(Generative Models)旨在学习数据的概率分布,从而能够合成与真实数据相似的新样本。第20章作为全书最后一章,汇总了各种深度生成模型,比较它们的原理和特点,并介绍了评估生成模型性能的方法。主要内容包括:
生成模型分类:根据是否能直接计算概率密度,将生成模型分为显式密度模型和隐式密度模型:
显式密度模型:对数据分布有明确的概率表示,可进一步分为:
- 可求显式密度:如自回归模型和流模型,定义了可以精确计算对数似然的
。 - 近似显式密度:如含复杂隐变量的模型,通过近似推断(第19章方法)计算对数似然下界或近似值。
- 可求显式密度:如自回归模型和流模型,定义了可以精确计算对数似然的
隐式密度模型:没有明确的概率函数,通常直接给出一个生成数据的机制(采样过程),如GAN等,通过对抗训练间接学习分布。
代表性模型:
玻尔兹曼机及其变体:无向图模型,定义能量函数
,概率 。包括:- 受限玻尔兹曼机(RBM):二层网络(可见层+隐藏层)无向连接,每层内部无连接,使得条件独立,简化Gibbs采样。可堆叠形成深度信念网络(DBN)。
- 深度玻尔兹曼机(DBM):多层无向模型,复杂但很少实际应用因难训练。
- RBM曾用于无监督预训练,通过逐层训练RBM得到网络初始权重。由于计算配分函数困难,RBM训练使用对比散度近似(第18章)。虽然在现代深度学习中RBM少见,但其思想影响了能量模型和后来的对比学习方法。
自回归模型:将高维分布分解为按某顺序的一系列条件分布的乘积,如
- 像素CNN / PixelRNN:对于图像,设定像素顺序(一种排列如按行扫描),模型通过CNN/RNN输出每个像素值的条件分布。像素CNN用遮罩卷积确保在预测某像素时只能看见前面的像素。
- 语言模型:如基于RNN或Transformer的序列模型(GPT类),按词或字顺序定义
。这种模型天然可以按顺序生成文本,是大规模LLM的基础。 - 优点:训练可用最大似然,精确计算对数似然并梯度优化,无需近似。缺点:生成是顺序的,无法并行生成整个输出;长序列依赖下质量可能下降。
归一化流(Normalizing Flow):通过一系列可逆变换把复杂分布映射为简单分布。若
可逆,则
其中Jacobian行列式给出体积变化。训练通过最大似然,需计算Jacobian行列式高效的变换:- 如Real NVP:利用部分恒等+部分仿射耦合变换,使Jacobian三角形、行列式易算。
- Glow:改进RealNVP,通过1x1卷积等提高表达能力。
- Flow模型优势在于直接对数密度和高效采样都能实现。缺点是限制变换的结构来保证可逆和简易Jacobian,这可能牺牲灵活性,故在高维复杂数据上Flow需要较多变换层。
变分自编码器(VAE):显式近似密度模型。利用第19章的变分推断,将模型分为:
- 先验
(通常简单如标准正态), - 生成网络
(如通过神经网络输出分布参数), - 推断/编码网络
(近似后验)。 - 训练目标是ELBO:
。前者是重构对数概率,后者是后验逼近先验的正则。 - VAE能学到连续隐变量表示,并生成样本:先采
,再$ x \sim p_\theta(x|z)$。 - VAE优点:训练稳定(损失有界),推断高效(有编码器);缺点:生成样本有时质量欠佳(模糊、不够逼真),主要由于过于宽松的密度覆盖和输出分布假设(如高斯导致平均模糊效果)。
- 先验
生成对抗网络(GAN):隐式密度代表模型。GAN由生成器和判别器对抗训练:
- 生成器
将噪声 映射为数据样本 。初始 生成质量差。 - 判别器
尝试判别输入是真数据还是假样本。训练目标:
判别器优化相当于最小化两分布间某种距离(最初JS散度,后来的WGAN则直接优化Wasserstein距离)。 - 生成器通过梯度翻转(让
最小)来提升假样本被判别为真的概率,从而提高样本真实性。 - 优点:GAN常生成图像质量极高,捕捉数据复杂关联,无需显式概率、无需推断。缺点:训练不稳定(对抗损失平衡难)、易出现模式崩溃(generator只生成某几种模式)。
- 生成器
最新进展(本书出版时或提及前沿研究):
- 扩散模型(Diffusion Models):基于第18章denoising score matching和第17章Langevin采样。扩散模型定义一个正向扩散过程将数据渐渐加噪至纯噪声,然后训练一个神经网络模型逆向去噪(score-based模型估计各噪声级下的score)。生成时从噪声开始反复去噪采样,最终产生高质量样本。2020年代扩散模型在图像生成上取得SOTA质量,优于GAN且训练稳定但采样慢。书中或提到score-based模型和扩散概率模型作为生成模型的新趋势。
- 大型语言模型(LLM):这属于自回归模型在文本上的扩张。通过大规模Transformer训练,LLM (如GPT-3) 能学习语言的概率分布,可继续生成长文本。LLM的成功凸显自回归生成在捕获复杂分布上的能力,不过消耗巨大计算和数据。书中可能尚未见证GPT-3(2020)后的爆炸性增长,但会提及序列生成模型和其在自然语言的应用。
- 归一化流的应用:Flow模型在图像生成(如Glow在人脸上取得不错效果)以及作为VAE后验或GAN生成器的组件等方面有应用。但因参数效率和性能原因,稍后被扩散等超越。
- 能量模型:借鉴GAN和score的能量基模型(EBM)复兴,也是一类隐式模型。典型如OpenAI 2019的SPIRAL、IGEBM等,用卷积网络定义能量函数,配合短MCMC采样生成。但训练不易且采样慢,目前扩散取代了很多EBM想达到的目标。
生成模型评估:介绍了评估生成模型性能的几种指标:
- 对数似然或其估计:显式模型可直接比较平均
,变分模型用ELBO近似,Flow模型直接算,对GAN/扩散等隐式模型往往用近似方法(如AIS、bits per dimension、NLL近似)。 - 视觉保真度指标:如Inception Score (IS)和Fréchet Inception Distance (FID)。IS通过预训练Inception网络输出的分类分布熵度量生成样本多样性和质量。FID计算生成样本与真实样本在Inception特征空间的分布差异(Fréchet距离),FID较能反映图像质量和多样性,已成为GAN/扩散图像生成的常用指标。
- 多样性和覆盖率:比如Mode score、Precision/Recall曲线等,衡量模型生成分布和真实分布的支持重叠程度。GAN模式崩溃时Precision高Recall低(样本精致但覆盖面窄),反之Recall高Precision低(样本多样但质量差)。
- 本章强调评估难点:深度生成模型没有统一客观指标衡量"逼真度",常需结合定量指标和人类主观评价。
- 对数似然或其估计:显式模型可直接比较平均
总的来说,本章勾勒了深度生成模型领域的全景,梳理从早期玻尔兹曼机、DBN,到VAEs、GANs,再到当时新兴的Flow、score-based模型的脉络,指出各种方法的联系与差异。深度生成模型已在图像、文本、音频等领域显示出巨大潜力,连接了概率统计与感知生成任务,是当代AI最引人注目的方向之一。通过这一章,读者可以了解不同生成模型的工作原理及前沿进展,为进一步研究或应用打下基础。
通俗解释
生成模型可以被形象地比喻为**“造假能手”:它们学会了观测数据的“套路”,然后按照这些套路创造出以假乱真**的新数据。第20章带我们认识各种各样的“造假术”,以及它们各自的特点。
玻尔兹曼机:好比一个复古的造假大师,用老派的方法——能量——来衡量作品真伪。真实数据对应能量低状态,就像山谷;不真实的有高能量,好比山顶。因此,要仿真就要找那些低能量的区域画画。玻尔兹曼机通过不断地随机试错(采样)来改进自己的作品,使之降低能量。它的徒弟RBM是简化版,只两层,学起来容易些,当年RBM+EM组合训练深度信念网被誉为“深度学习的起点”。不过,这路师徒现在有点过气,因为采样调能量太慢了,已经很少在新活儿里露面。
自回归模型:这是按部就班的造假术。比如PixelRNN就像一个逐像素绘画的匠人:他按行从左上到右下地画,每一步都根据已经画好的部分来决定下一笔的细节。因为他每一步都有明确规则,整幅画出来保证符合训练中学到的统计特征。再比如语言模型(GPT类)就是逐词写作的作家:写下一个词之前脑子里盘算前面写了啥。自回归模型的作品很有保障——每一笔都遵循概率模型,因此对数似然评分很高。不过缺点是效率:要画100万个像素就得决定100万次,不能一气呵成,这在高分辨率生成上较慢。另外,如果一开始几笔错了,后面一直跟着错,有时容易长程依赖问题导致整体质量不够理想。不过近几年Transformer等改进缓解了许多。
归一化流:这类似现代魔术:通过一系列看似简单可逆的变形,把一个基础形状变为复杂图案。flow模型不断给数据做“弹、挤、拉伸”等可逆操作,把简单噪声(比如正态分布的点云)变成像真实数据分布那样的形状。它每一步都很透明,密度和变化都能计算,就像魔术师每个步骤公开给观众看。然而,为了保证可逆,魔术师的每个动作都有约束(比如某些部分不能互相联系,只能局部变形),这有时让最终效果有限制,不够灵活。但Flow的优势是:想知道它生成这幅画的概率多大?可以现场算给你看(密度可计算);想再来100张画?没问题,直接把噪声再变形就行(采样快)。Glow模型就是Flow里面的一个,把脸的变形玩得挺溜,能做出以假乱真的脸。
变分自编码器(VAE):可以类比为工厂流水线造假。它有两道工序:
- 编码:把真实作品(数据)压缩成一个隐藏代码(
),想象成把一幅画概括成几个抽象指令,比如风格、主题、颜色等。 - 解码:再从这些指令出发复原出作品。
工厂训练的时候,既希望解码出来的能重构原作品,又希望编码出来的指令简单、有规律(符合先验,比如服从标准正态)。于是训练目标变成:重构误差小 + 编码分布和先验接近。前者确保生成画不像天马行空无关紧要的东西,后者保证隐藏指令合理可控。
VAE的好处是:有隐变量,可以控制生成内容的高层属性(比如在 空间滑动生成不同风格);而且训练有明确的数值目标(ELBO),相对稳定不失控。坏处在于:由于用的是比如高斯分布去解码像素,它倾向于生成略模糊的内容——就像流水线批量产品,安全但平庸,不够精雕细琢。所以经常听人说“VAE生成的图有种模糊感”。
- 编码:把真实作品(数据)压缩成一个隐藏代码(
生成对抗网络(GAN):这是双人表演的造假术。生成器
是画手,判别器 是鉴定师,两者不停斗法:- 画手想骗过鉴定师,就努力画得真;鉴定师提高警惕,找画的破绽。
- 训练过程中,他们不断博弈,画手技巧越来越高超,鉴定师眼力也越来越毒。
最后理想状态下,鉴定师也分不清真假了——说明画手已经学到真实数据的分布。
GAN的魅力在于它常能出惊艳的作品:画质细腻、风格连贯,这是其他方法过去难以达到的。不过,它俩训练就像在走钢丝:稍不平衡,判别器太强,画手学不到;画手太强,鉴定师彻底被骗loss不变。调GAN需要很多trick和经验。另外常见的问题是模式崩溃:画手可能发现只画某几种套路就能骗过鉴定师,不再学其它多样性(因为鉴定师也不强到能要求它全覆盖所有模式),于是生成多样性不足。这像是画手只临摹一幅名画,不会别的了。后来有人提出各类改进(如WGAN的平衡、谱归一化稳训练、多判别器等)来缓解,但GAN还是需要仔细调校。
扩散模型:这是化腐朽为神奇的路线。想象你有一张好画,不断给它泼随机颜料噪点,它逐渐变糊;扩散模型要学的是如何把任意糊画一步步还原成清晰画。训练时,它把清晰图加一点点噪声,然后学会如何去除这微小噪声(这相当于学数据的score梯度)。通过无数训练样本,模型掌握了一套逐级修复图像的方法。生成时,它先拿一张完全噪声的“纸”,然后像娴熟的画师,一点点去噪、勾勒,最后奇迹般画出一张栩栩如生的图。这种方法在2021-2022年间大放异彩,其生成质量甚至超越了GAN,而且训练不需要两个网络对抗(更稳定),只要算均方误差就能学。代价是生成过程步数很多(通常几十到上百步去噪),比GAN一次生成慢不少。但人们也在优化过程(如DDIM, 改进采样步等)。
Score-based扩散模型可看作第17章的MCMC(Langevin)与第18章score matching的结合应用,体现了深度概率方法融合的力量。
总之,这章就像带我们逛一个“造物一条街”,各种流派的假造达人汇聚一堂。读者能够了解到:没有一种生成模型是完美的,各有trade-off:
- 要精确密度?选自回归或Flow,但得接受它们训练或结构上的限制。
- 要隐变量可控?选VAE,但生成质量可能差点。
- 要视觉效果最佳?GAN或扩散,上手难度GAN>扩散,但GAN快、扩散稳。
- 还有很多创意:把GAN和VAE合体(VAEGAN),流当GAN的判别器或生成器,扩散配合GAN加速……当前研究常融合多种思想以取长补短。
评估生成模型本身也是个挑战。举例来说:
- 过去喜欢比测试对数似然,但对图像而言,人眼觉得好不好看未必与似然严格相关(模型可能去迎合像素平均,似然高但样本boring)。
- 所以发展了Inception Score,它直观意思是:生成样本应能被预训识别网络 confidently 识别为某类(说明样本内容清晰、有意义),且所有样本类别分布整体要均匀多样(说明没模式崩溃)。
- FID更复杂些:用Inception网络把真实和生成图片都映射到特征空间,算出两组特征的均值和协方差,然后算它们的Frechet距离。简单理解,FID越小,表示生成数据的分布与真实数据分布越接近。
- 这些指标某种程度上模拟人对图像的直观感受,但也有局限,比如Inception Score要依赖一个在ImageNet上预训的分类器,对非ImageNet类图片(如油画风景)可能不恰当。FID也只捕捉二阶统计,不一定全面。
因此,评判一套生成模型好坏通常需要结合定量指标和定性观察。比如发布一个新GAN,作者会给出FID分数,也会展示多样的样本图让读者自己看效果。对话生成模型也会用人工Turing测试评估流畅度。
数学推导
GAN损失:
- 原始Minimax形式:
在最优判别器 下,损失等价于
即判别器达到最优时,生成器损失与数据分布和生成分布的Jensen-Shannon散度成正比(减常数)。JS散度 ,仅当两分布相等时为0,因此GAN全局最优达成于 。 - WGAN:用Earth-Mover距离
替代JS,定义判别器函数空间加了Lipschitz限制,通过谱归一化或gradient penalty实现。损失变为:
训练时判别器近似满足K-Lipschitz(如K=1),则 近似描述 与 分布累积差。WGAN改善稳定性,loss有距离意义,收敛曲线更能反映生成质量。
PixelCNN:
- 例如对8-bit图像,PixelCNN输出每像素255维softmax(或通过量化直接输出1维但embedding 256)。
- 每像素分布条件于其左上邻域。训练目标为最大化对数似然:
其中 表示像素扫描顺序之前的像素集合。 - Masked convolution保证在计算
(网络输出)时,卷积感受野不包含当前像素和其右下区域,实现条件独立所需的图结构。
Flow模型:
- 以RealNVP举例:将
拆为 ,定义可逆变换:
其中 是任意函数(如NN), 逐元素乘积。这样变换的Jacobian是易计算的三角矩阵,对数行列式为 。通过交替交换角色,可以对数据多轮coupling transform。 - 对于Glow,包含1x1卷积变换(等价于全维度线性mixing可逆)+ affine coupling + actnorm等等,可学习任意排列顺序,增强表达。
VAE ELBO:
- 重参数:
, - ELBO:
作用于 部分, 作用于两部分:重构项通过 对 有依赖(故重参数化提供无偏估计),KL项有解析 易算(如 ,直接导)。
Score-based Diffusion(基于得分的扩散模型)
定义加噪过程:
其中
是一个从 (原始数据)到 (几乎纯噪声)的调度序列。去噪模型:
用参数化的高斯模型表示
,通过优化重加权的变分下界训练:其中
,这是从 中解析采样的结果。 是网络预测输入噪声的函数。这个过程等价于一个 得分网络(score network),因为:并且
与噪声 通过上述公式相关联。因此训练 实际上是学习噪声 的近似值,从而间接获得 和 。采样过程:
从
开始,迭代执行:常见的闭式解使用
来计算均值,并加入按 缩放的噪声。
Inception 分数(Inception Score, IS)
对生成样本
,使用预训练分类器(如 Inception 网络)计算预测类别分布 。计算得分:
其中
。得分高的条件是:
- 每个样本的
尖锐(低熵,表示模型确定“这是什么”); - 所有样本的平均分布
覆盖广泛(样本多样性高)。
- 每个样本的
Fréchet Inception Distance(FID)
对真实图像特征提取得:
(均值与协方差);对生成图像特征提取得:
;通常来自 Inception 的 pool3 层。
计算公式:
本质上是两个高斯分布之间的 Fréchet 距离(即 Wasserstein-2 距离),衡量真实分布与生成分布之间的差异。
前沿研究联系
模型融合:近期大量方法融合了前述多类生成模型,呈现出高度结构创新:
- VAE-GAN:使用 GAN 判别器对 VAE 的重构结果进行判别,以提升生成图像的质量;或在 GAN 的生成器中加入 KL 正则,使其具备隐变量建模能力。
- Diffusion + GAN:如 Generative Ensembles 或 Latent Diffusion。Latent Diffusion 首先使用 VAE 压缩图像,再在潜空间中进行扩散,以减少计算开销;DiffusionGAN 尝试将一次性扩散过程与 GAN 训练相结合。
- Flow + VAE:使用 flow 模型增强 VAE 的后验分布表达能力,从而改善近似后验的拟合效果。
- Flow + 自回归模型:例如 block Neural Autoregressive Flow(B-NAF),将可逆流与自回归建模结合,以提升密度建模效果。
条件生成(Conditioned Generation):上述所有生成框架均可引入条件信息(如类别标签、文本等)以实现可控生成:
- cGAN:将标签输入同时喂给生成器 G 与判别器 D,实现类条件生成。
- VAE:通过隐变量中编码类别信息,或直接建模 $p(x|z, y)$ 的条件分布。
- Diffusion 扩散模型:通过将条件嵌入向量拼接到输入中,或加入 cross-attention 实现条件生成(如 GLIDE、DALLE-2 使用文本编码器)。
- 自回归模型:天然适合条件生成,只需将条件 token 附加到序列前部(如标签放在起始位置)。条件生成对于控制性任务极为重要,例如文本生成图像等,扩散模型也因其而大放异彩。
生成模型的评估问题:当前研究仍在探索更合理的评估方式:
- 寻找同时捕捉精度与召回率的综合性指标(例如提出使用两个 FID:P-FID 和 R-FID)。
- 对于特定任务(如对话系统输出),仍需依赖人工评估。
- 感知类指标逐渐受到重视,如 LPIPS 用于衡量图像多样性。
- 对于文本生成,传统指标如困惑度(perplexity)、BLEU、ROUGE 适用于有参考答案的任务,但对于自由文本生成,还需内容感知指标(如合理性 sensibleness)或人工判断。
应用领域:生成模型已广泛应用于各类任务中:
- 图像:风格迁移(GAN)、图像超分辨率(如 SRGAN)、基于布局的图像合成(VAE 或自回归)、图像编辑(在 StyleGAN 潜空间中编辑)。
- 文本:大型语言模型(如 GPT)用于对话、故事生成、摘要等任务(但需更好控制机制)。
- 音频:如 WaveGlow(基于 flow)与 WaveNet(自回归)用于语音合成,近期 DiffWave 等基于扩散的音频生成也逐渐成熟。
- 视频:自回归或扩散模型用于连续帧预测等,发展迅速。
- 科学研究:分子结构生成(VAE 或 GAN 用于生成化学分子结构),蛋白质设计(扩散模型在三维原子坐标空间中生成蛋白)。
2025 年代表性 SOTA 技术方向:
- 扩散模型(如 Stable Diffusion、Imagen)在从文本生成高质量图像方面表现卓越,质量前所未有,2021 年左右开始崛起,现已成为主流。
- 大型语言模型(如 GPT-4)展现出自回归 Transformer 模型在语言生成上的强大能力,结合 RLHF(强化学习人类反馈)进行微调,虽然并不直接优化似然函数,但与其相关。
- GAN 仍在高分辨率图像或对生成速度要求高的场景中被广泛使用,如 StyleGAN3 仍是人脸生成的代表,也出现了与扩散模型的混合结构。
- 新兴范式:Score Distillation(如 DreamFusion),将扩散模型作为先验,结合优化器生成三维内容,打通多模态生成能力。
总结来看,生成模型领域极其活跃。本章内容仍具前瞻性价值,因为它奠定了后续所有先进方法的理论基础。章节中对旧方法与新技术之间联系的剖析,帮助读者理解思想的演进路径 —— 例如去噪自编码器的思想如何在扩散模型中被重新启用,又如对抗训练如何从另一个角度实现似然建模目标。
PyTorch 实例代码
考虑到模型的复杂性,我们可以为其中一个具有代表性的模型(例如 VAE 或 GAN)提供一段简洁的伪代码片段,用于展示其训练过程。
VAE PyTorch pseudo-code:
# Define encoder and decoder networks
encoder = EncoderNet() # outputs mu, logvar
decoder = DecoderNet() # outputs recon_x (parameters of p(x|z), assume Gaussian or Bernoulli)
optimizer = torch.optim.Adam(list(encoder.parameters())+list(decoder.parameters()), lr=1e-3)
for x in data_loader:
# Encode
mu, logvar = encoder(x)
# Reparam trick
eps = torch.randn_like(mu)
z = mu + torch.exp(0.5*logvar) * eps
# Decode
recon_x = decoder(z)
# Compute losses
recon_loss = bce_loss(recon_x, x) # or mse depending on output dist
# KL divergence for Gaussian
kl_loss = -0.5 * torch.sum(1 + logvar - mu**2 - logvar.exp())
loss = recon_loss + kl_loss
optimizer.zero_grad()
loss.backward()
optimizer.step()
This shows typical VAE training: producing a reconstruction and adding KL regularization.
GAN PyTorch pseudo-code (non-saturating loss):
G = Generator()
D = Discriminator()
optim_D = Adam(D.parameters(), lr=2e-4, betas=(0.5,0.999))
optim_G = Adam(G.parameters(), lr=2e-4, betas=(0.5,0.999))
for real_x in data_loader:
# Train D
z = torch.randn(batch_size, z_dim)
fake_x = G(z).detach()
D_real = D(real_x)
D_fake = D(fake_x)
# Labels: real=1, fake=0
loss_D = - (torch.log(D_real) + torch.log(1 - D_fake)).mean()
optim_D.zero_grad()
loss_D.backward()
optim_D.step()
# Train G
z = torch.randn(batch_size, z_dim)
fake_x = G(z)
D_fake = D(fake_x)
# Non-saturating generator loss: maximize log(D_fake) => minimize -log(D_fake)
loss_G = - torch.log(D_fake).mean()
optim_G.zero_grad()
loss_G.backward()
optim_G.step()
我们交替进行判别器(D)和生成器(G)的训练步骤(通常是一轮 D 步骤,然后一轮 G 步骤),配合正确的标签输入,有时也会使用标签平滑技术。
由于扩散模型的伪代码较为复杂,篇幅有限,这里暂略。
Mermaid:
Comparison of explicit vs implicit generative modeling:
flowchart LR
subgraph 显式模型
direction TB
param_density(直接定义 p(x) 或 p(x|z))
train1[通过最大似然或ELBO优化参数]
sample1[按模型采样/公式采样]
end
subgraph 隐式模型
direction TB
generator(生成器 G: z -> x)
train2[用判别器/对比 等 训练 G]
sample2[输入噪声得到样本]
end
这凸显出生成模型的两种训练方式的差异:显式模型使用似然训练,而隐式模型则依赖其他准则进行训练,并通过前向过程进行采样(例如向生成器输入噪声,或执行逐步去噪过程。
当然可以,以下是一段适合作为《深度学习》第三部分读书笔记的总结性结尾内容,风格延续你前两部分的写法,兼具回顾性与展望性,可直接插入 Markdown 文件末尾。
《深度学习》第三部分以“深层概率模型”为核心主题,不仅拓展了前两部分的判别式理解框架,更开启了对“生成式智能”的系统性思考。从配分函数的归一化挑战、到隐变量模型的建模技巧,再到自编码器、能量模型、对比学习与现代扩散框架的统一表达,本部分勾勒出了从概率推断到现代生成范式的一条清晰脉络。
我们看到:
- 似然建模与对抗训练的分野,实际上是对建模目标与优化方式理解的分歧;
- 自编码器思想的不断演化,最终成为 VAE、Diffusion 等主流模型的理论支柱;
- 扩散模型与 Score 网络的兴起,代表了生成学习从隐空间建模到密度梯度建模的重大转向;
- 生成质量评估的挑战与演化,提醒我们 AI 不只是数学,更关乎认知与感知的交汇。
在如今以 GPT、Sora、Stable Diffusion 为代表的生成浪潮中,第三部分中所讲述的每一个概念,都早已融入现代大模型的内核。它让我们意识到:深度生成模型不仅仅是技术的延伸,更是智能表达与理解世界的新方式。
未来,我们所面对的将不仅是生成图像、生成语言的能力,更是生成结构、行为、甚至科学假设的可能。而一切的根基,正源于我们对深层概率模型的深刻理解与持续探索。