任务一:
-
选修:尝试在任意平台上部署webui或comfy图形化工具,并生成一副作品
-
打卡内容:
-
学习笔记
-
作业:生成一副“赛博猫咪”主题的作品
-
Learning Note: Introduction to 🤗 Diffusers
目标:
本笔记的中心主题是让学习者深入了解扩散模型,并使用🤗 Diffusers库。通过这个模块,将具备使用扩散模型生成图像的实践经验,这里使用以蝴蝶为主题的图像生成作为教程。
基本原理介绍
生成模型
在深度学习中,⽣成模型的⽬标是根据给定的样本(训练数据)⽣成新样本。⾸先给定⼀批训练数据X,假设其服从某种复杂的真实分布p(x),则给定的训练数据可视为从该分布中采样的观测样本x。如果能够从这些观测样本中估计出训练数据的真实分布,不就可以从该分布中源源不断地采样出新的样本了吗?⽣成模型实际上就是这么做的,它的作⽤是估计训练数据的真实分布,并将其假定为q(x)。在深度学习中,这个过程称为拟合⽹络。
那么问题来了,怎么才能知道估计的分布q(x)和真实分布p(x)的差距⼤不⼤呢?⼀种简单的思路是要求所有的训练数据样本采样⾃q(x)的概率最⼤。这种思路实际上来⾃统计学中的最⼤似然估计思想,它也是⽣成模型的基本思想之⼀,因此⽣成模型的学习⽬标就是对训练数据的分布进⾏建模。
基本原理
扩散模型包括两个步骤:
-
固定的(或预设的)前向扩散过程q:该过程会逐渐将高斯噪声添加到图像中,直到最终得到纯噪声。
-
可训练的反向去噪扩散过程:训练一个神经网络,从纯噪音开始逐渐去噪,直到得到一个真实图像。
前向与后向的步数由下标 t定义,并且有预先定义好的总步数 T(DDPM原文中为1000)。
t=0 时为从数据集中采样得到的一张真实图片, t=T 时近似为一张纯粹的噪声。
因此,总体流程可以简单总结如下:
- 扩散模型的目的是什么?
学习从纯噪声生成图片的方法
- 扩散模型是怎么做的?
训练一个U-Net,接受一系列加了噪声的图片,学习预测所加的噪声
- 前向过程在干啥?
逐步向真实图片添加噪声最终得到一个纯噪声
对于训练集中的每张图片,都能生成一系列的噪声程度不同的加噪图片
在训练时,这些 【不同程度的噪声图片 + 生成它们所用的噪声】 是实际的训练样本
- 反向过程在干啥?
训练好模型后,采样、生成图片
Introduction to 🤗 Diffusers
一、环境准备工作
1.1 安装Diffusers库
%pip install -qq -U diffusers datasets transformers accelerate ftfy pyarrow==9.0.0
1.2 登录huggingface(optional)
我们计划把训练好的模型上传到huggingface中,因此我们需要首先登录huggingface,可以通过访问https://huggingface.co/settings/tokens获取huggingface的token。
到huggingface 的 account 下面找到你自己的 api 复制过来,然后执行下面的代码,并粘贴到执行如下代码的文本框中:
from huggingface_hub import notebook_login
notebook_login()
1.3 安装Git LFS以上传模型检查点,代码如下:
%%capture
!sudo apt -qq install git-lfs
!git config --global credential.helper store
1.4 定义所需的函数
import numpy as np
import torch
import torch.nn.functional as F
from matplotlib import pyplot as plt
from PIL import Image
def show_images(x):
"""给定一批图像,创建一个网格并将其转换为PIL"""
x = x * 0.5 + 0.5 # 将(-1,1)区间映射回(0,1)区间
grid = torchvision.utils.make_grid(x)
grid_im = grid.detach().cpu().permute(1, 2, 0).clip(0, 1) * 255
grid_im = Image.fromarray(np.array(grid_im).astype(np.uint8))
return grid_im
def make_grid(images, size=64):
"""给定一个PIL图像列表,将它们叠加成一行以便查看"""
output_im = Image.new("RGB", (size * len(images), size))
for i, im in enumerate(images):
output_im.paste(im.resize((size, size)), (i * size, 0))
return output_im
# 对于Mac,可能需要设置成device = 'mps'(未经测试)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
二、Diffusers核心API
- Pipeline(管道):高级API,便于部署;
- Model(模型):定义训练扩散模型时需要的网络结构,比如UNet模型
- Scheduler(调度器):在推理过程中使用多种不同的技巧来从噪声中生成图像,同时也可以生成训练过程中所需的”带噪“图像;
三、使用Diffusers生成蝴蝶图像案例
3.1 下载蝴蝶数据集
import torchvision
from datasets import load_dataset
from torchvision import transforms
dataset = load_dataset("huggan/smithsonian_butterflies_subset",
split="train")
# 也可以从本地文件夹中加载图像
# dataset = load_dataset("imagefolder", data_dir="path/to/folder")
# 我们将在32×32像素的正方形图像上进行训练,但