Dieser Beitrag ist der Artikel zum 25. Tag des Adventskalenders 2019 - Qiita zur Verarbeitung natürlicher Sprache.
Es ist siny.
In diesem Artikel haben wir die Erstellung eines negativ-positiven Klassifikators mit BERT zusammengefasst, der ab 2019 eine wichtige Rolle bei der Verarbeitung natürlicher Sprache spielt.
Ich denke, dass das Wissen über BERT in Büchern, Blogs, Qiita usw. weit verbreitet ist. Die meisten Datensätze, die für die Verarbeitung natürlicher Sprache verwendet werden können, basieren jedoch auf Englisch, und es gibt nicht viele japanische Datensätze. Daher gibt es nur wenige Fälle und Informationen zur Verwendung von BERT mit japanischem Text. fühlte.
Derzeit denke ich, dass die folgenden wichtigen japanischen Datensätze kostenlos verwendet werden können.
Als ich nach "** Gibt es einen Datensatz mit einer bestimmten Datenmenge und japanischen Textdaten, die kostenlos verwendet werden können? **" suchte, chABSA-Datensatz Ich fand einen japanischen Datensatz (ungefähr 2800 Daten) namens chakki-works / chABSA-Datensatz.
chABSA-Datensatz ist ein japanischer Datensatz, der auf der Grundlage der Wertpapierberichte börsennotierter Unternehmen erstellt wurde. Jeder Satz enthält nicht nur eine negative / positive emotionale Klassifizierung, sondern auch Informationen, die die Perspektive von "was" negativ / positiv ausdrücken. Das Folgende sind Beispieldaten von ** chABSA-Datensatz **.
{
"header": {
"document_id": "E00008",
"document_name": "Hokuto Co., Ltd.",
"doc_text": "Wertpapierbericht",
"edi_id": "E00008",
"security_code": "13790",
"category33": "Fischerei / Land- und Forstwirtschaft",
"category17": "Essen",
"scale": "6"
},
"sentences": [
{
"sentence_id": 0,
"sentence": "Im laufenden konsolidierten Geschäftsjahr wird die japanische Wirtschaft aufgrund der Wirtschaftspolitik der Regierung und der geldpolitischen Lockerungsmaßnahmen der Bank of Japan ihre Unternehmensleistung und ihr Beschäftigungs- / Einkommensumfeld verbessern....",
"opinions": [
{
"target": "Japanische Wirtschaft",
"category": "NULL#general",
"polarity": "neutral",
"from": 11,
"to": 16
},
{
"target": "Unternehmensleistung",
"category": "NULL#general",
"polarity": "positive",
"from": 38,
"to": 42
},...
],
},
{
"sentence_id": 1,
"sentence": "Das Umfeld rund um den Konzern ist so, dass die Reallöhne zwar schleppend sind, die Verbraucher jedoch...",
"opinions": [
{
"target": "Reallohn",
"category": "NULL#general",
"polarity": "negative",
"from": 15,
"to": 19
},...
]
},...
]
}
Mit ** ch ABSA-Datensatz ** gibt es Tausende von Daten und Werte, die Emotionen ausdrücken, sodass sie für die negativ-positive Klassifizierung verwendet werden können? “Also habe ich mit diesem Datensatz einen BERT-negativ-positiven Klassifizierer erstellt. Ich versuchte es.
Der gesamte in diesem Artikel erläuterte Implementierungscode befindet sich auf Github. Klonen Sie ihn daher bitte entsprechend. Darüber hinaus wird jeder Prozess in ** BERT-Modellerstellung-Lerninferenz.ipynb ** auf Github beschrieben. Bitte beziehen Sie sich daher entsprechend darauf.
「chABSA-dataset」(https://github.com/sinjorjob/chABSA-dataset)
In diesem Artikel erstellen wir einen negativ-positiven Klassifikator, der auf den folgenden Annahmen basiert.
Artikel | Bedeutung |
---|---|
OS | Ubuntu |
BERT-Modell | Herausgegeben von der Kyoto Universitypytorch-pretrained-BERT-ModellDie Feinabstimmung erfolgt basierend auf. |
Morphologische Analyse | Juman++ (v2.0.0-rc2) or (v2.0.0-rc3) |
Bibliothek | Pytorch |
Erstellen Sie mit PyTorch eine Umgebung, in der Sie das BERT Japanese Pretrained-Modell verwenden können.
conda create -n pytorch python=3.6
conda activate pytorch
conda install pytorch=0.4 torchvision -c pytorch
conda install pytorch=0.4 torchvision cudatoolkit -c pytorch
conda install pandas jupyter matplotlib scipy scikit-learn pillow tqdm cython
pip install torchtext
pip install mojimoji
pip install attrdict
pip install pyknp
Das diesmal verwendete BERT Japanese Pretrained-Modell verwendet Human ++ (v2.0.0-rc2) für die morphologische Analyse des Eingabetextes. Daher entspricht dieser Artikel auch dem morphologischen Analysewerkzeug ** Human ++ **. Die Vorgehensweise zur Installation von Juman ++ ist in einem separaten Artikel zusammengefasst. Weitere Informationen finden Sie im Folgenden.
[** Zusammenfassung der JUMAN ++ - Installationsprozedur **] https://sinyblog.com/deaplearning/juman/
Das BERT Japanese Pretrained-Modell kann von der folgenden URL heruntergeladen werden.
[BERT Japanese Pretrained model] http://nlp.ist.i.kyoto-u.ac.jp/index.php?BERT%E6%97%A5%E6%9C%AC%E8%AA%9EPretrained%E3 % 83% A2% E3% 83% 87% E3% 83% AB
Laden Sie ** Japanese_L-12_H-768_A-12_E-30_BPE .zip ** von "** Japanese_L-12_H-768_A-12_E-30_BPE.zip (1.6G) ****" auf den oben genannten HP herunter. Wenn Sie die Zip-Datei entpacken, sind einige Dateien enthalten, diesmal benötigen Sie jedoch die folgenden drei.
Artikel | Bedeutung |
---|---|
bert_config.json | Konfigurationsdatei für das BERT-Modell |
pytorch_model.bin | Pytorch Version BERT(pytorch-pretrained-BERT)Konvertiertes Modell für |
vocab.txt | BERT Glossar Wörterbuchdaten |
Die gesamte Verzeichnisstruktur ist wie folgt.
├─data
│ └─chABSA #chABSA json-Datei
│ └─test.tsv #Testdaten
│ └─train.tsv #Trainingsdaten
│ └─test_dumy.tsv #Dummy-Daten
│ └─train_dumy.tsv #Dummy-Daten
├─utils
│ └─bert.py #BERT-Modelldefinition
│ └─config.py #Definition verschiedener Pfade
│ └─dataloader.py #Für die Datenladergenerierung
│ └─predict.py #Zum Nachdenken
│ └─predict.py #Zum Nachdenken
│ └─tokenizer.py #Zur morphologischen Analyse
│ └─train.py #Zum Lernen
├─vocab #Bert Lexikon Wörterbuch Gesang.txt
└─weights # bert_config.json、pytorch_model.bin
└─Create_data_from_chABSA.ipynb #tsv Datenerstellung
└─BERT Modellbildung-Lernen~Inferenz.ipynb #Erstellung des Datenladers~Lernen~Inferenz
pytorch_model.bin(pytorch-pretrained-BERT) bert_fine_tuning_chABSA_22epoch.pth (Negative / Positive Learned Parameter File)
Es ist ein schematisches Diagramm des BERT-Modells der negativen / positiven Klassifizierung, das dieses Mal implementiert werden soll.
Das obige BERT-Modell basiert auf dem Quellcode des Buches "** Learn while make! Development Deep Learning von PyTorch **". In diesem Artikel werden die Details des BERT-Modells nicht erläutert. Wenn Sie interessiert sind, lesen Sie bitte das Buch.
Um nur die Punkte zu erklären, basiert der BERT-Quellcode selbst auf huggingface / transformers und ** alle für eine negativ-positive Klassifizierung am Ende des BERT-Modells. Eine Verbindungsschicht (linear **) wird hinzugefügt, und das Modell gibt 2 Klassenklassifikationen ** [negativ (0) oder positiv (1)] ** als Ausgabe aus. Verwenden Sie zur Klassifizierung die Merkmalsmenge des ersten Wortes [CLS] ** der eingegebenen Textdaten.
chABSA-Datensatz Der Datensatz enthält 230 Datendateien im JSON-Format, aber der negative / positive Klassifikator verwendet BERT Es kann nicht als Trainingsdaten verwendet werden.
Eine JSON-Datei enthält mehrere Textdaten und die folgenden Informationen.
Artikel | Bedeutung |
---|---|
sentence_id | ID, die die Daten eindeutig identifiziert |
sentence | Satzdaten |
opinions | Einige Optionen sind {Ziel,category,porarity,from,Es sind mehrere Sätze von to} enthalten. |
target | Das Schlüsselwort wird im Satz für das Ziel angegeben |
category | Brancheninformationen |
polarity | Ist das Ziel-Keyword positiv oder negativ? |
from, to | Von welchem Zeichen zu welchem Zeichen existiert das Schlüsselwort des Ziels im Satz? |
Erstellen Sie aus diesen JSON-Dateien ein tsv-Dataset, das wie folgt für das Training verwendet werden kann. Jede Zeile hat das Format "Eingabetext 0 (negativ) oder 1 (positiv)".
Auf der anderen Seite bleiben die Aussichten aufgrund von Risiken wie der wirtschaftlichen Abkühlung der chinesischen Wirtschaft, dem politischen Management der neuen US-Regierung und dem Austritt Großbritanniens aus der EU ungewiss.
Im Kosmetik- und sonstigen Warengeschäft stärken wir die Filialentwicklung durch große Filialen und arbeiten daran, Kunden durch digitale Verkaufsförderung zu gewinnen und Kunden durch Veranstaltungen mit einem Umsatz von 3.262 Millionen Yen (15 gegenüber dem Vorjahr) zu steigern..5% Abnahme) 0
Darüber hinaus nahmen die Wartungsverträge mit einem Umsatz von 6 stetig zu,952 Millionen Yen (1-Jahres-Vergleich).2% mehr) 1
In Bezug auf den Gewinn beträgt der Segmentgewinn (Betriebsgewinn) 1 aufgrund einer Zunahme der Ersatzarbeiten und der Sicherung eines stabilen Gewinns durch Wartungsverträge.,687 Millionen Yen (2 im Vergleich zum Vorjahreszeitraum).4% mehr) 1
In anderen Segmenten entwickelten sich Fahrradparksysteme mit einem Umsatz von 721 Millionen Yen (0 gegenüber dem Vorjahr) stetig..8% mehr) 1
Führen Sie zum Erstellen der Daten den Code ** Create_data_from_chABSA.ipynb ** im Jupyter-Notizbuch aus.
Durch Befolgen der Schritte werden Trainingsdaten (train.tsv) mit 1970 Sätzen und Testdaten (test.tsv) mit 843 Daten erstellt.
Wir haben die BertTokenizer-Klasse für wortaufteilende Eingabesätze in ** utils \ bert.py ** implementiert. Dieses Mal werden wir den japanischen Datensatz verwenden, aber [BERT Japanese Pretrained model](http://nlp.ist.i.kyoto-u.ac.jp/index.php?BERT%E6%97%A5% E6% 9C% AC% E8% AA% 9EPretrainiert% E3% 83% A2% E3% 83% 87% E3% 83% AB) Führen Sie eine morphologische Analyse mit Human ++ gemäß den Spezifikationen durch.
Außerdem [link](http://nlp.ist.i.kyoto-u.ac.jp/index.php?BERT%E6%97%A5%E6%9C%AC%E8%AA%9EPretrained%E3 % 83% A2% E3% 83% 87% E3% 83% AB) Wie beschrieben, sind die folgenden Punkte für Japanisch angepasst.
Setzen Sie die Option ** --do_lower_case ** in der BertTokenizer-Klasse in bert.py auf ** False **.
Class BertTokenizer(object):
#Implementierte Klasse zur Aufteilung von Satzwörtern für BERT
def __init__(self, vocab_file, do_lower_case=False): #In False geändert (anders als im englischen Modell)
Kommentieren Sie Folgendes in der BasicTokenizer-Klasse von tokenizer.py aus
#text = self._tokenize_chinese_chars(text) #Alle Kanji werden in einer Zeicheneinheit sein, also kommentieren Sie aus
** HumanTokenize-Klasse ** zur morphologischen Analyse mit Human ++ zu tokenizer.py hinzugefügt.
from pyknp import Juman
class JumanTokenize(object):
"""Runs JumanTokenizer."""
def __init__(self):
self.juman = Juman()
def tokenize(self, text):
result = self.juman.analysis(text)
return [mrph.midasi for mrph in result.mrph_list()]
Wenn Sie die obige HumanTokenizer-Klasse verwenden, wird der Eingabetext von Human ++ wie folgt morphologisch analysiert.
cd chABSA-dataset
python
>>>from utils.tokenizer import JumanTokenize
>>>from pyknp import Juman
>>>text = "Das ordentliche Einkommen verringerte sich gegenüber dem Vorjahr um 818 Millionen Yen, hauptsächlich aufgrund eines Rückgangs der Erträge aus dem Fondsmanagement wie etwa Zinsen für Kredite 2,Es war 27.811 Millionen Yen"
>>>juman = JumanTokenize()
>>>print(juman.tokenize(text))
['gewöhnliche', 'Einnahmen', 'Ist', '、', 'Ausleihe', 'Geld', 'Interesse', 'Eine solche', '資Geld', 'Operation', 'Einnahmen', 'von', 'Verringern', 'Zu', 'Hauptgrund', 'Zu', ' 、', 'Bisherige', 'Jahr', 'Verhältnis', '818 Millionen', 'Kreis', 'Verringern', 'Shi', '2,27.811 Millionen', 'Kreis', 'Wann', 'Nari', 'まShiた']
>>>
Erstellen Sie einen DataLoader mit torchtext, um Daten für Training und Test zu generieren. Dieses Mal wird die Funktion zum Erstellen des DataLoder "** get_chABSA_DataLoaders_and_TEXT **" in ** dataloder.py ** erstellt. Verwenden Sie diese Funktion.
** get_chABSA_DataLoaders_and_TEXT ** Der Rückgabewert der Funktion lautet wie folgt.
Artikel | Bedeutung |
---|---|
train_dl | Trainingsdatensatz |
val_dl | Validierungsdatensatz |
TEXT | torchtext.data.field.Feldobjekt |
dataloaders_dict | Iteratorwörterbuchdaten für Trainings- und Verifizierungsdaten**※1** |
** * 1 ** dataloaders_dict wird zum Lernen und Überprüfen verwendet.
Wenn Sie sich nicht sicher sind, wie Sie torchtext verwenden sollen, lesen Sie bitte den folgenden Artikel. Pytorch-Textvorverarbeitung (torchtext) [für Anfänger]
Unten finden Sie den Code, der den Dataloader generiert.
from utils.dataloader import get_chABSA_DataLoaders_and_TEXT
from utils.bert import BertTokenizer
train_dl, val_dl, TEXT, dataloaders_dict= get_chABSA_DataLoaders_and_TEXT(max_length=256, batch_size=32)
Nehmen wir die Daten aus den generierten Trainingsdaten (train_dl) und überprüfen den Inhalt.
#Funktionsprüfung Prüfen Sie anhand des Verifizierungsdatensatzes
batch = next(iter(train_dl))
print("Textform=", batch.Text[0].shape)
print("Etikettenform=", batch.Label.shape)
print(batch.Text)
print(batch.Label)
Wie unten gezeigt, werden Textdaten (maximale Länge 256) für die Stapelgröße (32 Stück) in Text (Eingabedaten) generiert. Die Eingabedaten sind numerische Listendaten, die durch Konvertieren der Wortliste in eine ID erhalten werden. Label enthält das korrekte Antwort-Label 0 (negativ) oder 1 (positiv) für den entsprechenden Satz.
Textform= torch.Size([32, 256])
Etikettenform= torch.Size([32])
(tensor([[ 2, 3718, 534, ..., 0, 0, 0],
[ 2, 17249, 442, ..., 0, 0, 0],
[ 2, 719, 3700, ..., 0, 0, 0],
...,
[ 2, 719, 3700, ..., 0, 0, 0],
[ 2, 64, 6, ..., 0, 0, 0],
[ 2, 1, 3962, ..., 0, 0, 0]]), tensor([68, 48, 31, 30, 33, 89, 55, 49, 53, 29, 61, 44, 21, 69, 51, 48, 30, 32,
54, 31, 39, 28, 27, 24, 24, 48, 21, 86, 39, 51, 71, 42]))
tensor([0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
1, 1, 0, 1, 0, 1, 0, 0])
Nehmen Sie für alle Fälle einen Satz aus dem Mini-Batch und übergeben Sie die digitalisierten Listendaten an die ** ids_to_tokens ** -Methode von ** tokenizer_bert **, um den ursprünglichen Satz (Wort) wiederherzustellen.
#Überprüfen Sie den ersten Satz der Mini-Charge
tokenizer_bert = BertTokenizer(vocab_file="./vocab/vocab.txt", do_lower_case=False)
text_minibatch_1 = (batch.Text[0][1]).numpy()
#ID zum Wort zurückgeben
text = tokenizer_bert.convert_ids_to_tokens(text_minibatch_1)
print(text)
['[CLS]', 'Der Umsatz', 'Profitieren', 'Ist', '、', 'Komplett', 'Konstruktion', 'Gesamt', 'Profitieren', 'Bewertung', 'Aber', 'Verbesserung', 'tat', 'Ding', 'Von', '、', 'Bisherige', 'Verknüpfen', 'Buchhaltung', 'Jahr', 'Verhältnis', '[UNK]', '.', '[UNK]', '%', 'Erhöhen, ansteigen', 'von', '[UNK]', 'Kreis', '(', 'Bisherige', 'Verknüpfen', 'Buchhaltung', 'Jahr', 'Ist', '[UNK]', 'Kreis', ')', 'Wann', 'wurde', '[SEP]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]', '[PAD]']
Der Anfang des Satzes ist ** [CLS] **, das Ende ist ** [SEP] **, das unbekannte Wort ist ** [UNK] ** und der Teil mit weniger als 256 Zeichen ist mit ** [PAD] ** aufgefüllt. Ich werde.
Bisher haben wir die Erstellung des Datensatzes und des tatsächlich generierten Mini-Batches bestätigt.
Als nächstes werden wir das negativ-positive Klassifizierungsmodell von BERT implementieren.
Das folgende BERT-Modell, das dieses Mal implementiert werden soll, ist in ** utils \ bert.py ** als ** BertModel-Klasse ** definiert. Verwenden Sie diese Klasse also, um das Modell zu generieren.
Verwenden Sie die folgenden Dateien, um das Modell zu erstellen.
Artikel | Erläuterung |
---|---|
bert_config.json | BERT-Modellparameterdatei |
pytorch_model.bin | Geschultes BERT-Modell |
Erstellen Sie zunächst ein Basis-BERT-Modell, indem Sie die Konfigurationseinstellungsdatei als Argument in der ** BertModel-Klasse ** angeben, und lernen Sie dann mit der in ** bert.py ** definierten ** set_learned_params ** -Methode. Stellen Sie die Parameter des fertigen BERT-Modells ein (** pytorch_model.bin **). Nachdem Sie ein negativ-positives Klassifizierungsmodell mit der ** BertForchABSA-Klasse ** erstellt haben, versetzen Sie es mit ** net.train () ** in den Lernmodus.
Der Code zum Generieren des Modells ist unten.
from utils.bert import get_config, BertModel,BertForchABSA, set_learned_params
#Lesen Sie die JOSN-Datei mit den Modelleinstellungen als Objektvariable
config = get_config(file_path="./weights/bert_config.json")
#Generieren Sie ein Basis-BERT-Modell
net_bert = BertModel(config)
#Geschulter Parametersatz für das BERT-Modell
net_bert = set_learned_params(
net_bert, weights_path="./weights/pytorch_model.bin")
#Generieren Sie ein negatives / positives BERT-Klassifizierungsmodell(Vollständig verbundene Schicht zur negativ-positiven Klassifizierung am Ende des Modells (linear))Hinzufügen)
net = BertForchABSA(net_bert)
#Auf Trainingsmodus einstellen
net.train()
In BERT's Originalarbeit sind alle 12-stufigen BertLayer-Ebenen (Self-Attention) fein abgestimmt, diesmal jedoch nur die letzte 1 Ebene + negativ-positiver Klassifikator Ist das Thema des Lernens.
#Führen Sie die Gradientenberechnung nur für das letzte BertLayer-Modul und den hinzugefügten Klassifizierungsadapter durch
# 1.Für die Gesamtgradientenberechnung auf Falsch setzen
for name, param in net.named_parameters():
param.requires_grad = False
# 2.Es wurde nur das letzte BertLayer-Modul geändert, um eine Gradientenberechnung zu erhalten
for name, param in net.bert.encoder.layer[-1].named_parameters():
param.requires_grad = True
# 3.Der Klassifikator (negativ oder positiv) wurde geändert, um eine Gradientenberechnung durchzuführen
for name, param in net.cls.named_parameters():
param.requires_grad = True
Geben Sie als Nächstes den Optimierer und die Verlustfunktion an, die für das Training verwendet werden sollen.
Sowohl die letzte Schicht von BertLayer (Self-Attention) als auch der Diskriminator verwenden die Klasse ** Torch.optim.Adam **. Die Lernrate (lr) beträgt ** 5e-e ** und Betas ist der Standardwert ** (0,9, 0,999) ** (die Werte in den Nachschlagewerken werden unverändert verwendet).
Und da es sich diesmal um eine Zwei-Klassen-Klassifizierung von negativ oder positiv handelt, wird ** torch.nn.CrossEntropyLoss ** als Kriterium angegeben.
#Der ursprüngliche Teil von BERT ist die Feinabstimmung
optimizer = optim.Adam([
{'params': net.bert.encoder.layer[-1].parameters(), 'lr': 5e-5},
{'params': net.cls.parameters(), 'lr': 5e-5}
], betas=(0.9, 0.999))
#Einstellungen der Verlustfunktion
criterion = nn.CrossEntropyLoss()
# nn.LogSoftmax()Nach der Berechnung von nn.NLLLoss(negative log likelihood loss)Berechnung
Als nächstes werden wir lernen und verifizieren. utls.py\train.pyに定義されている学習&検証用の関数train_modelを使って学習と検証を行います。 Verwenden Sie ** train.tsv (1970) ** für das Training und ** test.tsv (843) ** für die Validierung.
Das Erlernen in einer CPU-Umgebung erfordert einige Zeit. Wir empfehlen daher die Verwendung einer GPU-Umgebung wie Google Coraboratory.
#Führen Sie das Lernen / Verifizieren durch
from utils.train import train_model
#Führen Sie das Lernen / Verifizieren durch.
num_epochs = 1 #Bitte ändern Sie die Anzahl der Epochen entsprechend.
net_trained = train_model(net, dataloaders_dict,
criterion, optimizer, num_epochs=num_epochs)
#Speichern Sie die gelernten Netzwerkparameter(Dieses Mal wird der Dateiname unter der Annahme beschrieben, dass das Ergebnis der 22. Epoche gespeichert wird.
save_path = './weights/bert_fine_tuning_chABSA_22epoch.pth'
torch.save(net_trained.state_dict(), save_path)
Die Argumente von ** train_model ** lauten wie folgt.
Artikel | Erläuterung |
---|---|
net | BERT negatives / positives Klassifizierungsmodell |
dataloaders_dict | Iterator zum Lernen und Verifizieren |
criterion | Verlustfunktion |
optimizer | Optimierer |
num_epochs | Anzahl der Epochen |
Bei der Ausführung wird die richtige Antwortrate für jeweils 10 Iterationen und Lost and Acc für jede Epoche wie unten gezeigt angezeigt.
Verwendetes Gerät: CPU
-----start-------
Iteration 10|| Loss: 0.6958 || 10iter: 294.9368 sec. ||Richtige Antwortrate dieser Iteration: 0.46875
Iteration 20|| Loss: 0.7392 || 10iter: 288.1598 sec. ||Richtige Antwortrate dieser Iteration: 0.4375
Iteration 30|| Loss: 0.6995 || 10iter: 232.9404 sec. ||Richtige Antwortrate dieser Iteration: 0.53125
Iteration 40|| Loss: 0.5975 || 10iter: 244.0613 sec. ||Richtige Antwortrate dieser Iteration: 0.6875
Iteration 50|| Loss: 0.5678 || 10iter: 243.3908 sec. ||Richtige Antwortrate dieser Iteration: 0.71875
Iteration 60|| Loss: 0.5512 || 10iter: 269.5538 sec. ||Richtige Antwortrate dieser Iteration: 0.6875
Epoch 1/1 | train | Loss: 0.6560 Acc: 0.5975
Epoch 1/1 | val | Loss: 0.5591 Acc: 0.7711
Dieses Mal habe ich den MAX der Epochenzahl auf 50 gesetzt und die Genauigkeit mit den folgenden 3 Mustern verglichen.
--BertLayer (Selbstaufmerksamkeit) ** Nur die letzte Ebene ** Feinabstimmung --BertLayer (Selbstaufmerksamkeit) ** Nur die beiden hinteren Schichten ** Feinabstimmung
Die Ergebnisse sind wie folgt.
Das Folgende ist eine Zusammenfassung der Bewertung.
――In diesem Modell hatte die Erhöhung der Anzahl der Feinabstimmungsziele fast keinen Einfluss auf die Verbesserung der Genauigkeit. ――Die Genauigkeit erreicht ungefähr 86%, wenn Sie sie um etwa 5 Epochen drehen, und selbst wenn Sie die Anzahl der Epochen danach erhöhen, steigt die Genauigkeit nicht signifikant an. ――Wenn es 20 Epochen überschreitet, wird das Überlernen bemerkenswert.
Am Ende war die korrekte Antwortrate MAX (** 87,76% **), wenn nur die letzte Schicht von BertLayer fein abgestimmt und ** 22epoch ** gedreht wurde.
Geben Sie unter Verwendung des erlernten BERT-Negativ / Positiv-Klassifizierungsmodells einen Beispielsatz an, um den negativen / positiven Vorhersagewert und die Aufmerksamkeit (welches Wort wurde hervorgehoben?) Zu visualisieren.
Um das TEXT-Objekt (torchtext.data.field.Field) zu verwenden, das zum Zeitpunkt der Inferenz von torchtext generiert wurde, sichern Sie das TEXT-Objekt vorübergehend in der pkl-Datei.
from utils.predict create_vocab_text
TEXT = create_vocab_text()
Wenn der obige Code ausgeführt wird, wird text.pkl unter \ chABSA-dataset \ data generiert.
Die Methode create_vocab_text ist in Predict.py definiert. Dummy-Daten (train_dumy.tsv, test_dumy.tsv) und BERT-Glossardaten (vocab.txt) unter \ chABSA-dataset \ data werden verwendet, um ein TEXT-Objekt zu generieren und dann mit pickle auszugeben.
def create_vocab_text():
TEXT = torchtext.data.Field(sequential=True, tokenize=tokenizer_with_preprocessing, use_vocab=True,
lower=False, include_lengths=True, batch_first=True, fix_length=max_length, init_token="[CLS]", eos_token="[SEP]", pad_token='[PAD]', unk_token='[UNK]')
LABEL = torchtext.data.Field(sequential=False, use_vocab=False)
train_val_ds, test_ds = torchtext.data.TabularDataset.splits(
path=DATA_PATH, train='train_dumy.tsv',
test='test_dumy.tsv', format='tsv',
fields=[('Text', TEXT), ('Label', LABEL)])
vocab_bert, ids_to_tokens_bert = load_vocab(vocab_file=VOCAB_FILE)
TEXT.build_vocab(train_val_ds, min_freq=1)
TEXT.vocab.stoi = vocab_bert
pickle_dump(TEXT, PKL_FILE)
return TEXT
Da die Methode zum Erstellen des trainierten Modells (** build_bert_model ) und der Inferenz ( vorhersagen **) in ** utils \ predigen.py ** definiert ist, verwenden Sie diese, um den Beispieltext einzugeben. Visualisierung des vorhergesagten Werts und der Aufmerksamkeit. Achtung verwendet IPython, um HTML zu visualisieren.
from utils.config import *
from utils.predict import predict, build_bert_model
from IPython.display import HTML, display
input_text = "Infolgedessen ist der Umsatz im laufenden konsolidierten Geschäftsjahr 1,785 Millionen Yen(Rückgang gegenüber dem Vorjahreszeitraum um 357 Millionen Yen, 16.7% Rückgang)Betriebsverlust 117 Millionen Yen(Der Rückgang um 174 Millionen Yen gegenüber dem Vorjahreszeitraum und das Betriebsergebnis um 57 Millionen Yen gegenüber dem Vorjahreszeitraum)Gewöhnlicher Verlust 112 Millionen Yen(183 Millionen Yen weniger als im gleichen Zeitraum des Vorjahres, ordentliches Einkommen 71 Millionen Yen im gleichen Zeitraum des Vorjahres), Nettoverlust der Eigentümer der Muttergesellschaft 58 Millionen Yen(116 Millionen Yen weniger als im gleichen Zeitraum des Vorjahres, Nettogewinn der Eigentümer der Muttergesellschaft 57 Millionen Yen)ist geworden"
net_trained = build_bert_model()
html_output = predict(input_text, net_trained)
print("======================Anzeige der Inferenzergebnisse======================")
print(input_text)
display(HTML(html_output))
Wenn ich den obigen Code ausführe, erhalte ich das folgende Ergebnis.
Es macht automatisch Rückschlüsse unter Verwendung einer großen Menge von Testdaten und zeigt die Informationen der ** gemischten Matrix ** an, um das Ergebnis auszuwerten.
Importieren Sie zunächst die erforderlichen Module.
from utils.config import *
from utils.predict import predict2, create_vocab_text, build_bert_model
import pandas as pd
import numpy as np
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
Gemischte Matrizen werden mit ** sklearn ** angezeigt. Wir haben auch eine Methode Predict2 in Utils \ Predict.py hinzugefügt, die nur die vorhergesagten Werte (Preds) zurückgibt.
def predict2(input_text, net_trained):
TEXT = pickle_load(PKL_FILE) #Laden von Vokabeldaten
input = conver_to_model_format(input_text, TEXT)
input_pad = 1 #In der Wort-ID'<pad>':Weil es 1 ist
input_mask = (input != input_pad)
outputs, attention_probs = net_trained(input, token_type_ids=None, attention_mask=None,
output_all_encoded_layers=False, attention_show_flg=True)
_, preds = torch.max(outputs, 1) #Etikett vorhersagen
#html_output = mk_html(input, preds, attention_probs, TEXT) #HTML-Erstellung
return preds
Die einzugebenden Daten sind ** test.csv file ** und die folgenden Daten werden vorbereitet.
Lesen Sie als nächstes die obige test.csv mit Pandas, geben Sie dem trainierten BERT-Modell nacheinander die Sätze der Spalte ** INPUT **, treffen Sie eine negative / positive Beurteilung und speichern Sie das Vorhersageergebnis in der Spalte ** PREDICT **. .. Speichern Sie es nach der Verarbeitung bis zum Ende als ** prognostizierte_test.csv **.
df = pd.read_csv("test.csv", engine="python", encoding="utf-8-sig")
net_trained.eval() #Im Inferenzmodus.
for index, row in df.iterrows():
df.at[index, "PREDICT"] = predict(row['INPUT'], net_trained).numpy()[0] #Im Fall einer GPU-Umgebung ".cpu().numpy()Bitte.
df.to_csv("predicted_test .csv", encoding="utf-8-sig", index=False)
Predicted_test.csv mit den folgenden hinzugefügten Vorhersageergebnissen wird generiert.
Schließlich werden die gemischten Matrixinformationen aus dem Ergebnis dieser CSV-Datei angezeigt.
#Anzeige (Auswertung) der gemischten Matrix
y_true =[]
y_pred =[]
df = pd.read_csv("predicted_test .csv", engine="python", encoding="utf-8-sig")
for index, row in df.iterrows():
if row['LABEL'] == 0:
y_true.append("negative")
if row['LABEL'] ==1:
y_true.append("positive")
if row['PREDICT'] ==0:
y_pred.append("negative")
if row['PREDICT'] ==1:
y_pred.append("positive")
print(len(y_true))
print(len(y_pred))
#Verwirrte Matrix(confusion matrix)Erhalten
labels = ["negative", "positive"]
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_true, y_pred, labels=labels)
#In Datenrahmen konvertieren
cm_labeled = pd.DataFrame(cm, columns=labels, index=labels)
#Ergebnisse anzeigen
cm_labeled
Eine gemischte Matrix ähnlich der folgenden wird angezeigt.
Die Ansicht ist, dass das Negative und das Positive auf der linken Seite die Beschriftungen der tatsächlichen Daten sind und das Negative und das Positive in vertikaler Richtung die vorhergesagten Werte sind. Zum Beispiel repräsentiert die Zahl "** 62 **" die Anzahl der negativen Daten, die fälschlicherweise als positiv vorhergesagt wurden.
Als nächstes werden die richtige Antwortrate, Präzisionsrate, Rückrufrate und der F-Wert mit dem folgenden Code angezeigt.
y_true =[]
y_pred =[]
df = pd.read_csv("predicted_test .csv", engine="python", encoding="utf-8-sig")
for index, row in df.iterrows():
y_true.append(row["LABEL"])
y_pred.append(row["PREDICT"])
print("Richtige Antwortrate (Verhältnis der richtigen Antworten aus allen Stichproben)={}%".format((round(accuracy_score(y_true, y_pred),2)) *100 ))
print("Anpassungsrate (Wahrscheinlichkeit, positiv zu sein, was als positiv vorhergesagt wurde)={}%".format((round(precision_score(y_true, y_pred),2)) *100 ))
print("Rückrufrate (Wahrscheinlichkeit für positive Daten als positiv vorausgesagt)={}%".format((round(recall_score(y_true, y_pred),2)) *100 ))
print("F1 (harmonischer Durchschnitt von Präzision und Rückruf)={}%".format((round(f1_score(y_true, y_pred),2)) *100 ))
#Ausführungsergebnis
Richtige Antwortrate (Verhältnis der richtigen Antworten aus allen Stichproben)=76.0%
Anpassungsrate (Wahrscheinlichkeit, positiv zu sein, was als positiv vorhergesagt wurde)=85.0%
Rückrufrate (Wahrscheinlichkeit für positive Daten als positiv vorausgesagt)=71.0%
F1 (harmonischer Durchschnitt von Präzision und Rückruf)=78.0%
Dieses Mal haben wir eine vollständig verbundene Schicht (linear) hinzugefügt, die basierend auf dem BERT-Modell Negativ und Positiv beurteilt und zu einer binären Klassifizierung gemacht hat. Es scheint jedoch, dass sie auf verschiedene Aufgaben wie die mehrwertige Klassifizierung und die Anwendung auf die Qualitätssicherung angewendet werden kann. Ich möchte in Zukunft herausfordern. ** * Hinzugefügt am 25.12.2019 ** Wenn Sie daran interessiert sind, das Django REST-Framework mithilfe des in diesem Artikel erstellten BERT-Negativ / Positiv-Klassifikators zu implementieren, ** "Django-Adventskalender 2019 - Qiita-Artikel zum 20. Tag" Siehe / items / 30e10a3db76c6f7c5b4d) **.
Recommended Posts