BERTの学習済みモデルを使ってみる

 こんにちは。データサイエンスチームのtmtkです。
 この記事では、最近公開されたBERTの学習済みモデルを試してみます。

はじめに

 今年1月に、BERTという自然言語処理のモデルが発表されました。事前に学習したモデルをファインチューニングする仕組みで、自然言語処理の各種タスクで最高のスコアを更新したため、話題になりました。
 このBERTのソースコードと事前学習済みのモデルが、先月末にGitHubで公開されました。
 この記事では、このBERTの事前学習済みモデルをつかって、英語の文が「Alice’s Adventures in Wonderland(不思議の国のアリス)」と「Pride and Prejudice(高慢と偏見)」の二つのうちどちらの作品の文かを判定する機械学習モデルを作ってみます。

実験

 いつものように、AWSのEC2で実験をします。AMIとしてDeep Learning AMI (Ubuntu)をえらび、p2.xlargeタイプのインスタンスを作成します。SSHでログインします。

BERTの実験

 まずは公式リポジトリのREADME.mdで示されているチュートリアルを実験します。
 公式リポジトリをクローンします。

git clone https://github.com/google-research/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

 対象となるGLUEのデータを、スクリプトを使ってダウンロードします。

wget https://gist.githubusercontent.com/W4ngatang/60c2bdb54d156a41194446737ce03e2e/raw/becd574dd938f045ea5bd3cb77d1d506541b5345/download_glue_data.py
python download_glue_data.py --data_dir glue_data --tasks all

 TensorFlowの環境を有効にし、BERTの学習を実行します。

source activate tensorflow_p36
export BERT_BASE_DIR=uncased_L-12_H-768_A-12
export GLUE_DIR=glue_data/
python bert/run_classifier.py   --task_name=MRPC   --do_train=true   --do_eval=true   --data_dir=$GLUE_DIR/MRPC   --vocab_file=$BERT_BASE_DIR/vocab.txt   --bert_config_file=$BERT_BASE_DIR/bert_config.json   --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt   --max_seq_length=128   --train_batch_size=32   --learning_rate=2e-5   --num_train_epochs=3.0   --output_dir=/tmp/mrpc_output/

15分ほど待つと学習と評価が完了し、以下のようなメッセージが表示されます。

INFO:tensorflow:***** Eval results *****
INFO:tensorflow:  eval_accuracy = 0.85539216
INFO:tensorflow:  eval_loss = 0.42157498
INFO:tensorflow:  global_step = 343
INFO:tensorflow:  loss = 0.42157498

BERTによって、MRPCのタスクが開発用データセットでのaccuracy=85.5%で解かれています。

自分で作ったタスクを解く

 次に、GLUEにはない自分のタスクを作って、BERTで解いてみましょう。今回は、英語の文が「Alice’s Adventures in Wonderland(不思議の国のアリス)」と「Pride and Prejudice(高慢と偏見)」の二つのうちどちらの作品の文かを判定する機械学習モデルを作ってみます。
 BERTのリポジトリrun_classifier.pyは、CoLA、MNLI、MRPC、XNLIという4つのタスクに対応しているようです。この中ではCoLAのタスクがやりたいことに近そうです。CoLAは、与えられた英文が文法的に受け入れられるかどうかを判定するタスクです。データセットの例は

clc95   0   *   In which way is Sandy very anxious to see if the students will be able to solve the homework problem?
c-05    1       The book was written by John.
c-05    0   *   Books were sent to each other by the students.
swb04   1       She voted for herself.
swb04   1       I saw that gas can explode.

となっていて、「0」と書いてある1番目と3番目の文は英語の文として受け入れられず、「1」と書いてある2, 4, 5番目の文は英語の文として受け入れられるとされています。
 今回は、CoLAのデータセットと同じ形式にデータを整形し、BERTで解くことにします。
 Project Gutenbergから「Alice’s Adventures in Wonderland」「Pride and Prejudice」をダウンロードします。

wget http://www.gutenberg.org/files/11/11-0.txt
wget http://www.gutenberg.org/files/1342/1342-0.txt

 これらのデータを、適当にパースして学習用データセットを作成します。Pythonを起動して、

python

以下のスクリプトを実行します。

import random

random.seed(0)
lines = []

with open("11-0.txt", "r") as f:
    alice = f.read()

with open("1342-0.txt", "r") as f:
    pp = f.read()

for i, sentence in enumerate(alice.replace("\n", " ").split(".")[:1000]):
    lines.append("data{:03d}\t0\t*\t{}".format(i, sentence))

for i, sentence in enumerate(pp.replace("\n", " ").split(".")[:1000]):
    lines.append("data{:03d}\t1\t*\t{}".format(i, sentence))

random.shuffle(lines)

with open("train.tsv", "w") as f:
    for l in lines[:1800]:
        f.write(l + "\n")

with open("dev.tsv", "w") as f:
    for l in lines[1800:]:
        f.write(l + "\n") 

改行を空白に変え、ピリオドで区切るだけという、かなり雑な前処理になっています。自然言語処理の前処理としてはかなり不適切ですが、BERTの紹介をしたいのであって前処理の紹介をしたいわけではないため、このまま先に進みます。train.csvは、以下のような形式になります。(ここでは、環境の都合でタブ文字が空白文字に変換されてしまっています)

data748 1       *        It is what everybody says
data361 1       *       ”  “Your plan is a good one,” replied Elizabeth, “where nothing is in question but the desire of being well married, and if I were determined to get a rich husband, or any husband, I dare say I should adopt it
data671 1       *        Mrs
data865 0       *         ‘It began with the tea,’ the Hatter replied
data288 1       *        Bennet
data381 0       *        Now I growl when I’m pleased, and wag my tail when I’m angry
data400 0       *        It was so large a house, that she did not like to go nearer till she had nibbled some more of the lefthand bit of mushroom, and raised herself to about two feet high: even then she walked up towards it rather timidly, saying to herself ‘Suppose it should be raving mad after all! I almost wish I’d gone to see the Hatter instead!’     CHAPTER VII
data114 0       *        ‘I don’t know the meaning of half those long words, and, what’s more, I don’t believe you do either!’ And the Eaglet bent down its head to hide a smile: some of the other birds tittered audibly
data305 0       *       ’ He was looking up into the sky all the time he was speaking, and this Alice thought decidedly uncivil
data155 0       *        ‘Nobody seems to like her, down here, and I’m sure she’s the best cat in the world! Oh, my dear Dinah! I wonder if I shall ever see you any more!’ And here poor Alice began to cry again, for she felt very lonely and low-spirited

BERTで分類タスクを解いてみましょう。

python bert/run_classifier.py   --task_name=CoLA   --do_train=true   --do_eval=true   --data_dir=.   --vocab_file=$BERT_BASE_DIR/vocab.txt   --bert_config_file=$BERT_BASE_DIR/bert_config.json   --init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt   --max_seq_length=128   --train_batch_size=32   --learning_rate=2e-5   --num_train_epochs=3.0   --output_dir=/tmp/cola_output/
INFO:tensorflow:***** Eval results *****
INFO:tensorflow:  eval_accuracy = 0.97
INFO:tensorflow:  eval_loss = 0.11430232
INFO:tensorflow:  global_step = 168
INFO:tensorflow:  loss = 0.11430232

accuracy=97%のモデルが作成できました。

 「不思議の国のアリス」と「高慢と偏見」からそれぞれ2文ずつとってきて、推論を実行してみます。以下をtest.tsvとして保存します。tsvファイルなので、indexとsentenceの区切りは空白文字でなくタブ文字であることに注意します。(ここでも環境の都合で空白文字として表示されてしまっています)

index   sentence
0       First, she dreamed of little Alice herself, and once again the tiny hands were clasped upon her knee, and the bright eager eyes were looking up into hers--she could hear the very tones of her voice, and see that queer little toss of her head to keep back the wandering hair that WOULD always get into her eyes--and still as she listened, or seemed to listen, the whole place around her became alive with the strange creatures of her little sister’s dream.
1       Lastly, she pictured to herself how this same little sister of hers would, in the after-time, be herself a grown woman; and how she would keep, through all her riper years, the simple and loving heart of her childhood: and how she would gather about her other little children, and make THEIR eyes bright and eager with many a strange tale, perhaps even with the dream of Wonderland of long ago: and how she would feel with all their simple sorrows, and find a pleasure in all their simple joys, remembering her own child-life, and the happy summer days.
2       A deeper shade of _hauteur_ overspread his features, but he said not a word, and Elizabeth, though blaming herself for her own weakness, could not go on.
3       When the dancing recommenced, however, and Darcy approached to claim her hand, Charlotte could not help cautioning her in a whisper, not to be a simpleton, and allow her fancy for Wickham to make her appear unpleasant in the eyes of a man ten times his consequence.

 推論を実行します。

python bert/run_classifier.py --task_name=CoLA --do_predict=true --data_dir=. --vocab_file=$BERT_BASE_DIR/vocab.txt --bert_config_file=$BERT_BASE_DIR/bert_config.json --init_checkpoint=/tmp/cola_output --max_seq_length=128 --output_dir=.

 推論結果を確認します。

cat test_results.tsv
0.9990723       0.0009277124
0.99886715      0.0011329008
0.00067886716   0.9993211
0.0005702304    0.99942976

正しく分類できている様子が観察できます。

まとめ

 この記事では、先日公開されたBERTの学習済みモデルを実際に使ってみました。
 画像認識の分野では、ImageNetで学習されたVGG16などをファインチューニングするというのが深層学習モデル作成の標準的な手法になっています。今回、このBERTが公開されたことで、自然言語処理の分野でも画像認識のように、簡単で標準的な手法が確立されるのではないでしょうか。今後ますますBERTの活用事例が出てきて、BERTの有用性が実証されることが楽しみです。

AWS移行支援キャンペーン

あなたにおすすめの記事