chiTra事前学習モデルを使って評判分析を行う

[chiTra](https://github.com/WorksApplications/SudachiTra) はワークス徳島人工知能 NLP 研究所が開発する、形態素解析器 Sudachi を言語モデル技術へ応用するための OSS です。

2022/02/25 に chiTra を用いて事前学習を行った BERT モデルが公開されました。
本記事では評判分析タスクを題材にして、chiTra モデルのファインチューニングからテストデータでの評価までを行う手順を紹介します。

# 前提

## 対象とするタスク

評判分析タスクとして [Multilingual Amazon Reviews Corpus](https://registry.opendata.aws/amazon-reviews-ml/) を使用します。
各言語での Amazon の商品レビュー情報を集めたデータセットですが、chiTra モデルは日本語の処理を対象としているので、今回は日本語のものに絞って扱うことにします。
レビューの本文を入力として、評価として付与された星の数を推定してみましょう。

このデータセットは Hugging Face Hub にも[登録されており](https://huggingface.co/datasets/amazon_reviews_multi)、スクリプトからダウンロードを含めて処理を行うことができるので、事前準備は特に必要ありません。

## Hugging Face

Hugging Face は各種の言語モデルとその周辺技術を扱う OSS です。
chiTra は Hugging Face のライブラリ群と連携できるように作成されており、それらを使用することで chiTra モデルも手軽に利用することができます。

本記事でも簡単のため [Hugging Face Transformers](https://huggingface.co/docs/transformers/index) のサンプルコードをスクリプトのベースとして利用します。

# 準備

## chiTra のインストール

chiTra は次のコマンドでインストールできます。

```bash
pip install sudachitra
```

Hugging Face のサンプルコードを利用するため以下のモジュールも合わせてインストールしておきます。

```bash
pip install transformers datasets numpy
```

また深層学習フレームワークとして PyTorch もしくは Tensorflow、GPU を利用する場合はその設定も必要になりますが、ここでは割愛します。

## chiTra モデルのダウンロード

chiTra モデルのダウンロードリンクは [chiTra の github ページ](https://github.com/WorksApplications/SudachiTra)に記載されています。
今回は `chiTra-1.0.tar.gz` をダウンロード&解凍して、適宜扱いやすい位置に配置してください。
Transformers ライブラリを使って自動でモデルを推定するため、配置するディレクトリのパスに `bert` が含まれるようにしてください。

<details><summary>内容物について</summary><div>

配布データには以下の 4 ファイルが入っています。

- config.json
  - モデルの設定ファイル
- pytorch_model.bin
  - モデルデータ
- tokenizer_config.json
  - トークナイザの設定ファイル
- vocab.txt
  - トークナイザの語彙ファイル

上二つはモデルを構成するためのファイルで、Hugging Face の `AutoModel~` クラスにこれを渡すことでタスクに合わせた形式でモデルを読み込むことができます。

対して下二つは入力となる文章をモデルに合わせたトークン列に変換するためのトークナイザを構成するためのファイルです。
配布のモデルはこのトークナイザを使って事前学習を行っているため、異なるものを使うと想定と違う挙動となる可能性があります。

</div></details>

## スクリプトの準備

前述したように、Hugging Face Transformers リポジトリのサンプルコードを元にスクリプトを作成します。
[v4.16.2 時点](https://github.com/huggingface/transformers/tree/v4.16.2/examples/pytorch/text-classification)の文書分類サンプルコード `run_glue.py` をダウンロードしてください。

このスクリプトは英語のデータセット[GLUE](https://gluebenchmark.com/)でモデルの評価を行うサンプルコードです。
chiTra モデルおよび Amazon データセットを扱うにあたっていくつか書き換えが必要になります。
なお以下では PyTorch 用のサンプルコードを基準に行数などを記載しています。

### chiTra トークナイザの使用

chiTra モデルは、chiTra が提供する専用のトークナイザを利用することを前提としています。
Hugging Face にはトークナイザの設定を自動で行ってくれる `AutoTokenizer` というクラスがあるのですが、chiTra のトークナイザはこれに対応していないため、少し書き換えが必要です。

まずスクリプトの冒頭で chiTra トークナイザをインポートします。

```python
from sudachitra.tokenization_bert_sudachipy import BertSudachipyTokenizer
```

次にトークナイザの構築が行われている 341 行目を書き換えます。

```diff_python
- tokenizer = AutoTokenizer.from_pretrained(
+ tokenizer = BertSudachipyTokenizer.from_pretrained(
```

あとはスクリプト実行時に適切にパスを渡すことで、モデルを配置したディレクトリに置いた `vocab.txt` および `tokenizer_config.json` から chiTra トークナイザが自動で構築されます。

<details><summary>chiTra トークナイザを直接構築する</summary><div>

モデルとともにダウンロードした `tokenizer_config.json` にはトークナイザクラスへの引数が記載されており、今回の読込ではこれを用いて事前学習時と同じトークナイザを構築しました。
以下のようにすることで直接引数を渡して構築することも可能です。

```python
tokenizer = BertSudachipyTokenizer(
    do_lower_case=False,
    do_nfkc=True,
    do_word_tokenize=True,
    do_subword_tokenize=True,
    vocab_file=[path/to/vocab_file],
    word_form_type="normalized_and_surface",
    sudachipy_kwargs={
        "split_mode": "C",
        "dict_type": "core",
    }
)
```

</div></details>

### データセットの前処理

次に Amazon データセットを扱うための書き換えを行います。
具体的にはデータセットのどのカラムが入力の文章で、どのカラムが分類のラベルにあたるのかを指定してあげる必要があります。

まずラベルの方から行いましょう。
ラベル設定を行っている 308-327 行目の直前に以下を追加し、評価の星数を表すカラム `"stars"` を `"label"` に名称変更します。

```python
raw_datasets = raw_datasets.rename_column("stars", "label")
```

もともとのスクリプトが`"label"`という名称のカラムをラベルとして扱うようになっているので、以降の処理はスクリプト側でうまく行ってくれます。

次に入力となるカラムの設定を書き換えます。
これは 357-370 行目で行われていますが、これを丸々削除して以下に書き換えます。

```python
sentence1_key, sentence2_key = "review_body", None
```

これにより`"review_body"`、すなわちレビュー本文が入力として使用されるようになります。
`sentence2_key` を設定することで二つの文章を入力にできますが、今回は使用しないため`None`とします。（`"review_title"`カラムも渡してみるなどすると面白いかもしれません）

### 評価結果の出力

最後に、必須ではありませんが、テストデータでの評価結果を出力する部分を追加します。

GLUE はテストデータのラベルが公開されていないため、元のスクリプトは推定結果のファイルへの出力のみを行う形になっています。Amazon データセットはテストデータにもラベルがありますから、せっかくなので精度を表示させましょう。

572 行目で GLUE では不要な`"label"`カラムが除去されています。
今はラベルを使いたいので、この行は削除してしまいます。

```diff_python
- predict_dataset = predict_dataset.remove_columns("label")
```

次にテストデータでの評価結果を取得・表示する部分を追加します。
573-574 行目を次のように書き換えます。

```diff_python
- predictions = trainer.predict(
-     predict_dataset, metric_key_prefix="predict").predictions
+ result = trainer.predict(
+     predict_dataset, metric_key_prefix="predict")
+ trainer.log_metrics("test", result.metrics)
+ predictions = result.predictions
```

これでテストデータでの精度がログに出力されるようになります。

# 実行

以上で準備は完了です。
次のコマンドを実行することでファインチューニングとテストデータでの評価が行われます。

```bash
python ./run_glue.py \
    --model_name_or_path          "/path/to/chiTra/model" \
    --output_dir                  "/path/to/output_dir" \
    --dataset_name                "amazon_reviews_multi" \
    --dataset_config_name         "ja" \
    --do_train                    \
    --do_eval                     \
    --do_predict                  \
    --per_device_eval_batch_size  64 \
    --per_device_train_batch_size 8 \
    --gradient_accumulation_steps 4 \
    --learning_rate               5e-5 \
    --num_train_epochs            2 \
```

ここではハイパーパラメータ（バッチサイズ、学習率、エポック数）に事前調査で最も結果の良かった組み合わせを与えています。

ファインチューニングには GPU を使っても数時間が必要になるため、GPU 環境での実行をお勧めします。
なお `--max_train_samples 100` のように訓練で使うサンプルの数を指定することもできます。その他のオプションについてはサンプルコード上部の`~Arguments`データクラスを参照してください。

## 実行結果

うまく実行ができれば、引数リスト、前処理状況、訓練の経過、評価結果、とログが出力されていきます。
ここでは最後のテスト結果の部分から一部抜粋して記載します。
6 割程度のテスト精度が得られるはずです。

```
02/03/2022 09:59:57 - INFO - __main__ - *** Predict ***
[INFO|trainer.py:2340] 2022-02-03 09:59:57,702 >> ***** Running Prediction *****
[INFO|trainer.py:2342] 2022-02-03 09:59:57,702 >>   Num examples = 5000
[INFO|trainer.py:2345] 2022-02-03 09:59:57,702 >>   Batch size = 64
***** test metrics *****
  predict_accuracy           =     0.5962
  predict_loss               =     0.9515
  predict_runtime            = 0:00:03.80
  predict_samples_per_second =   1314.626
  predict_steps_per_second   =     20.771
```

`output_dir`として指定したディレクトリにはファインチューニング後のモデルファイルや評価結果が出力され、これを使うことで以降は追加の学習なしでデータの評価を行うことができます。

# おわりに

以上、chiTra モデルを使って評判分析タスクを解く手順を説明しました。

Hugging Face Transformers のリポジトリには他にも様々なタスクでのサンプルコードが用意されており、それらでも同様の書き換えを加えれば chiTra モデルを使うことができます。
ぜひ皆さんの興味のあるタスクにも chiTra モデルを使ってみてください。