Classifier Guidance 与 Classifier-Free Guidance

2023-12-14 11:28
文章标签 free guidance classifier

本文主要是介绍Classifier Guidance 与 Classifier-Free Guidance,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Classifier Guidance 与 Classifier-Free Guidance

DDPM 终于把 diffusion 模型做 work 了,但无条件的生成在现实中应用场景不多,我们终归还是要可控的图像生成。本文简要介绍两篇关于 diffusion 模型可控生成的工作。其中 Classifier-Free Guidance 的方法还是现在多数条件生成 diffusion 模型的主流思路。

Classifier Guidance: Diffusion Models Beat GANs on Image Synthesis

Classifier-Free Guidance: Classifier-Free Diffusion Guidance

Classifier Guidance

要做可控生成,即条件生成,首先想到我们可以拿类别来作为条件,比如要指定类别猫,就生成猫的图片。也就是说要给定类别 y y y,生成图片 x x x,即 P ( x ∣ y ) P(x|y) P(xy) 。而一般分类器做的事情正好是反过来,给定图片,预测类别,即 P ( y ∣ x ) P(y|x) P(yx) 。这刚好是一对逆条件概率,应该敏锐地想到贝叶斯公式就是处理这类逆概率问题的。推导如下:
∇ log ⁡ P ( x ∣ y ) = ∇ log ⁡ P ( x ) P ( y ∣ x ) P ( y ) = ∇ log ⁡ P ( y ) + ∇ log ⁡ P ( y ∣ x ) − ∇ log ⁡ P ( y ) = ∇ log ⁡ P ( x ) + ∇ log ⁡ P ( y ∣ x ) \begin{aligned} \nabla\log P(x|y)&=\nabla\log\frac{P(x)P(y|x)}{P(y)} \\ &=\nabla\log P(y)+\nabla\log P(y|x)-\nabla\log P(y) \\ &=\nabla\log P(x)+\nabla\log P(y|x) \end{aligned} logP(xy)=logP(y)P(x)P(yx)=logP(y)+logP(yx)logP(y)=logP(x)+logP(yx)
其中 P ( y ) P(y) P(y) 是某个类别的先验概率,是一个常数,其梯度为 0,故直接丢掉。这里的 ∇ P ( x ) \nabla P(x) P(x) 实际就是 score-base model 中所谓的 score,score-based model 实际可以看作是 diffusion model 的另一种形式,这里不展开。

在结果中,第一项 ∇ log ⁡ P ( x ) \nabla\log P(x) logP(x) 就是原本无条件生成的梯度,而第二项 ∇ P ( y ∣ x ) \nabla P(y|x) P(yx) 则相当于是分类器进行图形分类的梯度。也就是说,我们只要在无条件生成的基础上,加上想要的类别的分类器梯度,作为引导(或者称为条件的梯度修正),就可以导出以类别作为条件的生成。

推导看起来并不复杂,具体怎么实现呢?怎么在生成的时候加入分类器的梯度作为引导呢?这里我们参考 OpenAI 原 Classifier Guidance 给出的代码来理解:

# https://github.com/openai/guided-diffusion/blob/main/scripts/classifier_sample.py#L54
# 核心就是这里的cond_fn函数import torch as th
import torch.nn.functional as F
classifier = ... # 加载一个(噪声)图像分类器def cond_fn(x, t, y=None):assert y is not Nonewith th.enable_grad():x_in = x.detach().requires_grad_(True)logits = classifier(x_in, t)log_probs = F.log_softmax(logits, dim=-1)selected = log_probs[range(len(logits)), y.view(-1)]return th.autograd.grad(selected.sum(), x_in)[0] * args.classifier_scale

这里的 t 是当前时间步,x 是当前步的去噪结果图,y 是类别索引。我们看到,计算分类器梯度的过程其实很简单:

  1. 首先把 x 和原始的梯度断开(detach),准备计算分类器的梯度
  2. 把 x_in 和 t 都输入到分类其中,得到分类器预测的类别 logits
    • 注意,这里的分类器实际上需要是一个能够分类带噪声图像的分类器,不仅需要输入图像,还要输入当前时间步 t,相当于告知分类器当前噪声的强度。所以说,在 Classifier Guidance 的方法中,我们虽然不需要重新训练 diffusion 模型,但是我们需要单独训练一个噪声图像分类器。
  3. 再把预测的类别 logits 过一下 softmax,得到各类别的概率 log_probs
  4. 从 log_probs 中取出我们指定的类别 y 对应的概率,即 selected
  5. 最后将 selected 中各个目标类别的概率值加在一起,希望该值越大越好,取该值对于 x 的梯度,即为分类器引导的梯度。

Classifier-Free Guidance

Classifier Guidance 的方法虽然不需要重新训练 diffusion 模型,但是需要额外的训练一个噪声图像分类器,并且在采样时需要额外的梯度引导。最关键的是,其作为可控生成的方法,对结果的控制能力十分有限,仅能够支持分类器所认识的有限类别,这无疑是不能满足我们多种多样的使用需求的。我们想要的肯定是 zeroshot 的,能够直接理解自然语言的可控生成。所幸在 CLIP 之后,图像文本特征已经能够在一定程度上对齐,CV 各个方向都基于 CLIP 实现了 zeroshot / open-vocab,图像生成也不例外。

Classifier-Free Guidance 的方法训练额外的分类器,并且,可以实现各种条件的引导生成。以最火爆的文生图为例,只要结合 CLIP 文本编码器提取 prompt 的文本特征 embedding,输入到 diffusion 模型中作为条件,即可实现。目前,Classifier-Free Guidance 已经成为条件生成的主流思路。

Classifier-Free Guidance 的想法是这样的:同时训练无条件生成模型和条件生成模型(实际上这俩是一个模型,只是训练时有概率输入是有条件的,有概率是无条件的),在推理时,同时 forward 带输入条件的生成和无条件的生成吗,然后把俩结果进行线性组合外推,得到最终的条件生成结果。

直接来看一下伪代码(参考 diffusers 的 API):

unet = ... # 加载unet去噪模型
clip_model = ...  # 加载CLIP模型text = "a cat"  # 文本条件
text_embeddings = clip_model.text_encode(text)  # 编码条件文本,cond
empty_embeddings = clip_model.text_encode("")  # 编码空文本,uncond
text_embeddings = torch.cat(empty_embeddings, text_embeddings)  # concat到一起,只做一次forwardinput = torch.randn((1, 3, sample_size, sample_size), device="cuda") # 采样初始噪声for t in scheduler.timesteps:# 用 unet 推理,预测噪声with torch.no_grad():# 这里同时预测出了有文本的和空文本的图像噪声noise_pred = unet(input, t, encoder_hidden_states=text_embeddings).samplenoise_pred_uncond, noise_pred_text = noise_pred.chunk(2)  # 拆成无条件和有条件的噪声# Classifier-Free Guidance 引导 noise_pred = noise_pred_uncond + guidance_scale * (noise_pred_text - noise_pred_uncond)# 用预测出的 noise_pred 和 x_t 计算得到 x_t-1latents = scheduler.step(noise_pred, t, latents).prev_sample

代码里的写法是 ϵ ˉ = ϵ u + s ( ϵ c − ϵ u ) \bar\epsilon=\epsilon_u+s(\epsilon_c-\epsilon_u) ϵˉ=ϵu+s(ϵcϵu), 论文里的公式是 ϵ ˉ = ( 1 + w ) ϵ c − w ϵ u \bar{\epsilon}=(1+w)\epsilon_c-w\epsilon_u ϵˉ=(1+w)ϵcwϵu,二者是等价的,只是做了下变换 s = 1 + w s=1+w s=1+w。个人感觉代码里这个形式更好理解一点: ϵ c − ϵ w \epsilon_c-\epsilon_w ϵcϵw 表示从无条件到目标条件的一个方向, w w w 是多大程度上考虑条件的系数,在无条件 ϵ u \epsilon_u ϵu 的基础上,再朝目标类别移动一定距离,即: ϵ ˉ = ϵ u + s ( ϵ c − ϵ u ) \bar\epsilon=\epsilon_u+s(\epsilon_c-\epsilon_u) ϵˉ=ϵu+s(ϵcϵu)。(也可能是作者大佬的思路我没领悟到

Classifier-Free Guidance 的做法看起来并不复杂,但有几个问题值得讨论(笔者自己也很不明白,希望有大佬指点一下):

  1. 为什么不像 cvae 一样直接把 embedding 丢进去做条件生成,而是非要同时训练无条件生成的情况,再做一个线性作何外推呢?
    • 可能是因为采样时现需要有一个无条件的基准,然后像目标条件的方向再修正?
  2. 关于空门大佬提到的 Classifier-Free Guidance 破坏了 Neural Diffusion Operator 的准线性性质。
    • 提到在 w w w 很大时,采样结果会崩掉,实践中确实这种现象。但笔者目前尚在学习,还无法完全理解。贴一下大佬的文章链接:Classifer-free Guidance 是万恶之源 。

这些问题有大佬了解,可以指点一下,或者介绍下应该去补充哪些理论知识来深化理解,感激不尽。

这篇关于Classifier Guidance 与 Classifier-Free Guidance的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/492342

相关文章

神经网络训练不起来怎么办(零)| General Guidance

摘要:模型性能不理想时,如何判断 Model Bias, Optimization, Overfitting 等问题,并以此着手优化模型。在这个分析过程中,我们可以对Function Set,模型弹性有直观的理解。关键词:模型性能,Model Bias, Optimization, Overfitting。 零,领域背景 如果我们的模型表现较差,那么我们往往需要根据 Training l

HumanNeRF:Free-viewpoint Rendering of Moving People from Monocular Video 翻译

HumanNeRF:单目视频中运动人物的自由视点绘制 引言。我们介绍了一种自由视点渲染方法- HumanNeRF -它适用于一个给定的单眼视频ofa人类执行复杂的身体运动,例如,从YouTube的视频。我们的方法可以在任何帧暂停视频,并从任意新的摄像机视点或甚至针对该特定帧和身体姿势的完整360度摄像机路径渲染主体。这项任务特别具有挑战性,因为它需要合成身体的照片级真实感细节,如从输入视频中可能

delphi : 窗体的close,free,destroy的区别

一、我用application.create(TForm2,Form2)语句,创建了Form2,可是调用了Form2.close后,重新调用Form2.show. 刚才所创建的Form2仍然存在。问为了节约资源,应该怎样使用close,free,destroy. 三者的关系是什么? 1、Action:=caFree。 2、 with TForm1.Create(Application) do

C语言动态内存空间分配(malloc,calloc,realloc,free)

为了代码观感美观,我将代码部分的注释删了 malloc #include<stdio.h>#include<stdlib.h>#include<errno.h>//使用动态内存分配函数的注意事项://1.要判断指针是否为空指针,如果没有成功开辟动态内存空间,则不能继续使用该指针//2.分配的动态内存空间的数量要大于等于赋值的元素的数量,不能造成动态内存的越界访问//3.动态内存空间中

COD论文笔记 Adaptive Guidance Learning for Camouflaged Object Detection

论文的主要动机、现有方法的不足、拟解决的问题、主要贡献和创新点如下: 动机: 论文的核心动机是解决伪装目标检测(COD)中的挑战性任务。伪装目标检测旨在识别和分割那些在视觉上与周围环境高度相似的目标,这对于计算机视觉来说是非常困难的任务。尽管深度学习方法在该领域取得了一定进展,但现有方法仍面临有效分离目标和背景的难题,尤其是在伪装目标与背景特征高度相似的情况下。 现有方法的不足之处: 过于

【SPOJ】1825 Free tour II 点分治

传送门:【SPOJ】1825 Free tour II 题目分析:敲了两遍。。。 本题是论文题,具体见漆子超论文《分治算法在树的路径问题中的应用》。 在以root为根的第 i 棵子树上,我们用G[ i ,j ]表示root的第 i 棵子树的路径上严格有 j 个黑点的路径的最长长度。用F[ i ,j ]表示在root为根的第 i 棵子树的路径上不超过 j 个黑点的路径的最长长度。因

阅读笔记(五)多线程无锁的C++实现《Lock-Free Data Structures》

1. 前言   本文介绍使用C++实现多线程中无锁算法的实现和优化过程。 2. 无锁&CAS   在多线程程序中,加锁是一种必要的手段,由于保证数据操作的正确性(原子性)。但是这也在很多时候带来了性能的极度下降,因为所有共享数据的操作均需要加锁,有些时候会严重影响性能,比如当读键盘或者一些较慢的I/O操作时,锁会延误了其他线程的操作。更糟糕的是,不当操作可能会带来死锁。   首先介绍最经典

阅读笔记(四)NoSQL的选择指引《NoSQL database systems: a survey and decision guidance》

一. 前言   《NoSQL database systems: a survey and decision guidance》是一篇很好的综述类论文,详细的论述了NoSQL的特点和各种不同NoSQL数据库的选择依据。   传统的关系型数据库(relational database management systems ,RDBMSs)可以在保证一致性、可靠性、稳定性的前提下提供强有力的数据存储

Softmax classifier

Softmax classifier原文链接 SVM是两个常见的分类器之一。另一个比较常见的是Softmax分类器,它具有不同的损失函数。如果你听说过二分类的Logistic回归分类器,那么Softmax分类器就是将其推广到多个类。不同于SVM将  f(xi,W)  的输出结果 (为校准,可能难以解释)作为每个分类的评判标准,Softmax分类器给出了一个稍直观的输出(归一化的类概率),并且

特征选择错误:The classifier does not expose coef_ or feature_importances_ attributes

在利用RFE进行特征筛选的时候出现问题,源代码如下: from sklearn.svm import SVRmodel_SVR = SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1, gamma='auto',kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verb