PyTorchでBERTを少しやってみる

書いてる理由

  • NLPをこれまであんまりやってなかった
  • pytorchをもうちょい使い慣れたい
  • BERTの日本語のプレトレインが公開されたって記事をみた

やったこと

BERTのプレトレインを使って、文章を分かち書きして任意の単語をマスクして、マスクした場所に出てくる単語を確認。

参考

qiita.com

詳細

ほぼ、参考のリンクの通り動かした。

結果

入力テキスト:
 ['明日', 'は', '雨', 'が', '降り', 'そう', 'だ', 'から', '家', 'から', '出', 'ない', 'で', 'いよ', 'う']
 ['明日', 'は', '[MASK]', 'が', '降り', 'そう', 'だ', 'から', '家', 'から', '出', 'ない', 'で', 'いよ', 'う']
出力:
 0 雨
 1 雪
 2 霜
 3 天
 4 星

入力テキスト:
 ['ギター', 'を', '教え', 'て', 'もらっ', 'たら', '上', '##達', 'でき', 'た', '。']
 ['ギター', 'を', '[MASK]', 'て', 'もらっ', 'たら', '上', '##達', 'でき', 'た', '。']
出力:
 0 教え
 1 し
 2 付け
 3 やっ
 4 つけ

入力テキスト:
 ['台本', 'の', 'ない', '日々', 'を', '記録', '中']
 ['台本', 'の', 'ない', '[MASK]', 'を', '記録', '中']
出力:
 0 もの
 1 か
 2 音
 3 こと
 4 部分

入力テキスト:
 ['最初', 'の', '印象', 'から', '変わら', 'ず', 'に', '良い', '感じ', 'だっ', 'た']
 ['最初', 'の', '[MASK]', 'から', '変わら', 'ず', 'に', '良い', '感じ', 'だっ', 'た']
出力:
 0 頃
 1 時
 2 時代
 3 当時
 4 とき

感想

ぼちぼち使えそうな印象。天気はさすがの精度。
たまに、"##"が分かち書きに入ってるのが不明・・・。下のやつとか。
 ['ギター', 'を', '教え', 'て', 'もらっ', 'たら', '上', '##達', 'でき', 'た', '。']

"##"が入る条件が動かしても不明だった。。

あと分かち書きがしょぼそう?
 ['明日', 'は', '雨', 'が', '降り', 'そう', 'だ', 'から', '家', 'から', '出', 'ない', 'で', 'いよ', 'う']
の「降りそうだから」は、"降り" "そう" "だから"になりそうだけども。
Mecabと比較もしてみたい。

利用したコード[リンクのものをそのまま利用]

import torch
from transformers import BertJapaneseTokenizer, BertForMaskedLM

# Load pre-trained tokenizer
tokenizer = BertJapaneseTokenizer.from_pretrained('bert-base-japanese-whole-word-masking')

# Tokenize input
text = '台本のない日々を記録中'
tokenized_text = tokenizer.tokenize(text)
print(tokenized_text)

# Mask a token that we will try to predict back with `BertForMaskedLM`
masked_index = 3
tokenized_text[masked_index] = '[MASK]'
print(tokenized_text)

# Convert token to vocabulary indices
indexed_tokens = tokenizer.convert_tokens_to_ids(tokenized_text)

# Convert inputs to PyTorch tensors
tokens_tensor = torch.tensor([indexed_tokens])

# Load pre-trained model
model = BertForMaskedLM.from_pretrained('bert-base-japanese-whole-word-masking')
model.eval()

# Predict
with torch.no_grad():
    outputs = model(tokens_tensor)
    predictions = outputs[0][0, masked_index].topk(5) # 予測結果の上位5件を抽出

# Show results
for i, index_t in enumerate(predictions.indices):
    index = index_t.item()
    token = tokenizer.convert_ids_to_tokens([index])[0]
    print(i, token)