此文涉及公式推导,需要参考这篇文章:
Stable Diffusion扩散模型推导公式的基础知识
1、Diffusion的整体过程
扩散过程是模拟图像加噪的逆向过程,也就是实现去噪的过程,
加噪是如下图从右到左的过程,称为反向扩散过程,
去噪是从左往右的过程,称为前向扩散过程,

2、加噪过程
加噪过程如下图,下一时刻的图像是在上一时刻图像的基础上加入噪音生成的,
图中公式的含义:x
t
x_t
xt表示 t 时刻的图像,
ϵ
t
epsilon_t
ϵt 表示 t 时刻生成的随机分布的噪声图像,
β
t
beta_t
βt表示 t 时刻指定的常数,不同时刻的
β
t
beta_t
βt不同,随着时间 t 的递增而增加,但需要注意
β
t
beta_t
βt的值始终是比较小的,因为要让图像的数值占较大的比例,

2.1 加噪的具体细节
A、将图像
x
x
x像素值映射到[-1,1]之间
图像加噪不是在原有图像上进行加噪的,而是通过把图片的每个像素的值转换为-1到1之间,比如像素的值是
x
x
x,则需要经过下面公式的处理
x
255
×
2
−
1
frac{x}{255}times2-1
255x×2−1,转换到范围是-1到1之间,
代码:
def get_transform():
class RescaleChannels(object):
def __call__(self, sample):
return 2 * sample - 1
return torchvision.transforms.Compose([torchvision.transforms.ToTensor(), RescaleChannels()])
B、生成一张尺寸相同的噪声图片,像素值服从标准正态分布
ϵ
∼
N
(
0
,
1
)
epsilon sim N(0,1)
ϵ∼N(0,1)
x = {Tensor:(2, 3, 32, 32)}
noise = torch.randn_like(x)
C、
α
alpha
α和
β
beta
β
每个时刻的
β
t
beta_t
βt都各不相同,0
β
t
beta_t
βt
β
t
beta_t
βt是作为权重存在的,且
β
1
β1β2β3βT−1βT,
代码:
betas = generate_linear_schedule(
args.num_timesteps,
args.schedule_low * 1000 / args.num_timesteps,
args.schedule_high * 1000 / args.num_timesteps)
β
beta
β的取值代码,比如
β
1
beta_1
β1取值low,
β
T
beta_T
βT取值high,
# T:1000 Low/β1: 0.0001 high/βT: 0.02
def generate_linear_schedule(T, low, high):
return np.linspace(low, high, T)
α
t
=
1
−
β
t
alpha_t=1-beta_t
αt=1−βt,alphas = 1.0 – betas
alphas = 1.0 - betas
alphas_cumprod = np.cumprod(alphas)
to_torch = partial(torch.tensor, dtype=torch.float32)
self.registerbuffer("betas", totorch(betas))
self.registerbuffer("alphas", totorch(alphas))
self.register_buffer("alphas_cumprod", to_torch(alphas_cumprod))
self.register_buffer("sqrt_alphas_cumpnod", to_torch(np.sqrt(alphas_cumprod)))
self.register_buffer("sart_one_minus_alphas_cumprod", to_torch(np.sqrt(1 - alphas_cumprod)))
self.registerbuffer("reciprocal sart_alphas", totorch(np.sart(1 / alphas)))
self.register_buffer("remove_noise_coeff", to_torch(betas / np.sqrt(1 - alphas_cumprod)))
self.registerbuffer("siqma",to_torch(np.sqrt(betas)))
D、任一时刻的图像
x
t
x_t
xt都可以由原图像
x
0
x_0
x0直接生成(可以由含
x
0
x_0
x0的公式直接表示)
x
t
x_t
xt与
x
0
x_0
x0的关系:
x
t
=
1
−
α
t
‾
ϵ
+
α
t
‾
x
0
x_t=sqrt{1-overline{alpha_t}}epsilon+sqrt{overline{alpha_t}}x_0
xt=1−αtϵ+αtx0,
α
t
=
1
−
β
t
alpha_t=1-beta_t
αt=1−βt,
α
t
‾
=
α
t
α
t
−
1
.
.
.
α
2
α
1
overline{alpha_t}=alpha_talpha_{t-1}…alpha_2alpha_1
αt=αtαt−1…α2α1
由上式可知,
β
t
beta_t
βt是常数,则
α
t
alpha_t
αt,
1
−
α
t
‾
sqrt{1-overline{alpha_t}}
1−αt,
α
t
‾
sqrt{overline{alpha_t}}
αt也是常数,
ϵ
epsilon
ϵ也是已知的,所以可以直接由
x
0
x_0
x0生成
x
t
x_t
xt,
def perturb_x(self, x, t, noise):
return (extract(self.sqrt_alphas_cumprod, t, x.shape) * x +
extract(self.sqrt_one_minus_alphas_cumprod, t, x.shape) * noise)
def extract(a, t, x_shape):
b, *_ = t.shape
out = a.gather(-1, t)
return out.reshape(b, *((1,) * (len(x_shape) - 1)))
2.2 加噪过程的公式推导
加噪过程:

加噪过程的公式:




总结:

3、去噪过程
去噪是加噪的逆过程,由时间T时刻的图像逐渐去噪到时刻为0的图像,
下面介绍一下由时刻为T的图像x
T
x_T
xT去噪到时刻为T-1的图像
x
T
−
1
x_{T-1}
xT−1,输入为时刻为t的图像
x
t
x_t
xt和时刻t,喂给Unet网络生成
ϵ
θ
epsilon_theta
ϵθ,其中
θ
theta
θ是Unet网络的所有参数,然后由下图中的
x
t
−
1
{bf x}_{t-1}
xt−1的公式即可生成时刻为t-1的图像
x
t
−
1
{bf x}_{t-1}
xt−1,

3.1 图像概率分布
去噪过程的2个假设:
(1)加噪过程看作马尔可夫链,假设去噪过程也是马尔可夫链,
(2)假设去噪过程是高斯分布,

假设数据集中有100张图片,每张图片的shape是4x4x3,假设每张图片的每个channel的每个像素点都服从正态分布,
x
t
−
1
x_{t-1}
xt−1的正态分布的均值
μ
mu
μ 和方差
σ
2
sigma^2
σ2 只和
x
t
x_t
xt有关,已知在t时刻的图像,求t-1时刻的图像,

1、因为均值和方差
μ
(
x
t
)
mu(x_t)
μ(xt),
σ
2
(
x
t
)
sigma^2(x_t)
σ2(xt) 无法求出,所以我们决定让网络来帮我们预测均值和方差,
2、因为每一个像素都有自己的分布,都要预测出一个均值和方差,所以网络输出的尺寸需要和图像尺寸一致,所以我们选用 Unet 网络,
3、作者在论文中表示,方差并不会影响结果,所以网络只要预测均值就可以了,
4、损失函数

我们要求极大似然的最大值,需要对
μ
mu
μ和
σ
sigma
σ求导,但是对于扩散的过程是不可行的,如下面的公式无法求出,因为
x
1
:
x
T
x_1:x_T
x1:xT的不同组合所求出的
x
0
x_0
x0的值也不同,
p
(
x
0
)
=
∫
x
1
:
x
T
p
(
x
0
∣
x
1
:
x
T
)
d
x
1
:
x
T
p(x_0)=int_{x_1:x_T}p(x_0|x_1:x_T)d_{x_1:x_T}
p(x0)=∫x1:xTp(x0∣x1:xT)dx1:xT
为了实现对极大似然函数的求导,把对极大似然求导的问题转换为ELBO :Evidence Lower Bound

对ELBO的公式继续进行化简,


首先来看
q
(
x
t
−
1
∣
x
t
,
x
0
)
q(x_{t-1}|x_t,x_0)
q(xt−1∣xt,x0)表示已知
x
0
x_0
x0和
x
t
x_t
xt的情况下推导
x
t
−
1
x_{t-1}
xt−1,这个公式是可以求解的,如上图公式推导;
p
θ
(
x
t
−
1
∣
x
t
)
p_{theta}(x_{t-1}|x_t)
pθ(xt−1∣xt)需要使用 Unet 预测出该分布的均值,
q
(
x
t
−
1
∣
x
t
,
x
0
)
q(x_{t-1}|x_t,x_0)
q(xt−1∣xt,x0)公式的推导如下:


综上可知,UNet是在预测下面的公式,下面的公式中除了
ϵ
epsilon
ϵ之外都是已知量,所以UNet网络实际预测的就是
ϵ
epsilon
ϵ,
5、 伪代码过程
下图是训练阶段的伪代码,第1行和第6行表示第2行到第5行的代码一直在循环,
第2行:从数据集中筛选出一张图像,即为
x
0
bf{x}_0
x0,
第3行:从0到
T
T
T的均匀分布中筛选出
t
t
t,源码中
T
T
T的范围设为1000,
第4行:从均值为0,方差为1的标准正态分布中采样出
ϵ
epsilon
ϵ,
ϵ
epsilon
ϵ的size和
x
0
bf{x}_0
x0的size是相同的,
第5行:
x
t
x_t
xt和从0到
T
T
T的均匀分布中筛选出
t
t
t喂给Unet,输出
ϵ
θ
epsilon_theta
ϵθ,和第4行代码采样出的
ϵ
epsilon
ϵ,
∣
∣
ϵ
−
ϵ
θ
(
.
.
.
)
∣
∣
2
||epsilon-epsilon_theta(…)||^2
∣∣ϵ−ϵθ(…)∣∣2的均方差作为损失函数,对这个损失函数求梯度进行参数更新,参数是Unet所有参数的集合
θ
theta
θ,

下图是推导/采样/生成图片阶段的伪代码,
第1行:从随机分布中采样一个
x
T
{bf x}_T
xT,
第2行:遍历从
T
T
T到1,
第3行:从随机分布中采样一个
z
bf{z}
z,
第4行:已知
z
bf{z}
z、
α
t
alpha_t
αt、
σ
t
sigma_t
σt,
ϵ
θ
epsilon_theta
ϵθ是Unet网络生成的,就可以得到
x
t
−
1
{bf x}_{t-1}
xt−1
循环2-4行代码,


参考:
1、CSDN链接:链接
2、哔哩视频:https://www.bilibili.com/video/BV1ju4y1x7L4/?p=5&spm_id_from=pageDriver
3、论文Denoising Diffusion Probabilistic Models:https://arxiv.org/pdf/2006.11239.pdf
文章来源于互联网:Stable Diffusion扩散模型【详解】小白也能看懂!!
5bei.cn大模型教程网










