LoginSignup
2
5

More than 1 year has passed since last update.

lukeとdeberta-v2のアンサンブルモデルを作成したら最高の精度を達成した件

Last updated at Posted at 2023-02-06

こんにちにゃんです。
水色桜(みずいろさくら)です。
今回は前回までの記事でJCommonsenseQAを解くために作ったluke-japanese-baseのファインチューニングモデルと、deberta-v2-japanese-baseのファインチューニングモデルを利用して、アンサンブルモデルを作成してみました。
手法としては単純にvoting(多数決や学習器の平均をとる手法)を用いました。
アンサンブルモデルの精度は、以下のようになりました。

0.8480786416443361

以下の表からもわかる通り、今回作成したアンサンブルbaseモデルは既存のbaseモデルのSOTAを超える性能となりました(個々のモデルの精度は約0.800だったため、まさかSOTAを超えられるとは夢にも思っていませんでした!!)。
参考:既存のbaseモデルの性能(studio ousiaさんのホームページ( https://www.ousia.jp/ja/page/ja/2022/11/17/luke-japanese/
より引用)

image.png

では使用したコードなどについてみていきます(実装はかなり簡単です)

環境

pandas 1.4.4
numpy 1.23.4
torch 1.12.1
transformer 4.24.0
Python 3.9.13
sentencepiece 0.1.97

LUKE

image.png

2020年4月当時、5つのタスクで世界最高精度を達成した新しい言語モデル。
日本語バージョンのLUKE-baseモデルは執筆現在(2022年12月)も4つのタスク(MARC-ja, JSTS, JNLI, JCommonsenseQA)で最高スコアを有しています。LUKEはRoBERTaを元として構成され、entity-aware self-attentionという独自のメカニズムを用いています。LUKEに関して詳しくは下記記事をご覧ください。

image.png

deberta-v2-japanese

日本語Wikipedeia(3.2GB)および、cc100(85GB)、oscar(54GB)を用いて訓練されたモデルです。京都大学黒橋研究室が公表されました。

検証に使用したコード

以下のようなコードで精度の検証を行いました。
accuracyは0.848であり、既存のSOTAを超える値となりました(個々のモデルのハイパーパラメータを工夫するともう少し上がるかもしれません)

ensemble.py
ensemble.py
from transformers import AutoTokenizer, AutoModelForMultipleChoice
import torch

tokenizer1=AutoTokenizer.from_pretrained('Mizuiro-sakura/deberta-v2-japanese-base-finetuned-commonsenseqa')
model1=AutoModelForMultipleChoice.from_pretrained('Mizuiro-sakura/deberta-v2-japanese-base-finetuned-commonsenseqa')

import pandas as pd
import json
import os
import numpy as np
# JCommonsenseQAの読み込み
dataset_v = [json.loads(line)
        for line in open("CommonsenseQA_valid.json", 'r', encoding='utf-8')]

tokenizer2 = AutoTokenizer.from_pretrained('Mizuiro-sakura/luke-japanese-base-commonsenseqa')
model2 = AutoModelForMultipleChoice.from_pretrained('Mizuiro-sakura/luke-japanese-base-commonsenseqa')

acc=0
for i in range(len(dataset_v)):
    question=dataset_v[i]['question']
    x1=tokenizer1([question,question,question,question,question],[dataset_v[i]['choice0'],dataset_v[i]['choice1'],dataset_v[i]['choice2'],dataset_v[i]['choice3'],dataset_v[i]['choice4']]
    ,return_tensors='pt',padding=True)
    leng=len(x1['input_ids'][0])

    X1 = np.empty(shape=(1, 5, leng))
    X2 = np.empty(shape=(1, 5, leng))
    X1[0, :, :] = x1['input_ids']
    X2[0, :, :] = x1['attention_mask']
    result_deberta = model1(torch.tensor(X1).to(torch.int64),torch.tensor(X2).to(torch.int64))


    question=dataset_v[i]['question']
    x1=tokenizer2([question,question,question,question,question],[dataset_v[i]['choice0'],dataset_v[i]['choice1'],dataset_v[i]['choice2'],dataset_v[i]['choice3'],dataset_v[i]['choice4']]
    ,return_tensors='pt',padding=True)
    leng=len(x1['input_ids'][0])

    X1 = np.empty(shape=(1, 5, leng))
    X2 = np.empty(shape=(1, 5, leng))
    X1[0, :, :] = x1['input_ids']
    X2[0, :, :] = x1['attention_mask']
    result_luke = model2(torch.tensor(X1).to(torch.int64),torch.tensor(X2).to(torch.int64))

    results=torch.tensor(result_deberta.logits)+torch.tensor(result_luke.logits)
    max_r=torch.argmax(results)
    if max_r==dataset_v[i]['label']:
        acc=acc+1/len(dataset_v)
print(acc)

実際にモデルを使用してみる

以下のコードを用いることで、アンサンブルモデルによる解析が行えます。

exe.py
exe.py
from transformers import AutoTokenizer, AutoModelForMultipleChoice
import torch
import numpy as np

# modelのロード
tokenizer1=AutoTokenizer.from_pretrained('Mizuiro-sakura/deberta-v2-japanese-base-finetuned-commonsenseqa')#('Mizuiro-sakura/deberta-v2-base-juman-finetuned-commonsenseqa')
model1=AutoModelForMultipleChoice.from_pretrained('Mizuiro-sakura/deberta-v2-japanese-base-finetuned-commonsenseqa')

tokenizer2 = AutoTokenizer.from_pretrained('Mizuiro-sakura/luke-large-commonsenseqa-japanese')
model2 = AutoModelForMultipleChoice.from_pretrained('Mizuiro-sakura/luke-large-commonsenseqa-japanese')

# 質問と選択肢の代入
question = '電子機器で使用される最も主要な電子回路基板の事をなんと言う?'
choice1 = '掲示板'
choice2 = 'パソコン'
choice3 = 'マザーボード'
choice4 = 'ハードディスク'
choice5 = 'まな板'

# トークン化(エンコーディング・形態素解析)する
token = tokenizer1([question,question,question,question,question],[choice1,choice2,choice3,choice4,choice5],return_tensors='pt',padding=True)
leng=len(token['input_ids'][0])

# modelに入力するための下準備
X1 = np.empty(shape=(1, 5, leng))
X2 = np.empty(shape=(1, 5, leng))
X1[0, :, :] = token['input_ids']
X2[0, :, :] = token['attention_mask']

# modelにトークンを入力する
result_deberta = model1(torch.tensor(X1).to(torch.int64),torch.tensor(X2).to(torch.int64))

token = tokenizer2([question,question,question,question,question],[choice1,choice2,choice3,choice4,choice5],return_tensors='pt',padding=True)
leng=len(token['input_ids'][0])

# modelに入力するための下準備
X1 = np.empty(shape=(1, 5, leng))
X2 = np.empty(shape=(1, 5, leng))
X1[0, :, :] = token['input_ids']
X2[0, :, :] = token['attention_mask']

# modelにトークンを入力する
result_luke = model2(torch.tensor(X1).to(torch.int64),torch.tensor(X2).to(torch.int64))

results=result_deberta.logits+result_luke.logits

# 最も高い値のインデックスを取得する
max_result=torch.argmax(results)
print(max_result)

終わりに

アンサンブルモデルという存在は知っていましたが、ここまで精度が向上するものだとは、驚きました。
アンサンブルモデルの作成方法としてはほかにブースティングやスタッキングなどがあるため、まだ精度向上の余地があるかもしれません。
ぜひ皆さんもいろいろ試してみてください。
今回はここまでにしようと思います。
では、ばいにゃん~。

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