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

4.8 KiB
Raw Permalink Blame History

7.0. LoRA Improvements in fine-tuning

LoRA Improvements

{% hint style="success" %} Використання LoRA значно зменшує обчислення, необхідні для додаткового налаштування вже навчених моделей. {% endhint %}

LoRA робить можливим ефективне додаткове налаштування великих моделей, змінюючи лише невелику частину моделі. Це зменшує кількість параметрів, які потрібно навчати, заощаджуючи пам'ять та обчислювальні ресурси. Це відбувається тому, що:

  1. Зменшує кількість навчальних параметрів: Замість оновлення всієї матриці ваг у моделі, LoRA ділить матрицю ваг на дві менші матриці (названі A та B). Це робить навчання швидшим і вимагає менше пам'яті, оскільки потрібно оновити менше параметрів.
  2. Це відбувається тому, що замість обчислення повного оновлення ваги шару (матриці), воно апроксимує його до добутку 2 менших матриць, зменшуючи оновлення для обчислення:\
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:

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