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

7月 26, 2020

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

Flair,NER

Posted by vastee