1
0

言語処理100本ノック2020 (98. ドメイン適応)

Last updated at Posted at 2023-11-18

はじめに

本記事は言語処理100本ノックの解説です。
100本のノックを全てこなした記録をQiitaに残します。
使用言語はPythonです。

今回は第10章: 機械翻訳(98. ドメイン適応)の解答例をご紹介します。

98. ドメイン適応

Japanese-English Subtitle Corpus (JESC)やJParaCrawlなどの翻訳データを活用し,KFTTのテストデータの性能向上を試みよ.

準備
fairseqを入れます。

コマンド
$ git clone https://github.com/pytorch/fairseq
$ pip install --editable fairseq/

分かち書きをするためにMecabを入れます。

コマンド
$ pip install mecab-python3 unidic
$ python -m unidic download

データの作成

Japanese-English Subtitle Corpus (JESC)を訓練データに追加して学習をします。そのために以下のコードでJESCの日本語を分かち書きにして、KFTTのデータとマージします。

コード
import pandas as pd
import MeCab
m = MeCab.Tagger("-Owakati")
def Wakachi(text):
  w_text = m.parse(text)
  w_text = w_text.replace(" \n", "")
  return w_text

def MakeDataset(source):
  df = pd.read_table("[PATH]/JESC/split/{}".format(source), names=("English", "Japanese"))
  df["Japanese"].apply(Wakachi).to_csv("[PATH]/Source-JESC/JESC-{}.ja".format(source), header=False, index=False)
  df["English"].to_csv("[PATH]/Source-JESC/JESC-{}.en".format(source), header=False, index=False)

MakeDataset("test")
MakeDataset("dev")
MakeDataset("train")

def MargeDataset(name):
  !cat "[PATH]/Source-JESC/JESC-"$name".ja" "[PATH]/sorce/kyoto-"$name".ja" > "[PATH]/Source-98/Source98-"$name".ja"
  !cat "[PATH]/Source-JESC/JESC-"$name".en" "[PATH]/sorce/kyoto-"$name".en" > "[PATH]/Source-98/Source98-"$name".en"

MargeDataset("test")
MargeDataset("dev")
MargeDataset("train")

次にfairseqで学習できる形式にします。

コマンド
$ fairseq-preprocess -s ja -t en \
--trainpref  "[PATH]/Source-98/Source98-train" \
--validpref "[PATH]/Source-98/Source98-dev" \
--testpref "[PATH]/Source-98/Source98-test" \
--destdir "[PATH]/processed-98/" \
--task translation \
--thresholdsrc 5 \
--thresholdtgt 5

モデルの学習

コマンド
$ fairseq-train "[PATH]/processed-98/" \
  --task translation \
  --arch transformer \
  --tensorboard-logdir "logs" \
  --source-lang ja --target-lang en \
  --max-epoch 100 \
  --lr 1e-6 \
  --batch-size 32 \
  --optimizer adam \
  --save-interval 5 \
  --save-dir "[PATH]/model-98/" \
  --restore-file  "[PATH]/model-98/checkpoint_last.pt" \
  --skip-invalid-size-inputs-valid-test \
| tee -a "[PATH]/log-98/train.log"

再学習用のデータ作成

KFTTのテストデータの性能向上が目標なので、いったんJESC+KFTTで学習を行った後にKFTTのデータのみでfine-tuningをします。ポイントは辞書の指定をJESC+KFTTで作った辞書にするところです。

コマンド
$ fairseq-preprocess -s ja -t en \
--trainpref  "[PATH]/kftt-data-1.0/sorce/kyoto-train" \
--validpref "[PATH]/kftt-data-1.0/sorce/kyoto-dev" \
--testpref "[PATH]/kftt-data-1.0/sorce/kyoto-test" \
--destdir "[PATH]/processed-98-relearning/" \
--srcdict "[PATH]/processed-98/dict.ja.txt" \
--tgtdict "[PATH]/processed-98/dict.en.txt" \
--task translation \
--thresholdsrc 5 \
--thresholdtgt 5

Fine-tuning

コマンド
$ fairseq-train "[PATH]/processed-98-FT/" \
  --task translation \
  --arch transformer \
  --tensorboard-logdir "logs" \
  --source-lang ja --target-lang en \
  --max-epoch 30 \
  --lr 1e-6 \
  --batch-size 32 \
  --optimizer adam \
  --save-interval 5 \
  --save-dir "[PATH]/model-98-FT/" \
  --restore-file  "[PATH]/model-98-FT/checkpoint_last.pt" \
  --skip-invalid-size-inputs-valid-test \
| tee -a "[PATH]/log-98-FT/train.log"

テストデータの精度確認

fairseq-generateでテストデータに対して翻訳を実行します。その後、fairseq-scoreでbleuを算出します。

コマンド
$ fairseq-generate "[PATH]/processed-98-FT/" \
--path "[PATH]/model-98-FT/checkpoint_best.pt" \
--task translation \
--gen-subset test \
| tee >(grep "^H" | cut -f3 > "./test-transform.txt")\
| grep "^T" | cut -f2 > "./test-true.txt"

$ fairseq-score --sys  "./test-transform.txt"\
--ref  "./test-true.txt"

出力結果
image.png
Bleuスコア: 21.25

コメント

膨大な量のデータで事前にモデルを学習して、その後にドメインのデータでFine-tuningする手法はよく使われます。今後は如何に大量の学習データを用意できるか、学習リソースを確保できるかがモデルの優劣を決める時代になると思います。

他章の解答例

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0