CV・NLPハマりどころメモ

画像認識と自然言語処理を研究する上でうまくいかなかったことと,その対策をまとめる自分用のメモが中心.

FlairでNERを試す[Flair][NLP][NER]

CoNll2013のデータセットを使ってNERを実行するまでを雑にメモする.

Flairが入ったDockerfileをcloneしてくる.

git clone https://github.com/poteha/docker-nlp.git

DockerfileからFlairのImageを作成

docker build -t nlp-gpu -f ./Dockerfile.gpu .

作成したImageからcontainerを立てる

docker run -it --runtime=nvidia nlp-gpu:latest bash

コンテナに入って,Flairのアップデートを行う

pip install -U pip

pip install -U flair

CoNll2013のデータセットをダウンロードする

git clone https://github.com/synalp/NER.git

mkdir -p ~/.flair/datasets/conll_03

cp ~/NER/corpus/CoNLL-2003/eng.* ~/.flair/datasets/conll_03

ちなみに~/.flair/datasets/conll_03の中はこんな感じ

xxx@xxx:~/.flair/datasets/conll_03# ll
total 4756
drwxr-xr-x 2 root root    4096 Jun 12 08:12 ./
drwxr-xr-x 4 root root    4096 Jun 12 08:33 ../
-rw-r--r-- 1 root root  827012 Jun 12 08:11 eng.testa
-rw-r--r-- 1 root root  748096 Jun 12 08:11 eng.testb
-rw-r--r-- 1 root root 3281528 Jun 12 08:11 eng.train

ここからFlairを用いたNERのモデルの学習を始める

まずコーパスの準備

from flair.data import Corpus
from flair.datasets import ClassificationCorpus

# conll03のフォルダパスを指定
data_folder = '~/.flair/dataset/conll03'

# load corpus containing training, test and dev data
corpus: Corpus = ClassificationCorpus(data_folder,
                                      test_file='eng.testa',
                                      dev_file='eng.testb',
                                      train_file='eng.train')

フルでデータを使うと学習に時間がかかるので,コーパスから1割だけデータを取り出す

downcorpus = corpus.downsample(0.1)

print(downcorpus)

TaggedCorpus: 1499 train + 347 dev + 369 test sentences

タグを取り出してモデルが何を予測するかを事前に確認する.

tag_type = 'ner'
tag_dictionary = corpus.make_tag_dictionary(tag_type=tag_type)
print(tag_dictionary.idx2item)

[b'<unk>', b'O', b'S-PER', b'S-ORG', b'S-LOC', b'S-MISC', b'B-ORG', b'E-ORG', b'I-ORG', b'B-LOC', b'E-LOC', b'B-PER', b'E-PER', b'B-MISC', b'E-MISC', b'I-PER', b'I-MISC', b'I-LOC', b'<START>', b'<STOP>']

embeddingのモデルを指定

今回は,GloVeとCharacterEmbeddingsをstackさせて利用.

from flair.embeddings import TokenEmbeddings, WordEmbeddings, CharacterEmbeddings, StackedEmbeddings
from typing import List

embedding_types: List[TokenEmbeddings] = [
    WordEmbeddings('glove'),
    CharacterEmbeddings(),
]
 
embeddings: StackedEmbeddings = StackedEmbeddings(embeddings=embedding_types)

SequenceTaggerクラスに隠れ層のサイズやembeddings,タグの種類などを渡す.

from flair.models import SequenceTagger
 
tagger: SequenceTagger = SequenceTagger(hidden_size=256,
                                        embeddings=embeddings,
                                        tag_dictionary=tag_dictionary,
                                        tag_type=tag_type,
                                        use_crf=True)

ModelTrainerクラスにtaggerとcorpusを渡す.

from flair.trainers import ModelTrainer
 
trainer: ModelTrainer = ModelTrainer(tagger, corpus)

学習を開始

trainer.train('logs/',
              learning_rate=0.1,
              mini_batch_size=32,
              max_epochs=10)

2019-06-12 08:33:03,132 ----------------------------------------------------------------------------------------------------
2019-06-12 08:33:03,132 Evaluation method: MICRO_F1_SCORE
2019-06-12 08:33:03,283 ----------------------------------------------------------------------------------------------------
2019-06-12 08:33:04,025 epoch 1 - iter 0/47 - loss 55.90135956
2019-06-12 08:33:06,917 epoch 1 - iter 4/47 - loss 45.51642914
2019-06-12 08:33:08,778 epoch 1 - iter 8/47 - loss 35.78959168
2019-06-12 08:33:10,459 epoch 1 - iter 12/47 - loss 30.98981975

logsに経過やモデルが出力される.

学習曲線のプロットもできる

from flair.visual.training_curves import Plotter
 
plotter = Plotter()
plotter.plot_training_curves('logs/loss.tsv')

今回学習したモデルを用いて検出を実施する場合は,フォルダ「logs」の中にあるモデルを読み込んで利用

model = SequenceTagger.load_from_file('logs/final-model.pt')
 
sentence = Sentence('I love Berlin')
model.predict(sentence)
print(sentence.to_tagged_string())