[PYTHON] [PyTorch] Verwendung von BERT - Feinabstimmung japanischer vorab trainierter Modelle zur Lösung von Klassifizierungsproblemen

Einführung

Leute, die PyTorch verwenden, möchten die PyTorch-Version verwenden, aber da wir die PyTorch-Version nicht erstellt haben, verwenden Sie die von HuggingFace, aber wir entwickeln Bitten Sie sie um weitere Informationen, da sie nicht beteiligt sind! Und QA.

BERT von HuggingFace, aber bis Dezember 2019 gab es keine vorgefertigten japanischen Modelle. Daher konnte ich es leicht auf Englisch versuchen, aber auf Japanisch musste ich selbst vorgefertigte Modelle vorbereiten. Im Dezember 2019 wurden jedoch endlich japanische vorgefertigte Modelle hinzugefügt. https://huggingface.co/transformers/pretrained_models.html

  1. bert-base-japanese
  2. bert-base-japanese-whole-word-masking
  3. bert-base-japanese-char
  4. bert-base-japanese-char-whole-word-masking

In Erstellt vom Inui Laboratory der Tohoku University können vier Modelle verwendet werden. Sofern keine besonderen Umstände vorliegen, ist es besser, die zweite "Bert-Base-Japanisch-Ganzwort-Maskierung" zu verwenden. In der normalen Version und der Whole Word Masking-Version scheint die Whole Word Masking-Version tendenziell eine etwas höhere Genauigkeit für fein abgestimmte Aufgaben zu haben [^ 1].

Dies macht es einfach, die PyTorch-Version von BERT auf Japanisch auszuprobieren.

Was ist BERT?

Der Mechanismus von BERT wurde bereits in verschiedenen Blogs und Büchern eingeführt, daher werde ich auf eine ausführliche Erklärung verzichten. Einfach gesagt

--Erstellen Sie vorgefertigte Modelle aus einer großen Anzahl unbeaufsichtigter Korpora

Es wird der Ablauf der Verarbeitung sein. Das Erstellen vorgefertigter Modelle erfordert viel Computerressourcen und Zeit, aber einer der Punkte von BERT ist, dass es die Genauigkeit von Aufgaben verbessern kann.

Japanische vorgefertigte Modelle

Überprüfen Sie zunächst die Genauigkeit der vorab trainierten japanischen vorab trainierten Modelle. Dieses Mal werden wir die Genauigkeit des maskierten Sprachmodells überprüfen. Eine einfache Erklärung des maskierten Sprachmodells besteht darin, ein Wort in einem Satz zu maskieren und das maskierte Wort vorherzusagen.

Mit BertJapaneseTokenizer und BertForMaskedLM können Sie schreiben: Sagen Sie das Wort voraus, indem Sie "Fußball" im Satz "Sehen Sie sich ein Fußballspiel im Fernsehen an" maskieren.

import torch
from transformers import BertJapaneseTokenizer, BertForMaskedLM

# Load pre-trained tokenizer
tokenizer = BertJapaneseTokenizer.from_pretrained('bert-base-japanese-whole-word-masking')

# Tokenize input
text = 'Sehen Sie sich ein Fußballspiel im Fernsehen an.'
tokenized_text = tokenizer.tokenize(text)
# ['Fernsehgerät', 'damit', 'Fußball', 'von', 'Spiel', 'Zu', 'sehen', '。']

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 2
tokenized_text[masked_index] = '[MASK]'
# ['Fernsehgerät', 'damit', '[MASK]', 'von', 'Spiel', 'Zu', 'sehen', '。']

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)
# [571, 12, 4, 5, 608, 11, 2867, 8]

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])
# tensor([[ 571,   12,    4,    5,  608,   11, 2867,    8]])

# Load pre-trained model
model = BertForMaskedLM.from_pretrained('bert-base-japanese-whole-word-masking')
model.eval()

# Predict
with torch.no_grad():
    outputs = model(tokens_tensor)
    predictions = outputs[0][0, masked_index].topk(5) #Extrahieren Sie die Top 5 Vorhersageergebnisse

# Show results
for i, index_t in enumerate(predictions.indices):
    index = index_t.item()
    token = tokenizer.convert_ids_to_tokens([index])[0]
    print(i, token)

Das Ausführungsergebnis des obigen Programms ist wie folgt. "Fußball" ist auf dem 3. Platz erschienen, und andere Wörter sind wahrscheinlich als Japanisch korrekt. Es wird angenommen, dass der Grund, warum "Cricket" und die Teamnamen der wichtigsten Ligen, die in Japan nicht so bekannt sind, auftauchen, darin besteht, dass sie im Voraus aus den Daten von Wikipedia gelernt haben.

0 Cricket
1 Tiger
2 Fußball
3 Mets
4 Jungen

Aus dem Obigen wurde bestätigt, dass die vorab trainierten Modelle korrekt vorab trainiert wurden. Als nächstes können Sie die Aufgabe anhand dieser vorab trainierten Modelle optimieren und lösen.

Fine tuning with BERT

Der Quellcode wurde geändert, um mit japanischen Originaldaten zu arbeiten

GitHub of HuggingFace enthält einige Beispiele für die Feinabstimmung zur Lösung von Aufgaben. Diese gelten jedoch für englische Datensätze und keine für japanische Datensätze [^ 2].

Daher werden wir den vorhandenen Quellcode so ändern, dass er mit den ursprünglichen japanischen Daten funktioniert. Unter der Annahme, dass die Textklassifizierung eine grundlegende Aufgabe bei der Verarbeitung natürlicher Sprache darstellt, wird der für die GLUE-Textklassifizierung verwendete Quellcode als Ziel ausgewählt. Und

  1. transformers/data/processors/glue.py
  2. transformers/data/metrics/__init__.py

Ändern Sie zwei Programme.

Hinweis Beachten Sie, dass dies keine Datei ist, die von git clone usw. heruntergeladen wurde, sondern dass Sie die Datei im Installationsverzeichnis ändern müssen. Wenn Sie beispielsweise venv verwenden, lautet das Installationsverzeichnis "[venv-Verzeichnis] / lib / python3.7 / site-packages / transformers".

  1. transformers/data/processors/glue.py Dies ist der Teil, der die Trainingsdaten (train.tsv) und Verifizierungsdaten (dev.tsv) liest. Fügen Sie die Aufgabe "original" zu "glue_tasks_num_labels", "glue_processors", "glue_output_modes" hinzu und fügen Sie dann die Klasse "OriginalProcessor" wie folgt hinzu:
glue_tasks_num_labels = {
    "cola": 2,
    "mnli": 3,
    "mrpc": 2,
    "sst-2": 2,
    "sts-b": 1,
    "qqp": 2,
    "qnli": 2,
    "rte": 2,
    "wnli": 2,
    "original": 2, #hinzufügen
}

glue_processors = {
    "cola": ColaProcessor,
    "mnli": MnliProcessor,
    "mnli-mm": MnliMismatchedProcessor,
    "mrpc": MrpcProcessor,
    "sst-2": Sst2Processor,
    "sts-b": StsbProcessor,
    "qqp": QqpProcessor,
    "qnli": QnliProcessor,
    "rte": RteProcessor,
    "wnli": WnliProcessor,
    "original": OriginalProcessor, #hinzufügen
}

glue_output_modes = {
    "cola": "classification",
    "mnli": "classification",
    "mnli-mm": "classification",
    "mrpc": "classification",
    "sst-2": "classification",
    "sts-b": "regression",
    "qqp": "classification",
    "qnli": "classification",
    "rte": "classification",
    "wnli": "classification",
    "original": "classification", #hinzufügen
}
class OriginalProcessor(DataProcessor):
    """Processor for the original data set."""

    def get_example_from_tensor_dict(self, tensor_dict):
        """See base class."""
        return InputExample(
            tensor_dict["idx"].numpy(),
            tensor_dict["sentence"].numpy().decode("utf-8"),
            None,
            str(tensor_dict["label"].numpy()),
        )

    def get_train_examples(self, data_dir):
        """See base class."""
        return self._create_examples(self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")
 
    def get_dev_examples(self, data_dir):
        """See base class."""
        return self._create_examples(self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")
 
    def get_labels(self):
        """See base class."""
        return ["0", "1"]

    def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            #Kommentar entfernen, wenn die TSV-Datei eine Kopfzeile enthält
            # if i == 0:
            #     continue
            guid = "%s-%s" % (set_type, i)
            text_a = line[0]
            label = line[1]
            examples.append(InputExample(guid=guid, text_a=text_a, text_b=None, label=label))
        return examples

Trainingsdaten und Verifizierungsdaten

  1. Text
  2. Beschriften

Ich gehe von einer TSV-Datei aus, die aus zwei Spalten besteht.

train.tsv


Es war interessant 0
Es hat Spaß gemacht 0
War langweilig 1
Ich war traurig 1

dev.tsv


Genossen 0
Es war schmerzhaft 1

Das obige Programm setzt eine binäre Klassifizierung voraus. Bei einer mehrwertigen Klassifizierung ändern Sie bitte die Anzahl und den Wert der Beschriftungen entsprechend.

  1. transformers/data/metrics/__init__.py Dies ist der Teil, der die Genauigkeit anhand der Verifizierungsdaten berechnet. Fügen Sie einfach den Fall von task_name ==" original " wie folgt in den bedingten Ausdruck ein:
    def glue_compute_metrics(task_name, preds, labels):
        assert len(preds) == len(labels)
        if task_name == "cola":
            return {"mcc": matthews_corrcoef(labels, preds)}
        elif task_name == "sst-2":
            return {"acc": simple_accuracy(preds, labels)}
        elif task_name == "mrpc":
            return acc_and_f1(preds, labels)
        elif task_name == "sts-b":
            return pearson_and_spearman(preds, labels)
        elif task_name == "qqp":
            return acc_and_f1(preds, labels)
        elif task_name == "mnli":
            return {"acc": simple_accuracy(preds, labels)}
        elif task_name == "mnli-mm":
            return {"acc": simple_accuracy(preds, labels)}
        elif task_name == "qnli":
            return {"acc": simple_accuracy(preds, labels)}
        elif task_name == "rte":
            return {"acc": simple_accuracy(preds, labels)}
        elif task_name == "wnli":
            return {"acc": simple_accuracy(preds, labels)}
        #hinzufügen
        elif task_name == "original":
            return {"acc": simple_accuracy(preds, labels)}
        else:
            raise KeyError(task_name)

Feinabstimmung zur Lösung des Klassifizierungsproblems

Nachdem die Originaldaten auf Japanisch funktionieren, müssen Sie nur noch die Feinabstimmung vornehmen und das Klassifizierungsproblem lösen. Es wird nur der folgende Befehl ausgeführt: Fügen Sie die Trainingsdaten- und Verifizierungsdatendateien unter "data / original /" ein.

$ python examples/run_glue.py \
    --data_dir=data/original/ \
    --model_type=bert \
    --model_name_or_path=bert-base-japanese-whole-word-masking \
    --task_name=original \
    --do_train \
    --do_eval \
    --output_dir=output/original

Wenn Sie den obigen Befehl ausführen und problemlos beenden, wird das folgende Protokoll ausgegeben. Der Wert von acc ist "1.0", und Sie können sehen, dass die beiden Verifizierungsdaten korrekt klassifiziert werden können.

01/18/2020 17:08:39 - INFO - __main__ -   Saving features into cached file data/original/cached_dev_bert-base-japanese-whole-word-masking_128_original
01/18/2020 17:08:39 - INFO - __main__ -   ***** Running evaluation  *****
01/18/2020 17:08:39 - INFO - __main__ -     Num examples = 2
01/18/2020 17:08:39 - INFO - __main__ -     Batch size = 8
Evaluating: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00,  2.59it/s]
01/18/2020 17:08:40 - INFO - __main__ -   ***** Eval results  *****
01/18/2020 17:08:40 - INFO - __main__ -     acc = 1.0

Und Sie können sehen, dass die Modelldatei unter "output / original /" erstellt wird.

$ find output/original 
output/original
output/original/added_tokens.json
output/original/tokenizer_config.json
output/original/special_tokens_map.json
output/original/config.json
output/original/training_args.bin
output/original/vocab.txt
output/original/pytorch_model.bin
output/original/eval_results.txt

abschließend

Ich habe eingeführt, wie japanische Texte mit der PyTorch-Version von BERT klassifiziert werden. Durch Ändern anderer Quellcodes können Sie Aufgaben wie Texterzeugung und Beantwortung von Fragen sowie Textklassifizierung ausführen.

Bisher hatte das Ausführen von BERT auf Japanisch mit PyTorch eine hohe Hürde, aber ich denke, dass die Hürde mit der Veröffentlichung von vorab trainierten Modellen auf Japanisch sehr niedrig geworden ist. Probieren Sie auf jeden Fall die PyTorch-Version von BERT mit japanischen Aufgaben aus.

Referenzartikel

https://techlife.cookpad.com/entry/2018/12/04/093000 http://kento1109.hatenablog.com/entry/2019/08/23/092944

Recommended Posts

[PyTorch] Verwendung von BERT - Feinabstimmung japanischer vorab trainierter Modelle zur Lösung von Klassifizierungsproblemen
[PyTorch] Einführung in die Klassifizierung japanischer Dokumente mit BERT
[Erklärung zur Implementierung] Verwendung der japanischen Version von BERT in Google Colaboratory (PyTorch)
[PyTorch] Einführung in die Dokumentklassifizierung mit BERT
Verwendung von Japanisch mit NLTK-Plot
Grundlagen von PyTorch (1) - Verwendung von Tensor-
Ich habe versucht, Satzklassifizierung und Aufmerksamkeitsvisualisierung durch das japanische BERT mit PyTorch zu implementieren
Verwendung von xgboost: Mehrklassenklassifizierung mit Irisdaten
Verwendung des japanischen Spacy-Modells mit Google Colaboratory
Verwendung von xml.etree.ElementTree
Wie benutzt man Python-Shell
Hinweise zur Verwendung von tf.data
Verwendung von virtualenv
Wie benutzt man Seaboan?
Verwendung von Image-Match
Wie man Shogun benutzt
Verwendung von Virtualenv
Verwendung von numpy.vectorize
Verwendung von pytest_report_header
Wie man teilweise verwendet
Wie man Bio.Phylo benutzt
Verwendung von SymPy
Wie man x-means benutzt
Verwendung von WikiExtractor.py
Verwendung von virtualenv
Wie benutzt man Matplotlib?
Verwendung von iptables
Wie benutzt man numpy?
Verwendung von TokyoTechFes2015
Wie benutzt man venv
Verwendung des Wörterbuchs {}
Wie benutzt man Pyenv?
Verwendung der Liste []
Wie man Python-Kabusapi benutzt
Verwendung von OptParse
Verwendung von return
Wie man Imutils benutzt
13. Offline-Echtzeit So lösen Sie Schreibprobleme mit Python