文章链接:https://arxiv.org/abs/2105.05233
代码链接:https://github.com/openai/guided-diffusion
先读了guassian_diffusion.py这一个文件,刚起步,有大佬路过欢迎指正!
guassian_diffusion.py
get_named_beta_schedule(schedule_name, num_diffusion_timesteps)
根据不同的schedule_name选择不同的 β \beta β形式,给了线性和余弦两种
betas_for_alpha_bar(num_diffusion_timesteps, alpha_bar, max_beta=0.999)
根据
α
ˉ
\bar\alpha
αˉ计算
β
\beta
β,作用暂时未知?为什么可以用浮点数表示alpha_bar(t2) / alpha_bar(t1)
?
class ModelMeanType(enum.Enum)
枚举类型定义了三种模型预测输出类型:模型预测x_{t-1},模型预测x_0,模型预测epsilon
class ModelVarType(enum.Enum)
定义了四种模型输出方差类型:模型学习输出方差,模型固定输出方差较小,模型固定输出方差较大,模型学习输出范围
class LossType(enum.Enum)
定义了四种损失函数类型:均方误差损失(不使用KL散度进行学习方差),均方误差损失(使用RESCALED_KL散度进行学习方差),KL散度损失(使用变分下界),KL散度损失(使用RESCALED_KL散度进行估计完整的变分下界)
👆👆👆以上这些枚举类型可以在模型定义中使用,以便更好地描述和管理模型的输入和输出类型以及损失函数类型。
class GaussianDiffusion
该类定义了以下几个属性和方法:
-
model_mean_type,model_var_type,loss_type,rescale_timesteps:这些属性用于设置模型的输入和输出类型、损失函数类型和重新缩放时间步长。这些属性可以用于设置模型的行为和计算模型的预测输出。
-
betas,alphas_cumprod,alphas_cumprod_prev,alphas_cumprod_next,sqrt_alphas_cumprod,sqrt_one_minus_alphas_cumprod,log_one_minus_alphas_cumprod,sqrt_recip_alphas_cumprod,sqrt_recipm1_alphas_cumprod,posterior_variance,posterior_log_variance_clipped,posterior_mean_coef1,posterior_mean_coef2:这些属性用于计算模型的预测输出和损失函数。这些属性可以通过调用类的方法来计算。alphas_cumprod_prev相当于是在alphas_cumprod前面添了一个1,alphas_cumprod_prev(t)就等于alphas_cumprod(t-1)了。alphas_cumprod_next同理。
-
rescale_timesteps(),forward(),predict(),predict_diffusion(),log_prob():这些方法用于计算模型的预测输出、损失函数和对数概率。这些方法可以通过调用类的方法来计算。
(这些方法是在类内部定义的,并且没有在类的定义中直接显式地声明。这是因为这些方法是通过调用类的实例的方法来实现的。例如,如果您有一个名为model的类的实例,您可以调用model.rescale_timesteps()方法来计算模型的重新缩放时间步长。同样,您可以调用model.forward()方法来计算模型的预测输出,调用model.predict()方法来计算模型的预测输出,调用model.predict_diffusion()方法来计算模型的扩散预测输出,以及调用model.log_prob()方法来计算模型的对数概率。这些方法是在类内部定义的,并且可以通过调用类的实例的方法来实现。)
-
后验均值系数的计算:这些系数用于计算模型的后验均值。具体来说,posterior_mean_coef1是beta值乘以np.sqrt(self.alphas_cumprod_prev)除以(1.0 - self.alphas_cumprod),posterior_mean_coef2是(1.0 - self.alphas_cumprod_prev)乘以np.sqrt(alphas)除以(1.0 - self.alphas_cumprod)。这些系数可以用于计算模型的后验均值。
就是这俩系数
q_mean_variance(self, x_start, t)
计算 q ( x t ∣ x 0 ) q(x_t | x_0) q(xt∣x0)的均值和方差,并转化为tensor
q_sample(self, x_start, t, noise=None)
从 q ( x t ∣ x 0 ) q(x_t | x_0) q(xt∣x0)分布中采样,return结果 q ( x t ∣ x 0 ) = α t ˉ x 0 + 1 − α t ϵ q(xt|x_0)=\sqrt{\bar{\alpha_t} }x_0+\sqrt{1-\alpha_t}\epsilon q(xt∣x0)=αtˉx0+1−αtϵ
q_posterior_mean_variance(self, x_start, x_t, t)
计算模型的后验均值,将后验均值、后验方差和后验方差对数值转化为tensor
p_mean_variance(self, model, x, t, clip_denoised=True, denoised_fn=None, model_kwargs=None)
根据model_var_type选择不同的计算model_log_variance、model_variance的方式,然后转化为tensor。根据model_mean_type选择pred_xstart和model_mean的计算方式
assert model_output.shape == (B, C * 2, *x.shape[2:])
但是为什么要C*2?
_scale_timesteps(self, t)
用于处理时间步长。具体来说,它首先从模型的参数中获取模型的是否重新缩放时间步长的标志。然后,如果模型的是否重新缩放时间步长的标志为True,那么它将使用torch.float函数将时间步长转换为浮点数,并使用1000.0除以模型的总时间步长数来缩放时间步长。然后,它将缩放后的时间步长返回给调用者。如果模型的是否重新缩放时间步长的标志为False,那么它将直接返回时间步长。这个过程可以用于处理时间步长,以便在计算模型的预测输出和损失函数时使用。
condition_mean(self, cond_fn, p_mean_var, x, t, model_kwargs=None)
计算模型的预测输出
condition_score(self, cond_fn, p_mean_var, x, t, model_kwargs=None)
这个函数的作用是计算给定模型的条件得分。它使用了一个名为cond_fn的函数来对模型的得分函数进行条件处理。这个函数首先提取了时间步t和输入数据x的alpha_bar值,然后计算了一个eps值。这个eps值是基于pred_xstart的预测值和cond_fn的处理结果。然后,它使用这个eps值来更新pred_xstart的预测值,并计算新的均值和方差。最后,它返回更新后的均值和方差。
p_sample()
p_sample_loop()
p_sample_loop_progressive()
ddim_sample()
ddim_reverse_sample()
ddim_sample_loop()
ddim_sample_loop_progressive()
一些采样过程
_vb_terms_bpd(self, model, x_start, x_t, t, clip_denoised=True, model_kwargs=None)
这个函数接受模型、当前的x_{t-1}张量、当前的时间步长t,以及一些可选的参数,如clip_denoised、model_kwargs。然后,它会使用q_posterior_mean_variance函数来获取x_0的均值和方差的预测值,以及使用p_mean_variance函数来获取模型的预测值。然后,它会计算KL散度,这是两个概率分布之间的差异度量。最后,它会计算解码器的NLL(负对数似然),这是模型生成x_0的概率。然后,它会根据t的值来选择返回KL散度或解码器的NLL,这是模型的变分下界的一个项。
training_losses(self, model, x_start, t, model_kwargs=None, noise=None)
根据LossType计算loss
_prior_bpd(self, x_start)
这个函数接受模型和当前的时间步长t作为参数。然后,它会使用q_posterior_mean_variance函数来获取x_0的均值和方差的预测值,以及使用p_mean_variance函数来获取模型的预测值。然后,它会计算KL散度,这是两个概率分布之间的差异度量。然后,它会将这个KL散度转换为比特/维度,这是模型的性能的一个度量。最后,它会返回这个KL散度。
calc_bpd_loop(self, model, x_start, clip_denoised=True, model_kwargs=None)
计算变分下界
_extract_into_tensor(arr, timesteps, broadcast_shape)
转化为tensor