7.0. Améliorations de LoRA dans le fine-tuning

Reading time: 2 minutes

Améliorations de LoRA

tip

L'utilisation de LoRA réduit beaucoup le calcul nécessaire pour affiner des modèles déjà entraînés.

LoRA permet d'affiner de grands modèles de manière efficace en ne changeant qu'une petite partie du modèle. Cela réduit le nombre de paramètres que vous devez entraîner, économisant ainsi de la mémoire et des ressources informatiques. Cela est dû au fait que :

  1. Réduit le Nombre de Paramètres Entraînables : Au lieu de mettre à jour l'ensemble de la matrice de poids dans le modèle, LoRA divise la matrice de poids en deux matrices plus petites (appelées A et B). Cela rend l'entraînement plus rapide et nécessite moins de mémoire car moins de paramètres doivent être mis à jour.

  2. Cela est dû au fait qu'au lieu de calculer la mise à jour complète des poids d'une couche (matrice), il l'approxime à un produit de 2 matrices plus petites réduisant la mise à jour à calculer :\

  1. Garde les Poids du Modèle Original Inchangés : LoRA vous permet de garder les poids du modèle original identiques, et ne met à jour que les nouvelles petites matrices (A et B). Cela est utile car cela signifie que les connaissances originales du modèle sont préservées, et vous ne modifiez que ce qui est nécessaire.
  2. Affinage Efficace Spécifique à la Tâche : Lorsque vous souhaitez adapter le modèle à une nouvelle tâche, vous pouvez simplement entraîner les petites matrices LoRA (A et B) tout en laissant le reste du modèle tel quel. Cela est beaucoup plus efficace que de réentraîner l'ensemble du modèle.
  3. Efficacité de Stockage : Après le fine-tuning, au lieu de sauvegarder un nouveau modèle entier pour chaque tâche, vous n'avez besoin de stocker que les matrices LoRA, qui sont très petites par rapport à l'ensemble du modèle. Cela facilite l'adaptation du modèle à de nombreuses tâches sans utiliser trop de stockage.

Afin d'implémenter LoraLayers au lieu de Linear lors d'un fine-tuning, ce code est proposé ici 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)

Références