欢迎光临散文网 会员登陆 & 注册

浅谈stable diffusion (三)

2023-03-25 21:04 作者:FDX01  | 我要投稿

本系列的第三篇,如果你看过前俩篇,想必已经对stable diffuison原理和优势与劣势甚至未来的发展方向有了一定了解。

stable diffuison发展至今,商业(实用)属性已经相当高了,所以我们对stable diffusion剩下的细枝末节就从实际操作的角度讲起。

那么便从stable diffusion webUI讲起......

如果你不想了解任何和原理有关的东西,你甚至能把这篇文章当做新手教程,hhh~


Stable Diffusion web UI

A browser interface based on Gradio library for Stable Diffusion.

整体介绍

webui是基于gradio库搭建的图形界面,可以实现stable diffusion原始的txt2img和img2img模式,并提供了一键安装并运行的脚本。此外,webui还集成了许多二次开发功能,如outpainting、inpainting、color sketch等。它还提供了X/Y/Z图等脚本生成方式以及文本反转、超网络等图形界面训练按钮,以及一系列Extras方法的快捷使用。

虽然webui自称为stable diffusion的web图形界面,但实际上它是AI图像生成的综合工具。由于基于gradio的优势,它在搭建、扩展、多平台适配上都非常方便和实用。然而,受限于gradio和图形界面,一些精细的调整或者对生成流程的微调无法进行精细操作。虽然其中一些流程可以通过添加插件弥补,但仍有一些限制。

总的来说,stable diffusion web ui是初次接触扩散模型甚至是生成模型的新手最适合的图形化操作界面。接下来,我将按照webui的界面一一分析其中的原理、使用方法、效果和影响。此外,还可以通过webui进行许多扩展和调整,使其更适合个人的需求和喜好。


image-20230324184601532


webui 原版样式


Stable Diffusion checkpoint

image-20230324184633305

位置在webui的右上角,也是最重要的选项,可以在此处选择你的stable diffusion模型。

checkpoint(权重点),意味着里面存放着模型的权重参数,checkpoint 文件本质是一个变量名-变量值的词典。

一些疑问的解答

是否选择带ema的版本

如果你在很早期就亲自部署webUI或者经历或novelai的leak模型,你通常会有疑问,我究竟该选用animefull-latest的7G版本还是final-pruned的4G版本。

4G版本其实是7G版本的修剪版本,因为novelai在训练模型时使用了ema算法,试图提升模型最终生成的效果。

Ema是一种算法,可以近似获得近n步权重的平均值。该算法基于一个假设,即在训练的最后阶段,权重会在实际的最优点附近波动。通过取最近n步权重的平均值,可以使得模型更稳定。

早期一些人有一个误区,认为修剪版本的模型删除了ema部分的权重,事实上恰恰相反,修剪模型删除了所有非ema的权重。而且由于启用ema后运行非修剪版本时等同于运行修剪模型,所以单纯从生成的角度来说,俩个模型的效果是一致的。

泄露文件里模型对应的config文件可以控制是否启用ema

但是由于修剪版本的模型删除了非ema的权重,所以相比真实训练出的权重有失真,所以笔者认为如果你有数据洁癖或者坚持某种心理玄学在进行基于novelai leak模型进行二次训练时最好选择非修剪版本,但是笔者认为ema对于扩散模型来说不是很重要(相对于GAN)。

所以答案很明显:

  • 如果单纯用于生成应该选用不带ema的修剪模型,这样会节省内存和显存消耗。

  • 如果用于二次训练,如果显卡不错可以考虑基于带ema的版本(这里指的是非修剪版本,因为none-ema通常指修剪版本)进行二次训练。

该选择float16还是float32版本

float16和float32代表模型的权重保存的精度,float32的长度是float16近一倍,与之带来的是float32版本的模型文件通常要大很多。通常而言我们将float32称为单精度,float16称为半精度,float64称为双精度。

神经网络训练对精度降低的容忍度非常高

在实际生成的过程中,精度带来的影响微乎其微,笔者这里推荐是使用float16的版本作为生成使用,节省内存和显存。

在实际训练的过程中,对于stable diffusion来说精度带来的影响也是较小,当然实际训练过程中通常采用混合精度训练,最后使用float32的形式保存,财大气粗直接以float32的形式训练也行。

至于float16和float32版本对你来说谁更快,你应该参照你的N卡参数来判断。

说的就是你,T4

是否应该加载vae

模型文件即checkpoint是已经包含了vae(用于从隐空间解码,详见第一篇)相关参数,但是stable diffusion官方和novelai泄露出来的文件都有额外的vae,因为这些vae针对面部或者其他一些细节做了改良,所以加载vae文件实际是替换了模型文件中原有的与vae相关的参数。

当然由此引发的问题就是,如果你的模型原本的效果就很好,盲目加载vae可能弄巧成拙。或者如果你的模型文件已经注入过vae,你再加载同样的vae只是浪费时间。

我一直认为vae文件应该被称为vad(decoder,解码器)......

这里额外提一下设置,在setting里填入sd_vae,会在webui上方显示你价值的vae模型

image-20230325174701351

如图

image-20230325174816068


模型文件的后缀

模型文件的后缀为.ckpt或者.safetensors

.ckpt 文件是用 pickle 序列化的,这意味着它们可能包含恶意代码,如果你不信任模型来源,加载 .ckpt 文件可能会危及你的安全。

.safetensors 文件是用 numpy 保存的,这意味着它们只包含张量数据,没有任何代码,加载 .safetensors 文件更安全和快速。

其中风险利弊自行衡量

模型文件后面[]内的hash值

hash值通常来标注模型的唯一性,但是由于位数较短存在撞车可能,不是很实用。

stable diffusion算hash的算法经过变动,最近算16位hash的算法更改为了sha256,但是由于位数较低,撞车概率还是很高,如果遇到了相同hash的模型想要判断是否相同还请自行算更多位数的hash值来进行比较。


文生图/txt2img

image-20230324190024442


Prompt/Negative prompt

正向和反向提示词,用于文本条件生成。

正向提示词用于引导你想生成什么,反向提示词用于反向引导你不想生成的东西。

如果你阅读过前俩篇,你可能疑惑我之前没有提到过Negative prompt,那么我就在这里进行一并讲解

第一篇我们讲到在包含文本条件生成时,文本提示词被转换成语义向量,而语义向量则被送入U-Net进行噪声预测。在stable diffusion中实际上有俩组语义向量,一种用于正向提示,一组用于反向提示。那么这些提示究竟是怎么工作的呢?

我们先观看只有正向提示时的工作流程:

在stable diffusion进行采样时,算法首先使用由正向提示引导的条件采样对原始的图像(噪声)进行降噪,然后采样器再使用无条件采样再对同一图像(噪声)进行一些去噪(该过程不受文本提示影响),但是就算是无条件采样同样会是朝着一个具体的画面扩散,就像下图的篮球或酒杯(可以是任何东西,不过我们拿酒杯和篮球举例)。

在这样的一个过程中,你实际得到的图像是最开始的有条件采样得到的图像减去无条件采样的图像后的差异,这个过程重复数次最终获得你的成品图。过程如下图:

image-20230324191650019

Without negative prompt, a diffusion step is a step towards the prompt and away from random images.

那么如果我们携带反向提示会发生什么(该过程将胡子作为反向提示词)?

反向提示实际上是劫持了无条件采样,我们的无条件采样过程变成了使用反向提示进行采样,那我们的图像(噪声)就向着反向提示扩散,然后我们用正向提示得到的图减去反向提示得到的图,然后如此重复,不就减少了负面提示词代表的内容出现的可能吗。过程如下图

image-20230324193005023

When using negative prompt, a diffusion step is a step towards the positive prompt and away from the negative prompt.


以上的例子只是为了帮助理解而已图像的形式进行说明,实际stable diffusion的生成过程是在隐空间(latent space)进行,所以本例子并非真实的生成流程,但是本质是一致的

程序正义党不要喷我,嘤嘤嘤~



prompt的语法

如果你看到不同版本的说法,当你使用webui进行生成时请以笔者为准(从源码中整理出来,希望有人打脸)。

注意:通常有人认为|也是一种特殊语法,但是很遗憾webUI里是没有|这种语法的(我没有从代码中找到),这个语法仅用于novelai,用于混合不同元素,不过webui也提供了其他语法来变相实现这一过程(AND)。

增强/减弱(emphasized)

通常有如下语法来影响一个提示词的影响程度:

影响程度的范围在0.1到100之间

这种增强/减弱是如何实现的呢?你如果看过第一章,我们的单词其实是转化为了语义向量(768维空间中),那么缩放这个向量就能使得相关概念变强或减弱

注意当你不想使用emphasized而是想用()作为字符串时,你可以这样输入:

这里有个有关setting是默认被打开的

image-20230325175240715


渐变/调整作用时机(scheduled)

通常有如下语法来进行渐变(混合)俩个提示词:

amount的范围是0到1,代表混合强度,如何实现?

举个例子:如果你的amount为0.75,而采样步骤是40步,那么会有40*0.75=30步的过程,提示词为keyword1,剩下10步提示词为keyword2 所以如果你试图均匀混合,最好将amount调为0.5左右

示例如下图:

image-20230324195537241

注意当amount的大小>1时,amount指的就是特定步数切换

这个例子在第16步后变为 a cyberpunk landscape


所以由此诞生了一个非常有用的技巧,如下

image-20230324200606868

我们就得到了一张类似上图一般头发遮住耳朵的图

究其原因是在扩散的过程中最开始的步骤往往更重要,后面的步骤则是对细节进行了更精细的调整

通过这个技巧我们可以将一些提示词只作用于后面的步骤或者只作用于前面的步骤

值得注意的是这个语法有简写方式如下:

理解了,让我们来看个复杂例子


交替(alternate)

一个很有意思的语法,也可以用来混合一些提示,示例如下:

比如接下来的例子

在使用DPM++ 2M Karras采样时

第10步,头发偏向黄色(使用不同种子,多次生成)

image-20230324213556091

第11步,头发偏向红色(使用不同种子,多次生成)

image-20230324213634982

第13步,头发偏向黄色(使用不同种子,多次生成)

image-20230324213720351


如上面所说,扩散的过程中最开始的步骤往往更重要,所以在逐渐收敛的后,你的交替词往往也会效果减弱,最终发色也会其中偏向一种,不会在下一步产生大变。

组合/混合(composable)

组合的关键词是AND,注意要大写(我们实际短语的and应该是小写,笔者认为这样做是为了将prompt语法和实际自然语言进行区别),这个AND关键词允许组合(混合)多个提示的方法(对novelai的|的webui版实现)。

效果如下图

image-20230325000146948


值得注意的是,你可以像novelai中一般可以为每个词提供权重,默认为1,比如:

如果你的某个提示词权重低于0.1,那么该提示词对应的要素就很难产生影响


断开/打断(BREAK)

断开的关键词是BREAK,注意要大写。这个关键词会打断上下文的联系,强行进行再次分组(详见下文)。


词汇的具体解析

stable diffusion使用Clip作为文本的编码器(详见第一篇),Clip 的标记器在标记之前将所有单词小写。

得益于Clip的强大,你可以在提示词里使用自然语言(主要是英语,看模型训练时的情况),也可以使用类标记语言。

提示词中开头和结尾的额外空格会被直接丢弃,词与词之间的多余空格也会被丢弃。

支持颜文字 和 emoji ,Unicode 字符(如日语字符)。

拼写错误或罕见词

提示单词可以由一个或多个符号组成,常用词通常被解析为具有共同含义或少量含义的单个标记。而拼写错误和不常见的单词被解析为多个可以被识别的标记,示例如下:

笔者认为这个拼写错误被识别是很大原因因为Clip在训练过程中,人类也有拼写错误(人总会犯错,机械飞升吧~)然后联系上下文同样能产生识别这个词的效果。

而对于罕见词,他们的信息量(不准确的描述)太低会被理解为其他的词语,这也解释了颜文字和emoji的作用性相比自然语言更强,因为颜文字和emoji对特定的含义信息是强绑定的关系而且字符数短,而自然语言通常会有歧义。

词汇顺序/数量/位置影响

这是个好问题,以笔者对Clip浅薄的理解,词汇们被转化成语义向量输入到U-Net时利用了attention机制(详见第一篇),而语义向量将会添加到一个位置标记上( a position embedding token),早期的标记具有更一致的位置,因此神经网络更容易预测它们的相关性。而且由于attention机制的特殊性,每次训练时,开始的标记和结束的标记总会被注意到(attention)。而且由于标记越多,单个标记被被注意到的概率越低。

基于以上特性,笔者认为有以下几点需要注意:

  • 开头与结尾的词往往作用性更强

  • 提示词数量越多,单个提示词的作用性越低

  • 开头的数个提示词的作用较强,有更强的相关

关于数量,你可能已经注意到了,当你写prompt时会有数量限制

image-20230324223941776

但是在 webui中,你是可以写 75 个词汇以上的提示的。webui会自动通过对提示词进行分组。当提示超过 75 个 token(可以理解token代表你的提示词),提交多组 75 个 token。单个token只具有同一组中其他内容的上下文。

每一组都会被补充至(1,77,768)的张量,然后进行合并,比如俩组就会合并为(1,154,768)的张量,然后被送入U-Net。

值得注意的是

  • 为了避免将你的短语分成俩组,在分组时会查看附近是否有,来尽量还原你想要的输入


  • 然后你还能通过输入BREAK来快速分组,BREAK必须为大写


emoji和颜文字

对emoji的表现良好,对热门的颜文字表现良好(欧美环境),而且作用力很强

image-20230324223914140


采样方法/Sampling method

image-20230324225900065

如果你阅读过第一篇或第二篇,想必对采样方法已经有了自己的理解,我们可简单的将采样过程理解为一步一步将原有图片(噪声)去噪得到我们想要图片的过程。

webui中集成了很多不同的采样方法,这里结合设置中提供的选项,简单粗略的介绍下它们(不含数学,放心食用)。

Euler

基于Karras论文,在K-diffusion实现

20-30steps就能生成效果不错的图片

采样器设置页面中的 sigma noise,sigma tmin和sigma churn会影响

Euler a

使用了祖先采样(Ancestral sampling)的Euler方法

受采样器设置中的eta参数影响

LMS

线性多步调度器(Linear multistep scheduler)源于K-diffusion

heun

基于Karras论文,在K-diffusion实现

受采样器设置页面中的 sigma参数影响

DPM2

Katherine Crowson在K-diffusion实现

受采样器设置页面中的 sigma参数影响

DPM2 a

使用了祖先采样(Ancestral sampling)的DPM2方法

受采样器设置中的ETA参数影响

DPM++ 2S a

基于Cheng Lu等人的论文,在K-diffusion实现的2阶单步并使用了祖先采样(Ancestral sampling)的方法

受采样器设置中的eta参数影响

Cheng Lu的github](https://github.com/LuChengTHU/dpm-solver)中也提供已经实现的代码,并且可以自定义,1、2、3阶,和单步多步的选择

webui使用的是K-diffusion中已经固定好的版本

DPM++ 2M

基于Cheng Lu等人的论文的论文,在K-diffusion实现的2阶多步采样方法

被社区玩家称为最强采样器,速度和质量平衡优秀

比上方版本更优秀也更复杂

DPM++ SDE

基于Cheng Lu等人的论文的,DPM++的SDE版本(随机微分方程),DPM++原本是ODE(常微分方程)

在K-diffusion实现的版本中调用了祖先采样(Ancestral sampling)方法,所以受采样器设置中的ETA参数影响

DPM fast

基于Cheng Lu等人的论文,在K-diffusion实现的固定步长采样方法,用于steps小于20的情况

受采样器设置中的ETA参数影响

DPM adaptive

基于Cheng Lu等人的论文,在K-diffusion实现的自适应步长采样方法

受采样器设置中的ETA参数影响

LMS Karras

基于Karras论文,运用了相关Karras的noise schedule的方法,可以算作是LMS使用Karras noise schedule的版本

DPM2 Karras

使用Karras noise schedule的版本

DPM2 a Karras

使用Karras noise schedule的版本

DPM++ 2S a Karras

使用Karras noise schedule的版本

DPM++ 2M Karras

使用Karras noise schedule的版本

DPM++ SDE Karras

使用Karras noise schedule的版本

DDIM

随latent diffusion的最初repository一起出现, 基于Jiaming Song等人的论文

目前最容易被当作对比对象的采样方法

在采样器设置界面有自己的ETA

PLMS

元老级,随latent diffusion的最初repository一起出现

UniPC

目前最新采样器,基于Wenliang Zhao等人)的论文

理论上目前最快采样器,10步即可获得高质量结果

以上采样器,读者可以从字体大小中看出笔者的偏心,字体稍大的采样器在采样方法的发展史(虽然很短)中发挥了更大的作用,笔者也比较推荐用字体更大的那几种采样器(魔法师们开心就好,不要在意)。

俩个参数

eta参数

eta (noise multiplier) for DDIM只作用DDIM,不为零时DDIM在推理时图像会一直改变,生成的图像不会最终收敛

换句话说,即使跑了数百步,图像依旧可能产生大变化。

你可能主要到了上面很多款采样器提到了祖先采样,而且它们中的大多数名称内含有a,或者SDE

eta (noise multiplier) for ancestral samplers 作用于名字后缀带a和SDE的所有采样器,不为零时生成的图像也不会收敛(而且同种种子同样参数也可能会不同

eta noise seed delta,在该值不为零时起到固定初始值的作用,这样你就可以使用相同值还原某些其它人使用了对应eta值的图片(通过相同的seed)

相关设置:

image-20230325175828406

对于魔法师而言,要注意eta(前俩者)不要为0,否则可能会“失去”多样性和创造性,要注意eta(第三个)要和你准备复制的“法术”的eta相同,不然无法完美复制。

sigma参数

sigma包含:sigma churn,sigma tmin,sigma noise,仅对euler, heun和dpm2这三个采样器有效

sigma churn:决定sigma noise值如何被使用,如果churn值为0,即使noise值不为0,也没有任何效果。

sigma tmin:决定最小值范围的限制,可以为0

sigma noise:噪声本身的数值大小(注意,churn>0时,噪声值本身才有意义)

对于魔法师而言,sigma值也与多样性和创造性有关。


采样步数/Sampling steps


采样步骤与采样方法息息相关,每次采样相当于对原始图像(噪声)进行了一次去噪

最初的DDPM采样步数需要上千步才能获得高质量的图片,其消耗的算力和时间成本不可接受(隔壁GAN推理图片只要0.5秒内)

在牺牲准确和多样性的情况下,我们选用了效率更高的采样方式DDIM,获得高质量的图片只需要五十到上百步

后来如DPM++ 2M之类的采样算法更是将采样步骤缩进至20步,UniPC更是只需要10步左右就能获取高质量的图片,与之带来的是采样的时间和算力消耗大幅下降,生成出的作品能更多。

至于其中的牺牲,就笔者而言认为是微不足道的(无法诞生于世的东西是没有意义的)

对于魔法师来说,可能最好用的是Euler a或者DDIM或者PM++ 2M,请自行权衡。

注意一下,上述的eta参数和sigma参数会影响不同步数下的多样性


宽 高/Width Height

上面三个可选参数我们选择在后面再讲

非常明显,这俩按钮用来指定图片的宽和高

但是值得注意的是,stable diffusion 在2.0之前都是在原有的用256X256的latent diffusion model上用512X512的数据集进行训练,2.0后使用768X768的图片在继续进行训练

所以根据原理,stable diffusion 生成512X512左右的图片效果更好,当然stable diffusion在2.0后的模型版本至少将一侧设置为768像素更好

根据前俩篇文章我们知道,我们在生成时先是产生随机噪声,在隐空间中反映为一个张量,这个张量受到我们想生成的图片分辨率大小影响,比如我们隐空间图片张量大小为4X64X64时对应着外面的512X512图像,隐空间图片大小为4X96X96时对应着外面的768X512图像。

根据笔者自己从零训练的latent模型来看,数据集采用512的图片而去生成256尺寸的图片时只会生成图片的部分,而stable diffusion耗费巨资在训练时不断加入不同分辨率的数据集估计会减弱这一过程(大模型的黑盒)

但是就目前的stable diffusion来看生成过大图片还是会出现问题,比如:

生成图片如下,产生了俩个女孩(笔者认为在生成时局部空间内达到收敛,导致最后的图片看着像是俩张图片拼接)

正确的生成图片大小策略

基于以上讨论,我们认为以下是生成图片大小是应选择的策略

  • 在使用stable diffusion 2.0以前的模型时,图片一侧大小应该尽量接近512,图片整体靠近512X512;同理对于stable diffusion 2.0后的模型,图片一侧大小应该尽量接近768,图片整体靠近768X768

  • 图片如果需要更高的分辨率则请选择使用超分辨率的手段(后面再讲)

看到了这个按钮吗,这个按钮能轻松将宽和高进行数值交换


CFG指数/CFG Scale

这是个很重要的概念,前俩篇没讲,我这里具体讲一下(偏直观,不含数学推理)。

如果你看过前俩篇,我们知道扩散模型的前向扩散和反向去噪都可以用随机方程来进行描述,对于反向去噪过程我们通过神经网络来拟合当前输入关于原数据分布的梯度(噪声预测过程)。问题是原有的噪声预测适用于随机生成图像,单单有这个我们无法做到条件生成。

但是根据一些数学推论,我们推出看分类器来指导条件生成。

对于一个先验分布,我们想要再次获得数据分布里在条件约束下的数据点时,我们实际只要在原来往数据方向的梯度方向上再额外添加一个分类器的梯度方向即可。

那么我们如何去构造一个分类器呢?

构造显式分类器存在许多问题。首先,您需要额外训练一个能够在噪声图像上进行分类判别的分类器,这需要耗费很多时间和精力。其次,该分类器的质量将决定您按类别生成的效果。实际上,将图像的判别梯度更新到分类器上是一种经典的图像界对分类模型进行对抗攻击的方法,然而,骗过一个并不健壮的分类器并不代表我们确实逼近了条件分布。

GAN表示......

为了避免显式分类器的一些缺陷,我们推出了classifier-free,其核心是对无条件生成的网络以omega+1的强度进行有分类器引导的扩散生成等价于对有条件生成的网络以omega的强度进行有分类器引导,所以我们可以在diffusion里构造构建一个隐式的分类器梯度,使用隐式分类器引导的最终解析式要求我们只需要训练两个梯度预估模型,其中一个是无条件生成的梯度预估模型(例如常规的DDPM),另一个是基于条件的梯度预估模型。

一方面这大大减轻了条件生成的训练代价(无需训练额外的分类器,只需要在训练时进行随机drop out condition来同时训练两个目标),另一方面这样的条件生成并不是以一个类似于对抗攻击的方式进行的,本质上是它是两个梯度的差值所形成的。

如果你想到了我们上文提到的Prompt/Negative prompt的作用方式,恭喜你,你想对了,Prompt/Negative prompt处给的例子其实就是就是classifier-free过程造成的。

classifier-free guidance(无分类器引导生成)简称CGF堪称stable diffusion的奠基工作,以前说到跨模态我们通常只会想到clip,对生成的图像和文本的距离做一个损失差值来引导图像生成(详见第一篇),现在我们有了无分类引导生成,让文生图更加高效和自然。


实际使用时的CFG Scale

Classifier-free guidance (CFG) scale(CGF指数)用来调节文本提示对扩散过程的引导程度。

当数值为0时,图像生成是无条件的,数值较高时会向你的提示进行生成。

具体的数值应当与你的模型息息相关,但是鉴于市面上很少有像笔者这边从零练了latent diffusion model(至少需要一张A100),我们通过实验获得的CFG Scale参数经验基本是通用的,以下可能是对你有用的经验之谈:

  • 我们通常认为CFG scale的数值选为7-10是一个非常平衡的区间,既有创意也有能遵循我们的文本提示

  • CFG处于2-6时会创意力(不可控性)提高

  • CFG处于10-15时,你的作品受到你的提示的良性影响

  • CFG处于16-20时,你得确定你的提示真的是你想要的,否则效果不会太好

  • CFG高于20时,可能会产生一些奇怪的现象(建议魔法师来解释解释...)


生成/Gennerate

如果你有好好理解我前面所说的,就可以大胆按下这个按钮生成你想要的图像了

接下来我会讲解更加进阶的操作


面部修复/Restore faces

我只所以说webui是AI图像生成的综合工具,是因为它还集成了许多与diffusion关系不大的东西

比如我们现在讲的面部修复,面部修复是额外的模型,所以如果你初次使用可能会自动进行下载。

默认的面部修复模型是CoderFormer,此外还有GFPGAN,你可以在setting内进行更改。


下面的数值条可以控制CoderFormer的影响力度,为0时效果最强。

众所周知面部修复模型是用来修复面部的面部修复模型是用来修复面部的面部修复模型

可能对你生成的画风和细节产生一些不可预知的影响,笔者对这个选项不是很感兴趣,魔法师请自行确认效果。


生成无缝贴图/Tiling

这个功能可以说是设计师狂喜了,比如生成这样的图像,轻易突破想象极限(

image-20230325102703076


高清修复/Hires. fix

这个功能也是重量级了,尽管和diffusion模型的关系不大,但是根据上文,我们stable diffusion最好是生成512X512或者768X768附近大小的图片,但是显然这种像素级别对于现代24K钛晶眼来说不太够用,那么我们就可以通过高清修复(超分辨率/图像增强)来达到我们的目的。


我们点击该选项出现如下界面,按照惯例我们一个一个讲

image-20230325103237732


图像放大器/Upscaler

image-20230325103621676

点开的列表是一系列放大算法,由于大部分和stable diffusion无关,所以我们只讲部分

首先要讲的是

Lanczos插值和Nearest插值算法,这俩位是计算机图形学成果,是用于超分图像的传统算法,纯靠数学运算,充满了原始而自然的风味。

bicubic插值算法也被称作双三次插值算法,如果从信号与系统的角度讲,bicubic其作用原理接近一个低通滤波器,属于sa信号重建函数,是常见的视频图片质量增强算法。

而前缀有Latent的情况代表他们工作在隐空间(详见第一二篇)。


那么是什么现代的做法呢,我们的做法是讲算法和人工智能结合,这里我简单介绍一下与人工智能有关的放大器的通用原理。我们首先拿到高质量的图像数据,然后我们人为破坏将图片分辨率降低,然后尝试通过训练神经网络模型用来恢复原始图像。笔者认为以信息论的角度讲,一张图片单纯想要通过某种数学算法来增加信息是很难的,而神经网络模型本身蕴含巨量信息,可以对图片增加其信息。

LDSR

中文名为潜在扩散超分辨率模型,放大器们中唯一和diffusion模型靠边的,它出现于stable diffusion的v1.4版本。如果你读过前俩篇,我们知道扩散模型的前向过程是对图像的破坏,而反向过程是对图像的复原,你马上就联想到了上文我们提到的人工智能有关的放大器的通用原理,可以说扩散模型是天生适合干这件事的。但是基于diffusion的超分辨率相关工作还不是很成熟,目前存在一些缺点。

LDSR虽然能提供不错的放大效果(写实类),但是非常缓慢,不是很推荐。

R-ESRGAN 4x+

中文名为真实-增强型超分辨率生成对抗网络模型(R-ESRGAN),R-ESRGAN 4x是ESRGAN的增强版。GAN在这方面发展很早,所以效果出色,能保留精细的细节并产生清晰锐利的图像。而R-ESRGAN 4x在恢复各种真实世界图像时有更强效果,能产生更平滑的图像。

R-ESRGAN 4x+ Anime6B

上面的模型在6百万参数的动漫数据集上训练的结果,理论上相对上面能在二次元风格的图片上产生更优秀的效果。

以上俩个放大模型你可能需要前往设置进行添加

image-20230325110903301


SwinIR_4x

基于Jingyun Liang等人的论文,但是各方面性能打不过上面俩


放大步数/Hires steps

image-20230325113323716

你可以理解为我们在图像进行放大后基于该图像进行了二次生成

这个Hires steps就是我们二次生成时的步数,如果数值保持为0,就代表和原有步数相同。

步数对最终图像影响很大,所以生成图片时还请自行尝试对你模型和提示词和采样方法比较适合的步数。

如果你是个懒人直接置0即可。

去噪强度/Denoising strength

这个选项只使用于latent系列的放大器,也就是说如果你用ESRGAN就可以忽略本项。它将控制我们在进行Hires步数前,往latent空间的图像信息添加的噪声强度,通常该值处于0.5-0.8时效果较好。

放大倍数/Upscale by

image-20230325113954820

注意一下这个,表示你最终图片的像素大小

放大至/Resize width height to

如果启用这个,上面的方法倍数就会失效,方便微调

image-20230325114042519


经验总结

  • 当我们试图生成高像素级别图片时,我们仍然让stable diffusion生成一张512X768附近的图片,然后通过高清修复再次生成至更大的图片

  • 当我们生成真实图片时,我们一般采用R-ESRGAN 4x+,当我们生成二次元图片时我们一般采用R-ESRGAN 4x+ Anime6B


图像生成种子/Seed

image-20230325114441096

这是个非常有用的功能,设计到对图像的微调

Seed影响你生成时潜在空间生成的随机图像(噪声),理论上同样的Seed和然后其他参数不变时会产生一样的结果。(生成看似在玄学抽卡,实际每一步都有数学支撑)

注意Seed受到eta noise seed delta影响

在该值不为零时起到固定初始值的作用,这样你就可以使用相同值还原某些其它人使用了对应eta值的图片(通过相同的seed)

注意使用了祖先采样的采样器(ancestral samplers)同样的seed可能产生差别

Seed值在为-1时代表随机生成一个Seed

示例:

我们以-1为seed生成一张图

image-20230325135643050


下方出现的图片信息表示这张图的seed为632817208

image-20230325135710378

我们以632817208作为seed再生成一遍,便可以得到一样的图


image-20230325135805006


为什么说它很有用呢?

因为你可以在这个seed的基础上采用不同prompt或者采样步数或者超分来得到你想要的差异化结果。

上图俩按钮,一个用于随机生成种子(骰子),一个用于获取上张图的种子(回收)


附加/Extra

如果你点击了附加/Extra就会看到扩展栏


image-20230325140146486

种子变异/Variation seed

你想使用的变异种子,规则和seed一致

变异强度/Variation strength

变异种子和原种子的差异强度,为0时为原种子,为1时是新种子

这里有个技巧,首先我们seed设置为1进行生成,我的提示词里有red eyes

image-20230325141542226


然后我们seed修改为3,进行生成,发现姿势变化了

image-20230325141720203
image-20230325141731901

然后我们在种子变异栏里填上1,变异强度设置为1,便得到了和第一张一样的图

image-20230325142034183
image-20230325142107320


那我们把变异强度修改为0.5又会如何,得到了貌似是俩者之间的图(至少与两者有所关联)

image-20230325142320584
image-20230325142251534


调整种子大小

这个功能挺有用,其原理与上文提到调整图片大小类似,将隐空间大小进行改变,但是我们生成的图片的尺寸没有变化。通常,当改变分辨率时,图像会完全改变,即使保留了包括种子在内的所有其他参数。通过调整种子大小,可以指定原始图像的分辨率,而且模型很可能会产生与之非常相似的结果,即使在不同的分辨率下也是如此。

例子:

Seed resize not enabled

Seed resized from 512x512


批量生成

image-20230325143600644


上面的按钮是生成次数,下面的按钮是每次数量

理论上讲,显存够的话每次数量越高总体生成数量越快,但是每增加每次数量都会加大显存消耗


一些值得注意的是

  • 批量生成时指定种子后,第二张图将会是当前种子数+1,第三张以此类推

  • 批量生成时如果指定了种子变异,第二张图将会是当前种子变异数+1,第三张以此类推

通过批量生成+指定种子或种子变异可以在一个可控的范围内不断修改画面,方便使用者达到想要的效果。


脚本/Script

image-20230325144219263


webui提供了一系列脚本来方便生成,该功能非常好用,建议魔法师一定要学会。

描述词矩阵/Prompt matrix

使用|分离多个提示词,系统将会组合每个提示词用来生成图像。

例子:

a busy city street in a modern city|illustration|cinematic lighting
会生成四幅图像,分别为
a busy city street in a modern city
a busy city street in a modern city, illustration
a busy city street in a modern city, cinematic lighting
a busy city street in a modern city, illustration, cinematic lighting

image-20230325162127969

生成图片:

image-20230325161939267

载入描述词/Prompts from file or textbox

可以通过此脚本创建一个列表用于顺序生成

例子

输出:

以下参数受到支持:


XYZ图/XYZ plot

创建具有不同参数的多个图像网格。X 和 Y 用作行和列,而 Z 网格用作批处理维度(次数)。


使用X类型、Y类型和Z类型字段选择应由行、列和批次使用的参数,并将这些参数以逗号分隔输入到X/Y/Z值字段中。

语法支持整数、浮点数和范围。例如:

范围:

括号中带有增量的范围:

方括号内包含计数的范围:


生成下方的按钮

image-20230325163645727

第一个按钮用于回收上次的prompt

第二个按钮用于清除prompt

第三个按钮用于展示额外网络结构(之后再讲)

第五个按钮用于将当前prompt保存为预设,可以从styles中调用

第四个按钮则是启用当前styles,也就是启用预设


生成图片下方的按钮

image-20230325164138087

想必大家一看便懂,不多赘述


至此,关于文生图原版的所有按钮已讲解完毕,接下来我们进入图生图




图生图/img2img

由于图生图与文生图有很多功能和选项是一致的,所以下文只列出有差异的选项

image-20230325164506383

询问/Interrogate

webui提供了俩种询问途径,分别是询问CLIP和询问DeepBooru,这里涉及到了CLIP和DeepBooru俩个热门的模型,有必要详细讲讲。

询问CLIP

模态是指数据的存在形式,简单的来说,文本和视觉各自是一种模态。读过第一篇的朋友已经知道,CLIP模型是一个结合人类语言和计算机视觉的模型,它的存在意义就是为了帮助我们进行跨模态,即是从文本到图片,或者从图片到文本进行对应。

那么其中的一种应用是一张图片交给CLIP就能轻松地被CLIP判别给对应的文本,这也就是询问CLIP的本质。

例子:

首先上传图片

image-20230325165405677

点击

image-20230325165420307

获得

image-20230325165640428


询问DeepBooru

DeepBooru则是动漫风格的女孩图像标签估计系统(DeepDanbooru

专用于二次元,专用于二次元图片生成标签,二次元专业户

上图的对应结果:

image-20230325170245605


俩种Interrogate的优劣

  • clip注重画面内的联系,生成的自然语言描述

  • DeepBooru则是对二次元图片生成标签,对二次元的各种元素把握很好

注意如果你没有使用基于novelai泄露的模型(该模型在训练时大量使用了DeepBooru的数据和对应的二次元图片),使用DeepBooru似乎不是明智的行为。


缩放模式/Resize mode

image-20230325175939614

四种图像处理方式

拉伸 --简单的将图片缩放至指定比例,不保证原图尺寸比

裁剪--将图片按比例进行缩放,多余的直接裁剪掉

填充--将图片按比例进行缩放,缺少的部分填充

直接缩放(放大)--其实与前面三个不同,这个是用于图像超分辨率的快捷选项,低显存谨慎使用

去噪强度/Denoising strength

image-20230325192540542

换了一个汉化脚本,翻译成了重绘程度,虽然意思到了,但明显翻译没按词来

这里的去噪强度和之前我们在文生图里高清修复里的重绘强度是一致的

范围0-1,数值越大代表离原图距离越远


采样步数/Sampling steps

基本与文生图相同

值得注意的是,在默认情况下重绘程度低的时候,实际采样步数会下降

具体公式为采样步数X去噪强度=实际采样强度

我认为这是十分合理的调整,如果不喜欢可以在设置里进行更改

相关设置

image-20230325192954986


脚本/Script

image-20230325193102160

图生图的替代测试/img2img alternative test

一个非常鸡肋的功能,用于prompt微调,可以看看你的图片如果换了某个prompt大概的效果是什么样

其过程是对原图进行加噪破坏然后进行减噪生成

image-20230325195231603

我直接上例子吧

原图(该原图原始prompt为a girl ,red eyes)

image-20230325195206852

生成结果(生成的图的prompt的提示词被覆写为a girl ,yellow eyes)

image-20230325195251642

回送/Loopback

也是一个相当鸡肋的功能

image-20230325195905159

相当于用脚本帮你多次回环生成(上次生成的结果作为输入再次进行生成)

可以调整迭代次数和降噪系数

降噪系数的调整范围为0.9-1.1,相当于把上的降噪系数乘上这个调整值获得当前的调整系数

使用上述输入得到的例子如下


image-20230325200145511

效果稍差的向外绘制/Poor man's outpainting

image-20230325200504744

和图示相同用于一张图片向外拓展像素,蒙版我认为是没啥影响的,如果选用原图作为蒙版也许会色彩更丰富,用噪声的话也许有惊喜。

例子如下:

image-20230325200831692


需要注意的是,与正常生成不同,outpainting似乎非常依赖高步数,如下图


阿B啊~不会做富文本编辑器能不能直接抄markdown啊



向外绘制第二/Outpainting mk2

image-20230325201050838

上面的outpainting的改进版,翻译把我该干的事干完了,直接看图吧

使用SD放大/SD upscale

image-20230325201309139

非常鸡肋的功能

运行后的步骤为

  • 将图像进行放大2,3,4倍

  • 将图像按指定的宽高进行分割成数个片段

  • 将每个片段都做一次图生图

  • 然后将片段拼回,达成放大效果

可以说是非常具有自觉性的放大方式,但是直觉要是有用的话还要数学干什么?

由于这种操作要计算每次分割的块,否则会造成重叠过多,但是重叠过少连贯性也会下降

所以产生了如下例子

作用前


image-20230325202247821

作用后

image-20230325202607441


草绘/Sketch

局部绘制/Inpaint

局部草绘/Inpaint sketch

Inpaint upload

这几个属于img2img的二次开发,如果理解img2img这些也没有难度

Batch

img2img的快捷批量处理


图像增强/Extras

翻译显然对相关领域理解不够深入,翻译成了附加功能(虽然可能理解错误的是我)

image-20230325202920226


前面文生图高清修复和前面图生图放大的非隐空间版

当然,放大器自然也去掉了Latent系列

image-20230325203133028


基本上所有的按钮前面都有讲解,所以略过


图片信息/PNG Info

image-20230325203319073

凡是webui或者novelai生成出来的图都在元文件信息位置详细介绍了这张图的生成信息


值得注意的是,生成信息还包括了是否来自webui还是novelai,只不过webui没有把这部分信息展现出来,建议用相关软件查看

模型合并/Checkpoint Merger

image-20230325203620626

该区域用来合并模型,其规则都有些,如果你前面的部分都看过了,对这里应该没有理解难度

设置/setting

image-20230325203914071

如果你看完了本篇文章和前面的俩篇文章,我可以保证setting里的选项对你来说毫无理解难度,现在就打开setting自定义你的webui吧

本篇从webui的按钮入手,算是直接把前面两篇的内容串起来了,不知道有没有增进你们的理解呢~

至于训练相关和拓展相关就第四篇见面吧~



浅谈stable diffusion (三)的评论 (共 条)

分享到微博请遵守国家法律