文章目录
前言
原始的DDPM开启了图像生成的新方式,一个问题也随之出现,它无法控制生成的图片,虽然之后有类似CLIP的多模态大模型可以通过文本提示构建图片。但仅仅通过提示词很难精确地控制画面的布局、姿态、元素等。生成匹配的结果需要大量的尝试,也即我们说的“抽卡”。本文作者考虑是否有一个方法对结果进行控制,比如绘画师的草图,深度图,人体姿态图等。
相关的工作
微调神经网络
- HyperNetwork:是一种源于自然语言处理(NLP)领域的方法,旨在训练一个小型循环神经网络来影响大型网络的权重。截至ControlNet发布前,这个方法已经被应用在GAN中了。
- Adapter:Adapter是一种用于迁移学习的技术,旨在通过引入少量可训练的参数,将预训练模型快速适应到新任务或新领域。
- Additive Learning:为了网络能够适应新任务的同时,不会忘记原有知识而提出的相关方法(知识遗忘)。Side-tuning就是其中的一个方法,原理大概是会加入一个辅助的分支,两个分支结果的输出比例使用 α 来调节,在训练过程当中,这个比例可以变化。
- Low-Rank Adaptation (LoRA):LoRA应用就很广泛了,基本所有的大模型再训练都是用这个方法,在不破坏原始特征的情况下,用极小的资源就可以训练出一个模型。通过控制数据集,实现特定物体的生成。
- Zero-Initialized Layers:全零初始化网络层也被应用在ControlNet中,虽然有很多研究表明,高斯初始化权重比用零初始化更安全,但全零初始化能使微调开始的时候保持模型原有的输出。
图像扩散
- Image Diffusion Models:最早起源于DDPM,加上VAE技术,在潜空间里对变量进行扩散,大大减少内存占用。利用CLIP模型实现文本对结果的控制,商业化的产品有DALL-E2和Midjourney。
- Controlling Image Diffusion Models:利用Textual Inversion、DreamBooth技术等技术,对特定概念进行注入,也可以在一定程度实现对结果的控制。
图像到图像的转换
GAN的各种变体,如Conditional GANs、StyleGANs等。
ControlNet原理
从上图中可以看出,原始的Block是串行的结构, x x x作为输入, y y y是输出,而ControlNet则是从原始模型中新增一条旁路出来,将权重拷贝过来,同时在输入和输出的位置,加上两层全零初始化的卷积。而原始的权重是锁住的,其实本质上不参与训练。这样设计的好处有两点:
- 全零卷积:不会破坏原始Stable Diffusion模型的从大规模数据集的中学习到的特征
- 拷贝权重:从原始模型的基础上学习
可以看到,这两个设计是相辅相成,互相制约。
关于全零卷积会不会导致梯度消失,发生权重一直不更新的问题。我一开始也有这样的疑问,可能也是很多人问了作者同样的问题,作者在ControlNet的代码仓里也有写相关的FAQ,具体推导:
Zero Convolution Layer的初始权重
W
W
W和偏置
b
b
b都设为零:
W
=
0
,
b
=
0
W = 0, b= 0
W=0,b=0
因此,初始时他的输出
y
y
y为:
y
=
W
⋅
x
+
b
=
0
⋅
x
+
0
=
0
y = W \cdot x + b = 0 \cdot x + 0 = 0
y=W⋅x+b=0⋅x+0=0
在神经网络中,梯度是通过 链式法则 计算的。假设损失函数为
L
L
L,我们需要计算
L
L
L对权重
W
W
W的梯度,
∂
L
∂
W
\frac{\partial L}{\partial W}
∂W∂L。反向传播时
∂
L
∂
W
\frac{\partial L}{\partial W}
∂W∂L的计算公式为:
∂
L
∂
W
=
∂
L
∂
y
⋅
∂
y
∂
W
\frac{\partial L}{\partial W} = \frac{\partial L}{\partial y} \cdot \frac{\partial y}{\partial W}
∂W∂L=∂y∂L⋅∂W∂y
其中:
∂
y
∂
W
=
x
\frac{\partial y}{\partial W} = x
∂W∂y=x
因此:
∂
L
∂
W
=
∂
L
∂
y
⋅
x
\frac{\partial L}{\partial W} = \frac{\partial L}{\partial y} \cdot x
∂W∂L=∂y∂L⋅x
可以看到,梯度
∂
L
∂
W
\frac{\partial L}{\partial W}
∂W∂L并不直接依赖于
W
W
W,而是依赖于
∂
L
∂
y
\frac{\partial L}{\partial y}
∂y∂L和
x
x
x,损失函数对输出的求导不会为零(除非预测和实际完全一样),输入
x
x
x更不可能为零。所以实际上在权重更新完一次之后,Zero Convolution Layer就不会为全零了
网络结构
整体的网络结构如上图所示,作者是以Stable Diffusion作为baseline。只拷贝Encoder部分,Decoder部分用零卷积初始化。原始输入是512 x 512分辨率下的,经过一个4层的小型卷积网络,进行下采样到64 x 64分辨率下进行扩散。
因为Stable Diffusion部分的权重是锁住的,所以它只提供前向推理结果。只有ControlNet部分需要训练。实际训练过程中,在A100(40GB)上,只会多23%的GPU内存占用,34%的时间消耗。
训练阶段
损失函数为:
这里 z t z_t zt代表带有噪声的图像, t t t为时间步, c t c_t ct是文本引导词, c f c_f cf是任务相关的特定条件,即ControlNet输入。
作者还提到,训练过程中,会抹除50%的提示词信息。这种方法提高了ControlNet主动识别输入条件图像中的语义(例如边缘、姿势、深度等)的能力。
另外论文中还发现了一个有趣的现象。模型不是逐渐学会控制条件的,而是突然之间学会的。
如上图所示,ControlNet的输入是一个苹果植物,而在刚训练60K个step左右都还是苹果笔记本电脑。在6133个step时,模型就突然学会了。对于这个现象,作者在其个人博客上也解释为模型陷入了局部最优。推荐的解决方法是,在算力允许的情况下,扩大batch size,然后从头开始训练,不过一般增大到256之后,再增大也没什么影响了。
另外,文中还提及了,数据集大小对最终生成结果的影响。可以看到,数据集数量越大,其生成结果更精细。当然,这也是深度学习大力出奇迹的常态了。
推理阶段
Classifier-free guidance resolution weighting
Stable Diffusion依赖于一种称为无分类器引导(Classifier-free guidance)的技术来生成高质量图像。关于这部分,可以看看之前博客的讲解。
CFG的公式为:
ϵ
p
r
d
=
ϵ
u
c
+
β
c
f
g
(
ϵ
c
−
ϵ
u
c
)
\epsilon_{prd} = \epsilon_{uc} + \beta_{cfg}(\epsilon_c - \epsilon_{uc})
ϵprd=ϵuc+βcfg(ϵc−ϵuc)
ϵ
p
r
d
\epsilon_{prd}
ϵprd代表模型最终的输出,
ϵ
u
c
\epsilon_{uc}
ϵuc代表模型unconditional output(即纯噪声 + 无引导词的生成结果),
ϵ
c
\epsilon_c
ϵc代表带引导条件的输出(可以是提示词或ControlNet),
β
c
f
g
\beta_{cfg}
βcfg是可以调整的超参数。当控制图像通过ControlNet添加进条件图像时,它是可以被同时加到
ϵ
u
c
\epsilon_{uc}
ϵuc和
ϵ
c
\epsilon_c
ϵc,或者只加入到
ϵ
c
\epsilon_c
ϵc中。
下图中(a)是输入的Canny,当没有提示词的时候,无论是 ϵ u c \epsilon_{uc} ϵuc还是 ϵ c \epsilon_c ϵc,其guidance作用完全失效。如下图(b),但是如果只用condition,可能又会让指导过于强烈,如下图(c)所示。
Resolution weighting是指在生成过程的不同分辨率层级上,根据实际需要调整每个分辨率层级的权重,从而影响生成过程中的图像细节和结构。这种加权方式有助于生成过程中更好地平衡细节与全局结构。
例如,假设你有一个多分辨率生成的扩散模型(如在训练过程中从低分辨率到高分辨率逐步生成图像),你可能会对每个分辨率阶段赋予不同的权重。低分辨率阶段可能更多关注大致结构,而高分辨率阶段更多关注细节,因此在低分辨率阶段可能使用较小的权重,而在高分辨率阶段使用较大的权重。
将 Resolution weighting 与 Classifier-free guidance 结合在一起的想法是,在每个分辨率阶段应用不同的引导强度。这样可以让低分辨率阶段(关注全局结构)和高分辨率阶段(关注细节)根据其重要性,灵活地引导生成过程。
作者的解决方法是,首先将条件图像给到 ϵ c \epsilon_c ϵc,并且根据每个block的分辨率 h i h_i hi,得到 w i = 64 / h i w_i = 64 / h_i wi=64/hi,Stable Diffusion和ControlNet之间的连接乘上一个系数 w i w_i wi, i t h i^{th} ith是每个block的编号。通过减少CFG guidance的强度,可以得到更好的结果,如图(d)。
Composing multiple ControlNets
在推理时,可以将多个ControlNet组合在一起使用,如上图所示,将Pose和Depth组合一起生成的结果。
Strength, Start, End
在实际使用时,还有Strength, Start_Percent, End_Percent的三个参数可以设置:
- Strength:控制ControlNet对生成结果的影响强度,Strength=0时,ControlNet完全不起作用,,生成结果完全由主模型决定。Strength=1时,ControlNet的影响最大,生成结果会严格遵循 ControlNet 的引导
- Start_Percent, End_Percent:控制ControlNet在扩散时生效的时间段,一般是组合使用的。
Start_Percent = 0
,End_Percent = 0.5
时鼓励模型在一开始遵循ControlNet的条件,而后续填充的部分更遵循Stable Diffusion生成。
More Trick
更多的技巧和使用建议,作者有在其Github的issue中提及,写的也很详细。这里就不展开讲解了。
总结
ControlNet是一种神经网络结构,但他没有提出全新的结构。反而是利用现有的技术,对其进行小小的改动,使得用户可以对图片进行更精准的控制。甚至在训练时,其训练数据可以直接使用现有的图文对进行训练,例如Canny,Hough Line等,都可以用现有的OpenCV直接生成对应的输入图。人工标注的部分非常少。所以作者其实只用了非常少的成本就获得了比较好的结果,不愧是获得了ICCV 2023最佳论文奖的论文。