hacktricks/src/AI/AI-llm-architecture/7.0.-lora-improvements-in-fine-tuning.md

62 lines
3.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 7.0. LoRA 在微调中的改进
## LoRA 改进
> [!TIP]
> 使用 **LoRA 大大减少了所需的计算** 来 **微调** 已经训练好的模型。
LoRA 使得通过仅更改模型的 **一小部分** 来高效地微调 **大型模型** 成为可能。它减少了需要训练的参数数量,从而节省了 **内存****计算资源**。这是因为:
1. **减少可训练参数的数量**LoRA 不更新模型中的整个权重矩阵,而是将权重矩阵 **拆分** 为两个较小的矩阵(称为 **A****B**)。这使得训练 **更快**,并且需要 **更少的内存**,因为需要更新的参数更少。
1. 这是因为它不计算层(矩阵)的完整权重更新,而是将其近似为两个较小矩阵的乘积,从而减少了更新计算:\
<figure><img src="../../images/image (9) (1).png" alt=""><figcaption></figcaption></figure>
2. **保持原始模型权重不变**LoRA 允许您保持原始模型权重不变,仅更新 **新的小矩阵**A 和 B。这很有帮助因为这意味着模型的原始知识得以保留您只需调整必要的部分。
3. **高效的任务特定微调**:当您想将模型适应于 **新任务** 时,您只需训练 **小的 LoRA 矩阵**A 和 B而将模型的其余部分保持不变。这比重新训练整个模型 **高效得多**
4. **存储效率**:微调后,您只需存储 **LoRA 矩阵**,而不是为每个任务保存 **整个新模型**,这些矩阵与整个模型相比非常小。这使得将模型适应于多个任务而不占用过多存储变得更容易。
为了在微调过程中实现 LoraLayers 而不是线性层,这里提出了以下代码 [https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb](https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb)
```python
import math
# Create the LoRA layer with the 2 matrices and the alpha
class LoRALayer(torch.nn.Module):
def __init__(self, in_dim, out_dim, rank, alpha):
super().__init__()
self.A = torch.nn.Parameter(torch.empty(in_dim, rank))
torch.nn.init.kaiming_uniform_(self.A, a=math.sqrt(5)) # similar to standard weight initialization
self.B = torch.nn.Parameter(torch.zeros(rank, out_dim))
self.alpha = alpha
def forward(self, x):
x = self.alpha * (x @ self.A @ self.B)
return x
# Combine it with the linear layer
class LinearWithLoRA(torch.nn.Module):
def __init__(self, linear, rank, alpha):
super().__init__()
self.linear = linear
self.lora = LoRALayer(
linear.in_features, linear.out_features, rank, alpha
)
def forward(self, x):
return self.linear(x) + self.lora(x)
# Replace linear layers with LoRA ones
def replace_linear_with_lora(model, rank, alpha):
for name, module in model.named_children():
if isinstance(module, torch.nn.Linear):
# Replace the Linear layer with LinearWithLoRA
setattr(model, name, LinearWithLoRA(module, rank, alpha))
else:
# Recursively apply the same function to child modules
replace_linear_with_lora(module, rank, alpha)
```
## 参考文献
- [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)