diffusion 相关阅读笔记
diffusion模型的公式挺多的,codes内也有很多的公式,直接看codes还是看不懂的,codes内的公式太多了,diffusion主要包括了加噪声的过程,以及去噪声的过程。加噪声服从正态分布,去噪声也服从正态分布。加噪声的codes是这个:np.sqrt(aprodd).reshape(n, 1, 1, 1) * inputs + np.sqrt((1 - aprodd)).reshape
diffusion 相关阅读笔记
Diffusion Models A Comprehensive Survey of Methods and Applications.pdf
Understanding Diffusion Models A Unified Perspective.pdf
Denoising Diffusion Probabilistic Models.pdf
diffusion模型的公式挺多的,codes内也有很多的公式,直接看codes还是看不懂的,codes内的公式太多了,diffusion主要包括了加噪声的过程,以及去噪声的过程。加噪声服从正态分布,去噪声也服从正态分布。
加噪声的codes是这个:np.sqrt(aprodd).reshape(n, 1, 1, 1) * inputs + np.sqrt((1 - aprodd)).reshape(n, 1, 1, 1) * etamul
inputs是干净的输入图片,etamul是服从标准正态分布的 噪声,aprodd是逐渐递减到0的值,所以最后的输出就是正态分布的。
也就是首先给一个图片加随机的噪声,然后网络来predict噪声、或者输入的图片。看具体的公式
前向的Markov chain就是不断地加入噪声,而且前后两个图片加入噪声是相关的,加入噪声没有参数需要learn
逆向的Markov chain就是不断地去除噪声,去除噪声需要learn网络的参数才行。
class myddpm_noise(object):
def __init__(self, n_steps, embed_dim, minbeta = 0.0001, maxbeta = 0.03, shape = (1, 30 - 2, 30 - 2)):
self.n_steps = n_steps
self.embed_dim = embed_dim
# self.beta array([0.0001 , 0.00113103, 0.00216207, 0.0031931 , 0.00422414,
0.00525517, 0.00628621, 0.00731724, 0.00834828, 0.00937931,
.........
0.01556552, 0.01659655, 0.01762759, 0.01865862, 0.01968966,
0.02072069, 0.02175172, 0.02278276, 0.02381379, 0.02484483,
0.02587586, 0.0269069 , 0.02793793, 0.02896897, 0.03 ])
self.beta = np.linspace(minbeta, maxbeta, n_steps)
#self.alpha array([0.9999 , 0.99886897, 0.99783793, 0.9968069 , 0.99577586,
0.99474483, 0.99371379, 0.99268276, 0.99165172, 0.99062069,
.........
0.98443448, 0.98340345, 0.98237241, 0.98134138, 0.98031034,
0.97927931, 0.97824828, 0.97721724, 0.97618621, 0.97515517,
0.97412414, 0.9730931 , 0.97206207, 0.97103103, 0.97 ])
self.alpha = 1 - self.beta
# self.prod_alpha array([0.9999 , 0.99876908, 0.99660967, 0.99342739, 0.98923102,
0.98403244, 0.97784661, 0.97069147, 0.96258787, 0.95355946,
.........
4.43118813e-07, 4.30063974e-07, 4.17380875e-07, 4.05059324e-07,
3.93089395e-07, 3.81461425e-07, 3.70166005e-07, 3.59193973e-07,
3.48536411e-07, 3.38184636e-07, 3.28130193e-07, 3.18364855e-07,
3.08880609e-07, 2.99669660e-07, 2.90724415e-07, 2.82037488e-07,
2.73601688e-07, 2.65410015e-07, 2.57455658e-07, 2.49731988e-07])])
self.prod_alpha = np.array([np.prod(self.alpha[: i + 1]) for i in range(len(self.alpha))])
def forward(self, inputs, fixposition = None, etamul = None):
n, c, h, w = inputs.shape
aprodd = self.prod_alpha[fixposition]
noisy = np.sqrt(aprodd).reshape(n, 1, 1, 1) * inputs + np.sqrt((1 - aprodd)).reshape(n, 1, 1, 1) * etamul
return noisy
前向Markov chain的过程,用到了相关的 重采样方式,也就是 概率分布是不可导的,直接使用概率分布不可导,但是通过概率分布的性质,通过加或者乘,就可导了的,具体的可见: 九是否随意的称呼:重参数采样Reparameterization Trick和Gumbel-Softmax
前向加噪声的过程,每个图片的产生都服从正态分布: q ( x t ∣ x t − 1 ) = N ( x t ; α t x t − 1 , ( 1 − α t ) I ) q(x_t|x_{t−1}) = N (x_t;\sqrt{α_t}x_{t−1},(1 − α_t)I) q(xt∣xt−1)=N(xt;αtxt−1,(1−αt)I)
也就是条件概率的,已知上一个加了噪声的图片,怎么产生下一个加噪声的图片
已知前一个,那么下一个加噪声图片的产生,就服从正态分布。而且均值是 α t x t − 1 \sqrt{α_t}x_{t−1} αtxt−1 ,方差是 ( 1 − α t ) I (1 − α_t)I (1−αt)I , I I I 是 (0, 1) 标准正态分布。
所以前向Markov chain的转移公式就是上面的条件概率。
而且到了最后一个时间点T,产生的基本是噪声了,没有图片了的,也就是 p ( x T ) = N ( x T ; 0 , 1 ) p(x_T)=N(x_T;0,1) p(xT)=N(xT;0,1)
所以逆向过程的joint分布就是: p ( x 0 : T ) = p ( x T ) ∏ t = 1 T p θ ( x t − 1 ∣ x t ) p(x_{0:T})=p(x_T)\prod_{t=1}^{T}p_{\theta}(x_{t-1}|x_t) p(x0:T)=p(xT)∏t=1Tpθ(xt−1∣xt) , θ \theta θ 就是网络需要learn的参数。
前向过程也就是上面的条件概率,也可以转写到: x t = α t x t − 1 + 1 − α t ϵ x_t =\sqrt{α_t}x_{t−1} +\sqrt{1 − α_t}\epsilon xt=αtxt−1+1−αtϵ , ϵ \epsilon ϵ 服从标准正态分布。
也就是 均值加上标准差 的,得到的就是下一个噪声图片。类似的 x t − 1 = α t − 1 x t − 2 + 1 − α t − 1 ϵ x_{t-1} =\sqrt{α_{t-1}}x_{t−2} +\sqrt{1 − α_{t-1}}\epsilon xt−1=αt−1xt−2+1−αt−1ϵ
将上面的式子带入,然后不断地迭代最后就可以得到: x t = α ˉ t x 0 + 1 − α ˉ t ϵ 0 x_t =\sqrt{\barα_t}x_0 +\sqrt{1 − \barα_t}\epsilon_0 xt=αˉtx0+1−αˉtϵ0 ,也就是 x t x_t xt 可以直接使用 x 0 x_0 x0 求出来,而不需要用到前一个噪声图片。 x t − N ( x t ; α ˉ t x 0 , ( 1 − α ˉ t ) I ) x_t-N(x_t;\sqrt{\bar \alpha_t}x_0,(1-\bar\alpha_t)I) xt−N(xt;αˉtx0,(1−αˉt)I)
上面这个公式就是codes内需要用到的加噪声的公式,加噪声就是按照这个公式来计算的。
加完噪声以后,就送入到网络,来train网络,让网络可以更好的learn相关的参数 p ( x 0 : T ) = p ( x T ) ∏ t = 1 T p θ ( x t − 1 ∣ x t ) p(x_{0:T})=p(x_T)\prod_{t=1}^{T}p_{\theta}(x_{t-1}|x_t) p(x0:T)=p(xT)∏t=1Tpθ(xt−1∣xt)
train
通过不同的公式推导,可以得到网络train的三种方式:
1、predict输入的图片
2、predict加入的噪声
3、predict相应的评分
这三种predict方式都可以用来train网络,通常第二种比较常用。
predict
q ( x t − 1 ∣ x t , x 0 ) − N ( x t − 1 ; u q ( x t , x 0 ) , δ ) q(x_{t−1}|x_t, x_0)-N(x_{t-1};u_q(x_t,x_0),\delta) q(xt−1∣xt,x0)−N(xt−1;uq(xt,x0),δ) ,也就是逆向的图片恢复过程,是服从正态分布的
也就是sample的过程,有很多种采样的方式,像DDPM,DDIM等等,通常的采样公式,也就是逆向转移公式包括这一个:去噪声的转移均值: µ q ( x t , x 0 ) = 1 α t x t − 1 − α t 1 − α ˉ t α t ϵ 0 µ_q(x_t, x_0)=\frac{1}{\sqrt{\alpha_t}}x_t-\frac{1-\alpha_t}{\sqrt{1-\bar\alpha_t}\sqrt{\alpha_t}}\epsilon_0 µq(xt,x0)=αt1xt−1−αˉtαt1−αtϵ0 ,去噪声的转移方差是: δ = ( 1 − α t ) ( 1 − α ˉ t − 1 ) 1 − α ˉ t I \delta=\frac{(1-\alpha_t)(1-\bar\alpha_{t-1})}{1-\bar\alpha_t}I δ=1−αˉt(1−αt)(1−αˉt−1)I ,上面的 ϵ 0 \epsilon_0 ϵ0 就是网络输出的噪声,不是采样得到的,是网络predict的噪声。网络的输入是 x t x_t xt
所以sample采样的时候,从标准正态分布开始,然后将 x t x_t xt 送入到网络 predict 噪声 ϵ 0 \epsilon_0 ϵ0 ,然后使用这个噪声 ϵ 0 \epsilon_0 ϵ0 求均值 µ q ( x t , x 0 ) = 1 α t x t − 1 − α t 1 − α ˉ t α t ϵ 0 µ_q(x_t, x_0)=\frac{1}{\sqrt{\alpha_t}}x_t-\frac{1-\alpha_t}{\sqrt{1-\bar\alpha_t}\sqrt{\alpha_t}}\epsilon_0 µq(xt,x0)=αt1xt−1−αˉtαt1−αtϵ0 ,加上标准差 δ = ( 1 − α t ) ( 1 − α ˉ t − 1 ) 1 − α ˉ t I \delta=\frac{(1-\alpha_t)(1-\bar\alpha_{t-1})}{1-\bar\alpha_t}I δ=1−αˉt(1−αt)(1−αˉt−1)I ,就是下一次采样需要用到的 x t − 1 x_{t-1} xt−1 ,也就是下一次送入到网络的输入: x t − 1 x_{t-1} xt−1 。
上面的公式对应到的就是下面的codes。
inputs = np.random.rand(n_sample, c, h, w)
for id, fixposition in enumerate(np.arange(noisegen.n_steps)[::-1]):
array_fixpos = np.ones((n_sample, 1), dtype=np.uint) * fixposition
predict_noisy = myunet.forward(inputs, array_fixpos)
fix_alpha = noisegen.alpha[fixposition]
fixprod_alpha = noisegen.prod_alpha[fixposition]
inputs = (1 / np.sqrt(fix_alpha)) * (inputs - (1 - fix_alpha) / np.sqrt(1 - fixprod_alpha) * predict_noisy)
if fixposition > 0:
z = np.random.rand(n_sample, c, h, w)
#0
fixbeta = noisegen.beta[fixposition]
# fix_sigma = np.sqrt(fixbeta)
#1
preprod_alpha = noisegen.prod_alpha[fixposition - 1] if fixposition > 0 else noisegen.prod_alpha[0]
prebeta = ((1 - preprod_alpha) / (1 - fixprod_alpha)) * fixbeta
fix_sigma = np.sqrt(prebeta)
inputs = inputs + fix_sigma * z
很多工作都是在sample这的
条件diffusion
条件diffusion,通常是加了额外信息的diffusion,像多出来的向量用来放置其他条件
文本条件通常是embedding到向量空间,然后和图片做cross attention,拿到条件信息。
通过额外的输入,就可以控制diffusion输出的结果。
reference
Diffusion Models in AI - Everything You Need to Know - Unite.AI
Understanding Stable Diffusion from “Scratch” | Binxu Wang (harvard.edu)
Mathematical Foundation of Diffusion Generative Models | Binxu Wang (harvard.edu)
Research | Binxu Wang (harvard.edu)
Note on Diffusion Generative Models | The mind palace of Binxu (animadversio.github.io)
Kempner Institute - For the Study of Natural & Artificial Intelligence at Harvard University

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)