扩散模型理解
需要掌握的前置知识:
扩散模型
反向传播
圆周率火炬
tensor flow等
扩散模型的工作结果——个人理解为从有生无。
在本例子中即为通过训练大量的小精灵,生成训练集中并没有的小精灵
1. 怎样让训练集中的小精灵更有利于数据集
network怎么样知道小精灵的更精细的细节和一般轮廓的一种?
方法为添加噪音
噪声工程——一滴墨水滴入清水的过程
你可以想象一滴墨水滴入一杯水中,随着时间的推移,它会在水中扩散,直至消失。当你逐渐给图像添加更多的噪声时,图片的轮廓从清晰变模糊,直到完全无法辨别。这个逐渐添加不同程度噪声的过程很像墨水在水中逐渐消失的过程。
2. 训练模型
训练模型的目标:模型会移除你添加的噪声,将添加了不同噪声的图像变换为游戏角色。
不知道噪声的大小是很重要的——噪声遵从正态分布,每一个像素点都是取样于一个正态分布
通过不断从正态分布中抽取噪声,逐步去掉噪声,从no idea直到组装出一个sprite
你可以通过所有你训练过的sprite,生成新的sprite
3. sampling
采样是神经网络训练完成之后,从高斯噪声中生成原始图片(反向扩散/去噪过程)
假设有一个已经添加了噪声的样本,将其输入到已经训练好的神经网络中,这个神经网络已经理解了游戏角色图片。之后,让神经网络预测噪声,然后,从噪声样本中减去预测的噪声,得到的结果就更接近游戏角色图片。
现实情况是,这只是对噪声的预测,并没有完全消除所有的噪声,需要迭代很多次在能够得到接近原始图片的高质量的样本。
sampling iteration details 采样迭代细节:
再传入下一步之前增加额外噪音会增加模型稳定性,因为我们需要的是“noisy input”——需要的是符合正态分布的噪声样本而在。在迭代过程中,噪声样本减去模型预测的噪声之后得到的样本已经不符合正态分布了,容易导致模型坍缩。所以每次迭代之后需要根据所处的时间步长添加额外的采样噪声,以让其符合正态分布。从经验上看,这可以保证训练的稳定性,以避免模型模型坍缩,避免模型的预测结果接近于数据集的平均值。
- 防止陷入局部最优解:在一些情况下,扩散模型的采样过程可能会出现陷入局部最优解的情况。通过添加额外噪音,可以使采样过程更加随机化,从而增加跳出局部最优解的可能性。
- 提高探索能力:扩散模型的采样过程通常是用来探索模型空间,寻找新的解决方案。添加额外噪音可以促使模型在搜索空间中进行更广泛的探索,增加发现新解的机会。
- 平滑采样结果:扩散模型的采样结果可能会出现抖动或不稳定的情况,这对于后续的分析和应用可能不理想。通过添加额外噪音,可以平滑采样结果,使其更加稳定和可靠。
采样算法的实现:
- 首先采样一个随机噪声样本,这就是一开始的原始噪声
- 然后逆序从最后一次迭代的完全噪声的状态遍历到第一次迭代。就像是墨水的例子,一开始完全扩散的,然后一直倒退回到刚刚滴入水中的状态
- 之后,采样一些additional noise
- 通过神经网络得到一些预测的噪声。(这个预测的噪声就是训练过的神经网络得到的想从原始噪声中减去的噪声,从而得到更像原始的游戏角色的图片)
- 从原始噪声中减去预测的噪声,再加上一些额外的噪声
4. neural network
用于扩散模型的神经网络架构是U-Net。它将原始图像作为输入,输出与原始图像大小相同的预测噪声。输入与输出尺寸相同,这是其一大优点。
U-Net首先将这个输入的信息进行嵌入(Embedding),通过多层卷积将其降采样到一个压缩了所有信息的嵌入中。然后用相同数量的上采样块将输出返回到任务中,在这个例子中,它的任务就是预测应用到这个图片上的噪声。
U-Net的一个优点是可以接受额外的信息
嵌入更多信息
- 时间嵌入Time Embedding
这是一种告诉模型时间步长的嵌入,因此我们需要某种级别的噪声。对于这个时间嵌入,需要将其嵌入到一个向量中,然后将其添加到这些上采样块中。
在扩散模型中,时间嵌入是一种将时间信息编码到模型输入中的技术。它用于将时间步骤作为额外的特征引入模型,并帮助模型学习时间相关的模式和动态。
时间嵌入通常使用向量表示,其中每个时间步骤都有一个对应的时间嵌入向量。这些向量可以是固定的,也可以通过训练过程进行学习得到。
时间嵌入的目的是为了将时间信息与其他特征一起传递给模型,使其能够捕捉到不同时间点的变化和趋势。例如,在序列数据中,时间嵌入可以帮助模型识别周期性模式、季节性变化或长期趋势等。
通过引入时间嵌入,模型可以更好地理解数据中的时间相关性,并更准确地预测未来的值或生成与时间相关的输出。
- 上下文嵌入
它的根本作用是控制模型生成的内容。例如,一个文本描述,你想让它生成的是Bob,或者某种因子,或者某种颜色。
5. traing
训练神经网络(NN)的目标是让其预测噪声,真正的任务是让它学习图像上的噪声分布(也包括需要学习什么是游戏角色图片的特征)
怎么训练这个nn,让它预测噪音?
过程:从数据库中选一张sprite,给原sprite添加随机噪音,加噪音后喂给nn,将nn预测的噪音与实际噪音比较,计算loss。通过BP算法(反向传播)不断迭代,让NN学会更好的预测噪声。
这里加什么样的噪音:通过随机采样时间步长选取对应高斯噪声
可以通过时间和采样,给它不同的噪声级别。但在实际的训练过程中,我们不希望NN一直观察同一个游戏角色图片,因为如果在一个周期内观察到不同的游戏角色图片,NN会更稳定,更均匀。所以,我们实际上是随机采样一个可能的时间步长,然后获取相应的噪声级别,添加到图像中,再让NN做预测。
训练算法:
t = torch.randint(1, timesteps + 1, (x.shape[0],)).to(device)
取样时间步长t:
torch.randint:这是一个用于生成随机整数的函数。 1和timesteps +1:这是生成的随机整数的范围。1表示最小值(inclusive),timesteps + 1表示最大值(exclusive)。
(x.shape[0],):这是生成的随机整数张量t的形状。x.shape[0]表示与输入图像x的批处理大小相同的维度。
Controling
通过嵌入进行控制。嵌入的一个神奇之处是它可以捕获文本的语义,内容相似的文本具有相似的向量。并且可以对向量进行算术运算,例如,将巴黎的嵌入减去法国的嵌入,加上英国的嵌入,等于伦敦的嵌入。
context embedding
“向量运算” 也就是说,context embedding就是在训练network时同时嵌入相关语义,之后就可以通过语义组合达到图像元素组合的目的
向network输入“Avocado armchair”,用一个预测噪声减去那个噪声,得到Avocado armchair
从更广泛的意义上来看,上下文可以是一个控制NN生成的向量。除了文本Embedding当做上下文以外,也可以将one-hot编码后的图片类别当做上下文。
代码:
做上下文掩码 ——在生成过程中限制模型对上下文信息的使用。上下文掩码可以提供一种机制,使得模型只能使用先前已生成的部分内容来预测接下来要生成的内容,而不能访问未来的信息。
Speeding up
训练NN的目标是想要快速地获得更多的图片。但是目前采样速度很慢,因为涉及到很多时间步骤,之前的例子中都是需要500步,才能得到一个好的样本。而且每个时间步都遵循马尔科夫链过程,依赖于前一个时间。这一直是扩散模型的痛点,现在有许多新的采样器可以解决这个问题。
马尔可夫过程的大概意思就是未来只与现在有关,与过去无关。
P(Xt+1 = j | Xt = i, Xt-1 = i_t-1, …, X0 = i_0) = P(Xt+1 = j | Xt = i)
其中,Xt表示时间t时刻的状态,P(Xt+1 = j | Xt = i)表示在状态i下转移到状态j的概率。
这种“下一时刻的状态至于当前状态有关,与上一时刻状态无关”的性质,称为无后效性或者马尔可夫性。而具有这种性质的过程就称为马尔可夫过程。
去噪扩散隐式模型(Denoising Diffusion Implicit Models,DDIM)就是其中之一。
DDIM更快的原因是它能够跳过时间步长,不再遵循马尔科夫假设。马尔科夫链实际上只适用于概率过程,但是DDIM从采样过程中去处了随机性,因此是确定性的。DDIM所做的本质上就是预测最终输出的粗略草图,然后用去噪过程对其进行细化。
采样如果在500步以上,DDPM效果会更好,500步以内,DDIM会更好。
Summary
大家已经学会了关于扩散模型的基础,我们能训练扩散模型来预测噪声,主动减去预测噪声,从纯噪点获得良好的图像。可以从中抽取图像训练神经网络,使用更高效的采样器。我们还可以把语境带入模型。
扩散模型不只可以用于图像,还可以用于音乐或者提出新药物分子等等