7.0. LoRA Improvements in fine-tuning

Miglioramenti LoRA

L'uso di LoRA riduce notevolmente il calcolo necessario per fine-tunare modelli già addestrati.

LoRA rende possibile il fine-tuning di grandi modelli in modo efficiente cambiando solo una piccola parte del modello. Riduce il numero di parametri che devi addestrare, risparmiando memoria e risorse computazionali. Questo perché:

  1. Riduce il Numero di Parametri Allenabili: Invece di aggiornare l'intera matrice dei pesi nel modello, LoRA divide la matrice dei pesi in due matrici più piccole (chiamate A e B). Questo rende l'addestramento più veloce e richiede meno memoria perché devono essere aggiornati meno parametri.

  2. Questo perché, invece di calcolare l'aggiornamento completo dei pesi di uno strato (matrice), lo approssima a un prodotto di 2 matrici più piccole riducendo l'aggiornamento da calcolare:\

2. **Mantiene Invariati i Pesi del Modello Originale**: LoRA ti consente di mantenere i pesi del modello originale invariati e aggiorna solo le **nuove piccole matrici** (A e B). Questo è utile perché significa che la conoscenza originale del modello è preservata e modifichi solo ciò che è necessario. 3. **Fine-Tuning Efficiente per Compiti Specifici**: Quando vuoi adattare il modello a un **nuovo compito**, puoi semplicemente addestrare le **piccole matrici LoRA** (A e B) lasciando il resto del modello com'è. Questo è **molto più efficiente** rispetto a riaddestrare l'intero modello. 4. **Efficienza di Archiviazione**: Dopo il fine-tuning, invece di salvare un **nuovo modello intero** per ogni compito, devi solo memorizzare le **matrici LoRA**, che sono molto piccole rispetto all'intero modello. Questo rende più facile adattare il modello a molti compiti senza utilizzare troppo spazio di archiviazione.

Per implementare LoraLayers invece di quelli Lineari durante un fine-tuning, questo codice è proposto qui 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)

Riferimenti

Last updated