Einer unserer früheren Artikel befasste sich mit der LAMBADA-Methode. Diese nutzt Natural Language Generation (NLG), um *Trainings-Utterances für eine Natural Language Understanding (NLU)-Aufgabe zu generieren, genauer gesagt für die *Intent-Klassifikation. In diesem Tutorial führen wir Sie durch den Code, um unsere PoC-Implementierung von der LAMBADA-Methode bzw. von Datenaugmentierung zu reproduzieren.
Bevor Sie mit diesem Tutorial fortfahren, schlagen wir vor, einen Blick auf unseren Artikel zu werfen, in dem wir die grundlegenden Ideen und Konzepteausführlicher erläutern, die von der LAMBADA-Methode angewendet werden. In diesem Tutorial stellen wir wesentliche Methoden in einem COLAB-Notizbuchs zur Verfügung. Insgesamt erklären wir einige der Kernpunkte des Codes und demonstrieren, wie Sie die Parameter so anpassen können, dass sie Ihren Anforderungen entsprechen, während die weniger wichtigen Teile weggelassen werden. Sie können das Notebook über Ihr Google-Konto kopieren, um dem Code zu folgen. Für Training und Tests können Sie Ihre eigenen Daten einsetzen oder von uns bereitgestellte Daten verwenden.
Wir verwenden distilBERT als Klassifikationsmodell und GPT-2 als Textgenerierungsmodell. Für beide laden wir vortrainierte Gewichte und justieren sie nach. Im Falle von GPT-2 verwenden wir die Huggingface Transfomers-Bibliothek, um ein vortrainiertes Modell zu laden und es anschließend weiter zu verfeinern. Zum Laden und Finetuning von distilBERT verwenden wir Ktrain, eine Bibliothek, die ein High-Level-Interface für Sprachmodelle bietet, so dass wir uns nicht mehr um Tokenisierung und andere Pre-Processing-Aufgaben kümmern müssen.
Zunächst installieren wir beide Bibliotheken in unserer COLAB runtime:
Wir verwenden einen der vorgelabelten Chitchat-Datensätze von Microsofts Azure QnA Maker. Als nächstes teilen wir den Chitchat-Datensatz so auf, dass wir zehn *Intents mit jeweils zehn Utterances als einen anfänglichen Trainingsdatensatz und die restlichen 1047 Samples als einen Testdatensatz erhalten. Im Folgenden verwenden wir den Testdatensatz, um die verschiedenen Intent-Klassifikatoren zu vergleichen, die wir in diesem Tutorial trainieren.
Anschließend laden wir die Trainingsdaten aus der Datei train.csv und teilen sie so auf, dass wir sechs Utterances pro Intent für das Training und vier Utterances pro Intent für die Validierung erhalten.
WWir downloaden das vortrainierte distilBERT-Modell, transformieren die Trainings- und Validierungsdaten von reinem Text in das für unser Modell gültige Format und initialisieren ein learner-Objekt, das in KTrain zum Trainieren des Modells verwendet wird.
Jetzt ist es an der Zeit, das Modell zu trainieren. Wir speisen die Trainingsdaten mehrfach in das Netzwerk ein, spezifiziert durch die Anzahl der Epochen. Zu Beginn sollten beide überwachten Metriken, also die Verlustfunktion (Abnahme) und die Genauigkeit (Zunahme), eine Verbesserung des Modells mit jeder vergangenen Epoche anzeigen. Nachdem das Modell jedoch eine gewisse Zeit lang trainiert wurde, wird der Validierungsverlust zunehmen und die Validierungsgenauigkeit fallen. Dies ist eine Folge von Overfitting der Trainingsdaten, und es ist an der Zeit, die Einspeisung derselben Daten in das Netzwerk zu beenden.
Die optimale Anzahl von Epochen hängt von Ihrem Datensatz, Ihrem Modell und Ihren Trainingsparametern ab. Wenn Sie die richtige Anzahl von Epochen im Voraus nicht kennen, können Sie eine hohe Anzahl von Epochen verwenden und Checkpoints aktivieren, indem Sie den Parameter checkpoint_folder setzen, um anschließend das Modell mit der besten Performance auszuwählen.
Um die Leistung unseres trainierten Klassifikators zu überprüfen, verwenden wir unsere Testdaten in der Datei eval.csv.
Beachten Sie, dass wir dank des KTrain-Interface die Liste der Utterances einfach in den Predictor einspeisen können, ohne die ursprünglichen Strings vorher verarbeiten zu müssen. Als Ausgabe erhalten wir die Genauigkeit unseres Klassifikators:
Genauigkeit: 84,24%
Zum Finetuning von GPT-2 verwenden wir ein Python Skript, das von Huggingface auf deren Github-Repository zur Verfügung gestellt wird. Unter anderem spezifizieren wir die folgenden Parameter:
Let’s load our model and generate some utterances! To trigger the generation of new utterances for a specific intent we provide the model with this intent as seed ('<intent>,', e.g. ‘inform_hungry,’).</intent>
Das sieht gut aus! Die künstlich erzeugten Utterances passen zum Intent, aber um eine nützliche Ergänzung zu sein und unser Modell zu verbessern, müssen sich diese Utterances von denen unterscheiden, die für das Training verwendet werden. Die Trainingsdaten für die Intent inform_hungry waren die folgenden:
Wir sehen, dass die beiden Utterances " I want some food" und "I'm so hungry I could eat" nicht Teil der Trainingsdaten sind.
Wenn wir mit unseren generierten Utterances nicht zufrieden sind, weil sie alle sehr ähnlich sind, oder wenn sie nicht dem zugrunde liegenden Intent entsprechen, können wir die Variabilität des generierten Outputs anpassen, indem wir die folgenden Parameter modifizieren:
Wir erzeugen jetzt die neuen Utterances für alle Intents. Um eine ausreichend große Probe zu haben, aus der wir die besten Utterances auswählen können, erzeugen wir 200 pro Intent.
Nach einer Weile sind die Daten generiert, und wir können sie uns genauer ansehen. Zunächst verwenden wir unseren alten DestilBERT-Klassifikator, um den Intent für alle generierten Utterances vorherzusagen. Außerdem beobachten wir die Vorhersagewahrscheinlichkeit, die das Confidence Level jeder einzelnen Vorhersage unseres Modells angibt.
Werfen wir einen Blick auf einige der Utterances, bei denen der für die Erzeugung generierte Intent nicht mit dem vorhergesagten übereinstimmt.
In einigen Fällen ist die Vorhersage eindeutig falsch. Es gibt jedoch auch Fälle, in denen die Vorhersage mit der Utterance übereinstimmt, aber nicht mit dem Intent, der für die Generierung verwendet wurde. Dies deutet darauf hin, dass unser GPT-2-Modell nicht perfekt ist, da es nicht immer übereinstimmende Utterances für einen Intent generiert.
Um unseren Klassifikator nicht mehr mit korrupten Daten zu trainieren, streichen wir alle Utterances, bei denen der Basis-Intent nicht mit dem vorhergesagten Intent übereinstimmt. Von solchen mit übereinstimmenden Instanzen behalten wir nur diejenigen mit den höchsten Vorhersagewahrscheinlichkeitswerten.
Wir sehen, dass es für jeden Intent mindestens 35 unterschiedliche Utterances gibt. Um einen ausgewogenen Datensatz zu bewahren, wählen wir die besten 30 Utterances pro Intent entsprechend der Vorhersagewahrscheinlichkeit aus.
Wir kombinieren nun die generierten Daten mit den ursprünglichen Trainingsdaten und teilen den angereicherten Datensatz in Trainings- und Validierungsdaten auf.
Jetzt ist es an der Zeit, unser neues Intent-Klassifikationsmodell zu trainieren. Der Code ist wie der obige:
Schließlich verwenden wir unseren Evaluationsdatensatz, um die Genauigkeit unseres neuen Intent-Klassifikators zu überprüfen.
Wir können feststellen, dass sich die Performance um 7% verbessert hat. Insgesamt betrug die Verbesserung der Vorhersagegenauigkeit über alle von uns durchgeführten Experimente hinweg konstant mehr als 4%.
Wir setzten die LAMBADA-Methode zur Data Augmentation für Natural Language Understanding (NLU) Tasks ein. Wir trainierten ein GPT-2-Modell zur Generierung neuer Trainings-Utterances und nutzten sie als Trainingsdaten für unser Intent-Klassifikationsmodell (distilBERT). Die Leistung des Intent-Klassifikationsmodells verbesserte sich in jedem unserer Tests um mindestens 4%.
Darüber hinaus konnten wir feststellen, dass high-level-Bibliotheken wie KTrain und Huggingface Transformers dazu beitragen, die Komplexität der Anwendung hochmoderner Transformermodelle für Natural Language Generation (NLG) und andere Natural Language Processing (NLP)-Aufgaben wie die Klassifikation zu reduzieren und diese Ansätze auf breiter Basis anwendbar zu machen.