[PYTHON] Lassen Sie das japanische BERT-Modell den Zentraltest und die Satzgenerierung durchführen

1. Zuallererst

Beim letzten Mal habe ich ** Feinabstimmung der negativen / positiven Beurteilungsaufgabe ** mit dem vorab trainierten Modell von BERT versucht, aber es gibt keine Feinabstimmung. Aber natürlich funktioniert es.

Dieses Mal werde ich ** vorgeübtes japanisches BERT-Modell ** ausprobieren, wie es auf Google Colab ist.

2. Setup

Das Einrichtungsverfahren ist wie folgt. Den Code finden Sie in Google Colab (am Ende befindet sich ein Link).

** 1) Modulinstallation ** Installieren Sie die erforderlichen Module (** pyknp, Transformatoren **).

** 2) Installation einer morphologischen Analysebibliothek ** [** "Japanisches morphologisches Analysesystem JUMMAN ++" **](http://nlp.ist.i.kyoto-u.ac.jp/ index.php? JUMAN ++) wird verwendet.

** 3) Laden Sie das vorab trainierte japanische BERT-Modell herunter ** ** "BERT Japanese Pretrained Model" **, bereitgestellt von der Kyoto University / Kurohashi / Kaoru / Murawaki Laboratory .php (BERT Japanese Pretrained model) wird verwendet.

3. Kann BERT Prüfungsfragen im Zentrum lösen?

Dieses Modell wurde mit ** Japanese Wikipedia ** vorgelernt. Das bedeutet ** Ich studiere verschiedene Kenntnisse des Ostens und des Westens in Form der Lösung des Problems des Ausfüllens **, also werde ich so tun, als ob ich in der Lage sein könnte, die ** Frage des Ausfüllens der Prüfung des Hochschulzugangsprüfungszentrums ** zu lösen **. Ich habe mich dazu entschlossen. Das Thema ist Problem 9 der Weltgeschichte B im Jahr 2018. スクリーンショット 2020-08-06 12.55.39.png Die richtige Antwort lautet noble "edel" und "caesar", aber wie antwortet BERT?

import torch
from transformers import BertTokenizer, BertForMaskedLM, BertConfig
import numpy as np
import textwrap
config = BertConfig.from_json_file('./bert/Japanese_L-12_H-768_A-12_E-30_BPE_transformers/config.json')
model = BertForMaskedLM.from_pretrained('./bert/Japanese_L-12_H-768_A-12_E-30_BPE_transformers/pytorch_model.bin', config=config)
bert_tokenizer = BertTokenizer('./bert/Japanese_L-12_H-768_A-12_E-30_BPE_transformers/vocab.txt',
 do_lower_case=False, do_basic_tokenize=False)
from pyknp import Juman
jumanpp = Juman()

Importieren Sie zunächst die erforderlichen Bibliotheken und konfigurieren Sie BERT.

Setzen Sie bei der Eingabe in BERT [CLS] an den Anfang der Wortliste, setzen Sie [SEP] an das Satztrennzeichen und ersetzen Sie das Wort, das Sie vorhersagen möchten, durch [MASK]. Definieren Sie daher eine Funktion, um dies zu tun. Ich werde.

#Zur Wortliste[CLS],[SEP],[MASK]Funktion zum Hinzufügen
def preparation(tokenized_text):
    
    # [CLS],[SEP]Einfügen
    tokenized_text.insert(0, '[CLS]')  #Am Anfang der Wortliste[CLS]Anfügen
    tokenized_text.append('[SEP]')  #Am Ende der Wortliste[SEP]Anfügen
        
    maru = []
    for i, word in enumerate(tokenized_text):
        if word =='。' and i !=len(tokenized_text)-2:  #Positionserkennung von "."
            maru.append(i)

    for i, loc in enumerate(maru):
        tokenized_text.insert(loc+1+i, '[SEP]')  #Neben "." In der Wortliste[SEP]Einführen
        
    #"□"[MASK]Ersetzen mit
    mask_index = []
    for index, word in enumerate(tokenized_text):
        if word =='□':  #Positionserkennung von "□"
            tokenized_text[index] = '[MASK]'
            mask_index.append(index)
    
    return tokenized_text, mask_index  

Die Funktion fügt [CLS] am Anfang der Wortliste ein, hängt [SEP] am Ende an und fügt [SEP] nach "." In der Mitte ein. Nachdem Sie die Wortposition auf diese Weise festgelegt haben, ersetzen Sie den vorhergesagten Teil "□" durch [MASK] und geben Sie die Wortliste und die [MASK] -Position zurück.

Konvertieren Sie dann den Text in einen ID-Tensor.

#Konvertieren Sie Text in ID-Tensor
text = "In seinem Buch "Geschichte" lobt der griechische Polyubios das römisch-republikanische Staatssystem (politisches System) als ausgezeichnet. Ihm zufolge hat das nationale System ein königliches Element namens Konsul, ein □ Systemelement namens Senat und ein demokratisches Element namens Volk, und diese drei Parteien kooperieren und halten sich gegenseitig zurück und gleichen sich aus. Es wird gesagt, dass es tut. Die Römer sind stolz auf dieses politische System, das sich aus dem Namen "Römischer Senat und Volk" ableiten lässt, um sich auf ihre Nation zu beziehen. Sogar □, der am Ende der republikanischen Regierung den Bürgerkrieg gewonnen zu haben schien, wurde wegen des Verdachts, dieses System zu brechen, ermordet."
result = jumanpp.analysis(text)  #Teilen
tokenized_text = [mrph.midasi for mrph in result.mrph_list()]  #In Wortliste konvertieren
tokenized_text, mask_index = preparation(tokenized_text)  # [CLS],[SEP],[MASK]Hinzufügen
tokens = bert_tokenizer.convert_tokens_to_ids(tokenized_text)  #In ID-Liste konvertieren
tokens_tensor = torch.tensor([tokens])  #In ID-Tensor konvertieren

Verwandeln Sie den Text in eine Wortliste, fügen Sie mit der vorherigen Funktion [CLS], [SEP], [MASK] hinzu, konvertieren Sie ihn in eine ID-Liste und konvertieren Sie ihn in einen ID-Tensor, den Pytorch lesen kann.

スクリーンショット 2020-08-06 18.47.49.png Konvertiere es so.

Schliessen Sie nun den Teil [MASK] ab (Top 5 Kandidaten).

# [MASK]Leiten Sie den Ort ab(TOP5)
model.eval() 
tokens_tensor = tokens_tensor.to('cuda')
model.to('cuda')
print(textwrap.fill(text, 45))
print()

with torch.no_grad():
  outputs = model(tokens_tensor)
  predictions = outputs[0]
  
  for i in range(len(mask_index)):
     _, predicted_indexes = torch.topk(predictions[0, mask_index[i]], k=5)
     predicted_tokens = bert_tokenizer.convert_ids_to_tokens(predicted_indexes.tolist())
     print(i, predicted_tokens)

スクリーンショット 2020-08-06 15.35.16.png

Es war unvernünftig, aber die erste Vorhersage beinhaltete das richtige ** "edle" **! Leider konnte ich den zweiten "Caesar" nicht richtig beantworten, aber BERT wird es besser machen als ich erwartet hatte.

4. Kann BERT Sätze generieren?

BERT, das nur im Voraus gelernt hat, hat nur ** die Frage ausfüllen ** und ** die Verbindung zweier Sätze ** gelernt, so dass es nicht für die Satzgenerierung geeignet ist, wie es ist. Es gibt jedoch nichts, was im Prinzip nicht getan werden kann.

Wenn Sie einen bestimmten Text vorbereiten, multiplizieren Sie das erste Wort mit [MASK], um eine Vorhersage zu erstellen, ersetzen Sie das erste Wort durch das Vorhersageergebnis und multiplizieren Sie das nächste Wort mit [MASK], um eine Vorhersage zu erstellen, die dem Text ähnlich ist. Sie sollten in der Lage sein, eine neue Anweisung zu generieren.

Machen wir das. Das Thema ist "Rede von Präsident Kennedy, in der er seine Unterstützung für das Apollo-Projekt zum Ausdruck bringt". スクリーンショット 2020-08-06 13.28.39.png

#Morphologische Analyse
text = "Wir beschlossen, innerhalb von 10 Jahren zum Mond zu gehen, nicht weil es einfach war. Es ist ziemlich schwierig. Dieses Ziel wird uns helfen, das Beste aus unserer Energie und unseren Fähigkeiten zusammenzubringen und zu sehen, wie viel sie sind. Diese Herausforderung wollen wir annehmen und nicht aufschieben. Und das wollen wir gewinnen, und nicht nur wir."
result = jumanpp.analysis(text)  #Teilen
tokenized_text = [mrph.midasi for mrph in result.mrph_list()]  #In Wortliste konvertieren
tokenized_text, mask_index = preparation(tokenized_text)  # [CLS],[SEP]Hinzufügen
tokens = bert_tokenizer.convert_tokens_to_ids(tokenized_text)  #In ID-Liste konvertieren
tokens_tensor = torch.tensor([tokens])  #In ID-Tensor konvertieren

Verwandeln Sie den Text wie zuvor in eine Wortliste, fügen Sie mit der definierten Funktion [CLS], [SEP] hinzu, konvertieren Sie ihn in eine ID-Liste und konvertieren Sie ihn in einen ID-Tensor, den Pytorch lesen kann.

Da wir viele Male Wortvorhersagen machen, definieren wir eine Funktion, die ein Wort vorhersagt.

#1 Wort Vorhersagefunktion
def predict_one(tokens_tensor, mask_index):

    model.eval()    
    tokens_tensor = tokens_tensor.to('cuda')
    model.to('cuda')
 
    with torch.no_grad():
      outputs = model(tokens_tensor)
      predictions = outputs[0]
 
      _, predicted_indexes = torch.topk(predictions[0, mask_index], k=5)
      predicted_tokens = bert_tokenizer.convert_ids_to_tokens(predicted_indexes.tolist())
    return predicted_tokens, predicted_indexes.tolist()

Eine Funktion, die ein mit [MASK] multipliziertes Wort vorhersagt und das vorhergesagte Wort und die ID zurückgibt.

Schreiben Sie dann den Code, um den Satz zu generieren.

#Anweisungserstellung
for i in range(1,len(tokens_tensor[0])):
    tmp = torch.tensor(tokens_tensor)  # tokens_Kopieren Sie den Tensor nach tmp
    tmp[0, i]=4  #ich th[mask]Umschreiben an
    predicted_tokens, predicted_indexes =predict_one(tmp, i)  # [mask]Vorhersagen
    if predicted_indexes !=1:  #Die Vorhersage ist[UNK]Andernfalls
      tokens_tensor[0, i] = predicted_indexes[0]  #Vorhersage-ID[0]Zweite Token_I-ten Tensor überschreiben

target_list = tokens_tensor.tolist()[0]  
predict_list = bert_tokenizer.convert_ids_to_tokens(target_list)  
predict_sentence = ''.join(predict_list[1:])

print('------ original_text -------')
print(textwrap.fill(text,45))
print('------ predict_text -------')
print(textwrap.fill(predict_sentence,45))  

Kopieren Sie tokens_tensor einmal nach tmp, multiplizieren Sie tmp nacheinander mit [MASK] und überschreiben Sie den entsprechenden Teil von tokens_tensor mit dem Ergebnis der Vorhersage. Nun, wenn du das tust,

スクリーンショット 2020-08-06 15.37.18.png

Obwohl das Original sagte: "Lass uns innerhalb von 10 Jahren zum Mond gehen", lautete die Satzgeneration "sollte innerhalb eines Jahres ins Ausland gehen", und sie wurde klein (lacht). Der Inhalt des Satzes ist etwas unklar. Die Satzgenerierung scheint nur mit dem Vorlernen nicht sehr gut zu funktionieren.

Der gesamte Code wurde in Google Colab erstellt und auf Github veröffentlicht. Wenn Sie ihn also selbst ausprobieren möchten, klicken Sie auf diesen ** "Link" **. Klicken Sie auf BERT_pretrained_model.ipynb) und klicken Sie oben auf dem angezeigten Blatt auf die Schaltfläche ** "Colab on Web" **, um es zu verschieben.

(Referenz) ・ Ich habe versucht, anhand des japanischen BERT-Modells zu erraten, was ich für ein Weihnachtsgeschenk wollteVerwenden Sie JUMAN ++ mit Colab

Recommended Posts

Lassen Sie das japanische BERT-Modell den Zentraltest und die Satzgenerierung durchführen
Ich habe den Code für die japanische Satzgenerierung mit DeZero geschrieben
[Version 2020] Lassen Sie Python alle Steuer- und Take-Home-Berechnungen durchführen
[PyTorch] Japanische Satzgenerierung mit Transformer
Ich habe versucht, die Genauigkeit der japanischen BERT- und der japanischen Distil-BERT-Satzklassifizierung mit PyTorch & Einführung der BERT-Technik zur Verbesserung der Genauigkeit zu vergleichen