# 7.0. Miglioramenti LoRA nel fine-tuning ## Miglioramenti LoRA {% hint style="success" %} L'uso di **LoRA riduce notevolmente il calcolo** necessario per **fine-tunare** modelli già addestrati. {% endhint %} 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. 1. 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](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) ``` ## Riferimenti * [https://www.manning.com/books/build-a-large-language-model-from-scratch](https://www.manning.com/books/build-a-large-language-model-from-scratch)