Japanese BERT Pretrained Model
後継プロジェクト → aMLP-japanese
同じように使える学習済みモデルがあります。新規開発またはTF2環境ではこちらを使うことを推奨します。
RoBERTaとは、Liu, Yinhanらが提案する、BERTの改良版です。モデル構造そのものはオリジナルのBERTと同じで、学習手法に工夫があります。
このプロジェクトは、スポンサーを募集しています。
New
-
言語モデルのスコア表示を追加しました
-
Tensorflow 1.x/2.x両対応しました
✓smallモデルの公開(2020/12/6)
✓baseモデルの公開(2021/1/4)
GitHubからコードをクローンします
$ git clone https://github.com/tanreinama/RoBERTa-japanese
$ cd RoBERTa-japanese
モデルファイルをダウンロードして展開します
$ wget https://www.nama.ne.jp/models/RoBERTa-ja_base.tar.bz2
$ tar xvfj RoBERTa-ja_base.tar.bz2
分かち書きに使うJapanese-BPEEncoderをコピーします
$ git clone https://github.com/tanreinama/Japanese-BPEEncoder.git
$ cp Japanese-BPEEncoder/* ./
クラス分類問題は、BERTモデルに入力される「[CLS]」トークンに対するtransformerの出力を、全結合層で分類します。
サンプルプログラムは、
dir/<classA>/textA.txt
dir/<classA>/textB.txt
dir/<classB>/textC.txt
・・・
のように、「クラス名/ファイル」という形でテキストファイルが保存されている前提で、テキストファイルをクラス毎に分類するモデルを学習します。
ここでは、livedoor ニュースコーパスを使用する例をサンプルとして提示します。
まず、コーパスをダウンロードして展開すると、「text」以下に記事の入っているディレクトリが作成されます。
$ wget https://www.rondhuit.com/download/ldcc-20140209.tar.gz
$ tar xvfz ldcc-20140209.tar.gz
$ ls text/
ここではファイル1つを1データとして扱うので、「--input」にコーパスのディレクトリを、「--model」にモデル名を入れて、「train-classifier.py」を実行します。
学習したモデルは、「checkpoint」以下の「--run_name」で指定したディレクトリ内に保存されます。
$ python train-classifier.py --input text --model RoBERTa-ja_base --run_name run_classifier1
以下のようにサブディレクトリ名とクラスIDとの対応が表示された後、学習が進みます。
text/dokujo-tsushin mapped for id_0, read 871 contexts.
text/it-life-hack mapped for id_1, read 871 contexts.
text/kaden-channel mapped for id_2, read 865 contexts.
text/livedoor-homme mapped for id_3, read 512 contexts.
text/movie-enter mapped for id_4, read 871 contexts.
text/peachy mapped for id_5, read 843 contexts.
text/smax mapped for id_6, read 871 contexts.
text/sports-watch mapped for id_7, read 901 contexts.
text/topic-news mapped for id_8, read 771 contexts.
ここでは1ファイルが1データとして扱っていますが、「--train_by_line」オプションを指定することで、テキストファイル内のテキスト1行ずつを1データとして扱うことも出来ます。
推論は、「predict-classifier.py」を実行します。入力テキストの形式は学習時と同じです。
$ python predict-classifier.py --input text --model checkpoint/run_classifier1
出力先は、分類結果のcsvファイルで、デフォルトは「predict.csv」です。
「--output_file」オプションで変更出来ます。
$ head -n5 predict.csv
id,y_true,y_pred
dokujo-tsushin/dokujo-tsushin-6140446.txt,0,0
dokujo-tsushin/dokujo-tsushin-6502782.txt,0,0
dokujo-tsushin/dokujo-tsushin-5292054.txt,0,0
dokujo-tsushin/dokujo-tsushin-6340031.txt,0,0
分類結果を、タイル表示で可視化した結果も、「出力ファイル名_map.png」という名前で保存されます。
RoBERTaのモデルはtransformerベースなので、入力されたBPEに対して、それぞれの対応するベクトルを出力します。
入力文章に対して、分かち書きしたBPEに対応するベクトルを全て出力するには、「bert-transform.py」を起動します。
すると、「--context」で指定した文章を分かち書きして、対応するBPEのベクトルの列を返します。
$ python bert-transform.py --context "俺の名前は坂本俊之。何処にでもいるサラリーマンだ。" --model RoBERTa-ja_base
input#0:
[[-0.03498905 -0.39651284 0.08991005 ... -0.22224797 -0.47363394
0.24207689]
[-1.5242212 -0.376556 0.00792967 ... 0.79690623 -0.10436316
-0.8417113 ]
[ 0.32648042 0.63716465 0.53898436 ... -0.43589458 -1.5498768
-1.29899 ]
・・・(略)
BPEではなく、文章に対応するベクトルは、「[CLS]」トークンに対する出力ベクトルを利用します。
文章のベクトル化を行うには、「bert-transform.py」を「--output_cls」オプションを指定して起動します。
$ python bert-transform.py --context "俺の名前は坂本俊之。何処にでもいるサラリーマンだ。" --model RoBERTa-ja_base --output_cls
input#0:
[-2.73364842e-01 2.00292692e-01 2.09339023e-01 -4.24192771e-02
-1.32657290e-01 9.70005244e-03 -6.21969163e-01 1.17966272e-02
-2.89265156e-01 -4.36325669e-02 5.75233221e-01 7.28546530e-02
-1.82987601e-01 -3.07042986e-01 1.49002954e-01 -2.09294081e-01
・・・(略)
すると、文章を固定長のベクトルに出来ます。
RoBERTaのモデルは入力されたテキスト内の「[MASK]」部分を予測します。
「bert-predict.py」で、直接穴埋め問題を解かせることが出来ます。
「[MASK]」一つでエンコード後のBPE一つなので、「[MASK]」が日本語2文字か1文字になります。
$ python bert-predict.py --context "俺の名前は坂本[MASK]。何処にでもいるサラリー[MASK]だ。" --model RoBERTa-ja_base
俺の名前は坂本龍馬。何処にでもいるサラリーマンだ。
BPE単位で言語モデルが出力するスコアを表示します。「 --output_max」をつけると、言語モデル的にもっとも良いBPEの候補を表示します(ある程度以上の長文で元の文と違うBPEが候補に出ます)。
$ python bert-score.py --context="今日は1人でゲームしてた" --model RoBERTa-ja_base
-0.006962206214666367 今日
-0.00039867559098638594 は
-0.0003250309091527015 1
-0.00019333878299221396 人
-0.0012948471121490002 で
-0.001036107074469328 ゲー
-0.0005645350320264697 ム
-0.0020736397709697485 して
-0.0014481781981885433 た
コーパス2020でプレトレーニングしたモデルは公開しています。ここでの手順は、独自のデータでモデルをさらにファインチューニングする方法です。
Japanese-BPEEncoderを使用して、学習させたい独自のデータをエンコードします。
$ git clone https://github.com/tanreinama/Japanese-BPEEncoder.git
$ cd Japanese-BPEEncoder
$ python encode_bpe.py --src_dir <content file path> --dst_file finetune
$ mv finetune.npz ../
$ cd ..
「--base_model」に元のプレトレーニング済みモデルを「--dataset 」にエンコードしたファイルを指定して、「run_finetune.py」を起動します。
$ python run_finetune.py --base_model RoBERTa-ja_base --dataset finetune.npz --run_name RoBERTa-finetune_run1
学習したモデルは、「checkpoint」以下の「--run_name」で指定したディレクトリ内に保存されます。