hacktricks/todo/llm-training-data-preparation/7.0.-lora-improvements-in-fine-tuning.md

3.5 KiB

7.0. Ulepszenia LoRA w dostrajaniu

Ulepszenia LoRA

{% hint style="success" %} Użycie LoRA znacznie redukuje obliczenia potrzebne do dostrajania już wytrenowanych modeli. {% endhint %}

LoRA umożliwia efektywne dostrajanie dużych modeli poprzez zmianę tylko małej części modelu. Redukuje liczbę parametrów, które musisz wytrenować, oszczędzając pamięć i zasoby obliczeniowe. Dzieje się tak, ponieważ:

  1. Redukuje liczbę parametrów do wytrenowania: Zamiast aktualizować całą macierz wag w modelu, LoRA dzieli macierz wag na dwie mniejsze macierze (nazywane A i B). To sprawia, że trening jest szybszy i wymaga mniej pamięci, ponieważ mniej parametrów musi być aktualizowanych.
  2. Dzieje się tak, ponieważ zamiast obliczać pełną aktualizację wag warstwy (macierzy), przybliża ją do iloczynu 2 mniejszych macierzy, co redukuje aktualizację do obliczenia:\
2. **Zachowuje oryginalne wagi modelu bez zmian**: LoRA pozwala na zachowanie oryginalnych wag modelu, a jedynie aktualizuje **nowe małe macierze** (A i B). To jest pomocne, ponieważ oznacza, że oryginalna wiedza modelu jest zachowana, a ty tylko dostosowujesz to, co jest konieczne. 3. **Efektywne dostrajanie specyficzne dla zadania**: Kiedy chcesz dostosować model do **nowego zadania**, możesz po prostu wytrenować **małe macierze LoRA** (A i B), pozostawiając resztę modelu w niezmienionej formie. To jest **znacznie bardziej efektywne** niż ponowne trenowanie całego modelu. 4. **Efektywność przechowywania**: Po dostrojeniu, zamiast zapisywać **cały nowy model** dla każdego zadania, musisz tylko przechowywać **macierze LoRA**, które są bardzo małe w porównaniu do całego modelu. To ułatwia dostosowanie modelu do wielu zadań bez użycia zbyt dużej ilości pamięci.

Aby zaimplementować LoraLayers zamiast liniowych podczas dostrajania, proponowany jest tutaj ten kod https://github.com/rasbt/LLMs-from-scratch/blob/main/appendix-E/01_main-chapter-code/appendix-E.ipynb:

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)

References