具体理论公式的推导见Georgeqi'Blob
基于pytorch 实现的Diffusion模型
训练:
运行train_solver.py文件并且通过data_name指定数据集,具体可以见config.yaml文件。
CUDA_VISIBLE_DEVICES=0 python train_solver.py --data_name "Flower102"
在config.yaml中各个数据集使用默认的Training Setting,每个数据集特有的配置见config.yaml下的Train_Data.
测试:
下载训练好的模型,在run_test.sh指定model_path、image_size/image_channel、sample_num等一些常规参数,此外有一些重要参数如下:
-
test_mode: 选择测试的模式,目前是支持random_gen(随机生成)和interpolate(插值效果)两种方式
-
training_timestep_num: 加噪步数(一般是和训练时候采用的步数相同,默认1000)
-
sample_info: 采样方式,默认是两种形式:
- "DDPM_1000_0p0": 常规的DDPM采样,且去噪迭代次数为1000(也可以设定为小于1000的数,此时会默认采用间隔步数采样),第三个参数"0p0"在这个采样方式下用不到
- "DDIM_50_0p0": 加速的DDIM采样,采样步数为50,eta参数为0p0。
上述两种形式都以"_"为界限分别指定"采样方式"、"迭代步数"、"eta",可自行修改参数查看相关效果
其他注意点:在使用test_mode="interpolate"时候,最好使用sample_info="DDPM_1000_0p0"
数据集 | 去噪过程可视化 | 最终去噪效果 | 插值 |
---|---|---|---|
Mnist | |||
Fashion_Mnist | |||
Cifar10 | |||
Flower102 | |||
StyleGAN2人脸 |
上述训练数据集和已经训练好的模型放在这里.
- 去噪过程可视化中,如果在采样step内均匀采样时间戳,会发现前面的去噪过程过于缓慢而后面会突然“有效果”,所以这里对于时间戳采用了一个“先粗后细”的采样trick用于可视化(具体见test_solver.py的test_random_generate函数)。
- 上述插值方法采用原DDPM论文中提出,本仓库采用其默认配置:
扩散步数=500,插值系数从0~1均匀采样11次
其中第一行和最后一行分别为两个原始的插值图片,中间11行为插值的结果,并且第二行和倒数第二行插值系数分别为0和1,可以看成是对原始两个插值图片的重构。 实验下来:感觉插值的结果并非是平缓的,而是中间会有一个比较“陡峭”的突变过程.....暂时没找到这种突变的解释~
这里简单实验和讨论了在训练DDPM过程中使用的损失函数(L1或L2损失),并且实验了Improved DDPM 中提到的Cosine Beta Schedule带来的效果提升:
- 单通道较简单的数据集(如Mnist, Fashion_Mnist等)可以直接使用Linear的Beta采样,与Cosine采样无大区别
- 3通道相对复杂的数据集(如Cifar10, Flower102, StyleGAN_Face等)的Beta采样最好使用Improved DDPM中提出的Cosine schedule,不然会导致最终生成的图片偏白。
- L1损失和L2损失对比,L2损失下生成效果会更加"尖锐"有时候会稍显乱+脏,而L1损失则显得更加平滑。
上述提到的L1/L2损失、Linear Beta Schedule/Cosine Beta Schedule的效果对比如下:
配置 | L1 loss、Cosine Beta | L2 loss、Cosine Beta | L1 loss、Linear Beta |
---|---|---|---|
Cifar10 | |||
Flower102 |
推理加速主要使用DDIM 中的算法
配置 | 50步 | 100步 | 200步 | 500步 | 800步 | 1000步 |
---|---|---|---|---|---|---|
DDPM | ||||||
DDIM(eta=1) | ||||||
DDIM(eta=0) |
上面的DDPM在采样步数小于训练步数(1000)的时候,使用的是Improved DDPM 中的间隔步长采样。可以看到上面的结果:
- 常规的DDPM采样结果在步数比较小时候基本仍然为纯噪声,虽然在步数逐渐增大(如500和800步)后会逐渐出现生成主体,但是仍然有一层噪声,直到采样步数等于训练时候的去噪步数(1000步)才能生成比较好完全无噪声的图像。
- 使用DDIM算法时候即便在部署很小(50步)时,也已经具有了比较好的生成效果,生成速度能提升至少20倍。
- 从当前实验结果看下来,在DDIM采样中eta=0和eta=1好像并无太大的效果差异。
此外又使用lucidrains 的代码验证了一下其中比较重要配置(如EMA、P2 loss、Clip_denoised)的必要性,对比效果如下:
配置 | EMA✅ P2 loss✅ Clip denoised✅ | EMA❌ P2 loss✅ Clip denoised✅ |
---|---|---|
效果(26K steps) | ||
配置 | EMA✅ P2 loss❌ Clip denoised✅ | EMA✅ P2 loss✅ Clip denoised❌ |
效果(26K steps) |
上面看来无明显的大差别,所以在本仓库中未使用EMA和P2 Loss,但是用了Clip denoised。
其他重要的配置则使用lucidrains原代码仓库中默认的:
loss_type='l1' beta_schedule='cosine' objective='pred_noise' self_condition=False
DDPM
Improved DDPM
What are Diffusion Models
lucidrains/denoising-diffusion-pytorch
zoubohao/DenoisingDiffusionProbabilityModel-ddpm
LianShuaiLong/CV_Applications
yiyixuxu/denoising-diffusion-flax