扩散模型的悲惨开始
搞AI的都知道,一个模型好不好空口无凭,我们必须要用数据说话。但是扩散模型刚出来的时候存在一个问题,就是图片我们用人眼看起来好像效果还是挺好的,但是在数值上就是打不过GAN生成的图像,所谓的数值上就是在评价指标上,比如FID score和IS score。就算我们直接把图片放到论文中,人家也可能会质疑说,你这些图片肯定是把效果好的放出来了,效果不好的根本就没让我们看吧。所以如果数值提不上去,论文很难有说服力,审稿人那一关就过不了。所以很重要的一个努力方向就是提高模型的指标。另外还有一个问题就是模型的采样是按照时间步来的嘛,这样比较慢。所以大家就在想办法改进这些地方。就引出了我们今天要讲的东西,借助一些技巧或者guidance来帮助引导模型训练和采样。
其实在之前的这篇文章【翻译】最近兴起的扩散模型提过一嘴引导扩散这个事,今天就把它展开讲讲。
从uncondition到condition
我们扩散模型的反向过程是给定$x_T$时刻的输入,从$x_T$生成$x_{T-1}$,这样逐步一直到恢复图像$x_0$。恢复过程每一步用的都是一个U-Net,不停地采样、生成、采样、生成,算算算。
我们将每一步的过程formulate一下就是$f_\theta(x_t,t)$,就是时间步t的生成需要两个输入信息:
- 当前时间步的输入$x_t$
- 当前时间步$t$
引入guidance之后给模型提供指导,这个指导我们用$\mathbf y$表示,那我们就可以得到修改之后的网络$f_\theta(x_t,t,\mathbf y)$。接下来我们就来看一下$\mathbf y$究竟可以变成什么。
classifier guided diffusion
classifier gudied diffusion 就是在我们训练模型的同时 再 额外训练一个图像分类器,在很多论文中的实现方法就是直接用ImageNet的数据集去训练一个图像分类器,由于扩散模型的特性是从每一步的噪声图像中恢复,所以训练分类器的过程中是不断对ImageNet的图像加噪之后再训练分类器。
这个分类器的作用是:当我们拿到图片$x_t$之后,我们可以知道它分类的对不对,通过使用交叉熵目标函数,会得到一些梯度,然后我们用这些梯度去帮助模型进行接下来的采样和生成。
分类器的梯度暗含当前图片的一些信息,比如是否含有某个物体,比如图片是否真实等 。这个梯度引导就是给U-Net传递信息,我现在生成的图片要像什么东西。
经过classifier gudied diffusion的引导之后,生成的图片保真性就提高了很多,在FID score和IS score等指标上大幅度提高,扩散模型也第一次在评价指标的数值上超越了big GAN。详细的可以看《diffusion model beat GAN》这篇论文。这个做法是牺牲了一部分的多样性来换取图片的真实性,但是这个取舍是值得的,它的多样性依旧是比GAN要好很多的。评价指标数值提上来了,多样性还能吊打你,这样就开始奠定了新一位大魔王的地位了。
GAN、VAE、Diffusion model等生成模型如果大家不了解可以浅浅看一下这个文章:图像生成模型简介 - 掘金 (juejin.cn)
简单classifier之后的思路
除了用分类器我们还能借助什么产生指导信号呢?比如换成CLIP模型,这样文本和图像还能联系起来,这样我们就不止可以使用梯度来引导图像生成了,还可以使用文本信息来引导图像生成。
还有用语言模型进行文本方向引导的,利用图片的一些小任务引导的等等。
通过上述两大类改进方法,我们可以归结起来引导扩散模型生成和采样的一大方向就是:
$$ p(x_{t-1}|x_t) = \| \epsilon - f_\theta(x_t,t,\mathbf y) \| $$
其中的$\mathbf y$就是我们选定的控制方法。
但是这个方法有一个缺陷,就是我们需要借助另外一个模型进行引导。简单的分类器都要用带噪声的ImageNet数据集进行训练,更别说CLIP或者其他预训练的大型语言模型了。这样成本比较高,训练过程也是不可控的。
classifier-free guidance
因为我们上边提到的一些缺陷,所以有研究人员开始考虑不需要额外模型的方法,也就是classifier-free。不使用classifier之后我们能不能找到一种指导信号去让模型生成的更好呢?
在模型训练阶段让其产生两个输出,一个是在有条件的情况下产生的输出,一个是在无条件下产生的输出。
$$ f_\theta(x_t,x,\mathbf y) - f_\theta(x_t,x,\phi) $$
比如你用文本控制图像生成,训练时候用的是图像文本对,文本作为guidance信号。此时$\mathbf y$就是文本,你在训练的时候用$\mathbf y$去生成图像$f_\theta(x_t,x,\mathbf y)$,然后在某些情况下你随机去掉这个信号,取而代之传入一个空集$\phi$,再去生成另外一个输出$f_\theta(x_t,x,\phi)$,这样你就可以在生成图像的分布空间中知道有条件和无条件图像的距离,我们就可以知道在这个分布空间上如何从无条件输出得到有条件的输出,通过训练我们就可以知道有条件、无条件的差距是多少,最后去做图像生成的时候,即使我们没有条件去做生成,也可以获得一个比较合理的输出结果。这样就摆脱了分类器。
但是这样存在一个问题就是训练代价比较昂贵,扩散模型的训练本来就很烧钱,现在居然要一次做两个输出,一个有条件一个无条件,这样又增加很多成本。
但是这个真的是很好用的方法,GLIDE、DALL·E 2、Imagen等模型都用到了这个技巧。