1 Punkte von GN⁺ 2024-05-27 | 1 Kommentare | Auf WhatsApp teilen
  • mistral-finetune ist eine leichtgewichtige Codebasis, um Mistral-Modelle speichereffizient und mit guter Performance feinabzustimmen; das Repository ist inzwischen archiviert und wird nicht mehr aktiv gepflegt
  • Das Trainingsverfahren basiert auf LoRA, bei dem der Großteil der Gewichte eingefroren bleibt und nur 1–2 % der zusätzlichen Gewichte in Form niedrig-rangiger Matrixstörungen trainiert werden
  • Für maximale Effizienz werden A100- oder H100-GPUs empfohlen; der Code ist für Single-Node-Training mit mehreren GPUs optimiert, kleinere Modelle wie 7B laufen aber auch auf einer einzelnen GPU
  • Zu den unterstützten Modellen gehören 7B, Mixtral 8x7B, Mixtral 8x22B, Mistral-Nemo 12B und Mistral Large v2 123B Instruct; für Mistral-Nemo und Large v2 gelten jeweils Einschränkungen bei Sequenzlänge und Lernrate
  • Die Daten müssen dem Format jsonl und einem strikten Schema folgen; vor dem Training ist die Prüfung mit utils.validate_data wichtig, um das Format zu validieren und die Trainingszeit zu schätzen

Projektstatus und Ziel

  • Das Repository mistral-finetune hat den Status Archived und wird nicht mehr aktiv gepflegt
  • Falls es Community-Nachfrage gibt oder ein Mehrwert für das Fine-Tuning-Ökosystem gesehen wird, könnten künftig eine neue Bibliothek oder größere Updates erscheinen
  • Ziel ist es, einen einfachen und angeleiteten Einstiegspunkt für das Fine-Tuning von Mistral-Modellen bereitzustellen
  • Diese Codebasis ist besonders beim Datenformat stark meinungsgetrieben und zielt nicht auf ein universelles Tool ab, das viele Modellarchitekturen oder Hardwaretypen abdeckt
  • Für einen allgemeineren Ansatz kann man sich Projekte wie torchtune ansehen

Fine-Tuning-Verfahren und Hardware-Empfehlungen

  • mistral-finetune basiert auf LoRA
    • Der Großteil der Modellgewichte bleibt eingefroren
    • Es werden nur 1–2 % zusätzlicher Gewichte in Form niedrig-rangiger Matrixstörungen trainiert
  • Für maximale Effizienz werden A100- oder H100-GPUs empfohlen
  • Der Code ist für Single-Node-Training mit mehreren GPUs optimiert
  • Kleinere Modelle wie 7B sind auch mit nur einer GPU praktikabel

Aktuelle Updates bei kompatiblen Modellen

  • Seit dem 13. August 2024 ist Mistral Large v2 mit mistral-finetune kompatibel
    • Der 123B-Instruct-Checkpoint muss heruntergeladen und model_id_or_path auf dieses Checkpoint-Verzeichnis gesetzt werden
    • Wegen der Modellgröße wird für das Fine-Tuning deutlich mehr Speicher benötigt
    • Derzeit muss seq_len auf 8192 oder weniger gesetzt werden
    • Es wird eine niedrigere Lernrate als bei anderen Modellen empfohlen; in den meisten Fällen soll lr=1e-6 gut funktionieren
  • Seit dem 19. Juli 2024 ist Mistral Nemo mit mistral-finetune kompatibel
    • Das 12B-Base- oder Instruct-Modell muss heruntergeladen und model_id_or_path auf das Checkpoint-Verzeichnis gesetzt werden
    • Erforderlich ist eine mistral-common-Version mit Tekkenizer-Unterstützung; per pip install --upgrade mistral-common sollte Version >=1.3.1 installiert werden
    • Wegen des großen Vokabulars steigt der Spitzen-Speicherbedarf des CE loss, daher wird aktuell mehr Speicher benötigt
    • Derzeit muss seq_len auf 16384 oder weniger gesetzt werden
    • Es wird empfohlen, dieselben Hyperparameter wie bei 7B v3 zu verwenden

Installation und Modelldownload

  • Der Einstieg besteht aus dem Klonen des Repositorys und der Installation der Abhängigkeiten
  • Für das Fine-Tuning werden offizielle Mistral-Modelle empfohlen; das README liefert Download-Links und Prüfsummen für folgende Modelle
  • Bei 8x7B Base V1 und 8x7B Instruct V1 muss vor dem Fine-Tuning der v3-Tokenizer verwendet und die Vokabulargröße auf 32768 erweitert werden
  • Der Pfad zum heruntergeladenen Modellordner muss im Trainings-YAML als absoluter Pfad in model_id_or_path angegeben werden

Anforderungen an das Datenformat

  • Alle Datendateien müssen im Format jsonl vorliegen
  • Vortrainingsdaten speichern Klartext unter dem Schlüssel "text"
  • Instruction-Daten speichern eine Liste von Dialogen unter dem Schlüssel "messages"
    • Jeder Eintrag enthält die Schlüssel "content" und "role"
    • "role" ist einer von "user", "assistant" oder "system"
    • Der Loss wird nur berechnet, wenn "role" == "assistant" gilt
    • Mit "weight": 0 in einer Assistant-Nachricht kann dieses Trainingselement ausgeschlossen werden
  • Daten für Function Calling speichern ebenfalls eine Dialogliste unter dem Schlüssel "messages"
    • Jeder Eintrag enthält "role" und entweder "content" oder "tool_calls"
    • "role" ist einer von "user", "assistant", "system" oder "tool"
    • Der Loss wird nur berechnet, wenn "role" == "assistant" gilt
    • "id" in "tool_calls" und "tool_call_id" müssen zufällige Strings mit genau 9 Zeichen Länge sein
    • Das README empfiehlt, diese automatisch im Skript zur Datenaufbereitung zu erzeugen

Datenvalidierung und Beispiel-Workflow

  • Vor dem Trainingsstart sollte mit utils.validate_data das Datenformat geprüft und die Trainingszeit geschätzt werden
  • Das Instruction-Beispiel nutzt einen Teil von Ultachat_200k
    • Die Parquet-Daten werden mit Pandas geladen
    • Aufteilung in 95 % Training und 5 % Evaluation
    • Speicherung als jsonl
    • Die Pfade werden in data.instruct_data und data.eval_instruct_data von example/7B.yaml eingetragen
  • Bei der Validierung kann auffallen, dass einige Dialoge mit der Rolle user enden
    • Da nur Assistant-Nachrichten trainiert werden, ist die letzte user-Nachricht überflüssig
    • Mit utils.reformat_data.py lassen sich die Daten anpassen
  • Nach der Korrektur liefert eine erneute Validierung eine Zusammenfassung mit Anzahl der Datentokens, Anzahl der Trainingstokens, Zahl der Epochen, max_steps und geschätzter Laufzeit
  • Im README-Beispiel durchläuft max_steps=500 den Datensatz etwa fünfmal; für ein 8xH100-Cluster mit rund 30 Minuten Laufzeit wird max_steps=300 empfohlen

Beispiel für Function-Calling-Fine-Tuning

  • Das Function-Calling-Beispiel verwendet den Datensatz Glaive function calling dataset
  • Die Daten werden mit Pandas geladen, in 95 % Training und 5 % Evaluation aufgeteilt und dann als jsonl gespeichert
  • Der Originaldatensatz folgt nicht dem geforderten Function-Calling-Format und muss daher umformatiert werden
    • "from" muss zu "user" geändert werden
    • Überflüssige "\n"-Zeichen müssen entfernt werden
  • Mit utils.reformat_data_glaive.py lässt sich der Großteil der Samples in das richtige Format bringen
  • Da es unmöglich ist, ein Reformatierungsskript zu schreiben, das für alle Arten von Datensätzen funktioniert, kann für Datensätze außerhalb des geforderten Formats ein separates Skript nötig sein
  • Mit utils.validate_data --create_corrected lassen sich verbleibende Fehler entfernen und ein .corrected-Datensatz erzeugen

Trainingsstart und Ergebnisbeispiele

  • Nach der Datenvalidierung kann das Training gestartet werden
  • Für schnelleres Training wird eine Konfiguration mit max_steps = 300 empfohlen
  • run_dir sollte als Experimentordner gesetzt werden; optional kann wandb.project angegeben werden, um Logging mit Weights & Biases zu nutzen
  • Das Training wird mit torchrun ausgeführt; --nproc-per-node sollte auf die Zahl der verfügbaren GPUs gesetzt werden
  • UltraChat-Training dauert auf einem 8xH100-Knoten etwa 30 Minuten; die resultierenden Gewichte können auf MT Bench etwa 6,3 erreichen
  • Glaive-Training dauert auf einem 8xH100-Knoten etwa 1 Stunde; die resultierenden Gewichte sollen gut für Function Calling funktionieren

Wichtige Punkte der Trainingskonfiguration

  • model_id_or_path: vortrainiertes Modell oder Pfad zu einem lokalen Modellverzeichnis, von dem das Training startet
  • run_dir: Verzeichnis zum Speichern von Checkpoints und Metriken
  • seq_len: Länge der Trainingssequenz; Samples werden zur Effizienz passend auf seq_len gepackt
  • batch_size: Anzahl der Trainingsbeispiele pro GPU
    • Die gesamte effektive Token-Batch-Größe ist num_gpus x batch_size x seq_len
  • max_steps: Gesamtzahl der Trainingsiterationen
    • Die Gesamtzahl der im Training gesehenen Tokens ist max_steps x num_gpus x batch_size x seq_len
  • optim.lr: initiale Lernrate des Optimizers
  • optim.weight_decay: Weight Decay; das README empfiehlt, 0.1 beizubehalten
  • optim.pct_start: Anteil der Warm-up-Phase von PyTorch OneCycleLR
  • lora.rank: Größe des LoRA-Adapters; empfohlen wird 64 oder weniger
  • seed: Zufalls-Seed für Reproduzierbarkeit bei Initialisierung, Daten-Shuffling und Sampling
  • data.instruct_data: Pfad zu Instruction-Trainingsdaten
    • Möglich sind eine einzelne jsonl-Datei, ein jsonl-Verzeichnis oder mehrere gewichtete Datenquellen
  • data.data: optionaler Pfad zu zusätzlichen Vortrainingsdaten
  • data.eval_instruct_data: optionaler Pfad zu Evaluationsdaten für Instruction
  • eval_freq, no_eval, ckpt_freq: steuern die Intervalle für Evaluation, Zwischenevaluation und Checkpoint-Speicherung
  • save_adapters: legt fest, ob nur LoRA-Checkpoints gespeichert werden oder ob LoRA in das Basismodell gemergt und das Gesamtmodell gespeichert wird
    • save_adapters=False erfordert genug CPU- und GPU-Speicher, um das vollständige Modell in einem einzelnen Prozess zu speichern, und ist normalerweise nur bei 7B-Modellen möglich

Inferenz und Weights & Biases

  • Für die Inferenz mit trainierten Modellen wird mistral-inference empfohlen
  • Installation per pip install mistral_inference
  • Beim Start von mistral-chat können LoRA-Gewichte über den unter --lora_path angegebenen Pfad zu lora.safetensors genutzt werden
  • Unterstützung für Weights and Biases ist enthalten, um Trainingsmetriken und Experimente zu überwachen
    • Installation per pip install wandb
    • Es wird empfohlen, den API-Schlüssel über die Umgebungsvariable WANDB_API_KEY bereitzustellen
    • Aus Sicherheitsgründen wird der API-Schlüssel nicht aus der YAML-Konfiguration gelesen
    • Trainings-Loss, Evaluations-Loss, Lernrate und weitere Werte werden im Projekt-Dashboard von wandb protokolliert und visualisiert
  • Weitere Details stehen in der Weights and Biases documentation

Modellerweiterung und FAQ

  • Es lassen sich nur Mistral-Modelle feinabstimmen, die mit dem v3-Tokenizer kompatibel sind
  • Kompatible Modelle müssen eine Vokabulargröße von 32768 haben, nicht 32000
  • Ältere Modelle mit Vokabulargröße 32000 können mit utils.extend_model_vocab auf 32768 erweitert werden
  • Beim Fine-Tuning von MoE-Modellen ist die Leistungsschwankung größer
    • Empfohlen wird, dasselbe MoE-Fine-Tuning mehrfach mit unterschiedlichen Seeds auszuführen und das beste Ergebnis auszuwählen
    • Bei dichten Modellen wurde eine so hohe Varianz nicht beobachtet
  • Die Anzahl der im Training verwendeten Tokens kann geprüft werden, indem die YAML-Trainingsdatei an utils.validate_data.py übergeben wird
  • Tritt ein CUDA out-of-memory-Fehler auf, kann die Batch-Größe pro GPU reduziert werden
    • Die Batch-Größe ist seq_len x batch_size
    • Vorgeschlagen wird, batch_size auf 1 zu setzen und seq_len zu verringern
  • Die Bibliothek steht unter der Apache 2.0 License
  • Diese Bibliothek oder die Modelle dürfen nicht in einer Weise verwendet werden, die Rechte einschließlich geistigen Eigentums Dritter verletzt, missbraucht oder gegen sie verstößt

1 Kommentare

 
GN⁺ 2024-05-27
Hacker-News-Kommentare
  • Entwickeln sich Modelle so schnell weiter – hat Fine-Tuning dann überhaupt noch einen Wert? Mich würden praktische Anwendungsfälle interessieren.
    Bloomberg hat zum Beispiel letztes Jahr ein LLM auf GPT-3.5-Niveau mit Finanzdaten trainiert, doch kurz darauf übertraf GPT-4-8k es bei fast allen Finanzaufgaben.
    Am Ende konzentrieren wir uns auf hochwertige Evaluationsdaten und auf Architekturen, mit denen man leicht auf neue Modelle wechseln kann.

    • Ja. Wir haben personenbezogene Daten in einer anderen Sprache als Englisch, annotiert in einem Format, das für eine bestimmte gesundheitsbezogene Studie entwickelt wurde.
      LLMs haben solche Annotationen nie gesehen, nicht-englische LLMs haben für Unternehmen auch nicht höchste Priorität, und wegen Datenschutz können wir nur Offline-first-Modelle verwenden.
      In so einer Situation passt Fine-Tuning eines allgemeinen Sprachmodells sehr gut.
    • Wenn man große Mengen an Ausgaben in einem bestimmten Format erzeugen muss, kann Fine-Tuning nützlich sein.
      Wenn man mit formatierten Nachrichten fine-tuned, erzeugt das Modell dieses Format automatisch; so spart man bei jedem Prompt viele Tokens, die sonst zur Beschreibung des Ausgabeformats nötig wären.
    • Was ist mit internen Unternehmensdaten, die GPT-4 nie gesehen hat?
    • Bei klassischen Aufgaben der natürlichen Sprachverarbeitung liegen LLMs deutlich hinter spezialisierten NLP-Pipelines wie Part-of-Speech-Tagging oder Merkmal-Tagging zurück.
      Fine-Tuning schließt die Lücke zwischen beiden allerdings ein gutes Stück.
      Das gilt auch für den Großteil der Programmierung, auch wenn es ein enger Bereich ist. Wenn das Ziel nur ist, ein allgemeines LLM stärker in Richtung der eigenen Daten zu lenken, ist Fine-Tuning wahrscheinlich eher nicht relevant.
      Wenn man aber ein sehr konkretes und zugleich mehrdeutiges Problem lösen will und ein LLM nur einen Teil davon bewältigt, ist Fine-Tuning wahrscheinlich die beste Option.
    • Function Calling kann ebenfalls ein Grund sein.
      Wenn die App viele Custom Functions hat, die mit Tools interagieren, bevorzugt man möglicherweise Fine-Tuning statt Kontext-Tokens zu verbrauchen.
  • Welche GPU braucht man dafür? Ich habe die Laptop-Version einer 3060 Ti, einen i9 und 16 GB RAM.
    Ich habe keine AWS- oder GCP-Quota und habe von Paperspace gehört, aber ich möchte schnell mit Mistral-Fine-Tuning anfangen, weil ich in einem Kundenprojekt, an dem ich arbeite, einige Mistral-Modelle einsetzen will.

    • Wenn das Budget nicht wirklich bei 0 liegt, würde ich dringend zu einem Gaming-Desktop raten.
      Gaming-GPUs können problemlos 300 W Wärme abführen; eine Laptop-GPU würde dabei schmelzen und ist wahrscheinlich auf ungefähr 100 W begrenzt.
      Wärmeabfuhr steht in direktem Verhältnis zur Geschwindigkeit.
      Außerdem kann man einen Desktop auf eine schnellere GPU aufrüsten oder mehrere GPUs verwenden.
      Allerdings sind insbesondere Multi-GPU-Konfigurationen laut und erzeugen genug Wärme, um ein Zimmer schnell aufzuheizen.
      Wenn du in den nächsten Jahren voraussichtlich nicht mehr als 10 % der Zeit die GPU unter Volllast laufen lässt, ist die Cloud wahrscheinlich günstiger.
    • Schau dir diese Seite an: https://www.hardware-corner.net/llm-database/Mistral/
      Dort sind die Hardwareanforderungen je Modell zusammengefasst, und man kann VRAM und Systemspeicher auswählen, um die nutzbaren Modelle zu filtern.
    • Bei Hetzner kann man einen GPU-Server für 184 Euro pro Monat nutzen.
      Unser Unternehmen hat dort mit der RTX4000 Mistral und Llama 3 fine-getuned.
      Mit nur 20 GB RAM ist das etwas eingeschränkt, aber bei größeren Eingabe-Tokenzahlen hat es geholfen, die Quantisierungsstufe zu senken.
      Inzwischen bieten sie auch stundenweise Miete an.
    • Probier openpipe aus.
      Wir nutzen es derzeit im Unternehmen und haben ziemlich gute Ergebnisse gesehen.
  • Es ist sehr spannend, welche Tools für die gängigen LLM-Anwendungsfälle zum De-facto-Standard werden.
    Das Ökosystem ist so fragmentiert, dass ich das Gefühl habe, von den meisten Tools noch nie gehört zu haben.
    Vor ein paar Tagen habe ich Microsofts Olive gesehen, und das war für mich völlig neu.

  • Da viele Open-Source-LLMs inzwischen bereits „brauchbar“ sind, kommt es jetzt darauf an, die Entwicklung rundherum einfacher zu machen.
    Insbesondere müssen Menschen, die sowohl Nutzer als auch Entwickler sind, private Daten nutzen können – genauer gesagt Daten, die nicht im Pretraining des Modells enthalten waren.
    Im Repository steht, dass es für große Modelle optimiert ist und A100/H100 benötigt, aber trotzdem habe ich das Gefühl, dass dies kleineren Modellen sogar mehr helfen könnte als großen.
    „Wenn man es baut, kommen die Leute“ lässt sich zu „Wenn man die Tools bereitstellt, bauen die Leute“ erweitern.

    • „Wenn man die Tools bereitstellt, bauen die Leute“ gilt nur, wenn der Anreiz, die Technologie zu lernen, Aussicht auf künftigen Nutzen bietet.
  • Der Teil mit den Gewichtungen ist interessant.
    HuggingFaces SFTTrainer erlaubt es, wenn man möchte, nur den Completion-Teil zu trainieren; auch wenn das für Menschen natürlich wirkt, ist es für LLMs im Allgemeinen besser, darauf trainiert zu werden, die gesamte Eingabe vorherzusagen.
    Mit diesem Ansatz bekommt man die Vorteile beider Seiten.

  • Könnte man das so optimieren, dass man mit zwei 3090 oder 4090 größere Modellvarianten trainieren kann?

  • Wie könnte ich mein WhatsApp-Chat-Modell trainieren?

    • Du müsstest klarer sagen, was du meinst.
      Willst du ein Modell mit deinen eigenen WhatsApp-Nachrichten trainieren? Was ist der Zweck? Es hängt davon ab, ob es wie du schreiben soll oder ob du RAG-basierte Fragen und Antworten willst.