Connect with us

Der einzige Leitfaden, den Sie benötigen, um Llama 3 oder jedes andere Open-Source-Modell fein zu justieren

Künstliche Intelligenz

Der einzige Leitfaden, den Sie benötigen, um Llama 3 oder jedes andere Open-Source-Modell fein zu justieren

mm
FINE TUNING OPEN SOURCE LLM PYTHON GUIDE

Das Feinjustieren großer Sprachmodelle (LLMs) wie Llama 3 beinhaltet die Anpassung eines vorgebildeten Modells an spezifische Aufgaben mithilfe eines domänen-spezifischen Datensatzes. Dieser Prozess nutzt die vorherige Kenntnis des Modells, was es im Vergleich zum Training von Grund auf effizienter und kostengünstiger macht. In diesem Leitfaden gehen wir durch die Schritte, um Llama 3 mithilfe von QLoRA (Quantized LoRA) fein zu justieren, einer parameter-effizienten Methode, die den Speicherbedarf und die Rechenkosten minimiert.

Überblick über das Feinjustieren

Das Feinjustieren umfasst mehrere wichtige Schritte:

  1. Auswahl eines vorgebildeten Modells: Wählen Sie ein Basis-Modell, das mit Ihrer gewünschten Architektur übereinstimmt.
  2. Sammlung eines relevanten Datensatzes: Sammeln und Vorverarbeiten Sie einen Datensatz, der spezifisch für Ihre Aufgabe ist.
  3. Feinjustieren: Passen Sie das Modell mithilfe des Datensatzes an, um seine Leistung bei spezifischen Aufgaben zu verbessern.
  4. Auswertung: Bewerten Sie das feinjustierte Modell mithilfe qualitativer und quantitativer Metriken.

Konzepte und Techniken

Feinjustieren großer Sprachmodelle

Feinjustieren großer Sprachmodelle

Vollständiges Feinjustieren

Vollständiges Feinjustieren aktualisiert alle Parameter des Modells, macht es spezifisch für die neue Aufgabe. Diese Methode erfordert erhebliche Rechenressourcen und ist oft für sehr große Modelle impraktikabel.

Parameter-effizientes Feinjustieren (PEFT)

PEFT aktualisiert nur einen Teil der Modell-Parameter, reduziert den Speicherbedarf und die Rechenkosten. Diese Technik verhindert katastrophales Vergessen und erhält die allgemeine Kenntnis des Modells.

Low-Rank-Anpassung (LoRA) und Quantized LoRA (QLoRA)

LoRA justiert nur einige niedrig-rangige Matrizen, während QLoRA diese Matrizen quantisiert, um den Speicherbedarf weiter zu reduzieren.

Feinjustiermethoden

  1. Vollständiges Feinjustieren: Dies beinhaltet das Training aller Parameter des Modells auf dem Aufgaben-spezifischen Datensatz. Obwohl diese Methode sehr effektiv sein kann, ist sie auch rechenintensiv und erfordert erheblichen Speicher.
  2. Parameter-effizientes Feinjustieren (PEFT): PEFT aktualisiert nur einen Teil der Modell-Parameter, was es speicher-effizienter macht. Techniken wie Low-Rank-Anpassung (LoRA) und Quantized LoRA (QLoRA) fallen in diese Kategorie.

Was ist LoRA?

Vergleich von Feinjustiermethoden: QLORA verbessert LoRA mit 4-Bit-Präzisionsquantisierung und paged Optimizern für Speicher-Spike-Management

Vergleich von Feinjustiermethoden: QLORA verbessert LoRA mit 4-Bit-Präzisionsquantisierung und paged Optimizern für Speicher-Spike-Management

LoRA ist eine verbesserte Feinjustierungsmethode, bei der anstelle des Feinjustierens aller Gewichte des vorgebildeten Modells zwei kleinere Matrizen, die die größere Matrix approximieren, feinjustiert werden. Diese Matrizen bilden den LoRA-Adapter. Dieser feinjustierte Adapter wird dann in das vorgebildete Modell geladen und für die Inferenz verwendet.

Schlüsselvorteile von LoRA:

  • Speichereffizienz: LoRA reduziert den Speicherbedarf, indem nur kleine Matrizen anstelle des gesamten Modells feinjustiert werden.
  • Wiederverwendbarkeit: Das Originalmodell bleibt unverändert, und mehrere LoRA-Adapter können mit ihm verwendet werden, was die Behandlung mehrerer Aufgaben mit geringerem Speicherbedarf erleichtert.

Was ist Quantized LoRA (QLoRA)?

QLoRA geht einen Schritt weiter als LoRA, indem die Gewichte der LoRA-Adapter auf niedrigere Präzision (z. B. 4-Bit anstelle von 8-Bit) quantisiert werden. Dies reduziert den Speicherbedarf und die Speicheranforderungen weiter, während ein vergleichbares Maß an Effektivität beibehalten wird.

Schlüsselvorteile von QLoRA:

  • Noch größere Speichereffizienz: Durch die Quantisierung der Gewichte reduziert QLoRA den Speicherbedarf und die Speicheranforderungen des Modells erheblich.
  • Beibehaltung der Leistung: Trotz der reduzierten Präzision behält QLoRA Leistungs niveaus, die denen von Vollpräzisionsmodellen nahe kommen.

Aufgaben-spezifische Anpassung

Während des Feinjustierens werden die Modell-Parameter basierend auf dem neuen Datensatz angepasst, was es dem Modell ermöglicht, besser zu verstehen und Inhalte zu generieren, die für die spezifische Aufgabe relevant sind. Dieser Prozess bewahrt die allgemeine Sprachkenntnis, die während des Vorbildens erworben wurde, und passt das Modell an die Nuancen der Ziel-Domäne an.

Feinjustieren in der Praxis

Vollständiges Feinjustieren vs. PEFT

  • Vollständiges Feinjustieren: Beinhaltet das Training des gesamten Modells, was rechenintensiv und speicherintensiv ist.
  • Parameter-effizientes Feinjustieren (PEFT): Feinjustiert nur einen Teil der Modell-Parameter, was es speicher-effizienter macht und katastrophales Vergessen verhindert, was es zu einer effizienteren Alternative macht.

Implementierungsschritte

  1. Umgebung einrichten: Installieren Sie notwendige Bibliotheken und richten Sie die Rechenumgebung ein.
  2. Datensatz laden und vorverarbeiten: Laden Sie den Datensatz und verarbeiten Sie ihn in ein Format, das für das Modell geeignet ist.
  3. Vorgebildetes Modell laden: Laden Sie das Basis-Modell mit Quantisierungs-Konfigurationen, wenn Sie QLoRA verwenden.
  4. Tokenisierung: Tokenisieren Sie den Datensatz, um ihn für das Training vorzubereiten.
  5. Training: Feinjustieren Sie das Modell mithilfe des vorbereiteten Datensatzes.
  6. Auswertung: Bewerten Sie die Leistung des Modells mithilfe qualitativer und quantitativer Metriken.

Schritt-für-Schritt-Anleitung zum Feinjustieren von LLM

Einrichten der Umgebung

Wir verwenden ein Jupyter-Notebook für diesen Tutorial. Plattformen wie Kaggle, die kostenlose GPU-Nutzung anbieten, oder Google Colab sind ideal für das Ausführen dieser Experimente.

1. Erforderliche Bibliotheken installieren

Stellen Sie sicher, dass Sie die notwendigen Bibliotheken installiert haben:

!pip install -qqq -U bitsandbytes transformers peft accelerate datasets scipy einops evaluate trl rouge_score

2. Bibliotheken importieren und Umgebung einrichten


import os
import torch
from datasets import load_dataset
from transformers import (
AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, TrainingArguments,
pipeline, HfArgumentParser
)
from trl import ORPOConfig, ORPOTrainer, setup_chat_format, SFTTrainer
from tqdm import tqdm
import gc
import pandas as pd
import numpy as np
from huggingface_hub import interpreter_login

# Deaktivieren Sie Weights and Biases-Protokollierung
os.environ['WANDB_DISABLED'] = "true"
interpreter_login()

3. Datensatz laden

Wir verwenden den DialogSum-Datensatz für dieses Tutorial:

Verarbeiten Sie den Datensatz gemäß den Anforderungen des Modells, einschließlich der Anwendung geeigneter Vorlagen und der Sicherstellung, dass das Datenformat für das Feinjustieren geeignet ist​ (Hugging Face)​​ (DataCamp)​.


dataset_name = "neil-code/dialogsum-test"
dataset = load_dataset(dataset_name)

Überprüfen Sie die Struktur des Datensatzes:


print(dataset['test'][0])

4. BitsAndBytes-Konfiguration erstellen

Um das Modell im 4-Bit-Format zu laden:


compute_dtype = getattr(torch, "float16")
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type='nf4',
bnb_4bit_compute_dtype=compute_dtype,
bnb_4bit_use_double_quant=False,
)

5. Vorgebildetes Modell laden

Wir verwenden Microsofts Phi-2-Modell für dieses Tutorial:


model_name = 'microsoft/phi-2'
device_map = {"": 0}
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

6. Tokenisierung

Konfigurieren Sie den Tokenizer:


tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
padding_side="left",
add_eos_token=True,
add_bos_token=True,
use_fast=False
)
tokenizer.pad_token = tokenizer.eos_token

Feinjustieren von Llama 3 oder anderen Modellen

Wenn Sie Modelle wie Llama 3 oder andere State-of-the-Art-Open-Source-LLMs feinjustieren, gibt es spezifische Überlegungen und Anpassungen, die erforderlich sind, um optimale Leistung zu erzielen. Hier sind die detaillierten Schritte und Erkenntnisse, wie Sie dies für verschiedene Modelle, einschließlich Llama 3, GPT-3 und Mistral, durchführen können.

5.1 Verwendung von Llama 3

Modellauswahl:

  • Stellen Sie sicher, dass Sie den korrekten Modell-Identifikator aus dem Hugging Face-Modell-Hub haben. Zum Beispiel kann das Llama-3-Modell als meta-llama/Meta-Llama-3-8B auf Hugging Face identifiziert werden.
  • Stellen Sie sicher, dass Sie Zugriff anfordern und sich in Ihrem Hugging Face-Konto anmelden, wenn dies für Modelle wie Llama 3 erforderlich ist​ (Hugging Face)​​

Tokenisierung:

  • Verwenden Sie den geeigneten Tokenizer für Llama 3, um sicherzustellen, dass er mit dem Modell und den erforderlichen Funktionen wie Padding und Spezialtoken kompatibel ist.

Speicher und Rechenleistung:

  • Das Feinjustieren großer Modelle wie Llama 3 erfordert erhebliche Rechenressourcen. Stellen Sie sicher, dass Ihre Umgebung, wie eine leistungsstarke GPU-Konfiguration, die Speicher- und Rechenanforderungen bewältigen kann. Stellen Sie sicher, dass die Umgebung die Speicheranforderungen bewältigen kann, die durch Techniken wie QLoRA reduziert werden können, um den Speicherbedarf zu minimieren​ (Hugging Face-Forum)

Beispiel:

model_name = 'meta-llama/Meta-Llama-3-8B'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

Tokenisierung:

Abhängig von der spezifischen Verwendung und den Modellanforderungen stellen Sie sicher, dass der Tokenizer mit dem Modell und den erforderlichen Funktionen wie Padding und Spezialtoken kompatibel ist.

Llama-3-Tokenizer-Beispiel:


tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
padding_side="left",
add_eos_token=True,
add_bos_token=True,
use_fast=False
)
tokenizer.pad_token = tokenizer.eos_token

5.2 Verwendung anderer beliebter Modelle (z. B. GPT-3, Mistral)

Modellauswahl:

  • Stellen Sie sicher, dass Sie den korrekten Modell-Namen und -Identifikator aus dem Hugging Face-Modell-Hub oder anderen Quellen verwenden.

Tokenisierung:

  • Ähnlich wie bei Llama 3 stellen Sie sicher, dass der Tokenizer korrekt eingerichtet und mit dem Modell kompatibel ist.

Speicher und Rechenleistung:

  • Jedes Modell kann unterschiedliche Speicheranforderungen haben. Passen Sie Ihre Umgebung entsprechend an.

Beispiel für GPT-3:

model_name = 'openai/gpt-3'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

Beispiel für Mistral:

model_name = 'mistral-7B'
device_map = {"": 0}
bnb_config = BitsAndBytesConfig(
load_in_4bit=True,
bnb_4bit_quant_type="nf4",
bnb_4bit_compute_dtype=torch.float16,
bnb_4bit_use_double_quant=True,
)
original_model = AutoModelForCausalLM.from_pretrained(
model_name,
device_map=device_map,
quantization_config=bnb_config,
trust_remote_code=True,
use_auth_token=True
)

Tokenisierungsüberlegungen: Jedes Modell kann spezifische Tokenisierungsanforderungen haben. Stellen Sie sicher, dass der Tokenizer mit dem Modell und den erforderlichen Funktionen wie Padding und Spezialtoken kompatibel ist.

Llama-3-Tokenizer-Beispiel:

tokenizer = AutoTokenizer.from_pretrained(
model_name,
trust_remote_code=True,
padding_side="left",
add_eos_token=True,
add_bos_token=True,
use_fast=False
)
tokenizer.pad_token = tokenizer.eos_token

7. Testen des Modells mit Zero-Shot-Inferenz

Bewerten Sie das Basis-Modell mit einer Beispiel-Eingabe:

from transformers import set_seed

set_seed(42)
index = 10
prompt = dataset['test'][index]['dialogue']
formatted_prompt = f"Instruct: Summarize the following conversation.\n{prompt}\nOutput:\n"

# Generieren Sie die Ausgabe
def gen(model, prompt, max_length):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
outputs = model.generate(**inputs, max_length=max_length)
return tokenizer.batch_decode(outputs, skip_special_tokens=True)

res = gen(original_model, formatted_prompt, 100)
output = res[0].split('Output:\n')[1]

print(f'INPUT PROMPT:\n{formatted_prompt}')
print(f'MODEL GENERATION - ZERO SHOT:\n{output}')

8. Vorverarbeiten des Datensatzes

Konvertieren Sie Dialog-Zusammenfassungs-Paare in Prompts:


def create_prompt_formats(sample):
blurb = "Below is an instruction that describes a task. Write a response that appropriately completes the request."
instruction = "### Instruct: Summarize the below conversation."
input_context = sample['dialogue']
response = f"### Output:\n{sample['summary']}"
end = "### End"

parts = [blurb, instruction, input_context, response, end]
formatted_prompt = "\n\n".join(parts)
sample["text"] = formatted_prompt
return sample

dataset = dataset.map(create_prompt_formats)

Tokenisieren Sie den formatierten Datensatz:


def preprocess_batch(batch, tokenizer, max_length):
return tokenizer(batch["text"], max_length=max_length, truncation=True)

max_length = 1024
train_dataset = dataset["train"].map(lambda batch: preprocess_batch(batch, tokenizer, max_length), batched=True)
eval_dataset = dataset["validation"].map(lambda batch: preprocess_batch(batch, tokenizer, max_length), batched=True)

9. Vorbereiten des Modells für QLoRA

Vorbereiten des Modells für parameter-effizientes Feinjustieren:


original_model = prepare_model_for_kbit_training(original_model)

Hyperparameter und ihre Auswirkungen

Hyperparameter spielen eine entscheidende Rolle bei der Optimierung der Leistung Ihres Modells. Hier sind einige wichtige Hyperparameter, die Sie berücksichtigen sollten:

  1. Lernrate: Kontrolliert die Geschwindigkeit, mit der das Modell seine Parameter aktualisiert. Eine hohe Lernrate kann zu schneller Konvergenz führen, aber auch zu einer Überschreitung der optimalen Lösung. Eine niedrige Lernrate gewährleistet eine stabile Konvergenz, erfordert aber möglicherweise mehr Epochen.
  2. Batch-Größe: Die Anzahl der Proben, die vor dem Aktualisieren der Modell-Parameter verarbeitet werden. Größere Batch-Größen können die Stabilität verbessern, erfordern aber mehr Speicher. Kleinere Batch-Größen können zu mehr Rauschen im Trainingsprozess führen.
  3. Schritte der Gradienten-Akkumulation: Dieser Parameter hilft bei der Simulation größerer Batch-Größen, indem die Gradienten über mehrere Schritte akkumuliert werden, bevor eine Parameter-Aktualisierung durchgeführt wird.
  4. Anzahl der Epochen: Die Anzahl der Male, die der gesamte Datensatz durch das Modell verarbeitet wird. Mehr Epochen können die Leistung verbessern, können aber auch zu Überanpassung führen, wenn nicht richtig gehandhabt.
  5. Gewichts-Abfall: Regularisierungstechnik, um Überanpassung zu verhindern, indem große Gewichte bestraft werden.
  6. Lernrate-Planer: Passt die Lernrate während des Trainings an, um die Leistung und Konvergenz zu verbessern.

Passen Sie die Trainings-Konfiguration durch Anpassen von Hyperparametern wie Lernrate, Batch-Größe und Schritten der Gradienten-Akkumulation an die spezifischen Modell- und Aufgaben-Anforderungen an. Zum Beispiel können Llama-3-Modelle unterschiedliche Lernraten im Vergleich zu kleineren Modellen erfordern​ (Weights & Biases)​​ (GitHub)

Beispiel-Trainings-Konfiguration

orpo_args = ORPOConfig(
learning_rate=8e-6,
lr_scheduler_type="linear",max_length=1024,max_prompt_length=512,
beta=0.1,per_device_train_batch_size=2,per_device_eval_batch_size=2,
gradient_accumulation_steps=4,optim="paged_adamw_8bit",num_train_epochs=1,
evaluation_strategy="steps",eval_steps=0.2,logging_steps=1,warmup_steps=10,
report_to="wandb",output_dir="./results/",)

10. Trainieren des Modells

Richten Sie den Trainer ein und starten Sie das Training:

trainer = ORPOTrainer(
model=original_model,
args=orpo_args,
train_dataset=train_dataset,
eval_dataset=eval_dataset,
tokenizer=tokenizer,
)
trainer.train()
trainer.save_model("fine-tuned-llama-3")

Auswerten des feinjustierten Modells

Nach dem Training bewerten Sie die Leistung des Modells mithilfe qualitativer und quantitativer Methoden.

1. Menschliche Auswertung

Vergleichen Sie die generierten Zusammenfassungen mit menschlich geschriebenen, um die Qualität zu bewerten.

2. Quantitative Auswertung

Verwenden Sie Metriken wie ROUGE, um die Leistung zu bewerten:


from rouge_score import rouge_scorer

scorer = rouge_scorer.RougeScorer(['rouge1', 'rouge2', 'rougeL'], use_stemmer=True)
scores = scorer.score(reference_summary, generated_summary)
print(scores)

Häufige Herausforderungen und Lösungen

1. Speicher-Beschränkungen

Die Verwendung von QLoRA hilft, Speicher-Probleme zu mildern, indem die Modell-Gewichte auf 4-Bit quantisiert werden. Stellen Sie sicher, dass Sie genügend GPU-Speicher haben, um Ihre Batch-Größe und Modell-Größe zu bewältigen.

2. Überanpassung

Überwachen Sie die Validierungs-Metriken, um Überanpassung zu verhindern. Verwenden Sie Techniken wie Early-Stopping und Gewichts-Abfall.

3. Langsames Training

Optimieren Sie die Trainings-Geschwindigkeit, indem Sie die Batch-Größe, Lernrate und die Schritte der Gradienten-Akkumulation anpassen.

4. Daten-Qualität

Stellen Sie sicher, dass Ihr Datensatz sauber und gut vorverarbeitet ist. Eine schlechte Daten-Qualität kann die Modell-Leistung erheblich beeinträchtigen.

Schlussfolgerung

Das Feinjustieren von LLMs mithilfe von QLoRA ist eine effiziente Methode, um große vorgebildete Modelle an spezifische Aufgaben anzupassen, mit reduzierten Rechenkosten. Durch Befolgen dieser Anleitung können Sie PHI, Llama 3 oder jedes andere Open-Source-Modell feinjustieren, um hohe Leistung bei Ihren spezifischen Aufgaben zu erzielen.

Ich habe die letzten fünf Jahre damit verbracht, mich in die faszinierende Welt des Machine Learning und Deep Learning zu vertiefen. Meine Leidenschaft und mein Fachwissen haben mich dazu geführt, an über 50 verschiedenen Software-Entwicklungsprojekten mitzuwirken, mit einem besonderen Fokus auf KI/ML. Meine anhaltende Neugier hat mich auch zum Natural Language Processing hingezogen, ein Feld, das ich weiter erforschen möchte.