Prozesse und Informationen stehen im Mittelpunkt jedes Geschäfts. Die Sicherheitsanfälligkeit und Chancen dieses Moments ist die Frage, ob Ihr Unternehmen Ihre Prozesse mit KI automatisieren und die Belohnungen dazu nieren kann. Chatgpt, ein Allzweck -KI, hat unsere Augen für das geöffnet, was KI tun kann. Was jetzt zählt, ist die Anweisung der KI -Macht auf Ihre Geschäftsprobleme und die Erschließung des Werts Ihrer proprietären Daten. In diesem Dokument werde ich Ihnen zeigen, wie.
Sie wollen keine KI, die einfach chatten kann. Was Sie wirklich wollen, sind Automatisierungen, die die Arbeit ausführen, die Ihr Geschäft läuft-durch Geschäftsprozesse in großer Genauigkeit und Skalierung durchführen. Die nachgewiesene Möglichkeit, KI an Ihre Geschäftsprozesse anzupassen, besteht darin, einen LLM auf Ihre Daten und die Aktion, die KI ausführen soll, eine LLM zu fördern.
Lassen Sie uns speziell über die Feinabstimmung sprechen, die wir in diesem Dokument durchführen werden, und über die Technologie dahinter. Im Folgenden sind die fünf Tools aufgeführt, die wir ausgiebig verwenden werden:
Am Ende des Tages sollten Sie zwei Dinge aus diesem Dokument wegnehmen:
Ich werde Ihnen ein hartes, reales Problem beschreiben, welche Forscher maschinelles Lernen bereits getan haben, und die neue Grenze, die wir auf die Verwendung leistungsstarker SOTA-Tools drängen konnten. Wir werden Modelle auf GPUs in der Cloud trainieren. Wir werden auch leistungsstarke MLOPS-Praktiken in die Tat umsetzen und MLFlow verwenden, um unsere Experimente und Parameter zu organisieren. Auf dem Weg dorthin werde ich auf das Designmuster dieses Projekts hinweisen, damit Sie die Codebasis für Ihre eigenen Deep -Learning -Projekte anpassen können.
Beginnen wir mit dem Problemhintergrund.
Ein guter Prozess, um geeignete Probleme für maschinelles Lernen und für Qualitätsdatensätze zu finden, besteht darin, mit dem Surfen mit Benchmarks zu beginnen. Benchmarks bieten einen Referenzrahmen für das Schwierigkeitsgrad des Problems für maschinelles Lernen, mit dem wir unseren Fortschritt während der Modellentwicklung messen. Ein bestimmter Datensatz mit gut etablierten Benchmarks ist die unfairen Nutzungsbedingungen des Dienstes (unfaire Tos). Hier ist eine faszinierende Problemaussage: Verwenden Sie KI, um alle unfairen Klauseln in Bezug auf Serviceverträge zu finden. Der Kontext besteht darin, dass das europäische Verbrauchergesetz für unfaire Verträge festlegt, welche unfairen Klauseln sie sind und welche verschiedenen Arten von unfairen Klauseln. Was unfaire Tos für die Textklassifizierung perfekt macht, ist, dass sie in Übereinstimmung mit dem, was im europäischen Gesetz festgelegt wurde, manuell gekennzeichnet wurde.
Chalkidis et al. (2021) wandten acht verschiedene Methoden für maschinelles Lernen auf unfaire TOS an und erhielten Makro F1 im Bereich von 75 bis 83, und in Abbildung 1 direkt nach unten ziehen wir uns aus ihren veröffentlichten Ergebnissen aus.
| Verfahren | Unfaire Tos | |
|---|---|---|
| Mikro F1 | Makro F1 | |
| Tfidf-svm | 94.7 | 75,0 |
| Bert | 95.6 | 81.3 |
| Roberta | 95.2 | 79,2 |
| Deberta | 95,5 | 80.3 |
| Langformer | 95,5 | 80.9 |
| Bigbird | 95.7 | 81.3 |
| Legal-Bert | 96.0 | 83.0 |
| Fallschützer | 96.0 | 82.3 |
Interessante Dinge, die wir aus dieser Tabelle schließen können, sind:
Wenn man sich die Daten ansieht, ist sicherlich ein Klassenungleichgewicht vorhanden, was ein guter Grund für den ersten und zweiten Punkt oben ist.
Es gibt acht verschiedene Arten von unfairen Klauseln. Die Autoren dieses Papiers entwickelten Multi-Label-Klassifizierungsmodelle für die acht Typen, aber wir werden einfach ein binäres Klassifizierungsmodell erstellen, das eine Klausel als fair oder unfair einstuft.
Lassen Sie uns entwerfen, wie wir es tun werden.
__init__.py enthält die öffentliche API des Moduls, in der es sich befindet, damit wir die Importe für tief submodulierte Funktionen wie dieses Beispiel bequem verkürzen können: from . fine_tune_clsify_head import TransformerModule Der obige Import in architectures/__init__.py ermöglicht es Code außerhalb architectures , TransformerModule zu importieren, ohne sich an die Brotkrumen zu erinnern, die zu dieser Funktion führen, wie folgt:
from architectures import TransformerModuleSo sieht die Projektstruktur aus der Wurzel des Lightning_Mlflow -Moduls aus:
.
├── architectures
│ ├── __init__.py
│ └── fine_tune_clsify_head.py
├── config
│ ├── __init__.py
│ └── train_config.py
├── data
│ ├── __init__.py
│ └── lex_glue.py
└── train.py
Die Hauptfrage ist, warum das Projekt auf diese Weise strukturiert ist. Und die Antwort ist, dass zwischen den 3 Submodulen und 1 Einstiegspunkte die Trennung von Bedenken festgelegt wird. Lassen Sie uns nacheinander durch jedes dieser Module gehen:
architectures : Gibt im Wesentlichen alles an, was Pytorch mit Ausnahme der Daten wissen mussconfig : Hält alle Parameter und kann in train_config.py und inference_config.py und was auch immer unterteilt werdendata : Hält alle Datenverarbeitungslogik und Einstellungentrain.py : Der zentrale Kontrollpunkt; Dies ist der einzige Code, in dem architectures , config und data angezeigt werden können. MLFlow SDK -Anrufe finden Sie hierLassen Sie uns mit diesem kurzen Intro in den Weg rollen und versuchen, den Code in jedem der Module wirklich zu verstehen. Beginnen wir mit Architekturen/fine_tune_clsify_head.py. Dieser Code ist wie Abbildung 3 direkt unten organisiert.

Es ist klar, dass die wichtigsten Methoden in dieser Klasse zu verstehen sind: Der Konstruktor, der Vorwärtsgut durch das Netzwerk, die Metriken und die Schritte. Wir werden jeweils über jeden von diesen diskutieren. Beginnen wir mit dem Konstruktor. Dieser Ausschnitt sieht aus, wie der Code aussieht:
Was hier wirklich entscheidend ist, ist, dass der Konstruktor ein vorgezogenes Modell vom Umarmungsgesicht lädt und die Parameter effiziente Feinabstimmung (PEFT) festlegt. PEFT ist der Blutungsrand, um große Sprachmodelle zu fein und eine umarmende Gesichtsimplementierung von Qlora, die die Kombination von drei verschiedenen Effizienzstrategien darstellt: Quantisierung, niedriger Rang und Adapter. Quantisierung ist die Idee, dass eine Single-Byte-Ganzzahl von ausreichender numerischer Genauigkeit für Gradientenberechnungen im Deep-Lernen ist. Niedriger Rang kommt aus dem linearen Algebra-Konzept, dass der Rang einer Matrix die Anzahl der nicht redundanten Dimensionen des Vektorraums ist. Die Adapterabstimmung kann als eine Art Verallgemeinerung des Stimmens des Netzes des Netzwerks verstanden werden, indem ein Teil der Gewichte in vielen Schichten neu gestaltet wird.
Schauen wir uns die forward an:
Da ein neuronales Netzwerk die Abwechslung zwischen Backprop und Feed Forward beinhaltet, gibt dies den Vorwärtsenteil an, und das Bemerkenswerte ist, dass die Argumente von forward : input_ids , attention_mask und label sind. Dies sind die Ausgänge eines Umarmungs -Gesichts -Tokenizers, und sie ermöglichen es uns, um das Gesicht und den Pytorch -Blitz zusammenzubinden.
Schauen wir uns als nächstes die Methode _compute_metrics an:
Hier sind einige Dinge erwähnenswert. Beachten Sie zunächst, wie die Logits aus der Vorwärtsfunktionsbewertung ausgepackt und dann über die Softmax -Funktion in Wahrscheinlichkeiten umgewandelt werden. Dies führt wiederum zur binären Vorhersage. Wir verwenden die Vorhersage und die tatsächliche ( batch["label"] ), um die Genauigkeit, F1, Präzision und Rückruf zu berechnen.
Lassen Sie uns schließlich über training_step , validation_step und test_step sprechen.
Sie sehen fast ähnlich aus, wobei ein wichtiger Unterschied darin besteht, Ausgänge training_step outputs["loss"] anstelle von metrics . Dies ist sinnvoll, weil Backprop den Verlust iterativ minimiert. training_step ist nur Pytorch Lightning -Abstraktion der Trainingsschleife.
OK, jetzt sind wir mit architectures fertig, lassen Sie uns in config/Train_config.py eintauchen, die wie Abbildung 7 unten aussieht.
Dieser Code ist selbsterklärend, aber es gibt einige Möglichkeiten, die Sie aufrufen müssen. Das pretrained_model ist auf roberta-base eingestellt, und wenn wir ihn in jeden umarmenden Gesichtsmodellnamen ändern, der Autotokenizer unterstützt, sollte alles noch funktionieren (getestet). Es wurde festgestellt, dass die Genauigkeit der Modellgenauigkeit am sensibelsten gegenüber max_length und batch_size ist, daher sind dies die wichtigsten Hyperparameter, mit denen sie herumspielen können, und beide Kompromisse zwischen Genauigkeit und Rechenlast. Bei Azure ML habe ich die Standard -Instanz von Standard_NC24ADS_A100_V4 verwendet. Das VRAM in der A100 GPU erwies sich als ein begrenzender Faktor für diese beiden Hyperparameter. Was ich fand, war, dass 256 der größte batch_size war, der nicht dazu führen würde, dass CUDA einen außeremmory-Fehler warf.
Die Bestimmung von max_length von 128 war einfacher, da die überwiegende Mehrheit der Klauseln unter dieser Token -Grenze lag.
Schließlich wurde, wie wir später sehen werden, max_epochs von 10 durch Versuch und Irrtum ausgewählt, da die Validierung F1 -Metrik, die wir in MLFlow verfolgten, zu diesem Zeitpunkt abgeflacht hat.
OK, lass uns über Daten sprechen. Alles, was Sie wissen müssen, befindet sich in der LexGlueDataModule -Klasse in Data/Lex_glue.py, und dies ist seine Struktur:
In LexGlueDataModule gibt es einige Details mit kargen Zunahnen, aber die Hauptidee ist, dass die setup Methode die Daten direkt aus dem Umarmung des Gesichts abholt und dann eine Art Tokenisierung passieren muss. Die Details dieser Tokenisierung finden Sie in der Methode _shared_transform , die genau die Schnittstelle auf hoher Ebene für die _preprocess Callback -Methode ist.
Schließlich sind wir bereit für den Zug. Py, der zentrale Kontrollpunkt für alles. Erinnerst du dich, als wir diesen Abschnitt mit der Verzeichnisstruktur des Projekts begannen? Diese Struktur kommuniziert eine wichtige Botschaft: Die Abhängigkeiten werden im Verzeichnisbaum nach unten gelöst. Mit anderen Worten, wir haben den Code darauf eingeschränkt, nur einen anderen Code aufzurufen, der auf derselben oder niedrigeren Ebene liegt. Diese Einschränkung kommt sicherlich nicht aus Python; Es ist selbst auferlegt und warum? Vermutungen zu beseitigen. Es steht außer Frage, dass verwirrende Abhängigkeitsketten in großen Codebasen ein großes Problem darstellen. All dies bedeutet, dass train.py die Funktionalität aus den anderen Modulen importieren und dann einen Trainingslauf in Bewegung setzt. Schauen wir uns das Stück Code im Herzen an:
Wir instanziieren eine Pytorch Lightning Trainer-Klasse, schalten frühzeitig an und setzen die Präzision basierend auf der Maschine, auf der wir über precision="bf16-mixed" if torch. cuda.is_available() else "32-true" . Wir konfigurieren MLFlow, um alles zu verfolgen. Um alles zusammenzustellen, importieren wir die Funktionalität aus den anderen drei Modulen, die wir zuvor beschrieben hatten:
from architectures . fine_tune_clsify_head import TransformerModule
from config import TrainConfig
from data import LexGlueDataModuleDie Kernfunktionalitäten sind in unsere Unterklassen von Pytorch -Blitz -Superklassen eingewickelt, und so instanziieren wir sie:
model = TransformerModule (
pretrained_model = config . pretrained_model , num_classes = config . num_classes ,
lr = config . lr , )
datamodule = LexGlueDataModule (
pretrained_model = config . pretrained_model , max_length = config . max_length ,
batch_size = config . batch_size , num_workers = config . num_workers ,
debug_mode_sample = config . debug_mode_sample , ) Und schließlich berufen wir die fit und test des trainer :
trainer . fit ( model = model , datamodule = datamodule )
best_model_path = checkpoint_callback . best_model_path
# Evaluate the last and the best models on the test sample.
trainer . test ( model = model , datamodule = datamodule )
trainer . test (
model = model , datamodule = datamodule , ckpt_path = best_model_path , ) Wir hatten test zweimal angerufen, damit wir sowohl das letzte Modell zur Stoppzeit als auch das beste Modell gemäß unserer Metrik testen. Dies ist ein perfektes Beispiel für die reichhaltige Funktionalität, die mit Pytorch -Blitz einhergeht.
Und das schließt den Code -Walkthrough ab. Tauchen wir nun in die Modellergebnisse ein.
Hier ist ein Dashboard, das alles zusammenstellt:
Die engen Integration zwischen Azure und MLFlow nutzen die Metriken aus unserem Trainingslauf und wurden für den einfachen Verbrauch und die Visualisierung in der Azure ML -Webkonsole zur Verfügung gestellt. MLFlow hat mehr als nur die Metriken erfasst, aber tiefer in seine volle Funktionalität und die breiteren Anwendungsfälle von MLOPS sind für einen anderen Tag. Konzentrieren wir uns vorerst auf die Geschichte, die uns unsere Datenvisualisierung zeigt.
Eine Sache, die aus der oberen linken Tabelle hervorgeht, ist, dass das Training keinen Zweifel an der Validierungsstichprobe verbessert hat. Darüber hinaus beginnt sich die Kurve zwischen 125 und 190 Schritten zu verflachten, ein potenzieller Hinweis darauf, dass ein weiteres Training unnötig sein könnte. Da wir jedoch monotonisch sind, sehen wir, dass noch keine Überanpassung aufgetreten ist, und darüber hinaus die Kurve von 190 bis 210 wieder durchsetzt. Vielleicht hätten wir es für weitere 5 Epochen laufen lassen sollen.
Interessanterweise erzählen die oberste rechte Handlung eine ähnliche Geschichte. Das bemerkenswerteste Merkmal ist, wie hoch die Genauigkeitswerte sind und die Einheit hier prozentual ist. Dass die Zeilen von Anfang an 90% treffen, ist sinnvoll, da der Datensatz nach 1: 9-Verhältnis zwischen Unfair und fairen. Genau deshalb ist die bevorzugte Metrik F1, weshalb wir im unteren linken Diagramm anzeigen.
Die F1 -Kurven zeigen hier das klassische Muster, in dem sich das Modell zunächst schnell verbessert, aber schließlich den Punkt der Rückgabe von Rückgängen erreicht. Eine interessante Frage, die durch die F1 -Kurven hervorgerufen wird, ist, wie wir uns zwischen dem Verlust und dem F1 in Einklang bringen, wenn einer vorschlägt, während der andere Raum für weiteres Fahren lässt. Das folgende Stück Theorie wird dieses Rätsel knacken.
Wir beobachten die Welt in Form diskreter Ereignisse, aber kontinuierliche Konstrukte (z. B. Wahrscheinlichkeit) sind in der Mathematik häufig nützlicher. Die Ergebnisse im Datensatz für unfaire Tos sind "fair" oder "unfair" codiert, und es gibt eine latente Wahrscheinlichkeitsverteilung, die diese Ergebnisse generiert. Diese latente Wahrscheinlichkeitsverteilung ist das, womit die Cross-Entropy-Verlustfunktion funktionieren kann. Im Deep Learning optimieren wir also die kontinuierliche Metrik, aber wir beurteilen, wie gut unser Modell durch die diskrete Metrik ist, da kontinuierliche (latente) und diskrete (beobachtete) Annäherungen voneinander sind. Das ist die Idee.
Wenn der F1 also auf eine andere Geschichte als den Verlust hinweist, gibt es nur zwei mögliche Erklärungen: Zufälligkeit und Klassenungleichgewicht. In der Tat sind die Genauigkeit und die F1 so viel volatiler als der Verlust.
Zufälligkeit scheint auch die wahrscheinliche Erklärung für die Lücke zwischen der besten Validierung F1 -Punktzahl von 70% und dem Test F1 -Wert von 78% (aus der unteren rechten Tabelle) zu sein.
Dieses Spiel durch Spielanalyse der Modellbewertungsmetriken bringt diesen Abschnitt zu Ende. Als nächstes machen Sie sich damit, dieses Projekt zu Ihrem eigenen zu machen. Die folgende Installationshandbuch hilft Ihnen beim Basteln mit dem Code.
Schritt 1. Klonen Sie dieses Repository in ein lokales Arbeitsverzeichnis:
$ git clone https://github.com/zjohn77/lightning-mlflow-hf.git
$ cd lightning-mlflow-hf Schritt 2. Alle Projektabhängigkeiten befinden sich in environment.yml , und Sie werden eine virtuelle Umgebung dafür erstellen. Die folgenden Anweisungen gelten für conda , aber nichts in diesen Abhängigkeiten schließt venv oder poetry aus.
$ conda env create -n lightning-mlflow-hf -f environment.yml Schritt 3. Am Ende des Trainingslaufs kopiert die Funktion copy_dir_to_abs die Ausgänge in den Speicher von Azure Blob. Wenn Azure auch das ist, was Sie verwenden, geben Sie einfach Anmeldeinformationen an diese Funktion weiter und Sie sind alle festgelegt. Andernfalls ersetzen Sie durch Ihren eigenen Workflow.
Schritt 4. In Ihrer virtuellen Umgebung wechseln Sie in Ihre IDE auf die Stelle, an der sich train.py befindet.
$ python train.pyWenn es keine Fehler gibt, wird es gedruckt, um eine umarmende Gesichtsnachricht und viele Pytorch -Blitznachrichten zu trösten. Nach ein paar Minuten sollte es mit dem Drucken einer Fortschrittsleiste beginnen. Setzen Sie sich fest und lassen Sie es sein Ding machen. Wenn der Lauf schließlich beendet ist, wird eine ASCII -Tabelle, die die Bewertungsmetriken für das endgültige Modell zusammenfasst, zur Konsole gedruckt. Das ist alles, was es gibt!
Jeder Beitrag ist willkommen. Wir verwenden GitHub Pull -Anfragen für die Codeüberprüfung und verwenden das schwarze Formatierer, um die Konsistenz des Codestils sicherzustellen.
Unit -Tests und DOC -Tests sind ebenfalls sehr willkommen.
Eine Roadmap ist in Arbeit. Schauen Sie bald wieder vorbei.
Ilias Chalkidis, Abhik Jana, Dirk Hartung, Michael Bommarito, Ion Androutsopoulos, Daniel Martin Katz, Nikolaos Aletras. (2021). LexGlue: Ein Benchmark -Datensatz für das Verständnis der juristischen Sprache in Englisch . Abgerufen von Arxiv: https://arxiv.org/abs/2110.00976