Flair 0.6 Tutorial 7: モデルを訓練する (翻訳/解説)
翻訳 : (株)クラスキャット セールスインフォメーション
作成日時 : 09/30/2020 (0.6.1)
* 本ページは、Flair ドキュメントの以下のページを翻訳した上で適宜、補足説明したものです:
* サンプルコードの動作確認はしておりますが、必要な場合には適宜、追加改変しています。
* ご自由にリンクを張って頂いてかまいませんが、sales-info@classcat.com までご一報いただけると嬉しいです。
- お住まいの地域に関係なく Web ブラウザからご参加頂けます。事前登録 が必要ですのでご注意ください。
- Windows PC のブラウザからご参加が可能です。スマートデバイスもご利用可能です。
◆ お問合せ : 本件に関するお問い合わせ先は下記までお願いいたします。
株式会社クラスキャット セールス・マーケティング本部 セールス・インフォメーション |
E-Mail:sales-info@classcat.com ; WebSite: https://www.classcat.com/ |
Facebook: https://www.facebook.com/ClassCatJP/ |
Tutorial 7: モデルを訓練する
チュートリアルのこのパートは最先端の単語埋め込みを使用して貴方自身のシークエンス・ラベリングとテキスト分類モデルをどのように訓練するかを示します。
このチュートリアルのためには、このライブラリの 基本型 と 単語埋め込み がどのように動作するかに精通していることを仮定しています (理想的には、flair 埋め込み がどのように動作するかも知っていることです)。どのように コーパスをロードするか についても知るべきです。
シークエンス・ラベリング・モデルを訓練する
単純な GloVe 埋め込みを使用して、UD_ENGLISH (英語 universal dependency treebank) データに渡り訓練された小さな品詞タガー・モデルのためのサンプル・コードがここにあります。このサンプルでは、それを高速に実行するためにデータを元のデータの 10 % にダウンサンプリングしますが、普通は full データセットに渡り訓練するべきです :
from flair.data import Corpus from flair.datasets import UD_ENGLISH from flair.embeddings import TokenEmbeddings, WordEmbeddings, StackedEmbeddings # 1. get the corpus corpus: Corpus = UD_ENGLISH().downsample(0.1) print(corpus) # 2. what tag do we want to predict? tag_type = 'pos' # 3. make the tag dictionary from the corpus tag_dictionary = corpus.make_tag_dictionary(tag_type=tag_type) print(tag_dictionary) # 4. initialize embeddings embedding_types = [ WordEmbeddings('glove'), # comment in this line to use character embeddings # CharacterEmbeddings(), # comment in these lines to use flair embeddings # FlairEmbeddings('news-forward'), # FlairEmbeddings('news-backward'), ] embeddings: StackedEmbeddings = StackedEmbeddings(embeddings=embedding_types) # 5. initialize sequence tagger from flair.models import SequenceTagger tagger: SequenceTagger = SequenceTagger(hidden_size=256, embeddings=embeddings, tag_dictionary=tag_dictionary, tag_type=tag_type, use_crf=True) # 6. initialize trainer from flair.trainers import ModelTrainer trainer: ModelTrainer = ModelTrainer(tagger, corpus) # 7. start training trainer.train('resources/taggers/example-pos', learning_rate=0.1, mini_batch_size=32, max_epochs=150)
代わりに、full データに渡り、150 エポックの間 FlairEmbeddings と GloVe を持つ stacked 埋め込みを利用することを試してください。これはペーパーで報告した最先端の精度を与えます。実験を再生成するための full コードを見るためには、ここ を確認してください。
モデルがひとたび訓練されれば新しいセンテンスのためにタグを予測するためにそれを使用できます。モデルの predict メソッドを単に呼び出します。
# load the model you trained model = SequenceTagger.load('resources/taggers/example-pos/final-model.pt') # create example sentence sentence = Sentence('I love Berlin') # predict tags and print model.predict(sentence) print(sentence.to_tagged_string())
モデルが上手く動作すれば、このサンプルでは ‘love’ を verb として正しくタグ付けします。
テキスト分類モデルを訓練する
単純な Glove 埋め込みと Flair 埋め込みの組合せを使用する、TREC-6 コーパスに渡りテキスト分類器を訓練するためのサンプルコードがここにあります。
from flair.data import Corpus from flair.datasets import TREC_6 from flair.embeddings import WordEmbeddings, FlairEmbeddings, DocumentRNNEmbeddings from flair.models import TextClassifier from flair.trainers import ModelTrainer # 1. get the corpus corpus: Corpus = TREC_6() # 2. create the label dictionary label_dict = corpus.make_label_dictionary() # 3. make a list of word embeddings word_embeddings = [WordEmbeddings('glove')] # 4. initialize document embedding by passing list of word embeddings # Can choose between many RNN types (GRU by default, to change use rnn_type parameter) document_embeddings = DocumentRNNEmbeddings(word_embeddings, hidden_size=256) # 5. create the text classifier classifier = TextClassifier(document_embeddings, label_dictionary=label_dict) # 6. initialize the text classifier trainer trainer = ModelTrainer(classifier, corpus) # 7. start the training trainer.train('resources/taggers/trec', learning_rate=0.1, mini_batch_size=32, anneal_factor=0.5, patience=5, max_epochs=150)
モデルがひとたび訓練されれば、新しいセンテンスのクラスを予測するためにそれをロードできます。モデルの predict メソッドを単に呼び出します。
classifier = TextClassifier.load('resources/taggers/trec/final-model.pt') # create example sentence sentence = Sentence('Who built the Eiffel Tower ?') # predict class and print classifier.predict(sentence) print(sentence.labels)
トランスフォーマーでテキスト分類モデルを訓練する
テキスト分類の最善の結果は微調整されたトランスフォーマーを利用します。このために TransformerDocumentEmbeddings を使用して fine_tune=True を設定します。それから、以下のコードを使用します :
from torch.optim.adam import Adam from flair.data import Corpus from flair.datasets import TREC_6 from flair.embeddings import TransformerDocumentEmbeddings from flair.models import TextClassifier from flair.trainers import ModelTrainer # 1. get the corpus corpus: Corpus = TREC_6() # 2. create the label dictionary label_dict = corpus.make_label_dictionary() # 3. initialize transformer document embeddings (many models are available) document_embeddings = TransformerDocumentEmbeddings('distilbert-base-uncased', fine_tune=True) # 4. create the text classifier classifier = TextClassifier(document_embeddings, label_dictionary=label_dict) # 5. initialize the text classifier trainer with Adam optimizer trainer = ModelTrainer(classifier, corpus, optimizer=Adam) # 6. start the training trainer.train('resources/taggers/trec', learning_rate=3e-5, # use very small learning rate mini_batch_size=16, mini_batch_chunk_size=4, # optionally set this if transformer is too much for your machine max_epochs=5, # terminate after 5 epochs )
マルチデータセット訓練
今は、英語とドイツ語の両者のテキストに PoS タグ付けできる単一モデルを訓練しましょう。これを行なうため、英語とドイツ語の UD コーパスをロードして MultiCorpus オブジェクトを作成します。このタスクのために新しい多言語 Flair 埋め込みも利用します。
残り総ては前と同じです、e.g. :
from typing import List from flair.data import MultiCorpus from flair.datasets import UD_ENGLISH, UD_GERMAN from flair.embeddings import FlairEmbeddings, TokenEmbeddings, StackedEmbeddings from flair.training_utils import EvaluationMetric # 1. get the corpora - English and German UD corpus: MultiCorpus = MultiCorpus([UD_ENGLISH(), UD_GERMAN()]).downsample(0.1) # 2. what tag do we want to predict? tag_type = 'upos' # 3. make the tag dictionary from the corpus tag_dictionary = corpus.make_tag_dictionary(tag_type=tag_type) print(tag_dictionary) # 4. initialize embeddings embedding_types: List[TokenEmbeddings] = [ # we use multilingual Flair embeddings in this task FlairEmbeddings('multi-forward'), FlairEmbeddings('multi-backward'), ] embeddings: StackedEmbeddings = StackedEmbeddings(embeddings=embedding_types) # 5. initialize sequence tagger from flair.models import SequenceTagger tagger: SequenceTagger = SequenceTagger(hidden_size=256, embeddings=embeddings, tag_dictionary=tag_dictionary, tag_type=tag_type, use_crf=True) # 6. initialize trainer from flair.trainers import ModelTrainer trainer: ModelTrainer = ModelTrainer(tagger, corpus) # 7. start training trainer.train('resources/taggers/example-universal-pos', learning_rate=0.1, mini_batch_size=32, max_epochs=150, )
これは多言語モデルを与えます。より多くの言語で実験してみましょう!
訓練カーブと重みをプロットする
Flair は訓練カーブとニューラルネットワークの重みをプロットするためのヘルパーメソッドを含みます。ModelTrainer は result フォルダーに loss.tsv と weights.txt を自動的に生成します。
訓練後、単純にプロッターにこれらのファイルをポイントさせます :
from flair.visual.training_curves import Plotter plotter = Plotter() plotter.plot_training_curves('loss.tsv') plotter.plot_weights('weights.txt')
これは result フォルダに PNG プロットを生成します。
訓練を再開する
ある時点で訓練を停止して後でそれを再開することを望む場合、パラメータ checkpoint を True に設定して訓練するべきです。これは総てのエポック後にモデルをセーブしてパラメータを訓練します。いつでも後でモデルとトレーナーをロードして正確にやめたところで訓練を続けることができます。
下のサンプルコードは SequenceTagger の訓練をどのようにどのように訓練し、停止して続けるかを示します。同じことが TextClassifier のためにも成されます。
from flair.data import Corpus from flair.datasets import WNUT_17 from flair.embeddings import TokenEmbeddings, WordEmbeddings, StackedEmbeddings from typing import List # 1. get the corpus corpus: Corpus = WNUT_17().downsample(0.1) # 2. what tag do we want to predict? tag_type = 'ner' # 3. make the tag dictionary from the corpus tag_dictionary = corpus.make_tag_dictionary(tag_type=tag_type) # 4. initialize embeddings embedding_types: List[TokenEmbeddings] = [ WordEmbeddings('glove') ] embeddings: StackedEmbeddings = StackedEmbeddings(embeddings=embedding_types) # 5. initialize sequence tagger from flair.models import SequenceTagger tagger: SequenceTagger = SequenceTagger(hidden_size=256, embeddings=embeddings, tag_dictionary=tag_dictionary, tag_type=tag_type, use_crf=True) # 6. initialize trainer from flair.trainers import ModelTrainer from flair.training_utils import EvaluationMetric trainer: ModelTrainer = ModelTrainer(tagger, corpus) # 7. start training trainer.train('resources/taggers/example-ner', learning_rate=0.1, mini_batch_size=32, max_epochs=150, checkpoint=True) # 8. stop training at any point # 9. continue trainer at later point from pathlib import Path checkpoint = 'resources/taggers/example-ner/checkpoint.pt' trainer = ModelTrainer.load_checkpoint(checkpoint, corpus) trainer.train('resources/taggers/example-ner', learning_rate=0.1, mini_batch_size=32, max_epochs=150, checkpoint=True)
スケーラビリティ : 巨大データセットで訓練する
Flair の多くの埋め込みはランタイムの視点では生成するために幾分コスト高で巨大なベクトルを持つかもしれません。これのサンプルは FlairEmbeddings, BertEmbeddings と他のトランスフォーマーベースの埋め込みです。セットアップに依拠して、訓練時間を最適化するためにオプションを設定できます。
設定する必要がある主なパラメータは ModelTrainer の train() メソッドの embeddings_storage_mode です。それは 3 つの値の一つを持てます :
- ‘none’: embeddings_storage_mode=’none’ を設定する場合、埋め込みはメモリにストアされません。代わりにそれらは各訓練ミニバッチで (訓練の間に) on-the-fly に生成されます。主な優位点はこれはメモリ要求を低く保ちます。
- ‘cpu’: embeddings_storage_mode=’cpu’ を設定する場合、埋め込みは通常のメモリにストアされます。
- 訓練中: これは多くの場合物事を著しくスピードアップします、何故ならば埋め込みは最初のエポックで計算される必要があるだけで、その後それらはメモリから単に取得されるだけだからです。劣位点はこれはメモリ要求を増やすことです。データセットのサイズとメモリセットアップに依拠して、このオプションは可能ではないかもしれません。
- 推論中: これは GPU とともに使用されるとき推論をスローダウンします、何故ならば埋め込みは GPU メモリから通常のメモリに移動される必要があるからです。推論の間にこのオプションを使用する唯一の理由は予測を使用するだけでなく予測の後に埋め込みも使用することです。
- ‘gpu’: embeddings_storage_mode=’gpu’ を設定する場合、埋め込みは CUDA メモリにストアされます。これはしばしば最速のものです、何故ならばこれは CPU から CUDA に tensor を何度もシャッフルする必要性を除去するからです。もちろん、CUDA メモリはしばしば制限されますので、巨大なデータセットは CUDA メモリに収まりません。けれども、データセットが CUDA メモリに収まる場合、このオプションは最速の一つです。
以上