Lora

LoRA

论文链接:https://arxiv.org/abs/2106.09685
代码链接:https://github.com/microsoft/LoRA

LoRA是一种finetune扩散模型的训练技术。通过对标准的checkpoint模型微小的修改,可以比checkpoint模型小10到100倍。LoRA的原理比较简单,原始全量的finetune其实就是在原始模型参数基础上加入增量$W=W_0+\Delta W$,那么我们可以通过冻结原始参数 $W_0$,并且把增量部分通过低秩分解方式进一步降低参数量级$\Delta W = A*B^T$, 原始参数的维度是 $d*d$, 则低秩分解后的参数量级是 $2*r*d$, 这里 $r<<d$, 因此可以起到大幅降低微调参数量级的效果。

和textula inversion一样,不能直接使用LoRA模型,需要和checkpoint文件一起使用。

How does LoRA work in Stable diffusion?

image

LoRA通过在checkpoint上做小的修改替换风格,具体而言修改的地方是UNet中的cross-attention层。该层是图像和文本prompt交界的层。LORA的作者们发现微调该部分足以实现良好的性能。

cross attention层的权重是一个矩阵,LoRA fine tune这些权重来微调模型。那么LoRA是怎么做到模型文件如此小?LoRA的做法是将一个权重矩阵分解为两个矩阵存储,能起到的作用可以用下图表示,参数量由(1000 2000)减少到(1000 2+2000*2), 大概300多倍!

img

核心代码

1
2
3
4
5
6
7
8
9
10
11
12
13
## 初始化低秩矩阵A和B
self.lora_A.update(nn.ModuleDict({adapter_name: nn.Linear(self.in_features, r, bias=False)}))
self.lora_B.update(nn.ModuleDict({adapter_name: nn.Linear(r, self.out_features, bias=False)}))
self.scaling[adapter_name] = lora_alpha / r

## 向前计算
result = F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)
result += (
self.lora_B[self.active_adapter](
self.lora_A[self.active_adapter](self.lora_dropout[self.active_adapter](x))
)
* self.scaling[self.active_adapter]
)

alpha参数:alpha其实是个缩放参数,本质和learning rate相同。

SD微调中,lora作用域Cross attention层

cross attention

cross-attention是扩散模型中关键的技术之一,在LoRA中通过微调该模块,即可微调生成图片的样式,而在Hypernetwork中使用两个带有dropout和激活函数的全链接层,分别修改cross attention中的key和value,也可以定制想要的生成风格。可见cross attention的重要性。

在讲cross-attention之前,先看看经典的transformer中attention的含义,attnetion实际上用了三个QKV矩阵,来计算不同token之间的彼此的依赖关系,Q和K可以用来计算当前token和其他token的相似度,这个相似度作为权值对V进行加权求和,可以作为下一层的token。更通俗点说,Q和k的作用是用来在token之间搬运信息,而value本身就是从当前token当中提取出来的信息. 比较常见的是self-attention,该注意力是一个sequence内部不同token间产生注意力,而cross-attention的区别是在不同的sequence之间产生注意力。