大家好,这里是Goodnote(好评笔记),关注公主号Goodnote,专栏文章私信限时Free。本文是 SD 模型微调方法 LoRA 的详细介绍,包括数据集准备,模型微调过程,推理过程,优缺点等。
机器学习笔记合集
深度学习笔记合集
文章目录
- 热门专栏
- 机器学习
- 深度学习
- 论文
- 概念
- 核心原理
- 优点
- 训练过程
- 预训练模型加载
- 选择微调的层
- LoRA 优化的层
- Cross-Attention(跨注意力)层
- Self-Attention(自注意力)层
- LoRA 如何优化这些层
- 原始线性层的操作
- LoRA 的低秩矩阵分解
- 优化的关键步骤
- 推理过程中如何应用优化?
- 为什么选择优化这些层?
- LoRA对部分 Cross-Attention 和 Self-Attention 层进行局部调整,调整层主要是哪些?
- 低秩分解
- 训练 LoRA 的低秩矩阵
- 前向传播(Forward Pass)
- 反向传播(Backward Pass)
- 防止过拟合
- 推理过程
- 加载微调后的底层模型和 LoRA 权重
- 输入文本条件
- 图像生成
- 控制与调节
- 推荐阅读
论文地址:LoRA: Low-Rank Adaptation of Large Language Models
LoRA(Low-Rank Adaptation of Large Language Models)是一种用于高效微调大规模预训练模型的技术,特别适用于参数量巨大的模型,如 GPT-3、BERT 或 Stable Diffusion 等。LoRA 提供了一种解决方案,使得在进行模型微调时,只需要微调非常少量的参数,同时保持与全量参数微调相近的性能表现。
LoRA(Low-Rank Adaptation of Large Language Models) 的核心原理是通过低秩分解来减少大规模模型微调时需要更新的参数量,以此实现更高效的模型微调。它特别适用于像 GPT-3、BERT 或 Stable Diffusion 这样的预训练大模型,在微调这些模型时,LoRA 通过引入两个低秩矩阵来替代直接更新整个权重矩阵,从而显著降低了计算成本和存储需求。
核心思想:假设预训练模型中的权重矩阵 W 很大。LoRA 的基本思想是将它的更新部分 ΔW 分解为两个秩更小的矩阵 A 和 B 的乘积,从而减少需要更新的参数量,并且仅仅更新这两个矩阵。而不是更新整个 W 矩阵,保持预训练模型的原始性能。
权重矩阵分解的核心公式:
LoRA对权重矩阵 W W W 进行如下处理:
W = W 0 + Δ W W = W_0 + \Delta W W=W0+ΔW
其中:
在LoRA中,只训练矩阵 A A A 和 B B B,而不是训练整个权重矩阵 W W W,从而减少了需要更新的参数量。
通常来说,对于矩阵A,我们使用 随机高斯分布 初始化,并对矩阵B使用 全0 初始化,使得在训练初始状态下这两个矩阵相乘的结果为0。这样能够保证在训练初始阶段时,SD模型的权重完全生效。
小型任务:一般 r 取 1 到 4。
中型任务:通常 r 取 4 到 8。
复杂任务:一般 r 取 8 到 16。
结论来源:深入浅出完整解析LoRA(Low-Rank Adaptation)模型核心基础知识
LoRA 微调的训练过程可分为以下几个步骤:
首先,加载一个预训练的 Stable Diffusion 模型。这个模型已经在大规模的文本图像数据集上进行了训练,具备强大的生成能力。LoRA 的目标是在该预训练模型上微调,只需调整极少的参数。
在 Stable Diffusion 模型中,LoRA 通常作用于模型中的线性层(主要在注意力模块的 Q、K、V 的三个权重矩阵W)。具体来说,LoRA 会对 U-Net 中的 cross-attention 机制、自注意力机制的线性层等进行调整。
详细介绍如下:
LoRA 主要作用于 U-Net 网络中的 注意力机制相关的线性层,特别是用于跨模态交互的 Cross-Attention(跨注意力)层 以及 Self-Attention(自注意力)层。
在 Stable Diffusion 的 U-Net 中,主要有两种注意力机制:自注意力机制(Self-Attention) 和 跨注意力机制(Cross-Attention)。LoRA 主要对这些注意力层中的 线性层 进行优化,特别是以下几个部分:
LoRA 通过将注意力机制中的 线性层(例如,用于生成 Q、K、V 的线性变换层)进行低秩分解,从而减少参数更新量。具体的优化方式如下:
在注意力机制中,通常会对输入特征进行如下操作:
与原始公式直接更新整个 W Q W_Q WQ、 W K W_K WK、 W V W_V WV 矩阵相比,在 LoRA 中通过使用两个更小的矩阵 A 和 B 来 表示这些矩阵的变化:
引入 低秩分解 对权重矩阵进行调整: W Q W_Q WQ、 W K W_K WK、 W V W_V WV 被表示为预训练权重加上一个低秩矩阵的调整:
W Q = W Q 0 + Δ W Q , Δ W Q = A Q B Q W_Q = W_Q^0 + \Delta W_Q, \quad \Delta W_Q = A_Q B_Q WQ=WQ0+ΔWQ,ΔWQ=AQBQ
类似的公式用于 W K W_K WK 和 W V W_V WV。
在推理阶段,LoRA 的优化部分通过如下方式应用于模型:
应用权重更新:在推理过程中,LoRA 使用微调后的低秩矩阵 A 和 B,并将它们加到原始的权重矩阵中。例如,计算 Q 时:
Q = ( W Q 0 + A Q B Q ) X Q = (W_Q^0 + A_Q B_Q)X Q=(WQ0+AQBQ)X
这个更新后的权重矩阵确保模型能够在保持原始生成能力的同时,生成包含定制内容的图像。
LoRA 选择优化 Attention 层中的线性层 有以下原因:
Attention 层是核心:在 Stable Diffusion 的 U-Net 中,Attention 层(特别是 Cross-Attention 层)是将图像生成与文本提示结合的关键部分。对这些层进行优化,可以直接影响模型如何将文本信息传递给图像生成过程。
低秩分解的有效性:对于大型模型中的全连接层,低秩分解可以在不显著影响模型性能的情况下,显著减少参数更新量。Attention 层中的权重矩阵往往是高维的,因此通过 LoRA 对它们进行低秩分解能大幅降低训练成本。
减少计算开销:注意力机制中的线性层通常参数量大且计算密集,通过 LoRA 的低秩分解,可以在降低计算复杂度的同时保留模型的生成能力。
U-Net 中确实包含多个分辨率下的 Self-Attention 和 Cross-Attention 层,但 LoRA 的微调是有选择性的,并不会对每一个 Attention 层进行微调。LoRA 的设计初衷是通过低秩矩阵分解的方式只微调关键的 Attention 层。
LoRA 通常会优先选择在以下部分进行微调,而不会对整个 U-Net 中的所有层进行调整:
1.瓶颈部分的 Attention 层
2.解码器中的高分辨率层 Attention
3.部分中间层
其他的层不会进行改变。 DreamBooth会更改全部的Attention层。
对于每个需要微调的层,LoRA 将该层的权重矩阵 W 进行低秩分解:
W = W 0 + Δ W W = W_0 + \Delta W W=W0+ΔW
其中:
在 LoRA 的训练过程中,我们仅训练 A 和 B 这两个低秩矩阵,而保持模型中原始的权重 W 0 W_0 W0不变。这种方法显著减少了需要更新的参数量,降低了训练开销。
具体流程:
图像和文本输入:使用包含图片和文本描述的数据对模型进行训练,类似于 Stable Diffusion 的预训练任务。
损失函数:LoRA 的损失函数与原始 Stable Diffusion 的损失函数类似,主要通过预测噪声残差来进行训练。损失函数通常是均方误差(MSE),公式如下:
L MSE = E x 0 , ϵ , t [ ∥ ϵ − ϵ θ ( x t , t , c ) ∥ 2 ] L_{\text{MSE}} = \mathbb{E}_{x_0, \epsilon, t} [ \| \epsilon - \epsilon_{\theta}(x_t, t, c) \|^2 ] LMSE=Ex0,ϵ,t[∥ϵ−ϵθ(xt,t,c)∥2]
只更新低秩矩阵:在反向传播时,LoRA 只更新 A 和 B,而保持预训练模型的其余部分不变。通过这样的方法,模型能够在少量参数更新的情况下学会新的任务。
更详细的过程如下:
输入数据准备:
权重替换:
生成 Q、K 和 V 矩阵:
Q = W Q ⋅ input Q = W_Q \cdot \text{input} Q=WQ⋅input
K = W K ⋅ input K = W_K \cdot \text{input} K=WK⋅input
V = W V ⋅ input V = W_V \cdot \text{input} V=WV⋅input
W Q = W Q 0 + A Q ⋅ B Q W_Q = W_{Q0} + A_Q \cdot B_Q WQ=WQ0+AQ⋅BQ
W K = W K 0 + A K ⋅ B K W_K = W_{K0} + A_K \cdot B_K WK=WK0+AK⋅BK
W V = W V 0 + A V ⋅ B V W_V = W_{V0} + A_V \cdot B_V WV=WV0+AV⋅BV
计算注意力分数:
应用注意力分数到 Value 矩阵:
Attention Output = Attention Scores ⋅ V \text{Attention Output} = \text{Attention Scores} \cdot V Attention Output=Attention Scores⋅V
注意力输出用于噪声预测【同DDPM扩散过程】
DDPM原理参考:Stable Diffusion 笔记合集 中的《Diffusion Model原理》
。
损失计算:
L MSE = E x 0 , ϵ , t [ ∥ ϵ − ϵ θ ( x t , t , c ) ∥ 2 ] L_{\text{MSE}} = \mathbb{E}_{x_0, \epsilon, t} [ \| \epsilon - \epsilon_{\theta}(x_t, t, c) \|^2 ] LMSE=Ex0,ϵ,t[∥ϵ−ϵθ(xt,t,c)∥2]
计算损失的梯度:
锁定原始权重矩阵 W 0 W_0 W0:
更新低秩矩阵 A 和 B:
根据梯度,用优化算法(如 Adam)对 A 和 B 的参数进行更新:
A ← A − ∂ L ∂ A η A \leftarrow A - \frac{\partial L}{\partial A} \eta A←A−∂A∂Lη
B ← B − ∂ L ∂ B η B \leftarrow B - \frac{\partial L}{\partial B} \eta B←B−∂B∂Lη
为了避免微调时模型过拟合到新数据集,LoRA 引入了正则化技术,并且通常通过选择较小的秩(rank)来限制低秩矩阵的参数量。较小的秩 r 能够确保模型在学习新任务时不会丢失原有的生成能力,同时避免过拟合。
小型任务(简单图像生成、基本文本任务):一般 r 取 1 到 4。对于简单任务,这样的秩通常能够捕捉到足够的特征变化,并且显著减少了微调参数。
中型任务(如在特定风格或特定场景下生成图像):通常 r 取 4 到 8。这种秩设置在保持微调效率的同时,能够适应稍复杂的任务。
复杂任务(高分辨率图像生成、大规模定制化):一般 r 取 8 到 16。对于非常复杂的生成任务,较高的秩可以捕捉到更细致的特征,但会增加参数量和计算开销。
推理过程与标准的 Stable Diffusion 推理过程类似,但会在原始模型的基础上加上 LoRA 的调整部分。
推理的流程如下:
使用 LoRA 进行 Stable Diffusion 的高效参数微调
全世界 LoRA 训练脚本,联合起来!
LoRA使用脚本训练Unet和text encoder全过程
使用set_adapters加载LoRAS以进行推断,自定义适配器强度
负载适配器,加载Dreambooth、Textual inversion、LoRA、IP-Adapter:
https://huggingface.co/docs/diffusers/using-diffusers/loading_adapters#LoRA
https://huggingface.co/docs/diffusers/using-diffusers/merge_loras
说明: