Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

【Techの道も一歩から】第26回「BERTで日本語固有表現抽出器を作ってみた」

f:id:kanjirz50:20190104142720j:plain

こんにちは。DSOC 研究開発部の高橋寛治です。

流行りの BERT(Bidirectional Encoder Represenations from Transformers) ですが、論文を読んだあと、マスク部分を当てるというサンプルを動かしその的確さに驚いたところで、手が止まっていました。

今回は、BERTの特徴である優れた言語モデルを利用して、日本語固有表現抽出器を作ってみました。 その手順をいくつかかいつまんで紹介します。

準備から学習

BERT の実装には、 Hugging Face, Inc. が提供する transformers ライブラリを利用します。 実装は、固有表現抽出のサンプルに準じて行います。

transformers ライブラリは、例によって pip install transformers で完了します。素晴らしい。

ディレクトリ構成のイメージ

data ディレクトリには元テキスト(raw)と処理済み(preprocessed)のテキストを格納します。(これから作るテキストなので、現時点では空です) model ディレクトリには学習した結果や評価結果を格納します。 preprocess.pyrun_ner.pyutils_ner.py は transformers のレポジトリから取得します。 run_training.sh は後で自分で書きます。

.
├── data
│   ├── raw
│   │   ├── train.txt
│   │   ├── dev.txt
│   │   └── test.txt
│   └── preprocessed
│       ├── labels.txt
│       ├── train.txt
│       ├── dev.txt
│       └── test.txt
│
├── model
├── preprocess.py
├── run_ner.py
├── utils_ner.py
└── run_training.sh

学習や前処理用スクリプトの取得

次のコマンドで取得します。

wget "https://raw.githubusercontent.com/stefan-it/fine-tuned-berts-seq/master/scripts/preprocess.py"
wget "https://raw.githubusercontent.com/huggingface/transformers/master/examples/ner/run_ner.py"
wget "https://raw.githubusercontent.com/huggingface/transformers/master/examples/ner/utils_ner.py"

データの準備

次のような形式のデータを準備します。

Sansan B-ORGANIZATION
株式会社 I-ORGANIZATION
は O
法人 O
向け O
クラ O
ウド O 
名刺 O
管理 O
サービス O
を O
提供 O
し O
て O
い O
ます O
。 O

名刺管理 O
アプリ O
...

スペース区切りの2列のファイルとなり、1列目は単語の表層形、2列目はIOB2タグを記述します。 文と文の間には空行を挿入します。

そして、学習データ(train.txt)、検証データ(dev.txt)、評価データ(test.txt)の3セットに分けます。 比率としては、8:1:1くらいでいいでしょう。

次に、BERT用の前処理スクリプトを適用します。

export MAX_LENGTH=128
export BERT_MODEL=bert-base-multilingual-cased
python preprocess.py data/raw/train.txt $BERT_MODEL $MAX_LENGTH > data/preprocessed/train.txt
python preprocess.py data/raw/dev.txt $BERT_MODEL $MAX_LENGTH > data/preprocessed/dev.txt
python preprocess.py data/raw/test.txt $BERT_MODEL $MAX_LENGTH > data/preprocessed/test.txt

固有表現タグの種類を別ファイルとして出力します。

cat data/raw/train.txt data/raw/dev.txt data/raw/test.txt | cut -d " " -f 2 | grep -v "^$" | sort -u > data/preprocessed/labels.txt

これで、学習に必要なファイルが揃います。

学習

run_training.sh へ学習に必要なパラメータや学習の実行を記述します。 MAX_LENGTHBERT_MODEL は、先述の前処理時に指定したものと同じにします。 今回は、学習(do_train)、評価(do_eval)、推論(do_predict)を行います。

export MAX_LENGTH=128
export BERT_MODEL=bert-base-multilingual-cased
export OUTPUT_DIR=model
export BATCH_SIZE=32
export NUM_EPOCHS=3
export SAVE_STEPS=750
export SEED=1

python run_ner.py --data_dir ./data/preprocessed \
        --model_type bert \
        --labels ./data/preprocessed/labels.txt \
        --model_name_or_path $BERT_MODEL \
        --output_dir $OUTPUT_DIR \
        --max_seq_length  $MAX_LENGTH \
        --num_train_epochs $NUM_EPOCHS \
        --per_gpu_train_batch_size $BATCH_SIZE \
        --save_steps $SAVE_STEPS \
        --seed $SEED \
        --do_train \
        --do_eval \
        --do_predict

結果

学習が終了すると、いろいろと結果が表示されているかと思います。 ファイルにも出力されていますので、確認します。

検証用データと評価用データでの、各種スコアです。 評価用データのほうがすべてのスコアが若干悪いため間違っていなさそうです。

$ cat model/eval_results.txt
f1 = 0.7872696817420436
loss = 0.21322517199762936
precision = 0.7556270096463023
recall = 0.8216783216783217

$ cat model/test_results.txt
f1 = 0.7448347107438017
loss = 0.28327141856325083
precision = 0.7402464065708418
recall = 0.7494802494802495

実際の推論結果は、model/test_predictions.txt に入っています。

混同行列を見る場合は、この例でも使われている seqeval ライブラリを使うといいでしょう。 ただし model ファイル以下に出力されるファイルと前処理済みのファイルとで、行数が合わないことがあります。 まだ、原因はわかっていませんが、Precision や Recall で測定する都合上、ファイルは行をそろえる必要があります。 たかだか数千行程度であれば、目で見て修正可能ですので、表計算ソフト上で次のようなファイルとして、手動で整形するといいでしょう。

Sansan B-ORGANIZATION Sansan B-ORGANIZATION
株式会社 I-ORGANIZATION 株式会社 I-ORGANIZATION
は O は O
法人 O 法人 O
向け O 向け O
クラ O クラ O
ウド O  ウド O
...

学習済みモデルは心強い

組織名や人名をタグ付けして、試しに固有表現抽出モデルを学習させてみたところ、F値で0.8を超える固有表現抽出器を作ることができました(約1500文にアノテーション)。 比較的少ない学習データでも十分に性能を発揮するように感じます。 またBERTの多言語モデルでこれだけ性能が出ることにも驚きを隠せません。

次回は、推論エンドポイントとして動作させるための実装について紹介します。


▼本連載のほかの記事はこちら buildersbox.corp-sansan.com

執筆者プロフィール

高橋寛治 Sansan株式会社 DSOC (Data Strategy & Operation Center) R&Dグループ研究員

阿南工業高等専門学校卒業後に、長岡技術科学大学に編入学。同大学大学院電気電子情報工学専攻修了。在学中は、自然言語処理の研究に取り組み、解析ツールの開発や機械翻訳に関連する研究を行う。大学院を卒業後、2017年にSansan株式会社に入社。キーワード抽出など自然言語処理を生かした研究開発に取り組む。

© Sansan, Inc.