stable diffusion
-
机器学习
- 三类机器学习:分类、回归、聚类
- 基础方程:\(f(x) = w_1x_1+w_2x_2+\dots+w_dx_d+b = w^Tx +b\)
引入 \(x_0=1,w_0=b\)则 \(f(x) = w_0x_0+w_1x_1+w_2x_2+\dots+w_dx_d+b = w^Tx\) - 通过空间映射可以把非线性问题转换线性问题。通过求解w,即可解决问题,那么如何求解w呢?
- 先随机或指定初始的w
- 训练样本代入计算,结果称为期望值
- 用函数衡量期望值与实际值的损失loss,该函数即损失函数
- 根据损失值增大或减小w
- 重复执行b-d,直到找到最优w
- 利用梯度下降法找到loss(w)的局部最小值。
- 每次移动的步长,称为学习率$\eta $。
- \(w \gets w - \eta \frac{\partial Loss}{\partial w}\)
- \(\eta\) 小时,可以保证收敛。设置过小,参数更新会很慢(时间会很长)
- \(\eta\) 较大,训练将振荡收敛
- \(\eta\) 过大,系统无法收敛(可能导致直接从一个坑跳到另一个坑,甚至可能几个坑来回跳)
- 所以在实际的应用中,学习率的选择,一般是先大后小。先大可以让loss函数尽快的往loss小的方向下降,等到了坑里,学习率就要慢慢的减小,防止直接跳出坑。所以最好的方式,就是先比较大,然后慢慢缩减变小。
-
训练集、验证集、测试集
- 训练集(train set):用于训练模型(拟合参数):即模型拟合的数据样本集合,如通过训练拟合一些参数来建立一个分类器。
- 验证集(validation set): 用于确定网络结构或者控制模型复杂程度的超参数(拟合超参数):是模型训练过程中单独留出的样本集,它可以用于调整模型的超参数和用于对模型的能力进行初步评估。 通常用来在模型迭代训练时,用以验证当前模型泛化能力(准确率,召回率等),防止过拟合的现象出现,以决定如何调整超参数。具体原理参照本文的二(三)。
- 测试集(test set): 用来评估模最终模型的性能如何(评价模型好坏):测试集没有参于训练,主要是测试训练好的模型的准确能力等,但不能作为调参、选择特征等算法相关的选择的依据。说白了就只用于评价模型好坏的一个数据集。
-
激活函数
-
激活函数(Activation Function)是一种添加到人工神经网络中的函数,旨在帮助网络学习数据中的复杂模式。类似于人类大脑中基于神经元的模型,激活函数最终决定了要发射给下一个神经元的内容。
-
在人工神经网络中,一个节点的激活函数定义了该节点在给定的输入或输入集合下的输出。标准的计算机芯片电路可以看作是根据输入得到开(1)或关(0)输出的数字电路激活函数。因此,激活函数是确定神经网络输出的数学方程式。
-
关于神经网络中的激活函数的作用,通常都是这样解释:不使用激活函数的话,神经网络的每层都只是做线性变换,多层输入叠加后也还是线性变换。因为线性模型的表达能力通常不够,所以这时候就体现了激活函数的作用了,激活函数可以引入非线性因素。
-
-
-
可训练的参数:权重w,偏差b
-
-
无激活函数的神经网络
-
带激活函数的神经网络
-
-
加入非线性激励函数后,神经网络就有可能学习到*滑的曲线来分割*面,而不是用复杂的线性组合逼**滑曲线来分割*面,使神经网络的表示能力更强了,能够更好的拟合目标函数。 这就是为什么我们要有非线性的激活函数的原因。如下图所示说明加入非线性激活函数后的差异,上图为用线性组合逼**滑曲线来分割*面,下图为*滑的曲线来分割*面:
-
-
交叉熵(这里用于diffusion模型中度量随机变量间的相似程度,这里用于逆向去扩散过程的学习)
-
Diffision
- 前向过程(扩散过程):不断往输入数据加噪声。(为了学习生成图像时的去噪)
- 每一个时刻都要添加高斯噪声,后一时刻=前一刻添加噪声。一般2000时刻。
- 噪声可认为是标签
- \(q(\mathcal{X}_t=x_t|\mathcal{X}_{t-1}=x_{t-1})=\mathcal{N}(\mathcal{X}_{t},\sqrt{1-\beta_t}x_{t-1},\beta_tI)=\frac{1}{\sqrt{2\pi} \sqrt{\beta_tI}}exp\left(-\frac{1}{2}\left(\frac{x_t-\sqrt{1-\beta_t}x_{t-1} }{\sqrt{\beta_tI}}\right)^2\right)=\frac{1}{\sqrt{2\pi\beta_tI}}exp\left(- \frac{\left( x_t-\sqrt{1-\beta_t}x_{t-1} \right)^2}{2\beta_tI} \right)\)
即在随机变量\(\mathcal{X}_{t-1}\)已知的前提下随机变量\(\mathcal{X}_t\)的分布(即\(\mathcal{X}_t\)的概率密度函数)- \(\mathcal{N}(随机变量名,均值,方差)\)
- \(\mathcal{X}_t = \sqrt{\alpha_t}\mathcal{X}_{t-1} +\sqrt{1-\alpha_t}\mathcal{Z}\) ,其中\(\mathcal{Z}\) 为服从高斯分布噪音
- \(\beta\) 可认为是噪音前的权重项。\(\beta_1 \dots \beta_t\)都是提前设置好的。
- 每个时刻的噪音是不同的。为了保持扩散幅度,前面加一点噪声效果就很明显,后面加很多噪声效果也不明显。故一开始加少量噪声,之后加噪声是多加一些。
- 即\(\beta\) 越来越大,从0.0001到0.002(可认为是经验值)
- \(\alpha_t = 1 - \beta_t\),即\(\alpha_t\)越来越小
- 马尔科夫链,\(\mathcal{X}_t\) 只和 \(\mathcal{X}_{t-1}\)有关
- \(\beta_t\)越大,\(\alpha_t\)越小,\(\sqrt{1-\alpha_t}\)越大,即噪声的权重越大
- 之所以开根号与概率论有关
- 不采用一步步递归计算\(\mathcal{X}_t\),效率太低。直接一步到位计算\(\mathcal{X}_t\)的分布。代入\(\mathcal{X}_{t-1},\mathcal{X}_{t-2},\dots,\mathcal{X}_{1}\)的分布得
- \(\mathcal{X}_{t}=\sqrt{\alpha_t}\mathcal{X}_{t-1}+\sqrt{1-\alpha_t}\mathcal{Z}_t\)
\(\mathcal{X}_{t}=\sqrt{\alpha_t}(\sqrt{\alpha_{t-1}}\mathcal{X}_{t-2}+\sqrt{1-\alpha_{t-1}}\mathcal{Z}_{t-1})+\sqrt{1-\alpha_t}\mathcal{Z}_t\)
\(\mathcal{X}_{t}=\sqrt{\alpha_t}(\sqrt{\alpha_{t-1}}(\sqrt{\alpha_{t-2}}\mathcal{X}_{t-3}+\sqrt{1-\alpha_{t-2}}\mathcal{Z}_{t-2})+\sqrt{1-\alpha_{t-1}}\mathcal{Z}_{t-1})+\sqrt{1-\alpha_t}\mathcal{Z}_t\)
\(\mathcal{X}_{t}=\sqrt{\alpha_{t}\alpha_{t-1}\alpha_{t-2}}\mathcal{X}_{t-3} +\sqrt{\alpha_{t}\alpha_{t-1}(1-\alpha_{t-2})}\mathcal{Z}_{t-2} +\sqrt{\alpha_{t}(1-\alpha_{t-1})}\mathcal{Z}_{t-1} +\sqrt{1-\alpha_t}\mathcal{Z}_t\) - 噪音的高斯分布满足:
\(\mathcal{N}(0,\sigma_1^2\mathbf{I}) + \mathcal{N}(0,\sigma_2^2\mathbf{I}) \sim \mathcal{N}(0,(\sigma_1^2+\sigma_2^2)\mathbf{I})\)
即\(\mathcal{Z}_t,\mathcal{Z}_{t-1},\mathcal{Z}_{t-2}\)满足\(\mathcal{N}((1-\alpha_{t})\mathbf{I}) +\mathcal{N}(0,(\alpha_t(1-\alpha_{t-1})\mathbf{I}) +\mathcal{N}(0,(\alpha_t\alpha_{t-1}(1-\alpha_{t-2}))\mathbf{I}) \sim \mathcal{N}(0,(1-\alpha_t\alpha_{t-1}\alpha_{t-2})\mathbf{I})\) - 故 \(\mathcal{X}_t=\sqrt{\alpha_t\alpha_{t-1}\dots\alpha_1}\mathcal{X}_0+\sqrt{1-\alpha_t\alpha_{t-1}\dots\alpha_1}\mathcal{Z}_t\)
故 \(\mathcal{X}_t=\sqrt{\overline{\alpha}_t}\mathcal{X}_0+\sqrt{1-\overline{\alpha}_t }\mathcal{Z}_t \sim \mathcal{N}(\mathcal{X}_t,\sqrt{\overline{\alpha}_t}x_0,1-\overline{\alpha}_t)\)
- 后向过程(复原过程,学习如何去噪):求解\(p(x_0|x_t)\),先求\(p(x_{t-1}|x_t)\)
- 利用贝叶斯公式:
- \(q(\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{t}=x_{t},\mathcal{X}_{0}=x_{0})=
\frac{q(\mathcal{X}_{t}=x_{t},\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{0}=x_{0})}
{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{0}=x_{0})} \stackrel{\mathrm{Markov}}{=}
\frac{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{t-1}=x_{t-1})q(\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{0}=x_{0})}
{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{0}=x_{0})}\)
- \(q(\mathcal{X}_t=x_t|\mathcal{X}_{t-1}=x_{t-1})=\frac{1}{\sqrt{2\pi\beta_tI}}exp\left(- \frac{\left( x_t-\sqrt{1-\beta_t}x_{t-1} \right)^2}{2\beta_tI} \right)\)
- \(q(\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{0}=x_{0})=\frac{1}{\sqrt{2\pi(1-\overline{\alpha}_{t-1})I}}exp\left(- \frac{\left( x_{t-1}-\sqrt{\overline{\alpha}_{t-1}}x_{0} \right)^2}{2(1-\overline{\alpha}_{t-1})I} \right)\)
- \(q(\mathcal{X}_t=x_t|\mathcal{X}_{0}=x_{0})=\frac{1}{\sqrt{2\pi(1-\overline{\alpha}_t)I}}exp\left(- \frac{\left( x_t-\sqrt{\overline{\alpha}_t}x_{0} \right)^2}{2(1-\overline{\alpha}_t)I} \right)\)
- 通过配方得到\(\mathcal{X}_{t-1}\)的真实均值\(\widetilde{\mu}\)(含噪声\(\mathcal{Z}\))和真实方差\(\widetilde{\beta}\)。
- 神经网络基于\(x_t,t\)预测得到噪声\(\mathcal{Z}\)
- 然后计算得到\(\mathcal{X}_{t-1}\)的真实均值和方差,从而得到\(\mathcal{X}_{t-1}\)的概率分布。
- 基于\(\mathcal{X}_{t-1}\)的概率分布进行采样得到\(x_{t-1}\)。
- 以此类推最后得到\(x_0\)。
- \(q(\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{t}=x_{t},\mathcal{X}_{0}=x_{0})=
\frac{q(\mathcal{X}_{t}=x_{t},\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{0}=x_{0})}
{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{0}=x_{0})} \stackrel{\mathrm{Markov}}{=}
\frac{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{t-1}=x_{t-1})q(\mathcal{X}_{t-1}=x_{t-1}|\mathcal{X}_{0}=x_{0})}
{q(\mathcal{X}_{t}=x_{t}|\mathcal{X}_{0}=x_{0})}\)
- 利用贝叶斯公式:
- 前向过程(扩散过程):不断往输入数据加噪声。(为了学习生成图像时的去噪)
-
Stable Diffusion :文本->图像的生成公共AI模型。
-
Automatic1111 web UI:开源社区开发工具,用于使用Stable Diffusion。
-
DreamBooth:一种AI算法。向现有Stable Diffusion模型传授主题/风格。
- 直接拿样本数据对整个模型进行微调
- 好处
- 训练结果可直接保存在模型中
- 在模型风格和添加的图像之间可得到不错的*衡
- 缺点
- 每次都生成一个.ckpt的模型,100步的模型每20步保存一次,4G的模型就用了20G容量。难以保存、很耗容量。
- 硬体要求高。常用的是8G显卡,但DreamBooth建议24G的显卡,最低12G
-
LoRA:
- 好处
- 模型很小。一个LoRA模型常见的为100+MB,最小可为2MB。
- 训练很快。建议学习率1e-4。(DreamBooth建议1e-6)
- 极限可在6G显卡训练(即VRAM=6GB)(DreamBooth最低12GB)
- 一个模型中可载入多个LoRA,搭配扩充功能可以使一个模型产生多个角色。
- 坏处
- 训练成果品质低。对模型调整仅限与部分(Dreambooth更全面)。
- 训练成果品质低。对模型调整仅限与部分(Dreambooth更全面)。
- 好处
-
三个核心模块:VAE图像编码器/解码器,U-net负责预测噪声,text encoder负责把文本转换成embedding
- VAE图像编码器/解码器:将图像编码到潜在空间方便操作,之后再还原成人能看的图像
- 编码到潜在空间
- 用于训练
- 反向利用它来推理
- 编码到潜在空间
- text encoder:把输入的文本转化成编码embedding
- u-net用于预测噪声:具有真正生成图像的能力,里面包含diffusion模型
- 三个输入:潜在空间的噪声信息、文本编码信息embedding、时间戳编码信息seed
- 推理过程:
- 根据seed生成潜在空间中的随机噪声
- 每次用u-net基于embedding预测噪声,然后将噪声删除。大概二三十步。
- VAE进行解码,把图像从潜在空间中还原出来
- 训练方法:
- 训练text encoder:
- embedding嵌入方式:
- textual inversion:文本反转
- 在给定的一些图像样本之上寻找一些合适的prompt,以精准描述我想要的画风/特征,然后嵌入text encoder。下一次输入文本后即可对应一堆prompt以精准描述该文本。
- DreamArtist:
- 进一步改进:不仅训练正面嵌入,还训练负面嵌入。
- textual inversion:文本反转
- finetune方式:
- Dreambooth
- native finetune
- LoRA
- embedding嵌入方式:
- 训练U-net:
- Dreambooth
- native finetune
- LoRA
- 训练text encoder:
- 推理过程:
- 三个输入:潜在空间的噪声信息、文本编码信息embedding、时间戳编码信息seed
- VAE图像编码器/解码器:将图像编码到潜在空间方便操作,之后再还原成人能看的图像
-
Dreambooth和native finetune:
- Dreambooth:
- 多用于训练人物
- 单一文本标签(以前没有的标志词token,如sks dog)
- 需要先验知识(class prompt,如dog)
- 输入sks dog,会出现自家狗
- 输入dog,不会出现自家狗,会基于先验知识产生任意狗
- native finetune:对Dreambooth 进行魔改
- 多用于训练画风
- 多文本标签
- 无需先验知识
- Dreambooth:
-
Dreambooth和LoRA:
- 都训练text encoder和U-net
- Dreambooth:训练所有网络层
- 可能发生灾难性遗忘:用很多二次元女孩去训练,再重新跑“男孩”/“猫狗”,出来的还是二次元女孩
- 即重新训练后通用能力大量退化
- LoRA:只训练nn.Linear层(输出层)。
- 并不只是用于stable diffusion。还用于文本生成模型,如chatGPT3
- 把认为需要训练的Linear线性层用自己的LoRA类去替换
- 创建和原本一样的全连接层,把原本的权重复制过来
- 额外创建两个全连接层:LoRA up和LoRA down
- 全连接层可以表示成矩阵。矩阵可以分解。
- \(\left[\begin{matrix} a_1 & a_2 & a_3\end{matrix} \right]\left[\begin{matrix} w_{11}&w_{12} \\ w_{21}&w_{22} \\ w_{31}&w_{32}\end{matrix} \right] =\left[\begin{matrix}b_1 & b_2\end{matrix}\right]\)
- 训练LoRA时要设置LoRA rank(又称为network size)(如768等)
- 时间开销、收敛速度快了很多,只需要保存替代的文件即可,故很小
- 质量没有比Dreambooth差很多
-
各种常见格式
- pt,pth,ckpt都是torch(python模块)权重,与训练方法无关
- bin是diffusers(python模块)的权重 ,可以直接torch.load
- safetensors是一种安全的、独立于框架的三方权重文件格式(推荐)
-
模型融合:
- 训练得到的不是模型,得到的ckpy文件中是模型的各个权重
- 一个模型是高维空间中的特征向量,描述了一种画风
- 2个方法:
- 整个融合
- 遍历两个模型中U-net模块的各个权重,按同一比例合并(如0.5+0.5)得到新的权重(音乐的风格也可融合)
- 分层融合
- U-net中的各个层的权重合并比例可以不同。如第一层0.5+0.5,第二层0.3+0.7
- 整个融合
-