跳转至

3.Diffusion学习

Auto-regression

如何从零生成一张图片?比如给定一个任意的,比如纯黑的,64*64的图片,在其上生成逼真的图片?

一个naive的想法是,训练一个神经网络,输入这个64*64的全黑图片,输出训练集中的真实照片,进行反向传播。但是因为输入一直不变,神经网络根本不知道有什么区别导致了不一样的输出,所以训练后,它只会输出所有训练集图片的均值。

所以我们要引入不同的input,就可以挖掉每个图片的最后一个像素,训练一个神经网络,根据前面的64*64-1个像素,预测最后一个像素的值。这样的神经网络训练好后,可以较好的在新任务上预测图片的最后一个像素值。

继续这么干,我们把最后两个像素mask掉,然后训练神经网络就预测倒数第二个像素,这也是可行的。于是一直倒退,我们就有了64*64个神经网络,分别预测图片的每一个像素,我们按照先后顺序,让每个神经网络根据预测把图片填充回去, 就生成了一张图片。这就是以一个auto-regressor

并且对于每个神经网络,我们用的是random sampling,避免用greedy导致每次生成相同的图片。

缺点:太慢了,要是1024*1024,那要训练太多神经网络,生成也是时序的,非常的慢。

改进

既然一次生成一个像素很慢,那我一次mask掉一个2*2, 4*4的区域,让一个网络能同时生成多个像素呢?这是个好想法,但是存在一个trade-off,同时生成的区域越小,生成的越精确,质量越高;区域很大,最大就是一个网络生成整个图片,就像最naive的想法,会直接输出所有图片的均值,而非一些精确的像素。当一次生成比如32*32时,也会有这种现象,因为我们把精确生成需要的信息(附近的像素)都给mask掉了。一次删除的信息越多,损失的生成质量也就越多。

于是,自然而然地会想到,那我一次生成许多不相关的像素呢?图片中,一般位置相邻的像素相关性较高,所以每次移除一批随机相距较远的像素,如下图,也可以大大提高效率,同时保持较好的效果。

alt text

再进一步,auto-regressor的思想就是,从图片中一点点删除信息,再学习undo这个过程,一点点添加信息。并且基于前面的推演,每次remove information要random,要分散,并且还不能一下删太多信息。

Diffusion

So,我们干脆每次在图片中随机加一点点噪声,如此能够一次删掉更多的信息,但是trade-off的生成质量损失更少。我们以凸组合的方式混合原图像和噪声, 这样方差不爆炸, 保证可逆性。并且我们使用同一个神经网络进行每一次的去噪,而不是像自回归里面对于每个位置的像素单独进行训练。

alt text

不过在实践中,一般不会按照理论,每次训练让神经网络去除一层噪声,而是每次的target output都是干净的图片,这样模型不会花费算力和能力去学如何生成图片的噪声版本。

3

并且也有diffusion model是预测噪声而非原图,因为对于加了很多噪声了,根本无从预测原图,但噪声是高斯分布好预测一点,所以预测出噪声再从给定图片减去,就可以得到原图了。