Score Based Model
图片里每个像素可以看作一个维度真实的图片在这个高维空间里服从一个分布我们把这个真实分布叫做pdatap_{data}pdata​我们可以求得pdatap_{data}pdata​从pdatap_{data}pdata​里面采样就可以得到真实的图片。如果随机给我们一张图片我们也可以通过pdatap_{data}pdata​计算出它是一个真实图片的概率值我们再深入思考下pdatap_{data}pdata​的分布pdatap_{data}pdata​只存在于理想状态下理想状态下pdatap_{data}pdata​反应了一张图片出现在我们世界里的可能性并且会随着我们世界的改变而动态改变比如在古代出现一个飞机图片的可能性就为0我们生活中出现越多的物体他作为图片出现的概率就大比如以下图片的概率另外我们的一个假设我们的训练数据是对pdatap_{data}pdata​的采样但是无论如何我们的训练数据总是有偏的比如我们之前训练过生成人脸的模型在这个模型世界里就只有人脸图片pdatap_{data}pdata​描述的是人脸图片出现的概率密度模型生成也只能生成人脸不能生成猫狗汽车等其他图片所以pdatap_{data}pdata​真正描述的是你构建的这个训练数据的概率分布如果我们训练数据都是猫那么pdatap_{data}pdata​描述的就是不同猫图片的概率分布了有了pdatap_{data}pdata​我们希望按照概率密度对图片进行采样采样时生成高概率密度区域的图片多低概率密度区域的图片少假如我们有了pdatap_{data}pdata​你传入一个图片它生成一个概率密度值。对于一个多维的概率密度函数因为你不知道概率密度的整体分布只能传入一个图片得到一个概率密度在这种情况下采样还是非常困难的你不好生成一个图片。但是如果我们有了pdatap_{data}pdata​对x的梯度值然后我们随机生成一个点xpdatap_{data}pdata​对x的梯度就表明x往哪个方向移动概率密度会提升我们就让x沿着梯度方向移动一段距离然后用新的x再计算它的梯度值这样经过多次迭代总是能把x向概率密度高的位置移动这样我们就可以生成更像真实图片的图片了。这个图是我们生成的一个混合高斯分布的梯度场箭头代表梯度方向长度代表梯度大小。可以看到这些箭头都指向概率密度大的地方但是你可能也发现一个问题那就是周边概率密度低的地方梯度值基本都是0.如果我们随机生成的初始点落在边缘的这些位置那就没有办法按照梯度进行移动了还是不能生成我们想要的图片。我们分析一下为什么周围这些点的梯度值接近0呢因为这些区域的概率变化基本都接近0变化非常小变化小求导就接近0所以梯度值为0怎么解决这个问题呢我们不对p(x)p_(x)p(​x)求梯度而对logp(x)logp(x)logp(x)求梯度这样你可以看到所有空间都有梯度值了因为对log函数求导等于原函数求导再除以原函数虽然在周边区域的概率密度变化率小但是它的概率值也小所以这个除法就刚好做了缩放而且保持了梯度方向一致从而保证概率密度小的区域也有梯度值这样我们在高维空间中采样任意一个点都可以沿着梯度指导方向前进移动到高概率密度区域从而生成一个接近真实的图片了。所以score的定义就是对概率密度函数取对数再对x求梯度。这里要注意是对图片里的像素值x求梯度不是我们神经网络里的参数值求梯度。取log值还有一个好处假如输入网络的图片为x输出的fθ(x)f_\theta(x)fθ​(x)为概率密度值神经网络输出的logits值有正有负但是概率密度值只能是非负的我们可以通过fθ(x)f_\theta(x)fθ​(x)加上指数函数来将它转化为一个非负值但是概率密度函数还有一个强制要求就是积分值需要为1我们需要对每一个算出来的原始概率密度值进行归一化但是这个归一化的值zθz_{\theta}zθ​很难计算他需要对整个空间所有维度进行积分这是我们很难计算的。我们如果直接对概率密度函数求导这个难求的zθz_{\theta}zθ​还是在梯度值里但是如果我们对概率密度加上log函数然后再对x求导log里的除法可以转化为两个log的减法后面的zθz_{\theta}zθ​在θ\thetaθ确定后是个常数和x无关对x求导为0。所以score函数的设计就巧妙的规避了对难求的归一化常数的计算。我们之前说pdatap_{data}pdata​实际上反应的是你训练数据的概率密度分布一般采集的数据集里都是清晰的常见的图片他们每个图片的概率密度都是均等的一般认为这个pdatap_{data}pdata​是在低维流形分布上的。低维流形可以想象为在一个空旷的大房间里漂浮着的一个小的丝带你采集的数据都分布在这个丝带上我们随机采样一个图片就像在这个房间的3维空间内随机采样一个点它位于丝带上的概率几乎为0.所以目前有两个难题由于训练数据都是从高概率密度区域采集图片根据我们采集的这些训练图片我们无法写出它的概率密度函数更不要输其他的score函数了。怎么解决呢首先我们认为训练数据里都是高概率密度的点并且这些点的概率密度都相等然后我们自己定义概率密度函数并且用自己定义的概率密度函数来生成那些低概率密度的图片。x0x_0x0​是从pdatap_{data}pdata​里采样的真实图片然后我们给x0x_0x0​加上噪声这里你可以认为是给图片x0x_0x0​每个维度都加上噪声ϵ\epsilonϵ是个标准正态分布σ\sigmaσ是噪声强度这样xtx_txt​就服从以x0x_0x0​为中心以σ\sigmaσ为标准差的一个正态分布这样产生的带噪声的图片xtx_txt​在pdatap_{data}pdata​分布里的概率密度值会比较低但是也会有一个具体的值这个值是可以通过正态分布的公式计算出来通过加噪我们就解决了上边的两个难题。第一个是通过加噪构造出了低概率密度的区域的图片加的噪声越少概率密度越大加的噪声越大概率密度越小。而且这个概率密度函数我们是知道的是一个正态分布我们可以写出他的概率密度函数从而可以求出score的值。实际我们做的时候会对图片加不同等级的噪声并且通过公式计算出不同等级噪声下pdatap_{data}pdata​的score值然后我们训练一个神经网络SθS_{\theta}Sθ​,让这个这个神经网络传入一个图片xtx_txt​和当前的噪声等级σt{\sigma}_tσt​神经网络可以输出对图片xtx_txt​的score值从而指导图片向概率密度更高的地方移动。这里我们不直接通过公式结算score值而要通过神经网络进行预测呢后面会发现通过我们定义的概率密度公式计算score函数值的时候会依赖训练数据原始图片x0x_0x0​。但是在图片生成时我们是没有x0x_0x0​的。我们希望训练一个神经网络仅在输入噪声的图片和当前噪声等级时就可以计算出score值。为什么我们要训练神经网络可以输出不同等级噪声下对x的score值呢因为通过这里的图片可以观察到噪声越大他支持的空间越大但是细节越模糊生成的图片可能会在实际图片并不存在的中间区域噪声越小支持的空间越小但是他的细节越清晰越接近真实的图片分布所以我们的思想是先用大的噪声概率分布下的score值引导随机生成的图片x朝着一个大致的方向走随着迭代的进行再逐渐替换成小的噪声分布下的score来指引方向指导方向越来越精细同时在这个过程中刚开始步长比较大然后随着噪声强度的下降步长也越来越短。直到最后就到达了和我们训练数据非常接近的区域就生成了一张照片在整个过程中我们的步长也是越来越短。这样采样有个问题就是我们每次得到的都是一些局部概率密度最大的点生成图片缺乏多样性。比如对上边的图片最终score函数引导下的x只会有两个最优点也就是我们这个生成模型只能生成2个不同的图片图片生成任务不是求最优解我们期望是对整个分布按照概率密度进行采样来生成图片尽可能生成多样的图片为了解决这个问题我们可以采用朗之万动力学公式来采样。先看图片左边是根据score函数生成的梯度场进行梯度上升采样可以发现最终生成的图片都集中在几个局部最优点上但是利用朗之万动力学公式可以很好的对整个分布按概率密度进行采样我们看一下朗之万动力学公式xtx_txt​是当前图片xt1x_{t1}xt1​是移动一步后的图片可以看到中间这一项就是步长τ\tauτ乘以score函数值进行梯度上升采样。加了第三项也就是2τz\sqrt{2\tau} z2τ​zz是一个标准正态分布这样就在采样过程中增加了随机性让采样图片的分布接近真实的概率分布让我们看一下退火朗之万动力学采样。退火的意思是刚开始噪声很大步长也很大让系统的探索性更强到后边噪声越来越小步长也越来越小朗之万动力学公式就是每一步都是确定的梯度乘以步长再加上一个随机运动这里用黑线表示确定性的移动红线表示随机移动我们可以看到正是因为加入了随机性可以在刚开始高噪声的分布下让图片x跨过两个高概率区域之间的低概率密度区域这样就增大了图片生成时的随机性