[PYTHON] [PyTorch] Comment utiliser BERT - Réglage fin des modèles pré-entraînés japonais pour résoudre les problèmes de classification

introduction

BERT met à jour SOTA pour diverses tâches de traitement du langage naturel, mais celle publiée par la famille principale de Google sur Github est basée sur Tensorflow Il est mis en œuvre. Les personnes qui utilisent PyTorch veulent utiliser la version PyTorch, mais comme nous n'avons pas fait la version PyTorch, utilisez celle faite par HuggingFace, mais nous développons Demandez-leur plus d'informations car ils ne sont pas impliqués! Et QA.

BERT fabriqué par HuggingFace, mais il n'y avait pas de modèles pré-entraînés japonais avant décembre 2019. Par conséquent, je pouvais facilement l'essayer en anglais, mais en japonais, je devais préparer moi-même des modèles pré-entraînés. Cependant, en décembre 2019, des modèles pré-entraînés japonais ont finalement été ajoutés. 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

Quatre modèles peuvent être utilisés dans Créé par le laboratoire Inui de l'Université de Tohoku. Sauf circonstances particulières, il est préférable d'utiliser le deuxième "bert-base-japanese-whole-word-masking". Dans la version normale et la version Whole Word Masking, la version Whole Word Masking semble avoir tendance à avoir une précision légèrement supérieure des tâches affinées [^ 1].

Cela permet d'essayer facilement la version PyTorch de BERT en japonais.

Qu'est-ce que BERT?

Le mécanisme de BERT a déjà été introduit dans divers blogs et livres, je vais donc omettre une explication détaillée. Tout simplement

--Créer des modèles pré-entraînés à partir d'un grand nombre de corpus non supervisés

Ce sera le flux du traitement. La création de modèles pré-entraînés nécessite beaucoup de ressources informatiques et de temps, mais l'un des points forts de BERT est qu'il peut améliorer la précision des tâches.

Modèles pré-formés japonais

Tout d'abord, vérifiez l'exactitude des modèles pré-entraînés japonais pré-entraînés. Cette fois, nous vérifierons l'exactitude du modèle de langage masqué. Une explication simple du modèle de langage masqué consiste à masquer un mot dans une phrase et à prédire le mot masqué.

En utilisant BertJapaneseTokenizer et BertForMaskedLM, vous pouvez écrire: Prédisez le mot en masquant «football» dans la phrase «regarder un match de football à la télévision».

import torch
from transformers import BertJapaneseTokenizer, BertForMaskedLM

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

# Tokenize input
text = 'Regardez un match de football à la télévision.'
tokenized_text = tokenizer.tokenize(text)
# ['poste de télévision', 'alors', 'Football', 'de', 'rencontre', 'À', 'à voir', '。']

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 2
tokenized_text[masked_index] = '[MASK]'
# ['poste de télévision', 'alors', '[MASK]', 'de', 'rencontre', 'À', 'à voir', '。']

# 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) #Extraire les 5 meilleurs résultats de prédiction

# 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)

Le résultat de l'exécution du programme ci-dessus est le suivant. "Soccer" est apparu à la 3e place, et d'autres mots sont probablement corrects en japonais. On pense que la raison pour laquelle les noms des équipes de "cricket" et des ligues majeures, qui ne sont pas si familiers au Japon, apparaissent est parce qu'ils ont appris à l'avance des données de Wikipedia.

0 cricket
1 tigres
2 football
3 mets
4 petits

D'après ce qui précède, il a été confirmé que les modèles pré-entraînés étaient correctement pré-formés. Ensuite, affinez et résolvez la tâche en fonction de ces modèles pré-entraînés.

Fine tuning with BERT

Modification du code source pour fonctionner avec les données d'origine japonaises

Hugging Face GitHub a quelques exemples de réglages fins pour résoudre des tâches. Cependant, il s'agit des ensembles de données anglais et aucun ne concerne les ensembles de données japonais [^ 2].

Par conséquent, nous modifierons le code source existant afin qu'il fonctionne avec les données japonaises d'origine. En supposant la classification de texte, qui est une tâche de base dans le traitement du langage naturel, le code source utilisé pour la classification de texte GLUE est ciblé. Et

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

Modifiez les deux programmes dans.

Mise en garde Notez que ce n'est pas un fichier téléchargé par git clone etc., mais vous devez changer le fichier dans le répertoire d'installation. Par exemple, si vous utilisez venv, le répertoire d'installation sera [répertoire venv] / lib / python3.7 / site-packages / transformers.

  1. transformers/data/processors/glue.py C'est la partie qui lit les données d'entraînement (train.tsv) et les données de vérification (dev.tsv). Ajoutez la tâche ʻoriginal à glue_tasks_num_labels, glue_processors, glue_output_modes, puis ajoutez la classe ʻOriginalProcessor comme suit:
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, #ajouter à
}

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, #ajouter à
}

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", #ajouter à
}
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):
            #Décommenter si le fichier TSV a une ligne d'en-tête
            # 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

Données de formation et données de vérification

  1. Texte
  2. Étiquette

Je suppose un fichier TSV composé de deux colonnes.

train.tsv


C'était intéressant 0
C'était amusant 0
Était ennuyeux 1
J'étais triste 1

dev.tsv


Apprécié 0
C'était douloureux 1

Le programme ci-dessus suppose une classification binaire, mais en cas de classification à valeurs multiples, veuillez modifier le nombre et la valeur des étiquettes comme il convient.

  1. transformers/data/metrics/__init__.py C'est la partie qui calcule la précision à l'aide des données de vérification. Ajoutez simplement le cas de nom_tâche ==" original " dans l'expression conditionnelle comme suit:
    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)}
        #ajouter à
        elif task_name == "original":
            return {"acc": simple_accuracy(preds, labels)}
        else:
            raise KeyError(task_name)

Réglage fin pour résoudre le problème de classification

Maintenant que les données originales en japonais fonctionnent, tout ce que vous avez à faire est de peaufiner et de résoudre le problème de classification. Il exécute uniquement la commande suivante: Placez les données d'entraînement et les fichiers de données de vérification sous data / original /.

$ 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

Si vous exécutez la commande ci-dessus et terminez sans aucun problème, le journal suivant sera généré. La valeur de acc est «1.0», et vous pouvez voir que les deux données de vérification peuvent être classées correctement.

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

Et vous pouvez voir que le fichier modèle est créé sous ʻoutput / original / `.

$ 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

en conclusion

J'ai présenté comment classer les textes japonais en utilisant la version PyTorch de BERT. En modifiant un autre code source, vous pouvez effectuer des tâches telles que la génération de texte et la réponse aux questions ainsi que la classification de texte.

Jusqu'à présent, exécuter BERT en japonais avec PyTorch posait un gros problème, mais je pense que cet obstacle est devenu très bas avec la sortie de modèles pré-entraînés en japonais. Bien sûr, essayez la version PyTorch de BERT avec des tâches japonaises.

Article de référence

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

Recommended Posts

[PyTorch] Comment utiliser BERT - Réglage fin des modèles pré-entraînés japonais pour résoudre les problèmes de classification
[PyTorch] Introduction à la classification des documents japonais à l'aide de BERT
[Explication de la mise en œuvre] Comment utiliser la version japonaise de BERT dans Google Colaboratory (PyTorch)
[PyTorch] Introduction à la classification de documents à l'aide de BERT
Comment utiliser le japonais avec le tracé NLTK
Bases de PyTorch (1) -Comment utiliser Tensor-
J'ai essayé d'implémenter la classification des phrases et la visualisation de l'attention par le japonais BERT avec PyTorch
Comment utiliser xgboost: classification multi-classes avec des données d'iris
Comment utiliser le modèle japonais Spacy avec Google Colaboratory
Comment utiliser xml.etree.ElementTree
Comment utiliser Python-shell
Remarques sur l'utilisation de tf.data
Comment utiliser virtualenv
Comment utiliser Seaboan
Comment utiliser la correspondance d'image
Comment utiliser le shogun
Comment utiliser Virtualenv
Comment utiliser numpy.vectorize
Comment utiliser pytest_report_header
Comment utiliser partiel
Comment utiliser Bio.Phylo
Comment utiliser SymPy
Comment utiliser x-means
Comment utiliser WikiExtractor.py
Comment utiliser virtualenv
Comment utiliser Matplotlib
Comment utiliser iptables
Comment utiliser numpy
Comment utiliser TokyoTechFes2015
Comment utiliser venv
Comment utiliser le dictionnaire {}
Comment utiliser Pyenv
Comment utiliser la liste []
Comment utiliser python-kabusapi
Comment utiliser OptParse
Comment utiliser le retour
Comment utiliser pyenv-virtualenv
Comment utiliser imutils
13th Offline en temps réel Comment résoudre les problèmes d'écriture avec Python