私の研究で BERT を使うことになったので BERT の使い方の備忘録を記事にしました。環境構築~テスト実行を載せています。これから初めて BERT を触ろうとしている方の参考になれば幸いです。
環境構築の前に
日本語の自然言語処理をするために BERT を使うのですが、自然言語処理で欠かせない形態素解析には JUMAN++ というものを使います。これは京大で開発された形態素解析器なのですが、MeCabよりも優れているという情報があったので今回は BERT と JUMAN++ をインストールします。
そして、今回もGoogleColaboratoryで開発を進めることを前提に話を進めていきます。
JUMAN++ のインストール
今回参照するサイトはこちらです
まず、環境構築のためだけのファイル(例「BERT・JUMAN++インストール.ipynb」)を作成します。
そのファイルの最初のコードブロックを以下のようにします。
# JUMAN++インストール
!wget https://github.com/ku-nlp/jumanpp/releases/download/v2.0.0-rc2/jumanpp-2.0.0-rc2.tar.xz
!tar xfv jumanpp-2.0.0-rc2.tar.xz
%cd jumanpp-2.0.0-rc2
!mkdir bld
%cd bld
!cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local
!make install -j2
# インストールしたものを自分のGoogleドライブにコピー
!mkdir juman_bu
!mkdir juman_bu/bin
!mkdir juman_bu/libexec
!cp -rf /usr/local/bin/jumanpp ./juman_bu/bin/
!cp -rf /usr/local/libexec/jumanpp ./juman_bu/libexec/
# 使うとき(実行ファイルの初めの部分にこれをコピペ)
# !mkdir /usr/local/libexec
# !cp -rf ./juman_bu/bin/jumanpp /usr/local/bin/
# !cp -rf ./juman_bu/libexec/jumanpp /usr/local/libexec/
# !chmod 755 /usr/local/bin/jumanpp
# !chmod 755 /usr/local/libexec/jumanpp/jumandic.config
# !chmod 755 /usr/local/libexec/jumanpp/jumandic.jppmdl
# 動作確認(コマンド)
!echo "おはようございます" | jumanpp
# 動作確認(pyknpから)
!pip install pyknp
from pyknp import Juman
jumanpp = Juman()
result = jumanpp.analysis("おはようございます")
for mrph in result.mrph_list():
print(mrph.midasi, mrph.yomi, mrph.genkei, mrph.hinsi)
これを実行すればJUMAN++がインストールされて、動作確認までできます。
ちなみに動作確認の結果はこんな感じでした。↓
mkdir: cannot create directory ‘/usr/local/libexec’: File exists
おはよう おはよう おはよう 感動詞 12 * 0 * 0 * 0 "代表表記:おはよう/おはよう"
ございます ございます ございます 接尾辞 14 動詞性接尾辞 7 動詞性接尾辞ます型 31 基本形 2 "代表表記:御座います/ございます"
EOS
Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/
Requirement already satisfied: pyknp in /usr/local/lib/python3.7/dist-packages (0.6.1)
Requirement already satisfied: six in /usr/local/lib/python3.7/dist-packages (from pyknp) (1.15.0)
おはよう おはよう おはよう 感動詞
ございます ございます ございます 接尾辞
細かい解説は参照元のサイトにありますが、簡単に説明します。
本来GoogleColaboratoryでJUMAN++を使おうと思ったら数分かかるこのインストールを、実行ファイルを作成する度にしないといけないのですが、一旦自分のGoogleドライブにJUMAN++を保存して次回からはドライブからコピーしてくることでインストール作業を省くという、単純ですが画期的な手法です。
「次回からコピーしてくる」というのは上記コードの「# 使うとき(実行ファイルの初めの部分にこれをコピペ)」でコメントアウトしている部分のコードでできますが、その方法もこの後「 BERT を実行」で説明します。
BERT (日本語Pretrainedモデル)のダウンロード
ここからは次のサイトを参照します
先ほどのファイルの続きに以下の二つのコードブロックを追加していきます。
# Googleドライブと接続
from google.colab import drive
drive.mount('/content/drive')
!mkdir -p /content/drive/'My Drive'/bert/japanese
cd /content/drive/'My Drive'/bert/japanese
import urllib.request
kyoto_u_bert_url = "http://nlp.ist.i.kyoto-u.ac.jp/nl-resource/JapaneseBertPretrainedModel/Japanese_L-12_H-768_A-12_E-30_BPE.zip"
urllib.request.urlretrieve(kyoto_u_bert_url, "Japanese_L-12_H-768_A-12_E-30_BPE.zip")
!unzip Japanese_L-12_H-768_A-12_E-30_BPE.zip
これらを実行してエラーが起きなかったら成功です。
これで環境構築は終了です!
次は実際に BERT で自然言語処理をテスト実行します。
BERT を実行
引き続き先ほどのサイトを見ながら進めていきます。
新たに実行ファイルを作成して最初のコードブロックに以下のコードを書きます。
!mkdir /usr/local/libexec
!cp -rf /content/drive/'My Drive'/bert/japanese/juman_bu/bin/jumanpp /usr/local/bin/
!cp -rf /content/drive/'My Drive'/bert/japanese/juman_bu/libexec/jumanpp /usr/local/libexec/
!chmod 755 /usr/local/bin/jumanpp
!chmod 755 /usr/local/libexec/jumanpp/jumandic.config
!chmod 755 /usr/local/libexec/jumanpp/jumandic.jppmdl
このコードは先ほどJUMAN++をインストールしたときにコメントアウトしていたコードです。インストールして保存していたJUMAN++を引っ張り出します。ここで使うんですねー。
続けて以下のコードブロックを追加してください。
# Googleドライブに接続
from google.colab import drive
drive.mount('/content/drive')
# ライブラリをpipインストール
!pip install transformers
!pip install pyknp
# Python上のインポート
import torch
from transformers import BertTokenizer, BertForMaskedLM, BertConfig
import numpy as np
from pyknp import Juman
jumanpp = Juman()
# 必要なパラメータやモデル、BERTが扱いやすい形に加工するための変換処理などを先ほどダウンロードした日本語Pretrainedモデルから取得
config = BertConfig.from_json_file('/content/drive/My Drive/bert/japanese/Japanese_L-12_H-768_A-12_E-30_BPE/bert_config.json')
model = BertForMaskedLM.from_pretrained('/content/drive/My Drive/bert/japanese/Japanese_L-12_H-768_A-12_E-30_BPE/pytorch_model.bin', config=config)
bert_tokenizer = BertTokenizer('/content/drive/My Drive/bert/japanese/Japanese_L-12_H-768_A-12_E-30_BPE/vocab.txt',
do_lower_case=False, do_basic_tokenize=False)
ここまでは準備で、ここから処理をしていきます。
コードとその結果を示していきます。
# JUMAN++によって品詞分解
text = "KankyouKouchikuは*を発信するサイトです"
result = jumanpp.analysis(text)
tokenized_text = [mrph.midasi for mrph in result.mrph_list()]
print(tokenized_text)
['KankyouKouchiku', 'は', '*', 'を', '発信', 'する', 'サイト', 'です']
# 文章の区切れやマスクする部分をBERTに明示的に知らせるために、SEPやMASKを挿入
tokenized_text.insert(0, '[CLS]')
tokenized_text.append('[SEP]')
masked_index = 3
tokenized_text[masked_index] = '[MASK]'
print(tokenized_text)
['[CLS]', 'KankyouKouchiku', 'は', '[MASK]', 'を', '発信', 'する', 'サイト', 'です', '[SEP]']
# 得られたテキストをBERT用に変換
tokens = bert_tokenizer.convert_tokens_to_ids(tokenized_text)
tokens_tensor = torch.tensor([tokens])
# マスクされた部分をBERTで予測
model.eval()
with torch.no_grad():
outputs = model(tokens_tensor)
predictions = outputs[0]
_,predicted_indexes = torch.topk(predictions[0, masked_index], k=20)
predicted_tokens = bert_tokenizer.convert_ids_to_tokens(predicted_indexes.tolist())
print(predicted_tokens)
ここまで実行して、以下のような結果になれば成功です!
['情報', 'ニュース', 'インターネット', 'コンテンツ', 'ブログ', '音楽', '文化', '魅力', '[UNK]', '動画', 'メッセージ', 'トレンド', '日本', 'それ', '話題', '広告', 'サービス', 'メール', '写真', '技術']