7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JGLUE/MARC-jaをGoogle Colabで評価してみる

Last updated at Posted at 2022-06-05

JGLUE/MARC-jaをGoogle Colabで評価してみる

TL;DR

ヤフー株式会社により、標準的な自然言語処理の標準ベンチマークであるGLUEの日本語版としてJGLUEが公開されています。

今回は日本語の二項分類タスクの評価用データセットであるMARC-jaについて、Google Colab上で実際に評価してみました。モデルはHuggingfaceを利用し、以下に対するファインチューニングを行っています。

No. Model Train example num Valid(Dev) example num Accuracy Time Note
1 JGLUE - Tohoku BERT base(※) 187,528 5,654 0.958 na JGLUE公式
2 今回 - Tohoku BERT base(※) 187,528 5,654 0.955 約6時間50分 TPU利用、4 Epochs中最高の結果
3 今回 - Tohoku BERT base(※) 15,000 2,500 0.942 約1時間40分 GPU利用、4 Epochs中最高の結果
4 今回 - Tohoku BERT base(※) 15,000 2,500 0.948 約40分 TPU利用、4 Epochs中最高の結果

※ JGLUE公式に合わせてTohoku BERT baseと表記していますが、cl-tohoku/bert-base-japanese-v2と同一です(-v2である点に注意)。

なお、JGLUEで公開されているベンチマークとハイパーパラメータをできる限り合わせていますが、評価用のスクリプト(run_glue.py)を使用していなかったり、バッチサイズが異なる等、厳密には一致しない点にご注意ください。

MARC-ja

Multilingual Amazon Reviews Corpus (MARC)から日本語のレビューを抜粋したものです。星評価による判断の他にクラウドソーシングによる評価を交えてpositivenegativeの2クラスにラベルされています。

No. Dataset Positive num Negative num (Negative) Ratio
1 Train 165,477 22,051 0.133
2 Valid(Dev) 4,832 822 0.170

データの準備

MARC-jaJGLUEのGithubに格納されていないため、個別にダウンロードしてスクリプトで処理する必要があります。データ準備の手順については以下を参照してください。

処理した結果、以下のファイルが生成されます。以降の手順はこれらのファイルをGoogle Drive上にアップロードしてある前提としています。

  • train-v1.0.json
  • valid-v1.0.json

モジュールの準備

!pip install ipadic
!pip install datasets
!pip install transformers
!pip install sklearn
!pip install fugashi
!pip install unidic-lite
!pip install accelerate # for auto_find_batch_size

データ変換

準備したMARC-jaのデータをGoogle Driveにアップロードしてある前提です。Google Driveをマウントしてデータセットを読み込んでいます。

from google.colab import drive
drive.mount('/content/drive')
from datasets import load_dataset

dataset = load_dataset('json', data_files={
    'train': '/content/drive/MyDrive/[Your Dataset Parent Path]/marc_ja-v1.0/train-v1.0.json',
    'valid': '/content/drive/MyDrive/[Your Dataset Parent Path]/marc_ja-v1.0/valid-v1.0.json',
}).map(lambda example: {'label': 1 if example['label'] == 'positive' else 0})

display(dataset)

[Your Dataset Parent Path]を実際のパスで置き換えてください。

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v2')

def tokenize_function(examples):
    return tokenizer(examples['sentence'], padding='max_length', truncation=True, max_length=512)

tokenized_datasets = dataset.map(tokenize_function, batched=True)
small_train_ds = tokenized_datasets['train'].shuffle(seed=51).select(range(15000))
small_valid_ds = tokenized_datasets['valid'].shuffle(seed=51).select(range(2500))

seed=51でサンプリングしています。

モデルの準備

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained('cl-tohoku/bert-base-japanese-v2', num_labels=2)

トレーニングの実行

import numpy as np
from datasets import load_metric

metric = load_metric('accuracy')

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(output_dir='outputs',
                                    evaluation_strategy='epoch',
                                    auto_find_batch_size=True,
                                    learning_rate=5e-05,
                                    num_train_epochs=4,
                                    warmup_ratio=0.1,
                                    save_steps=5000
                                  )
trainer = Trainer(
    model=model,
    args=training_args,
    #train_dataset=tokenized_datasets['train'],
    train_dataset=small_train_ds,
    #eval_dataset=tokenized_datasets['valid'],
    eval_dataset=small_valid_ds,
    compute_metrics=compute_metrics,
)
%%time

trainer.train()

結果の保存

outputs = trainer.predict(small_valid_ds)
import pandas as pd

preds_df = pd.DataFrame({
    'pred': outputs.predictions.argmax(axis=-1),
    'label': outputs.label_ids
})
preds_df.to_csv('/content/drive/MyDrive/[Your Dataset Parent Path]/bert-gpu-result.csv')

TPUを利用したフルデータセットの評価

MARC-jaの全てのレコードを利用すると、(引き当てるGPUにもよりますが)Google ColabのGPUインスタンスでも12時間以上かかるため、無料版だと実行できない可能性があります。このため、前述の例ではサンプリングした上でベンチマークしていますが、TPUインスタンスを利用して全レコードによる評価を行うことも可能です。

モジュールの準備

!pip install ipadic
!pip install datasets
!pip install transformers
!pip install sklearn
!pip install fugashi
!pip install unidic-lite
!pip install accelerate # for auto_find_batch_size
!pip install cloud-tpu-client==0.10 https://storage.googleapis.com/tpu-pytorch/wheels/torch_xla-1.8-cp37-cp37m-linux_x86_64.whl # for TPU
!pip install torch==1.8 torchtext==0.9.0 # for TPU

cl-tohoku/bert-base-japanese-v2はPyTorchによるモデルとなっています。TPUでの実行最適化にcloud-tpu-clientを利用していますが、PyTorch-1.8にしか対応していないため、PyTorchを1.8にダウングレードしています(最新のTransformersだと1.9がインストースされるため)。

データ変換

from google.colab import drive
drive.mount('/content/drive')
from datasets import load_dataset

dataset = load_dataset('json', data_files={
    'train': '/content/drive/MyDrive/[Your Dataset Parent Path]/marc_ja-v1.0/train-v1.0.json',
    'valid': '/content/drive/MyDrive/[Your Dataset Parent Path]/marc_ja-v1.0/valid-v1.0.json',
}).map(lambda example: {'label': 1 if example['label'] == 'positive' else 0})

display(dataset)

[Your Dataset Parent Path]を実際のパスで置き換えてください。

from transformers import AutoTokenizer

tokenizer = AutoTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-v2')

def tokenize_function(examples):
    return tokenizer(examples['sentence'], padding='max_length', truncation=True, max_length=512)

tokenized_datasets = dataset.map(tokenize_function, batched=True)

モデルの準備

from transformers import AutoModelForSequenceClassification

model = AutoModelForSequenceClassification.from_pretrained('cl-tohoku/bert-base-japanese-v2', num_labels=2)

トレーニングの実行

import numpy as np
from datasets import load_metric

metric = load_metric('accuracy')

def compute_metrics(eval_pred):
    logits, labels = eval_pred
    predictions = np.argmax(logits, axis=-1)
    return metric.compute(predictions=predictions, references=labels)
from transformers import TrainingArguments, Trainer

training_args = TrainingArguments(output_dir='outputs',
                                    evaluation_strategy='epoch',
                                    #auto_find_batch_size=True,
                                    per_device_train_batch_size=16,
                                    learning_rate=5e-05,
                                    num_train_epochs=4,
                                    warmup_ratio=0.1,
                                    save_steps=5000,
                                    tpu_num_cores=8
                                  )
trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=tokenized_datasets['train'],
    eval_dataset=tokenized_datasets['valid'],
    compute_metrics=compute_metrics,
)
%%time

trainer.train()

結果の保存

outputs = trainer.predict(tokenized_datasets['valid'])
import pandas as pd

preds_df = pd.DataFrame({
    'pred': outputs.predictions.argmax(axis=-1),
    'label': outputs.label_ids
})
preds_df.to_csv('/content/drive/MyDrive/[Your Dataset Parent Path]/bert-tpu-full-result.csv')

参考文献

7
5
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
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?