教会你使用AI绘画利器Stable Diffusion

Posted 轻风博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了教会你使用AI绘画利器Stable Diffusion相关的知识,希望对你有一定的参考价值。

随着 stable-diffusion 的开源,让更多人有机会直接参与到 AI 绘画的创作中,相关的教程也如雨后春笋般的出现。可是目前我看到的教程同质性较高,通常只能称作为"使用流程讲解",但是通常没有对其原理和逻辑进行深入说明。 所以本文的目的,是用尽可能少的废话,给大家补充一些重要的相关知识。对于"怎么用"这类的问题,通常有别人已经讲解过,我就不会过多赘述(而是贴一个教程链接,请读者自己学习)。如果你想了解更多关于"是什么"、"为什么"的问题,那么本文将会给你更多的解答,尽可能让读者做到"知其然,亦知其所以然"。

随着 stable-diffusion 的开源,让更多人有机会直接参与到 AI 绘画的创作中,相关的教程也如雨后春笋般的出现。可是目前我看到的教程同质性较高,通常只能称作为"使用流程讲解",但是通常没有对其原理和逻辑进行深入说明。

所以本文的目的,是用尽可能少的废话,给大家补充一些重要的相关知识。对于"怎么用"这类的问题,通常有别人已经讲解过,我就不会过多赘述(而是贴一个教程链接,请读者自己学习)。如果你想了解更多关于"是什么"、"为什么"的问题,那么本文将会给你更多的解答,尽可能让读者做到"知其然,亦知其所以然"。

 

背景知识

Stable Diffusion 是什么?

Stable Diffusion 是利用扩散模型进行图像生成的产品,可以支持 text2image、image2image。并且由于“论文公开+代码开源”,其用户群体远大于其他 AI 图像生成产品。另外,而且众人拾柴火焰高,代码和项目开源使得各项优化技术在其上快速应用,使其不断迭代优化。

传送门:官网 | 论文 | Git

WebUI 是什么?

Stable Diffusion WebUI 是 AUTOMATIC1111 为 Stable Diffusion 开发的一套 UI 操作界面,大幅度降低了 Stable Diffusion 的使用门槛,让用户甚至可以不用写代码就能够实现模型的推理、训练等操作。

传送门:Git

启动器是什么?

启动器是秋葉 aaaki 团推开发的用来启动 Stable Diffusion WebUI 的启动工具。不仅能够实现一键启动(否则需要用户先打开 webui 服务,在打开浏览器网页),还包含了诸如环境选项、疑难解答、版本管理、模型管理、扩展插件管理等诸多功能。让没有开发经验的同学能够用起来更顺手。

传送门:教程 | 网盘下载

这三者依次递进,最终呈现在我们眼前,让我们能够方便的使用 Stable Diffusion 的能力。下面我们分 2 个大块,分别介绍如何使用 WebUI 进行推理(即生成内容)和训练,以及他们的应用场景。

 

1 上篇:推理应用

在开始之前,需要用户安装 Stable-Diffusion-WebUI,网络上有很多安装教程,比如:https://www.bilibili.com/video/BV1NX4y1Q7MH

但是实际上,在 WebUI 的官方介绍中已经列举了安装步骤:

1.1 文生图

1.1.1 模型风格介绍

首先不同模型所生成的图风格是会完全不一样的,在 C 站 上可以直接下载模型。用户只需要把CHECKPOINT格式的模型下载下来并放到stable-diffusion-webui/models/Stable-diffusion这个路径下就可以直接使用。在 WebUI 界面左上角既可以选择模型:

我将其按风格分成两大类:偏二次元风格 和 偏写实风格。下面我们分别以“Call of Duty”作为 prompt,看一些不同模型生成图片的效果:

【说明】:问了方便,本文后面的介绍全部都是基于 chilloutmix 模型进行的。

1.1.2 text2image 超参数设置

【说明】:该界面随着版本迭代会有些不同,如果读者自己的界面和我这个不通,不用太在意

我们举一个例子,打开 txt2image 的标签,左上角选择你想用的模型;在下方两个方框中分别输入提示词(prompt)来生成你想要什么样的图片,以及反向提示词来控制你不想要什么图片;后面几个参数说明如下:

  1. 采样器:其实就是在做图像生成的步骤,选用哪种模型(或扩散模型)
  2. 采样步数:其实就是扩散模型进行扩散的 step(这里的“采样”就是“生成图片”的意思,并不是我们平常理解的从很多数据中抽出一部分的那个采样)。一般设置为 60 就已经很清楚了,用户可根据对显存大小和耗时进行调整。
  3. 高度/宽度:生成图片的 size
  4. 生成批次/每批数量:最终会生成“生成批次 x 每批数量”张图片,这里分成两个参数是考虑到显存的限制,无法一口气生成大量图片
  5. 图像生成种子:随机种子不多介绍
  6. Aditional Networks:是一个插件,可以为模型加上一些其他结构(如 LoRA 等),关于模型训练和组合,我们以后找机会专门介绍
  7. ControlNet:是一个插件,可以通过输入一张图片,来控制生成结果与输入图片相似(下一节单独介绍)

这样输入相关参数后,可以看到 girl holding a gun 作为 prompt,所生成的 6 张图片

1.1.3 ControlNet 的应用

传送门:论文 | 代码 | 插件

  • 是做什么的?

We present a neural network structure, ControlNet, to control pretrained large diffusion models to support additional input conditions.

我们提出了一个神经网络结构,ControlNet,以控制预训练的大型扩散模型,以支持额外的输入条件。

其实就是在大型扩散生成模型的基础上,再加上一个结构,使得扩散生成模型能够接受一个新的“图像输入”。并且对模型的输出起到控制作用,使其与输入图像类似。

  • 特点是什么?
  1. 是一个与训练模型,拿来即用,且已经集成在 Stable Diffusion WebUI 中
  2. 在 text2image 时,需要额外输入一张图片
  3. 生成的结果会与输入图片保持较高的一致性
  4. 用户可以对输入图片进行一定的预处理,以保留最关注的信息,从而产生不同风格
  • 怎么做到的?

Step1: 将预训练好的扩散生成模型参数冻结,并 copy 一个新的可训练模型

The ControlNet clones the weights of a large diffusion model into a "trainable copy" and a "locked copy"

Step2: 将得到的两个模型按照下图的模式一起训练,其中可训练模型中的 Decoder 结构是“零卷积”结构

The trainable and locked neural network blocks are connected with an unique type of convolution layer called "zero convolution", where the convolution weights progressively grow from zeros to optimized parameters in a learned manner.

  • 怎么使用?

重述下本文的原则是,已经有人讲解过我就不废话了,直接把现有的教程链接贴给你。

  1. 安装插件,教程:https://www.bilibili.com/video/BV15k4y1t7Mo/
  2. 下载模型,主要 controlnet 模型下载地址:https://huggingface.co/lllyasviel/ControlNet
  3. 全流程例子:https://www.bilibili.com/read/cv21829826
  4. 官方参数说明:https://github.com/Mikubill/sd-webui-controlnet
1.1.4 脚本的使用

在 text2image 页面的左下方提供了脚本的选择。这里的脚本其实就是保存在stable-diffusion-webui/scripts/路径下的 python 脚本文件,目的就是为我们提供了一些方便的功能。

截至目前,text2image 功能支持 4 个脚本选择:

我们分别简单介绍:

提示词矩阵 :当我们有多个提示词时,该脚本提供一个能够看不同组合效果的功能。例如我们输入"girl with skirt|gun|blue hair"作为 prompt,其中包含 3 个提示词,且用"|"分割。这样就可以生成下图这种两两组合的效果图:

从文本框或文件载入提示词 :顾名思义,就是让用户能够从文件中导入提示词。举个例子我们在上面的 prompt 中输入 girl,在下面的文本框中输入 boy,结果生成的图片是男孩,说明通过“脚本”导入的提示词覆盖了在上面文本框中的提示词

X/Y/Z 图表 :针对特定 prompt,对比不同纬度的参数取不同值时的效果。如下例中,我们选用 prompt 为“girl holding a gun”,然后对比三个模型以及 10,20,30 三个不同采样步数的效果:

controlnet m2m :这个是一个视频处理功能,本质上是把用户上传的视频切帧,并分别进行 image2image,最后捏成一整个新的视频。由于视频不方便展示,而且 text2image 的 m2m 效果一般,容易产生图像的跳动/闪烁,本文在这里就直接略过了,大家感兴趣可以去尝试一下。

1.2 图生图

1.2.1 Deepbooru

传送门:代码

对于一些通用的超参数,如:采样器、采样步数在前文 text2image 中就已经介绍过了,这里介绍一下 image2image 特有的一个功能:Deepbooru 反向推导提示词。即输入一张图片,输出该图像对应的提示词,以求根据该提示词能尽可能的还原输入图像。

  • 怎么做到的?

根据代码可知,本质上它就是把 self.model.tags 遍历一遍,并且通过阈值过滤以及排序给出来的一份 tags 列表。

  • 怎么使用?

在 image2image 中,上传图片后,点击“DeepBooru 反向推倒提示词”,等一会就可以看到提示词窗口中生成了一串提示词。并且该提示词会被应用后续的图像生成过程。

1.2.2 功能介绍

除了进行 image2image,还提供了其他功能,如涂鸦绘制(sketch)、局部绘制(inpaint)等:

涂鸦绘制(sketch):允许用户在上传的图像上进行涂鸦,并根据涂鸦后的结果生成新的图像。如下例中,我把角色和黄色背景用黑笔框起来,生成的图片就会把这部分内容放在手机屏幕上。

局部绘制(inpaint):允许用户指定在图像中特定区域进行修改,而保证其他区域不变。如下例中,我们把角色的头发涂掉,然后在 prompt 中输入"colorful hair",试图让模型把头发改成彩色。

局部绘制-涂鸦蒙版(inpaint sketch):其实也是一种局部绘制(inpaint),区别之处在于在局部绘制(inpaint)中,用户涂黑的部分表示该部分可以被重绘;而在局部绘制-涂鸦蒙版(inpaint sketch)中,用户涂鸦的部分不仅表示可以重绘,用户涂鸦的内容还会成为图像生成的内容来源。下例中依然涂抹了角色的头发,并且在 prompt 中写入“colorful hair”试图让模型生成彩色头发:

结果发现没有成功生成彩色头发,反而是黑色头发(而且质量也不高),这是因为我们用黑笔进行的涂鸦。模型会把我们涂鸦的内容作为生成图像的素材来源。

局部绘制-上传蒙版(inpaint upload):其实就是不需要用户手动在前端页面进行涂鸦,取而代之是用户上传一张图片作为蒙版(类似于我们前面的涂鸦的作用)。这里就不展示了。

1.2.3 ControlNet 的使用

这部分内容网上已经有很多例子和教程了,比如:https://www.bilibili.com/video/BV1Wo4y1i77v

这里我们只简单举一个例子,选取下面这张角色跳舞的图进行 control,模式选择人物姿势检测

然后随便找一张图片来进行生成,根据结果可以明显看出 ControlNet 起到了作用,结果图中的人物都摆出了相同的姿势,但是输入图片的内容中只有色调和输出图片接近,人物的形象/装扮等都没有很好的保留。

1.2.4 脚本的使用

相比 text2image 来说,目前的版本中 image2image 有更多的脚本可以使用,除了已经介绍过的 4 个,还有:图生图替代测试(img2img alternative test)、图像迭代(Lookback)、向外绘制第二版(Outpainting mk2)、低质量画布补全(Poor man\'s outpainting)、SD 模式方法(SD upscale)共 5 个脚本功能。关于每种脚本的功能和使用说明,由于有 WebUI 作者的 官方说明 ,并且内容很多很杂,本文就不在这里废话了。

2 下篇:模型训练

目前常用的模型微调方法,主要包含以下几种模式:

  1. Dreambooth:微调整个网络参数
  2. LoRA:通过矩阵分解的方式,微调少量参数,并加总在整体参数上
  3. Textual Inversion:只微调新词对应的 embedding
  4. HyperNetworks:微调一个额外的网络结构,作用于 diffusion 过程的 attention 结构上

由于 Textual Inversion 和 HyperNetworks 的训练难度较大,效果也通常不尽如人意,目前并没有成为模型微调的主流选择。所以下文我们主要介绍 Dreambooth 和 LoRA(以及 LoRA 的变体 LyCORIS)相关的技术原理、特点、使用场景、使用方法。

2.1 Dreambooth

传送门:论文 | 代码 | 插件

2.1.1 是做什么的?

our technique enables synthesizing the subject in diverse scenes, poses, views, and lighting conditions that do not appear in the reference images

我们的技术能够在参考图像中没有出现的不同场景、姿势、视图和光照条件下合成主题

2.1.2 特点是什么?

最少只需要 3-5 个样本进行微调(但这几个样本需要时同一个主体的不同图片)

生成的结果是这个主体(subject)在不同场景下的图片(如下图)

2.1.3 怎么做到的?

Step1: 通过图像-提示词的唯一标识符,来微调低分辨率模型

We first fine-tune the low-resolution text-to- image model with the input images and text prompts containing a unique identifier followed by the class name of the subject (e.g., “A [V] dog”)

而这一步的难点是避免过拟合,文中作者通过新增一种 autogenous class-specific prior preservation loss,来避免遗忘问题

A key problem is that fine-tuning on a small set of images showing our subject is prone to overfitting on the given images. For this, we present an autogenous class-specific prior preservation loss, where we alleviate overfitting and prevent language drift by encouraging the diffusion model to keep generating diverse instances of the same class as our subject.

Step2: 通过低-高分辨率的配对,来微调超分辨率组件(就是根据低分辨率生成高分辨率的那个模型)

In the second step, we fine-tune the super-resolution component with pairs of low-resolution and high-resolution versions of the input images.

而其模型结构如下:

其中 reconstruction loss 就是 AutoEncoder 常用的重建损失,而 class-specific prior preservation loss 在文中的形式为:

2.1.4 如何使用?

首先这是关于Dreambooth 插件的详细说明 ,以及为大家提供一份Dreambooth 的参数设定指南 ,本文简单介绍一个例子:

Step1: Create Model

所谓 Create Model,就是创建一个初始化的模型,后面训练微调会在此基础上进行梯度更新。Create 出来的模型,会作为中间文件保存在stable-diffusion-webui/models/dreambooth路径下,而是包含 logging、samples、working、db_config.json 等多个子路径和文件的空间(而非 ckpt 文件),你可以把他理解成一个 workspace,该空间作为中间文件。

其中,Source Checkpoint 参数就是选择哪一个模型的参数作为初始化模型参数,模型路径为:stable-diffusion-webui/models/Stable-diffusion/下的 ckpt 文件模型。而所谓 Scheduler,也就是采样器,就是选择扩散模型的形式。都设置好之后,点击黄色的 Create Model,再等一会就能看到创建好的模型了。这时在 Output 处可以看到 successfully 的日志,以及在左边 Model Selection 处可以看到自己刚 Create 出来的模型。

Step2: 设置相关参数

这部分参数比较多,大家可以参考前文提到的 官方说明 ,既然有了官方说明,本文只作简要说明:

  • Settings 部分主要需要设置是否采用 LoRA、Epochs、模型保存策略、Batch Size、学习率等,都是基本参数基本不需要额外介绍。
  • Concepts 部分主要有两个,一个是数据路径,另一个是 class 和 promote。所谓 prompt,就是我们的目标样本对应应该输入什么提示词;而 class 是在前文 dreambooth 原理介绍中,为了避免过拟合,需要补充一些与目标主体属于同一类别但不是同一个体的样本,并计算 class-specific prior preservation loss 的那部分样本的类别(prompt),模型会根据此内容来生成一部分图片,作为微调样本。
  • Saving 部分主要设置 ckpt 持久化保存策略,具体来说就是.ckpt 文件、loRA 小模型、扩散模型分别以什么样的策略进行保存。
  • Generate 部分主要设置模型生成

Step3: 训练和监控

全都参数都设置好后,直接点击上面橙色的 Train,就可以开始训练了。在训练过程中,不需要我们做什么,如果感兴趣的话可以盯着日志/WebUI 的 Output 界面看一看训练过程中的 loss,以及模型生成出来的图片。

其中 Steps 指的是正在进行本次训练的多少步,而 Lifetime 指的是这个模型总共训练了多少步(对于首次训练的模型二者相等,如果这个模型之前被你训练过,这次拿出来继续训练,那么 Lifetime 大于 Steps)。上例中我们采用 CODM 中的一个角色“Ghost”作为 prompt 进行微调训练,训练数据共 8 张图片:

由于数据量很小,不到半个小时就训练完成了。下面是微调前后根据“Ghost”进行生成的图像对比,微调前:

微调后:

模型已经学习到了,“Ghost”是一个带着面罩+护目镜+耳罩的军人(而不是鬼魂),但是目前还没有学习到 ghost 面罩上的骷髅图案。想必在更多数据以及更加精细化的微调后,是能够做到的。下面是选取了 50 张经过简单清洗的样本,进行训练的结果,可见模型已经能够学习到 ghost 的很多细节了,而且成功剔除了无关的文字。

以及我们可以试图制作一版圣诞节主题的图片:

而且还可以结合 ControlNet,进行人物动作的控制:

另外我们开可以通过 prompt 对 ghost 的风格进行调整:

2.1.5 补充说明 A

在 Dreambooth 训练中,class 的信息是可选的(对应论文中的 class-specific prior preservation loss),在我自己的经验中,如果不是为了训练比较通用的大模型,一般可以忽略 class 选项。下面举一个栗子:

不加 class 项的训练过程(从左到右,训练 epoch 递增):

加了 class 项(man)的训练过程(从左到右,训练 epoch 递增):

明显看出,在加了 class 信息之后,对于背景的学习的更好了,但是在以下 2 个方面的效果下降了:

  1. 明显看出 ghost 身旁经常有其他人,这是由于训练样本截图中,通常会出现这种情况
  2. 会出现一张图有多个骷髅的情况,以及 CODM 的 logo

具体原因,个人理解为:加了 class 之后,模型会认为把 target sample 中出现,但是在 class sample 中没有出现的元素都当作要学习的目标内容,当样本不太干净时,会让模型把冗余的背景信息也学进去(比如 ghost 旁边的人、CODM 的 logo),从而导致过拟合。反而不加 class 时,模型会忽略这些样本中时有时无的背景信息。

有趣的是,一项以避免过拟合而提出的技术,却在样本不太干净的情况下,反而导致了过拟合。

2.1.6 补充说明 B

Dreambooth 可以在一次训练中,指定多个 concepts 一起训练。但是笔者发现这样会让训练变得困难,导致结果不如之前。下面举一个 ghost 和星瞳的例子:

结果就是,同时设置多个 concept 时,模型会学到每个 concept(虽然学的不如单 concept 好),但是如果让模型同时输出多个 concept 结果,或多个 concept 之间的关系,就比较困难。

原因分析:当输入一个短语时(如:ghost and 星瞳),多主体之间的关系,应该是由 CLIP 模型进行语义解码的。经过微调后,模型虽然学到了特定词对应的图像信息,但是 CLIP 模型解码得到的语义信息没有充分学习(或被覆盖掉了),导致微调后多个新主题之间的复杂关系难以直接通过提示词体现。

2.2 LoRA 技术原理和在 Dreambooth 上的应用

传送门:论文 | 代码

2.2.1 是做什么的?

We propose Low-Rank Adaptation, or LoRA, which freezes the pre- trained model weights and injects trainable rank decomposition matrices into each layer of the Transformer architecture, greatly reducing the number of trainable pa- rameters for downstream tasks.

我们提出了低秩自适应(Low-Rank Adaptation, LoRA),它冻结了预训练的模型权重,并将可训练的秩分解矩阵注入到 Transformer 架构的每一层,极大地减少了下游任务的可训练参数的数量。

其实就是加速微调:通过“矩阵分解”的方式,只需要微调更少的参数。

2.2.2 特点是什么?
  1. 通用:任何网络结构都可以利用 LoRA 的思路来进行微调
  2. 可移植:微调结束后,只需要让原模型参数+新矩阵乘积,即可得到新模型。并且可以通过+/-的操作,直接进行 LoRA 的迁移
  3. 推理性能不变:模型总参数量不变,推理性能不变(相比 ControlNet 等新增参数的结构相比)
2.2.3 怎么做到的?

Step1: 冻结原模型(图中蓝色部分)

Step2: 训练微调两个小矩阵参数 A 和 B(图中橙色部分),可以理解为学习一个残差,只不过是通过矩阵分解的形式表达

Step3: 把模型参数矩阵相乘(BA)后,加到原来的模型参数上,形成新的模型

2.2.4 如何使用?

目前使用 LoRA 技术进行 AI 绘画的方式主要有 2 个:

  1. 在 Dreambooth 的 Settings 中勾选“Use LoRA”
  2. 通过脚本直接训练 LoRA 模型

由于后者的内容很多,下一节中我会单独进行介绍,本节主要介绍 LoRA 技术在 Dreambooth 上的应用。即直接在 Dreambooth 的 Settings 中勾选“Use LoRA”选项。

个人感觉 Dreambooth 采用了 LoRA 后,效果略有下降,对比图如下:

2.2.5 补充说明
  1. 通过 Dreambooth 训练导出的 LoRA,无法直接通过 Additional Network 使用,报错如下,是一个 AttributeError。(猜测 Additional Network 这个插件制作的时候,主要是针对秋葉 aaaki 训练出来的 LoRA ,所以如果 LoRA 模型与秋葉 aaaki 的训练方法不同,就没有兼容)
  1. 通过 Dreambooth 训练导出的 LoRA,同样无法在 prompt 中加入,报错内容如下,是一个 TypeError(猜测同样是 WebUI 的使用方式和 Dreambooth 的 LoRA 导出的模型结构对不上,还是插件兼容性问题)。

如此一来,Dreambooth 导出的 LoRA 模型岂不是全无用武之地?

2.3 LoRA 的脚本训练与代码解读

2.3.1 一些基础

关于 LoRA 的训练,一般采用秋葉 aaaki 的这个LoRA 教程 (请读者先学习该教程),除了教程内包含的使用方法以外,简单补充几个知识点:

  1. lora-scripts 这个项目是在sd-scripts 项目的外面包了一层,目的是让 sd-scripts 更加易用
  2. sd-scripts 提供了更加灵活的功能,如:训练 lora、训练 dreambooth、训练 test-embedding、指定训练 UNet 或 Text Encoder、图像生成、模型转换等多种能力
  3. lora-scripts 调用了 sd-scripts 中的训练 lora 训练的脚本,但是把很多的设置、参数等进行了说明和整理,且顺便带了 tensorbord 的功能,让用户能够一键完成环境配置
2.3.2 浅浅看下代码

lora-scripts/train.ps1中可以看出,实际调用的是lora-scripts/sd-scripts/train_network.py

而在这个过程中实际上有两个主要过程:

  1. 模型创建
  2. 模型训练
  • 创建模型过程

lora-scripts/sd-scripts/train_network.py中,在训练前会先读取 base 模型,并创建一个带 lora 的可训练模型

然后我们具体看下creat_network这个函数内部,如何创建新的 lora 模型的,脚本在lora-scripts/sd-scripts/networks/lora.py

进入到LoRANetwork类的__init__函数内部看看,具体如何创建新的 lora 模型的。下方代码中显示,会根据原始的 unet 和 text-encoder 创建新的带 lora 的 unet 和 text-encoder(不会针对 vae 进行训练):

再进一步,看一下LoRAModule__init__函数内部,是如何创建一个 lora 的。实际上就是针对原始模型中每一个层,都创建两个全连接层(就是 lora):

在最后进行前向计算时,把原始模型该层的输出与两个全连接层的输出相加。这与论文中的做法是一样的。

  • 训练模型过程

创建好带 lora 的模型(network)后,看lora-scripts/sd-scripts/train_network.py中核心训练过程如下,中规中矩

然后我们看下最核心的遍历样本训练的过程,可以看出有完整的正向扩散和反向去噪两个过程。

2.3.3 跑几个 demo
  • Ghost 的 case

为了方便与前文进行对比,我选择 ghost 的数据集进行训练,下图展示了不同的 “训练 step“ x ”lora 权重” 的效果:

结论:

  1. 随着训练的进行,lora 也能够逐渐认识 ghost,并且在训练过程中也能去除掉文字。
  2. 权重适中即可,理论上训练完美的情况下权重==1 是合理的(因为在训练过程就是 1);如果训练不充分(如第二行),可适当调大 lora 权重(但过大会让结果糊掉),反之如果过拟合,可适当调小 lora 权重。
  3. 个人经验:如果要进行更多的控制操作(如 ControlNet,复杂的 prompt 等),建议把权重调小一些,以此来增大泛化性能
  4. 像比于前文的 Dreambooth,lora 模型对于背景细节的控制能力较弱。好处是不容易对背景过拟合,坏处是可能需要对背景进行更多调教。
  5. 尝试了不同的种子,生成图片的多样性较低(相对于 Dreambooth)
  • 星瞳的 case

同样的方式,我们在星瞳的例子上进行尝试:

在星瞳的例子中,生成图中有不少“类文字”的内容,这是因为训练样本中有很多图片中就包含文字,在 ghost 训练样本中文字被我手动抹去了。这也从另一方面说明了 lora 与 dreambooth 的一个不同点:

  1. dreambooth 通过“唯一标识符”来学习样本,对细节把控更加精准。只有训练样本中出现频率高且变化不大的元素,才能被精准学习到(比如 CODM 的 ghost 和 logo、背景风格、星瞳的脸)
  2. lora 对训练样本的学习更加泛化,训练样本中出现频率没那么高的内容也可以被学习到,但是对这部分信息学习的不准确,(比如星瞳身旁的文字,以及 ghost 身后的背景)

总结起来可以理解为:dreambooth 学习的是,仔细对比不同样本中同时出现的特定元素;而 lora 学习的是,大概看一眼不同样本中同时出现的大概内容

  • 多 concept 融合的 badcase

这里我同样尝试下 lora 的多 concept 是否表现更好,在数据目录下分别创建了 ghost 和星瞳两个 concept,并进行训练。但是在训练完成后,同样出现了 concept 融合的情况:

关于 concept 融合的一些经验,目前网上的讲解不多,我看到比较好的是这篇:Lora 人物训练(多 concept)导论 ,他利用多 concept 来对同一个角色进行换装,concept 之间的差异较小。

【补充说明】:上边这篇资料中提到,秋叶的脚本无法调整keep_tokens,但实际上是可以的。在秋叶脚本的train_util.py中,add_dataset_arguments这个函数里可以看到keep_tokens参数的定义。当然我们也就可以在 launch 的命令中加入这个参数。

总的来说,concept 融合是比较难以避免的问题,因为从原理上看,模型就是把多个 concept 的数据放在一起直接进行训练的,模型在学习过程中难免会学混。(没有像 CLIP 模型那样采用了对比学习的方法,个人推测,如果采用对比学习的方法,再对错误配对的样本进行一定的惩罚,也许可以解决这个问题)

另外,如果对每个 concept 单独训练一个 lora 模型,然后在推理时一起应用,也会出现比较严重的融合现象。因为实际应用时,时先将所有 lora 模型加和到大模型上,在进行生成的。下面是同时使用 2 个 lora 生成的 badcase:

对此,我总结了一些个人的经验:

  1. concepts 之间如果是同类主体(比如两个都是人脸),融合风险较大;反之如果是不同主体(一个人脸,一个是装备),融合风险较低
  2. 训练样本,要尽可能保证非目标主体内容尽可能多样化(比如目标主体是人脸,就尽可能有多样的背景、动作等)
  3. 如果确实有比较强的多主体出图的需求,建议尝试 textual-inversion 的训练方法,这样不会把多个主体的梯度同时更新到共有的模型上。

所以目前的结论就是:如果要训练多个 concept,只有两种办法:

  1. 准备足够精良的样本,同时包含两个 concept,并定义此为一个新的 concept(比如 C 站上 233 娘的那个 lora,应该就是把 22 娘和 33 娘两张脸当作一个共同的 concept 来学习)
  2. 进行更加细致的样本、参数、训练方式(如 textual-inversion、对比学习等等)的调整和尝试。至少像我这样用默认参数和低质样本简单跑一下是不行的。

2.4 LoRA 的变体:LyCORIS

2.4.1 LyCORIS 是什么

LyCORIS(Lora beYond Conventional methods, Other Rank adaptation Implementations for Stable diffusion) 是一些在 LoRA 的思想基础上,对具体网络结构的改进。

A project for implementing different algorithm to do parameter-efficient finetuning on stable diffusion or more.

从前面代码中可以了解到,LoRA 实际上是对原始模型中每个层,都创建了 2 层线性全连接层,并在该层输出的时候加上去。那么如果我们创建的新结构不是 2 层线性全连接,而是其他什么结构,是否会有更好的效果呢?这就是 LyCORIS 项目研究的内容。

具体来说,截至目前(2023.04.04)LyCORIS 包含了 2 种方法(也就是 2 种不同的结构来替代 2 层全连接),分别为 LoCon 和 LoHa。这是官方的说明文档 ,下面我们分别简单介绍:

【补充说明】:与 lora 不同,lycoris 的脚本不放在lora-scripts/sd-scripts/networks下,而是在安装过程中直接集成在 python 环境中(具体在lora-scripts/install.ps1中的pip install --upgrade lion-pytorch lycoris-lora),因此其脚本保存在lora-scripts/venv/Lib/site-packages/lycoris下面。

  • LoCon 介绍

模型原理在官方的说明中已经介绍的很清楚了,其实就是用两个 Conv 操作,代替原来的两个矩阵相乘(Wa 和 Wb 相乘)的操作:

安装前准备

ubuntu系统推荐使用20.04,这个版本的glibc、gcc比较高,安装起来非常丝滑
之前尝试过用centos7安装,但是glibc升级有点麻烦,搞了好几次都没搞好

系统配置

安装系统的时候选择镜像,直接帮我们把conda、python、cuda全部装好;
(该页面的GPU服务器官网可以关注公众号:飞链云3D数字生态,输入:【sd教学】四个字获取服务器购买地址)

手动安装:

也可以手动安装,如果镜像中安装好了,就不用手动安装了,但是要注意版本!!!
python:3.8,最好是直接把python替换成python3,这样的话脚本运行起来很方便
cuda:11.6:https://developer.nvidia.com/cuda-11-6-0-download-archive
miniconda3:https://repo.anaconda.com/miniconda/Miniconda3-py38_4.12.0-Linux-x86_64.sh

更新pip

python -m pip install --upgrade pip

设置pip源(一定要设置清华大学的,阿里的有点问题)
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

下载ui代码

git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git
cd stable-diffusion-webui
python launch.py

大概需要等待十几分钟需要访问github下载项目

等待十几分钟后,下方出现这个标识说明项目依赖已经弄好了,就差模型了

广告开始----
【飞链云版图】微信小程序欢迎使用;目前国内顶尖的AI绘画小程序;

教程出自飞链云AI技术人员,欢迎使用目前国内顶尖的AI绘画工具,微信小程序搜索:【飞链云版图】
----广告结束

模型下载

经过测试目前sd2.0只有以下两种模型可以用 ,其他模型加载都会报错,github上看了issue上大家都有遇到这个问题

768-v-ema.ckpt

这个模型需要生成的图片在768768的时候效果比较好,如果是生成512512的,图片有点拉垮;

# 768-v-ema.ckpt
https://huggingface.co/stabilityai/stable-diffusion-2/resolve/main/768-v-ema.ckpt
# 配置文件(下载以后注意把文件名修改为768-v-ema.yaml)
https://raw.githubusercontent.com/Stability-AI/stablediffusion/main/configs/stable-diffusion/v2-inference-v.yaml

512-base-ema.ckpt

如果显存不够的,比较小的,可以使用这个模型;比较推荐768,效果比512的好;

# 512-base-ema.ckpt
https://huggingface.co/stabilityai/stable-diffusion-2-base/resolve/main/512-base-ema.ckpt
# 配置文件(下载以后注意把文件名修改为512-base-ema.yaml)
https://raw.githubusercontent.com/Stability-AI/stablediffusion/main/configs/stable-diffusion/v2-inference.yaml

模型安装

以上模型下载到下面这个目录(stable-diffusion-webui文件夹内)
cd models/Stable-diffusion/

我只下载了一个768-v-ema模型

开始运行

接下来回到stable-diffusion-webui目录运行webui.py

第一次运行会比较慢,要下载一个3.94g的文件

出现这个就表示启动好了

以上教程出自飞链云AI技术人员,欢迎使用国内顶尖的AI绘画工具,微信小程序搜索:【飞链云版图】

以上是关于教会你使用AI绘画利器Stable Diffusion的主要内容,如果未能解决你的问题,请参考以下文章

教会你AI绘画

教会你AI绘画

AI绘画AI绘画真的太强悍了!Stable Diffusion + ControlNet 骨架分析,输出的高清大图让我大吃一惊. 附安装使用教程

AI绘画Stable Diffusion关键字技巧分享

AI绘画Stable Diffusion关键字技巧分享

AI绘画Stable Diffusion关键字技巧分享