CV・NLPハマりどころメモ

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

汎用言語モデルBERTをつかってNERを動かしてみる

本記事は,2018秋にバズった汎用言語モデルBERTをとりあえずつかってみたときのレポートである.

このBERTというモデルをpre-trainingに用いると,様々なNLPタスクで高精度がでるようだ.詳細に関しては以下のリンクを参照.

[1810.04805] BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

早速手順に入る.

今回はdockerにBERT-NER専用のコンテナを構築するところから始める.

まず,BERT-NER専用のコンテナを以下のコマンドで作成.

GPUを使うので,nvidia-docker2でコンテナをつくった.

$ docker run -it --runtime=nvidia --name "bert" nvidia/cuda:8.0-cudnn5-devel-ubuntu16.04 /bin/bash

コンテナに入り, 標準搭載されていないパッケージを入れる.

# apt update
# apt install git
# apt install unzip

Anacondaに必要なパッケージをインストール

# apt install -y make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev libncursesw5-dev libpng-dev

pyenvのインストール

# cd ~
# mkdir git
# cd git
# git clone git://github.com/yyuu/pyenv.git ~/.pyenv
# git clone https://github.com/yyuu/pyenv-pip-rehash.git ~/.pyenv/plugins/pyenv-pip-rehash
# echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
# echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
# echo 'eval "$(pyenv init -)"' >> ~/.bashrc
# source ~/.bashrc

Anaconda(Python3系)のバージョンを確認

root@xxxx:~/git# pyenv install -l | grep anaconda3
  anaconda3-4.1.1
  anaconda3-4.2.0
  anaconda3-4.3.0
  anaconda3-4.3.1
  anaconda3-4.4.0
  anaconda3-5.0.0
  anaconda3-5.0.1
  anaconda3-5.1.0
  anaconda3-5.2.0
  anaconda3-5.3.0

最新のanaconda3-5.3.0をインストールし, デフォルトとして設定.

# pyenv install anaconda3-5.3.0
# pyenv global anaconda3-5.3.0
# echo 'export PATH="$PYENV_ROOT/versions/anaconda3-5.3.0/bin:$PATH"' >> ~/.bashrc
# source ~/.bashrc

Pythonの環境を確認

# python --version
Python 3.7.0 (default, Jun 28 2018, 13:15:42) 
[GCC 7.2.0]

TensorflowをインストールするためにPython3.6の環境を構築

conda create -n tf_p36 python=3.6 anaconda

source activate tf_p36

echo 'source activate tf_p36' >> ~/.bashrc

source ~/.bashrc

Tensorflowをpipでインストール

pip install tensorflow-gpu

GoogleのBERTをクローンしてくる

git clone https://github.com/google-research/bert

学習済みのBERTモデルをダウンロードしてくる

wget https://storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip

unzip uncased_L-12_H-768_A-12.zip

BERTをpre-trainingにつかってNERするためのコードを落としてくる

git clone https://github.com/kyzhouhzau/BERT-NER

GoogleのBERTを以下のように配置する

BERT-NER
|____ bert # GoogleのBERTリポジトリ
|____ BERT_NER.py # kyzhouhzau氏のスクリプトを配置
|____ output/result_dir # mkdir -p output/result_dirで新たに作成
|____ NERdata # NER用のデータ(CoNLL-2003)

最後に以下のコマンドで実行

各種パラメータは私の環境下で指定したものなので,皆さんがつかうときには適宜書き換えてください.

python BERT_NER.py --task_name="NER" --do_train=True --do_eval=True --do_predict=True --data_dir=NERdata --vocab_file=/root/share/disk2/20190214_BERT/uncased_L-12_H-768_A-12/vocab.txt --bert_config_file=/root/share/disk2/20190214_BERT/uncased_L-12_H-768_A-12/bert_config.json --init_checkpoint=/root/share/disk2/20190214_BERT/uncased_L-12_H-768_A-12/bert_model.ckpt.index --max_seq_length=128 --train_batch_size=16 --learning_rate=2e-5 --num_train_epochs=3.0 --output_dir=./output/result_dir/

ちなみに筆者の環境(CPU:16コア, GPUメモリ:122GiB)で--train_batch_size=32に設定するとOOM(Out of Memory) Errorがでたので, --train_batch_size=16に変更した

実行後, BERT-NER/output/result_dir の下にあるeval_results.txtを確認すると精度が確認できる

以下は筆者の結果


epoch=3のときの結果

eval_f = 0.5213871

eval_precision = 0.6434281

eval_recall = 0.45150447

global_step = 1307

loss = 106.11042


epoch=30のときの結果

eval_f = 0.6811273

eval_precision = 0.72659624

eval_recall = 0.6476951

global_step = 13074

loss = 109.76331


あれ?なんでこんなに精度が低いのだろうか?

検証が必要だ.