Meta AI hat Ende 2021 wav2vec2 XLS-R („XLS-R“) eingeführt. XLS-R ist ein maschinelles Lernmodell („ML“) für das Lernen sprachübergreifender Sprachdarstellungen. Es wurde mit über 400.000 Stunden öffentlich verfügbarem Sprachaudio in 128 Sprachen trainiert. Bei seiner Veröffentlichung stellte das Modell einen Sprung gegenüber dem sprachübergreifenden Modell XLSR-53 von Meta AI dar, das mit etwa 50.000 Stunden Sprachaudio in 53 Sprachen trainiert wurde.
In diesem Handbuch werden die Schritte zum Optimieren von XLS-R für die automatische Spracherkennung („ASR“) mithilfe eines Kaggle-Notebooks erläutert. Das Modell wird auf chilenisches Spanisch optimiert, aber die allgemeinen Schritte können befolgt werden, um XLS-R auf andere gewünschte Sprachen zu optimieren.
Das Ausführen von Inferenzen auf dem fein abgestimmten Modell wird in einem begleitenden Tutorial beschrieben, sodass dieser Leitfaden der erste von zwei Teilen ist. Ich habe beschlossen, einen separaten, inferenzspezifischen Leitfaden zu erstellen, da dieser Leitfaden zur Feinabstimmung etwas lang geworden ist.
Es wird vorausgesetzt, dass Sie über einen vorhandenen ML-Hintergrund verfügen und grundlegende ASR-Konzepte verstehen. Anfänger haben möglicherweise Schwierigkeiten, den Build-Schritten zu folgen/sie zu verstehen.
Das ursprüngliche wav2vec2-Modell, das 2020 eingeführt wurde, wurde mit 960 Stunden Sprachaudio aus dem Librispeech -Datensatz und ~53.200 Stunden Sprachaudio aus dem LibriVox- Datensatz vortrainiert. Bei seiner Veröffentlichung waren zwei Modellgrößen verfügbar: das BASE- Modell mit 95 Millionen Parametern und das LARGE- Modell mit 317 Millionen Parametern.
XLS-R hingegen wurde anhand mehrsprachiger Sprachaufnahmen aus fünf Datensätzen vortrainiert:
Es gibt 3 XLS-R-Modelle: XLS-R (0,3 B) mit 300 Millionen Parametern, XLS-R (1 B) mit 1 Milliarde Parametern und XLS-R (2 B) mit 2 Milliarden Parametern. In dieser Anleitung wird das XLS-R-Modell (0,3 B) verwendet.
Es gibt einige großartige Anleitungen zum Optimieren von wav2vev2 -Modellen, wobei diese hier vielleicht eine Art „Goldstandard“ darstellt. Natürlich ähnelt der allgemeine Ansatz hier dem, was Sie in anderen Anleitungen finden. Sie werden:
Es gibt jedoch drei wesentliche Unterschiede zwischen diesem Leitfaden und anderen:
Zum Ausfüllen des Handbuchs benötigen Sie:
Bevor Sie mit dem Erstellen des Notebooks beginnen, kann es hilfreich sein, die beiden Unterabschnitte direkt darunter durchzulesen. Sie beschreiben:
Wie in der Einleitung erwähnt, wird das XLS-R-Modell auf chilenisches Spanisch optimiert. Der spezifische Datensatz ist der von Guevara-Rukoz et al. entwickelte Chilean Spanish Speech Data Set . Er steht auf OpenSLR zum Download bereit. Der Datensatz besteht aus zwei Unterdatensätzen: (1) 2.636 Audioaufnahmen von chilenischen männlichen Sprechern und (2) 1.738 Audioaufnahmen von chilenischen weiblichen Sprechern.
Jeder Unterdatensatz enthält eine Indexdatei line_index.tsv
. Jede Zeile jeder Indexdatei enthält ein Paar aus einem Audiodateinamen und einer Transkription des Audios in der zugehörigen Datei, z. B.:
clm_08421_01719502739 Es un viaje de negocios solamente voy por una noche clm_02436_02011517900 Se usa para incitar a alguien a sacar el mayor provecho del dia presente
Ich habe den Datensatz mit chilenisch-spanischer Sprache der Einfachheit halber auf Kaggle hochgeladen. Es gibt einen Kaggle-Datensatz für die Aufnahmen chilenischer männlicher Sprecher und einen Kaggle-Datensatz für die Aufnahmen chilenischer weiblicher Sprecher . Diese Kaggle-Datensätze werden dem Kaggle-Notebook hinzugefügt, das Sie nach den Schritten in dieser Anleitung erstellen.
WER ist eine Metrik, mit der die Leistung automatischer Spracherkennungsmodelle gemessen werden kann. WER bietet einen Mechanismus, um zu messen, wie nahe eine Textvorhersage an einer Textreferenz liegt. WER erreicht dies, indem es Fehler von 3 Typen aufzeichnet:
Ersetzungen ( S
): Ein Ersetzungsfehler wird aufgezeichnet, wenn die Vorhersage ein Wort enthält, das sich vom analogen Wort in der Referenz unterscheidet. Dies tritt beispielsweise auf, wenn die Vorhersage ein Wort in der Referenz falsch schreibt.
Löschungen ( D
): Ein Löschungsfehler wird aufgezeichnet, wenn die Vorhersage ein Wort enthält, das in der Referenz nicht vorhanden ist.
Einfügungen ( I
): Ein Einfügungsfehler wird aufgezeichnet, wenn die Vorhersage ein Wort nicht enthält, das in der Referenz vorhanden ist.
Offensichtlich funktioniert WER auf Wortebene. Die Formel für die WER-Metrik lautet wie folgt:
WER = (S + D + I)/N where: S = number of substition errors D = number of deletion errors I = number of insertion errors N = number of words in the reference
Ein einfaches WER-Beispiel auf Spanisch lautet wie folgt:
prediction: "Él está saliendo." reference: "Él está saltando."
Eine Tabelle hilft, die Fehler in der Vorhersage zu visualisieren:
TEXT | WORT 1 | WORT 2 | WORT 3 |
---|---|---|---|
Vorhersage | El | está | saliendo |
Referenz | El | está | Salzand |
| richtig | richtig | Auswechslung |
Die Vorhersage enthält 1 Substitutionsfehler, 0 Löschfehler und 0 Einfügungsfehler. Der WER für dieses Beispiel lautet also:
WER = 1 + 0 + 0 / 3 = 1/3 = 0.33
Es sollte offensichtlich sein, dass die Wortfehlerrate uns nicht unbedingt sagt, welche spezifischen Fehler vorliegen. Im obigen Beispiel erkennt WER, dass WORT 3 einen Fehler im vorhergesagten Text enthält, sagt uns aber nicht, dass die Zeichen i und e in der Vorhersage falsch sind. Andere Metriken, wie die Zeichenfehlerrate („CER“), können für eine genauere Fehleranalyse verwendet werden.
Jetzt können Sie mit dem Erstellen des Feinabstimmungsnotizbuchs beginnen.
Ihr Kaggle-Notebook muss so konfiguriert sein, dass Trainingslaufdaten mit Ihrem WandB-API-Schlüssel an WandB gesendet werden. Dazu müssen Sie ihn kopieren.
www.wandb.com
an.www.wandb.ai/authorize
.
xls-r-300m-chilean-spanish-asr
verwendet.Zum sicheren Speichern Ihres WandB-API-Schlüssels wird ein Kaggle-Geheimnis verwendet.
WANDB_API_KEY
in das Feld „Bezeichnung“ ein und geben Sie als Wert Ihren WandB-API-Schlüssel ein.WANDB_API_KEY
aktiviert ist.Der Datensatz zur chilenischen spanischen Sprache wurde in zwei unterschiedlichen Datensätzen auf Kaggle hochgeladen:
Fügen Sie beide Datensätze zu Ihrem Kaggle-Notebook hinzu.
Die folgenden 32 Unterschritte bauen der Reihe nach jede der 32 Zellen des Feinabstimmungsnotizbuchs auf.
Die erste Zelle des Finetuning-Notebooks installiert Abhängigkeiten. Legen Sie die erste Zelle fest auf:
### CELL 1: Install Packages ### !pip install --upgrade torchaudio !pip install jiwer
torchaudio
Paket auf die neueste Version. torchaudio
wird zum Laden von Audiodateien und erneuten Abtasten von Audiodaten verwendet.jiwer
Paket, das zur Verwendung der später verwendeten load_metric
Methode der Bibliothek HuggingFace Datasets
erforderlich ist.Die zweite Zelle importiert erforderliche Python-Pakete. Legen Sie die zweite Zelle fest auf:
### CELL 2: Import Python packages ### import wandb from kaggle_secrets import UserSecretsClient import math import re import numpy as np import pandas as pd import torch import torchaudio import json from typing import Any, Dict, List, Optional, Union from dataclasses import dataclass from datasets import Dataset, load_metric, load_dataset, Audio from transformers import Wav2Vec2CTCTokenizer from transformers import Wav2Vec2FeatureExtractor from transformers import Wav2Vec2Processor from transformers import Wav2Vec2ForCTC from transformers import TrainingArguments from transformers import Trainer
transformers
und die zugehörigen Wav2Vec2*
-Klassen das Rückgrat der zur Feinabstimmung verwendeten Funktionalität bilden.Die dritte Zelle importiert die HuggingFace WER-Auswertungsmetrik. Legen Sie die dritte Zelle fest auf:
### CELL 3: Load WER metric ### wer_metric = load_metric("wer")
Die vierte Zelle ruft Ihr WANDB_API_KEY
Geheimnis ab, das in Schritt 2.2 festgelegt wurde. Legen Sie die vierte Zelle wie folgt fest:
### CELL 4: Login to WandB ### user_secrets = UserSecretsClient() wandb_api_key = user_secrets.get_secret("WANDB_API_KEY") wandb.login(key = wandb_api_key)
In der fünften Zelle werden Konstanten festgelegt, die im gesamten Notebook verwendet werden. Legen Sie die fünfte Zelle wie folgt fest:
### CELL 5: Constants ### # Training data TRAINING_DATA_PATH_MALE = "/kaggle/input/google-spanish-speakers-chile-male/" TRAINING_DATA_PATH_FEMALE = "/kaggle/input/google-spanish-speakers-chile-female/" EXT = ".wav" NUM_LOAD_FROM_EACH_SET = 1600 # Vocabulary VOCAB_FILE_PATH = "/kaggle/working/" SPECIAL_CHARS = r"[\d\,\-\;\!\¡\?\¿\।\'\'\"\–\'\:\/\.\“\”\৷\…\‚\॥\\]" # Sampling rates ORIG_SAMPLING_RATE = 48000 TGT_SAMPLING_RATE = 16000 # Training/validation data split SPLIT_PCT = 0.10 # Model parameters MODEL = "facebook/wav2vec2-xls-r-300m" USE_SAFETENSORS = False # Training arguments OUTPUT_DIR_PATH = "/kaggle/working/xls-r-300m-chilean-spanish-asr" TRAIN_BATCH_SIZE = 18 EVAL_BATCH_SIZE = 10 TRAIN_EPOCHS = 30 SAVE_STEPS = 3200 EVAL_STEPS = 100 LOGGING_STEPS = 100 LEARNING_RATE = 1e-4 WARMUP_STEPS = 800
Die sechste Zelle definiert Hilfsmethoden zum Lesen der Datensatzindexdateien (siehe den Unterabschnitt Trainingsdatensatz oben) sowie zum Bereinigen des Transkriptionstexts und Erstellen des Vokabulars. Legen Sie die sechste Zelle wie folgt fest:
### CELL 6: Utility methods for reading index files, cleaning text, and creating vocabulary ### def read_index_file_data(path: str, filename: str): data = [] with open(path + filename, "r", encoding = "utf8") as f: lines = f.readlines() for line in lines: file_and_text = line.split("\t") data.append([path + file_and_text[0] + EXT, file_and_text[1].replace("\n", "")]) return data def truncate_training_dataset(dataset: list) -> list: if type(NUM_LOAD_FROM_EACH_SET) == str and "all" == NUM_LOAD_FROM_EACH_SET.lower(): return else: return dataset[:NUM_LOAD_FROM_EACH_SET] def clean_text(text: str) -> str: cleaned_text = re.sub(SPECIAL_CHARS, "", text) cleaned_text = cleaned_text.lower() return cleaned_text def create_vocab(data): vocab_list = [] for index in range(len(data)): text = data[index][1] words = text.split(" ") for word in words: chars = list(word) for char in chars: if char not in vocab_list: vocab_list.append(char) return vocab_list
Die Methode read_index_file_data
liest eine Indexdatei des Datensatzes line_index.tsv
und erstellt eine Liste von Listen mit Audiodateinamen und Transkriptionsdaten, z. B.:
[ ["/kaggle/input/google-spanish-speakers-chile-male/clm_08421_01719502739", "Es un viaje de negocios solamente voy por una noche"] ... ]
truncate_training_dataset
kürzt die Daten einer Listenindexdatei mithilfe der in Schritt 3.5 festgelegten Konstante NUM_LOAD_FROM_EACH_SET
. Insbesondere wird die Konstante NUM_LOAD_FROM_EACH_SET
verwendet, um die Anzahl der Audiobeispiele anzugeben, die aus jedem Datensatz geladen werden sollen. Für die Zwecke dieses Handbuchs wird die Zahl auf 1600
festgelegt, was bedeutet, dass letztendlich insgesamt 3200
Audiobeispiele geladen werden. Um alle Beispiele zu laden, legen Sie NUM_LOAD_FROM_EACH_SET
auf den Zeichenfolgenwert all
fest.clean_text
wird verwendet, um aus jeder Texttranskription die Zeichen zu entfernen, die durch den regulären Ausdruck angegeben wurden, der SPECIAL_CHARS
in Schritt 3.5 zugewiesen wurde. Diese Zeichen, einschließlich der Satzzeichen, können eliminiert werden, da sie beim Trainieren des Modells zum Erlernen von Zuordnungen zwischen Audiomerkmalen und Texttranskriptionen keinen semantischen Wert bieten.create_vocab
erstellt ein Vokabular aus bereinigten Texttranskriptionen. Sie extrahiert einfach alle eindeutigen Zeichen aus dem Satz bereinigter Texttranskriptionen. Ein Beispiel des generierten Vokabulars finden Sie in Schritt 3.14 . Die siebte Zelle definiert Hilfsmethoden, torchaudio
verwenden, um Audiodaten zu laden und neu abzutasten. Legen Sie die siebte Zelle wie folgt fest:
### CELL 7: Utility methods for loading and resampling audio data ### def read_audio_data(file): speech_array, sampling_rate = torchaudio.load(file, normalize = True) return speech_array, sampling_rate def resample(waveform): transform = torchaudio.transforms.Resample(ORIG_SAMPLING_RATE, TGT_SAMPLING_RATE) waveform = transform(waveform) return waveform[0]
read_audio_data
lädt eine angegebene Audiodatei und gibt eine mehrdimensionale torch.Tensor
-Matrix der Audiodaten zusammen mit der Abtastrate des Audios zurück. Alle Audiodateien in den Trainingsdaten haben eine Abtastrate von 48000
Hz. Diese „ursprüngliche“ Abtastrate wird durch die Konstante ORIG_SAMPLING_RATE
in Schritt 3.5 erfasst.resample
Methode wird verwendet, um Audiodaten von einer Abtastrate von 48000
auf 16000
herunterzusampeln. wav2vec2 ist mit Audiodaten vortrainiert, die mit 16000
Hz abgetastet wurden. Dementsprechend muss jedes Audio, das zur Feinabstimmung verwendet wird, dieselbe Abtastrate haben. In diesem Fall müssen die Audiobeispiele von 48000
Hz auf 16000
Hz heruntergesampelt werden. 16000
Hz wird durch die Konstante TGT_SAMPLING_RATE
in Schritt 3.5 erfasst.Die achte Zelle definiert Hilfsmethoden, die die Audio- und Transkriptionsdaten verarbeiten. Legen Sie die achte Zelle wie folgt fest:
### CELL 8: Utility methods to prepare input data for training ### def process_speech_audio(speech_array, sampling_rate): input_values = processor(speech_array, sampling_rate = sampling_rate).input_values return input_values[0] def process_target_text(target_text): with processor.as_target_processor(): encoding = processor(target_text).input_ids return encoding
process_speech_audio
gibt die Eingabewerte aus einer bereitgestellten Trainingsprobe zurück.process_target_text
kodiert jede Texttranskription als eine Liste von Labels, also eine Liste von Indizes, die auf Zeichen im Vokabular verweisen. Eine Beispielkodierung sehen Sie in Schritt 3.15 .Die neunte Zelle ist die letzte Hilfsmethodezelle und enthält die Methode zum Berechnen der Wortfehlerrate zwischen einer Referenztranskription und einer vorhergesagten Transkription. Stellen Sie die neunte Zelle auf:
### CELL 9: Utility method to calculate Word Error Rate def compute_wer(pred): pred_logits = pred.predictions pred_ids = np.argmax(pred_logits, axis = -1) pred.label_ids[pred.label_ids == -100] = processor.tokenizer.pad_token_id pred_str = processor.batch_decode(pred_ids) label_str = processor.batch_decode(pred.label_ids, group_tokens = False) wer = wer_metric.compute(predictions = pred_str, references = label_str) return {"wer": wer}
Die zehnte Zelle liest die Trainingsdatenindexdateien für die Aufnahmen männlicher Sprecher und die Aufnahmen weiblicher Sprecher mithilfe der in Schritt 3.6 definierten Methode read_index_file_data
. Stellen Sie die zehnte Zelle auf:
### CELL 10: Read training data ### training_samples_male_cl = read_index_file_data(TRAINING_DATA_PATH_MALE, "line_index.tsv") training_samples_female_cl = read_index_file_data(TRAINING_DATA_PATH_FEMALE, "line_index.tsv")
Die elfte Zelle kürzt die Trainingsdatenlisten mit der in Schritt 3.6 definierten Methode truncate_training_dataset
. Stellen Sie die elfte Zelle auf:
### CELL 11: Truncate training data ### training_samples_male_cl = truncate_training_dataset(training_samples_male_cl) training_samples_female_cl = truncate_training_dataset(training_samples_female_cl)
NUM_LOAD_FROM_EACH_SET
definiert die Anzahl der Samples, die von jedem Datensatz beibehalten werden sollen. In dieser Anleitung ist die Konstante auf 1600
festgelegt, was insgesamt 3200
Samples ergibt.Die zwölfte Zelle kombiniert die gekürzten Trainingsdatenlisten. Legen Sie die zwölfte Zelle fest auf:
### CELL 12: Combine training samples data ### all_training_samples = training_samples_male_cl + training_samples_female_cl
Die dreizehnte Zelle iteriert über jede Trainingsdatenprobe und bereinigt den zugehörigen Transkriptionstext mithilfe der in Schritt 3.6 definierten Methode clean_text
. Legen Sie die dreizehnte Zelle wie folgt fest:
for index in range(len(all_training_samples)): all_training_samples[index][1] = clean_text(all_training_samples[index][1])
Die vierzehnte Zelle erstellt ein Vokabular unter Verwendung der bereinigten Transkriptionen aus dem vorherigen Schritt und der in Schritt 3.6 definierten Methode create_vocab
. Legen Sie die vierzehnte Zelle fest auf:
### CELL 14: Create vocabulary ### vocab_list = create_vocab(all_training_samples) vocab_dict = {v: i for i, v in enumerate(vocab_list)}
Das Vokabular wird als Wörterbuch mit Zeichen als Schlüssel und Vokabularindizes als Werte gespeichert.
Sie können vocab_dict
ausdrucken, was die folgende Ausgabe erzeugen sollte:
{'l': 0, 'a': 1, 'v': 2, 'i': 3, 'g': 4, 'e': 5, 'n': 6, 'c': 7, 'd': 8, 't': 9, 'u': 10, 'r': 11, 'j': 12, 's': 13, 'o': 14, 'h': 15, 'm': 16, 'q': 17, 'b': 18, 'p': 19, 'y': 20, 'f': 21, 'z': 22, 'á': 23, 'ú': 24, 'í': 25, 'ó': 26, 'é': 27, 'ñ': 28, 'x': 29, 'k': 30, 'w': 31, 'ü': 32}
Die fünfzehnte Zelle fügt dem Vokabular das Worttrennzeichen |
hinzu. Legen Sie die fünfzehnte Zelle wie folgt fest:
### CELL 15: Add word delimiter to vocabulary ### vocab_dict["|"] = len(vocab_dict)
Das Worttrennzeichen wird verwendet, wenn Texttranskriptionen als Liste von Beschriftungen tokenisiert werden. Insbesondere wird es verwendet, um das Ende eines Worts zu definieren, und es wird beim Initialisieren der Klasse Wav2Vec2CTCTokenizer
verwendet, wie in Schritt 3.17 zu sehen ist.
Beispielsweise kodiert die folgende Liste no te entiendo nada
unter Verwendung des Vokabulars aus Schritt 3.14 :
# Encoded text [6, 14, 33, 9, 5, 33, 5, 6, 9, 3, 5, 6, 8, 14, 33, 6, 1, 8, 1] # Vocabulary {'l': 0, 'a': 1, 'v': 2, 'i': 3, 'g': 4, 'e': 5, 'n': 6, 'c': 7, 'd': 8, 't': 9, 'u': 10, 'r': 11, 'j': 12, 's': 13, 'o': 14, 'h': 15, 'm': 16, 'q': 17, 'b': 18, 'p': 19, 'y': 20, 'f': 21, 'z': 22, 'á': 23, 'ú': 24, 'í': 25, 'ó': 26, 'é': 27, 'ñ': 28, 'x': 29, 'k': 30, 'w': 31, 'ü': 32, '|': 33}
Die sechzehnte Zelle überträgt das Vokabular in eine Datei. Stellen Sie die sechzehnte Zelle ein auf:
### CELL 16: Export vocabulary ### with open(VOCAB_FILE_PATH + "vocab.json", "w", encoding = "utf8") as vocab_file: json.dump(vocab_dict, vocab_file)
Wav2Vec2CTCTokenizer
zu initialisieren. Die siebzehnte Zelle initialisiert eine Instanz von Wav2Vec2CTCTokenizer
. Setzen Sie die siebzehnte Zelle auf:
### CELL 17: Initialize tokenizer ### tokenizer = Wav2Vec2CTCTokenizer( VOCAB_FILE_PATH + "vocab.json", unk_token = "[UNK]", pad_token = "[PAD]", word_delimiter_token = "|", replace_word_delimiter_char = " " )
Der Tokenizer wird zum Kodieren von Texttranskriptionen und zum Zurückdekodieren einer Liste von Beschriftungen in Text verwendet.
Beachten Sie, dass der tokenizer
mit [UNK]
initialisiert wird, das unk_token
zugewiesen ist, und [PAD]
das pad_token
zugewiesen ist. Ersteres wird verwendet, um unbekannte Token in Texttranskriptionen darzustellen, und letzteres wird verwendet, um Transkriptionen aufzufüllen, wenn Stapel von Transkriptionen mit unterschiedlichen Längen erstellt werden. Diese beiden Werte werden vom Tokenizer dem Vokabular hinzugefügt.
Durch die Initialisierung des Tokenizers in diesem Schritt werden dem Vokabular auch zwei weitere Token hinzugefügt, nämlich <s>
und /</s>
, die verwendet werden, um den Anfang und das Ende von Sätzen abzugrenzen.
|
wird in diesem Schritt explizit dem word_delimiter_token
zugewiesen, um zu verdeutlichen, dass das Pipe-Symbol verwendet wird, um das Ende von Wörtern entsprechend unserer Hinzufügung des Zeichens zum Vokabular in Schritt 3.15 abzugrenzen. Das Symbol |
ist der Standardwert für word_delimiter_token
. Es musste also nicht explizit festgelegt werden, wurde aber der Übersichtlichkeit halber so festgelegt.
Ähnlich wie bei word_delimiter_token
wird replace_word_delimiter_char
explizit ein einzelnes Leerzeichen zugewiesen, was bedeutet, dass das Pipe-Symbol |
verwendet wird, um Leerzeichen in Texttranskriptionen zu ersetzen. Leerzeichen sind der Standardwert für replace_word_delimiter_char
. Daher musste es auch nicht explizit festgelegt werden, wurde aber der Übersichtlichkeit halber so gemacht.
Sie können das vollständige Vokabular des Tokenizers ausdrucken, indem Sie die Methode get_vocab()
des tokenizer
aufrufen.
vocab = tokenizer.get_vocab() print(vocab) # Output: {'e': 0, 's': 1, 'u': 2, 'n': 3, 'v': 4, 'i': 5, 'a': 6, 'j': 7, 'd': 8, 'g': 9, 'o': 10, 'c': 11, 'l': 12, 'm': 13, 't': 14, 'y': 15, 'p': 16, 'r': 17, 'h': 18, 'ñ': 19, 'ó': 20, 'b': 21, 'q': 22, 'f': 23, 'ú': 24, 'z': 25, 'é': 26, 'í': 27, 'x': 28, 'á': 29, 'w': 30, 'k': 31, 'ü': 32, '|': 33, '<s>': 34, '</s>': 35, '[UNK]': 36, '[PAD]': 37}
Die achtzehnte Zelle initialisiert eine Instanz von Wav2Vec2FeatureExtractor
. Setzen Sie die achtzehnte Zelle auf:
### CELL 18: Initialize feature extractor ### feature_extractor = Wav2Vec2FeatureExtractor( feature_size = 1, sampling_rate = 16000, padding_value = 0.0, do_normalize = True, return_attention_mask = True )
Wav2Vec2FeatureExtractor
übergebenen Parameterwerte sind alle Standardwerte, mit Ausnahme von return_attention_mask
, das standardmäßig auf False
gesetzt ist. Die Standardwerte werden der Übersichtlichkeit halber angezeigt/übergeben.feature_size
gibt die Dimensionsgröße der Eingabefunktionen (d. h. Audiodatenfunktionen) an. Der Standardwert dieses Parameters ist 1
.sampling_rate
teilt dem Feature-Extraktor die Samplingrate mit, mit der die Audiodaten digitalisiert werden sollen. Wie in Schritt 3.7 erläutert, ist wav2vec2 mit Audiodaten mit einer Abtastrate von 16000
Hz vortrainiert, und daher ist 16000
der Standardwert für diesen Parameter.padding_value
gibt den Wert an, der beim Auffüllen von Audiodaten verwendet wird, wie es beim Batching von Audio-Samples unterschiedlicher Länge erforderlich ist. Der Standardwert ist 0.0
.do_normalize
wird verwendet, um anzugeben, ob Eingabedaten in eine Standardnormalverteilung umgewandelt werden sollen. Der Standardwert ist True
. In der Dokumentation der Klasse Wav2Vec2FeatureExtractor
wird darauf hingewiesen, dass „[Normalisierung] dazu beitragen kann, die Leistung einiger Modelle erheblich zu verbessern.“return_attention_mask
gibt an, ob die Aufmerksamkeitsmaske übergeben werden soll oder nicht. Für diesen Anwendungsfall ist der Wert auf True
gesetzt. Die neunzehnte Zelle initialisiert eine Instanz von Wav2Vec2Processor
. Setzen Sie die neunzehnte Zelle auf:
### CELL 19: Initialize processor ### processor = Wav2Vec2Processor(feature_extractor = feature_extractor, tokenizer = tokenizer)
Die Klasse Wav2Vec2Processor
kombiniert tokenizer
und feature_extractor
aus Schritt 3.17 bzw. Schritt 3.18 in einem einzigen Prozessor.
Beachten Sie, dass die Prozessorkonfiguration durch Aufrufen der Methode save_pretrained
der Klasseninstanz Wav2Vec2Processor
gespeichert werden kann.
processor.save_pretrained(OUTPUT_DIR_PATH)
Die zwanzigste Zelle lädt jede Audiodatei, die in der Liste all_training_samples
angegeben ist. Stellen Sie die zwanzigste Zelle auf:
### CELL 20: Load audio data ### all_input_data = [] for index in range(len(all_training_samples)): speech_array, sampling_rate = read_audio_data(all_training_samples[index][0]) all_input_data.append({ "input_values": speech_array, "labels": all_training_samples[index][1] })
torch.Tensor
zurückgegeben und in all_input_data
als Liste von Wörterbüchern gespeichert. Jedes Wörterbuch enthält die Audiodaten für eine bestimmte Probe sowie die Texttranskription des Audios.read_audio_data
auch die Abtastrate der Audiodaten zurückgibt. Da wir wissen, dass die Abtastrate für alle Audiodateien in diesem Anwendungsfall 48000
Hz beträgt, wird die Abtastrate in diesem Schritt ignoriert.all_input_data
in einen Pandas DataFrame Die einundzwanzigste Zelle konvertiert die Liste all_input_data
in einen Pandas DataFrame, um die Datenbearbeitung zu vereinfachen. Legen Sie die einundzwanzigste Zelle wie folgt fest:
### CELL 21: Convert audio training data list to Pandas DataFrame ### all_input_data_df = pd.DataFrame(data = all_input_data)
Die zweiundzwanzigste Zelle verwendet den in Schritt 3.19 initialisierten processor
, um Merkmale aus jeder Audiodatenprobe zu extrahieren und jede Texttranskription als Liste von Beschriftungen zu kodieren. Stellen Sie die zweiundzwanzigste Zelle auf:
### CELL 22: Process audio data and text transcriptions ### all_input_data_df["input_values"] = all_input_data_df["input_values"].apply(lambda x: process_speech_audio(resample(x), 16000)) all_input_data_df["labels"] = all_input_data_df["labels"].apply(lambda x: process_target_text(x))
Die dreiundzwanzigste Zelle teilt den all_input_data_df
DataFrame mithilfe der SPLIT_PCT
Konstante aus Schritt 3.5 in Trainings- und Auswertungsdatensätze (Validierungsdatensätze) auf. Stellen Sie die dreiundzwanzigste Zelle auf:
### CELL 23: Split input data into training and validation datasets ### split = math.floor((NUM_LOAD_FROM_EACH_SET * 2) * SPLIT_PCT) valid_data_df = all_input_data_df.iloc[-split:] train_data_df = all_input_data_df.iloc[:-split]
SPLIT_PCT
Wert beträgt in dieser Anleitung 0.10
was bedeutet, dass 10 % aller Eingabedaten für die Auswertung zurückgehalten werden und 90 % der Daten für das Training/die Feinabstimmung verwendet werden.Dataset
Die vierundzwanzigste Zelle konvertiert die DataFrames train_data_df
und valid_data_df
in Dataset
Objekte. Legen Sie die vierundzwanzigste Zelle wie folgt fest:
### CELL 24: Convert training and validation datasets to Dataset objects ### train_data = Dataset.from_pandas(train_data_df) valid_data = Dataset.from_pandas(valid_data_df)
Dataset
Objekte werden von Instanzen der HuggingFace Trainer
-Klasse verwendet, wie Sie in Schritt 3.30 sehen werden.
Diese Objekte enthalten Metadaten zum Datensatz sowie den Datensatz selbst.
Sie können train_data
und valid_data
ausdrucken, um die Metadaten für beide Dataset
Objekte anzuzeigen.
print(train_data) print(valid_data) # Output: Dataset({ features: ['input_values', 'labels'], num_rows: 2880 }) Dataset({ features: ['input_values', 'labels'], num_rows: 320 })
Die fünfundzwanzigste Zelle initialisiert das vorab trainierte XLS-R-Modell (0,3). Stellen Sie die fünfundzwanzigste Zelle ein auf:
### CELL 25: Initialize pretrained model ### model = Wav2Vec2ForCTC.from_pretrained( MODEL, ctc_loss_reduction = "mean", pad_token_id = processor.tokenizer.pad_token_id, vocab_size = len(processor.tokenizer) )
Wav2Vec2ForCTC
aufgerufene Methode from_pretrained
gibt an, dass wir die vortrainierten Gewichte für das angegebene Modell laden möchten.MODEL
Konstante wurde in Schritt 3.5 angegeben und auf facebook/wav2vec2-xls-r-300m
gesetzt, was das XLS-R-Modell (0.3) widerspiegelt.ctc_loss_reduction
gibt die Art der Reduktion an, die auf die Ausgabe der Verlustfunktion Connectionist Temporal Classification („CTC“) angewendet werden soll. CTC-Verlust wird verwendet, um den Verlust zwischen einer kontinuierlichen Eingabe (in diesem Fall Audiodaten) und einer Zielsequenz (in diesem Fall Texttranskriptionen) zu berechnen. Durch Festlegen des Werts auf mean
werden die Ausgabeverluste für einen Stapel von Eingaben durch die Ziellängen geteilt. Anschließend wird der Mittelwert über den Stapel berechnet und die Reduktion auf die Verlustwerte angewendet.pad_token_id
gibt das Token an, das beim Batching zum Auffüllen verwendet werden soll. Es wird auf die [PAD]
-ID gesetzt, die beim Initialisieren des Tokenizers in Schritt 3.17 festgelegt wurde.vocab_size
definiert die Vokabulargröße des Modells. Dies ist die Vokabulargröße nach der Initialisierung des Tokenizers in Schritt 3.17 und spiegelt die Anzahl der Ausgabeschichtknoten des Vorwärtsteils des Netzwerks wider.Die 26. Zelle friert die vorab trainierten Gewichte des Merkmalsextraktors ein. Stellen Sie die 26. Zelle auf:
### CELL 26: Freeze feature extractor ### model.freeze_feature_extractor()
Die siebenundzwanzigste Zelle initialisiert die Trainingsargumente, die an eine Trainer
übergeben werden. Legen Sie die siebenundzwanzigste Zelle wie folgt fest:
### CELL 27: Set training arguments ### training_args = TrainingArguments( output_dir = OUTPUT_DIR_PATH, save_safetensors = False, group_by_length = True, per_device_train_batch_size = TRAIN_BATCH_SIZE, per_device_eval_batch_size = EVAL_BATCH_SIZE, num_train_epochs = TRAIN_EPOCHS, gradient_checkpointing = True, evaluation_strategy = "steps", save_strategy = "steps", logging_strategy = "steps", eval_steps = EVAL_STEPS, save_steps = SAVE_STEPS, logging_steps = LOGGING_STEPS, learning_rate = LEARNING_RATE, warmup_steps = WARMUP_STEPS )
TrainingArguments
akzeptiert mehr als 100 Parameter .save_safetensors
gibt, wenn er auf False
gesetzt ist, an, dass das fein abgestimmte Modell in einer pickle
-Datei gespeichert werden soll, anstatt das safetensors
Format zu verwenden.group_by_length
gibt bei True
an, dass Beispiele von ungefähr gleicher Länge gruppiert werden sollen. Dies minimiert die Auffüllung und verbessert die Trainingseffizienz.per_device_train_batch_size
legt die Anzahl der Samples pro Trainings-Mini-Batch fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante TRAIN_BATCH_SIZE
auf 18
gesetzt. Dies bedeutet 160 Schritte pro Epoche.per_device_eval_batch_size
legt die Anzahl der Samples pro Auswertungs-Mini-Batch (Holdout) fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante EVAL_BATCH_SIZE
auf 10
gesetzt.num_train_epochs
legt die Anzahl der Trainingsepochen fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante TRAIN_EPOCHS
auf 30
gesetzt. Dies bedeutet insgesamt 4.800 Schritte während des Trainings.gradient_checkpointing
hilft, wenn True
gesetzt ist, Speicher zu sparen, indem er Prüfpunkte für Gradientenberechnungen setzt, führt aber zu langsameren Rückwärtsdurchläufen.evaluation_strategy
auf steps
gesetzt ist, bedeutet dies, dass die Auswertung während des Trainings in den durch den Parameter eval_steps
angegebenen Intervallen durchgeführt und protokolliert wird.logging_strategy
auf steps
gesetzt ist, werden die Statistiken des Trainingslaufs in einem durch den Parameter logging_steps
angegebenen Intervall protokolliert.save_strategy
auf steps
gesetzt ist, bedeutet dies, dass ein Prüfpunkt des feinabgestimmten Modells in einem durch den Parameter save_steps
angegebenen Intervall gespeichert wird.eval_steps
legt die Anzahl der Schritte zwischen den Auswertungen der Holdout-Daten fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante EVAL_STEPS
auf 100
gesetzt.save_steps
legt die Anzahl der Schritte fest, nach denen ein Prüfpunkt des fein abgestimmten Modells gespeichert wird. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante SAVE_STEPS
auf 3200
gesetzt.logging_steps
legt die Anzahl der Schritte zwischen den Protokollen der Trainingslaufstatistiken fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante LOGGING_STEPS
auf 100
gesetzt.learning_rate
legt die anfängliche Lernrate fest. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante LEARNING_RATE
auf 1e-4
gesetzt.warmup_steps
legt die Anzahl der Schritte fest, um die Lernrate linear von 0 auf den durch learning_rate
festgelegten Wert zu erhöhen. Dieser Parameter wird über die in Schritt 3.5 zugewiesene Konstante WARMUP_STEPS
auf 800
gesetzt.Die achtundzwanzigste Zelle definiert die Logik zum dynamischen Auffüllen von Eingabe- und Zielsequenzen. Legen Sie die achtundzwanzigste Zelle wie folgt fest:
### CELL 28: Define data collator logic ### @dataclass class DataCollatorCTCWithPadding: processor: Wav2Vec2Processor padding: Union[bool, str] = True max_length: Optional[int] = None max_length_labels: Optional[int] = None pad_to_multiple_of: Optional[int] = None pad_to_multiple_of_labels: Optional[int] = None def __call__(self, features: List[Dict[str, Union[List[int], torch.Tensor]]]) -> Dict[str, torch.Tensor]: input_features = [{"input_values": feature["input_values"]} for feature in features] label_features = [{"input_ids": feature["labels"]} for feature in features] batch = self.processor.pad( input_features, padding = self.padding, max_length = self.max_length, pad_to_multiple_of = self.pad_to_multiple_of, return_tensors = "pt", ) with self.processor.as_target_processor(): labels_batch = self.processor.pad( label_features, padding = self.padding, max_length = self.max_length_labels, pad_to_multiple_of = self.pad_to_multiple_of_labels, return_tensors = "pt", ) labels = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100) batch["labels"] = labels return batch
Trainer
Instanz übergeben, die in Schritt 3.30 kurzzeitig initialisiert wird. Da die Länge der Eingabesequenzen und Label-Sequenzen in jedem Mini-Batch variiert, müssen einige Sequenzen aufgefüllt werden, damit sie alle die gleiche Länge haben.DataCollatorCTCWithPadding
füllt Mini-Batch-Daten dynamisch auf. Wenn der padding
-Parameter auf True
gesetzt ist, gibt er an, dass kürzere Audioeingabe-Feature-Sequenzen und Label-Sequenzen dieselbe Länge haben sollen wie die längste Sequenz in einem Mini-Batch.0.0
aufgefüllt, der beim Initialisieren des Feature-Extraktors in Schritt 3.18 festgelegt wurde.-100
ersetzt, sodass diese Labels bei der Berechnung der WER-Metrik ignoriert werden.Die neunundzwanzigste Zelle initialisiert eine Instanz des im vorherigen Schritt definierten Datenkollators. Legen Sie die neunundzwanzigste Zelle fest auf:
### CELL 29: Initialize instance of data collator ### data_collator = DataCollatorCTCWithPadding(processor = processor, padding = True)
Die dreißigste Zelle initialisiert eine Instanz der Trainer
-Klasse. Setzen Sie die dreißigste Zelle auf:
### CELL 30: Initialize trainer ### trainer = Trainer( model = model, data_collator = data_collator, args = training_args, compute_metrics = compute_wer, train_dataset = train_data, eval_dataset = valid_data, tokenizer = processor.feature_extractor )
Trainer
-Klasse mit Folgendem initialisiert:model
wurde in Schritt 3.25 initialisiert.train_data
Dataset
Objekt aus Schritt 3.24 .valid_data
Dataset
Objekt aus Schritt 3.24 .tokenizer
Parameter wird processor.feature_extractor
zugewiesen und arbeitet mit data_collator
, um die Eingaben automatisch auf die Eingabe mit der maximalen Länge jedes Mini-Batches aufzufüllen. Die einunddreißigste Zelle ruft die train
der Trainer
-Klasseninstanz auf, um das Modell zu optimieren. Legen Sie die einunddreißigste Zelle wie folgt fest:
### CELL 31: Finetune the model ### trainer.train()
Die zweiunddreißigste Zelle ist die letzte Notebook-Zelle. Sie speichert das fein abgestimmte Modell, indem sie die Methode save_model
für die Trainer
Instanz aufruft. Stellen Sie die zweiunddreißigste Zelle auf:
### CELL 32: Save the finetuned model ### trainer.save_model(OUTPUT_DIR_PATH)
Nachdem nun alle Zellen des Notebooks verbaut sind, geht es ans Feintuning.
Richten Sie das Kaggle-Notebook so ein, dass es mit dem NVIDIA GPU P100- Beschleuniger ausgeführt wird.
Übernehmen Sie das Notebook in Kaggle.
Überwachen Sie die Trainingslaufdaten, indem Sie sich bei Ihrem WandB-Konto anmelden und den zugehörigen Lauf suchen.
Das Training über 30 Epochen sollte mit dem NVIDIA GPU P100-Beschleuniger etwa 5 Stunden dauern. Der WER bei Holdout-Daten sollte am Ende des Trainings auf etwa 0,15 sinken. Dies ist zwar kein hochmodernes Ergebnis, aber das fein abgestimmte Modell ist für viele Anwendungen immer noch ausreichend nützlich.
Das feinabgestimmte Modell wird in das Kaggle-Verzeichnis ausgegeben, das durch die in Schritt 3.5 angegebene Konstante OUTPUT_DIR_PATH
angegeben wird. Die Modellausgabe sollte die folgenden Dateien enthalten:
pytorch_model.bin config.json preprocessor_config.json vocab.json training_args.bin
Diese Dateien können lokal heruntergeladen werden. Darüber hinaus können Sie mit den Modelldateien ein neues Kaggle-Modell erstellen. Das Kaggle-Modell wird zusammen mit dem begleitenden Inferenzhandbuch verwendet, um Inferenzen auf dem fein abgestimmten Modell auszuführen.
Herzlichen Glückwunsch zur Feinabstimmung von wav2vec2 XLS-R! Denken Sie daran, dass Sie diese allgemeinen Schritte verwenden können, um das Modell in anderen gewünschten Sprachen zu optimieren. Die Ausführung von Inferenzen auf dem in diesem Handbuch generierten, feinabgestimmten Modell ist ziemlich unkompliziert. Die Inferenzschritte werden in einem separaten Begleithandbuch zu diesem beschrieben. Bitte suchen Sie nach meinem HackerNoon-Benutzernamen, um das Begleithandbuch zu finden.