BERTを動かしてみた
モチベーション
Kaggleに自然言語処理×感情分析っぽい問題を発見。そういえば、最近流行りのBERTを触ってみたいなぁ。 以上。
BERT
BERTはBidirectional Encoder Representations from Transformersの略称。訳すと、『トランスフォーマーを使った、両方向から符号化した表現』とかですかね。ちょっと意味わかんないね。最近、自然言語処理の界隈すごく流行ってる。googleの検索エンジンとか翻訳にも使われてる。 論文:https://arxiv.org/abs/1810.04805 参考: https://ainow.ai/2019/05/21/167211/
こんな認識
・Transformerベースの符号器
・教師なしで、文章データから知識獲得をする
・ものすごく表現力の高い分散表現を生成する
・転移学習に優れ、あらゆる分野に応用できる
動かしてみる
今回は、Hugging Faceさんの"Transformers "を拝借する。 github: https://github.com/huggingface/transformers docs: https://huggingface.co/transformers/index.html
目的: BERTを動かす 実装: Pytorch + Transformers 実行環境: google Colaboratory
英語学習済みモデル
まずはTransformersをインストール
!pip install transformers今回はPytorch+TransformersでBERTを動かすのに必要なライブラリをインポート。今回はBERTの英語学習済みモデルとトークナイザーを使ってみる。
import torch from transformers import BertTokenizer,BertModel tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model = BertModel.from_pretrained('bert-base-uncased')"I love dogs."という文章の各単語を分散表現にしてみる。
text = 'I love dogs.' input_ids = torch.tensor(tokenizer.encode(text,add_special_tokens=True)).unsqueeze(0) outputs = model(input_ids) outputs[0]すると、(1,6,768)のテンソルが出力される。'I love dogs.'はトークナイザーで([CLS], I, love, dogs, ., [SEP])の6単語に分解されてる。出力結果は768次元の各単語の分散表現をテンソル型で格納してる模様。
日本語学習済みモデル
次に日本語学習済みモデルとトークナイザーを使って単語の穴埋め問題をしてみる。 まずはMeCabをインストール
!pip install mecab-python3次に先ほどと違い、日本語学習済みモデルとトークナイザーを使ってみる。なお、今回は単語予測をしたいのでBertForMaskedLMってやつをインポート
import torch from transformers import BertJapaneseTokenizer,BertForMaskedLM tokenizer = BertJapaneseTokenizer.from_pretrained('bert-base-japanese-whole-word-masking') model = BertForMaskedLM.from_pretrained('bert-base-japanese-whole-word-masking')今回は"ジャコ・パストリアスは僕の敬愛する偉大なベーシストだ"という文章を"ジャコ・パストリアスは僕の敬愛するxxxなベーシストだ"と加工して、BERTに僕がジャコパスをどう思っているか予想させる。
text = 'ジャコ・パストリアスは私の敬愛する偉大なベーシストだ' input_ids = torch.tensor(tokenizer.encode(text,add_special_tokens=True)).unsqueeze(0) outputs = model(input_ids)
masked_index = 11 predictions = outputs[0][0,masked_index].topk(5) for i,index_t in enumerate(predictions.indices): index = index_t.item() token = tokenizer.convert_ids_to_tokens([index])[0] print(str(i+1)+'位:',token)予想結果はこんな感じ。
1位: 偉大 2位: 重要 3位: 優秀 4位: 強力 5位: 有名見事、BERTは僕がジャコパスを"偉大"と思ってることを見抜いた。BERT君、君とはうまい酒が飲めそうだ。