😽

量子化済みのTanuki-8bにfine-tuning

2024/11/24に公開

はじめに

SNSへの投稿が誹謗中傷であるかどうかを自動で判別するシステムを開発する前段階として、fine-tuingを行った生成モデルがどの程度の精度を出せるか検証を行いました。

今回使ったモデルはGoogle colabの中で動かすことのできる軽量モデルとして8bitに量子化されたTanuki-8B-dpo-v1.0です。

SNSに投稿された文章を入力し誹謗中傷であるかどうか判断したうえで誹謗中傷度合いを出すことを目的に作りました。

tanukiモデルについて

東京大学松尾・岩澤研究室が開発した生成AIであり、8Bモデル、8Bモデルを8つ組み合わせた性能の良い8x8モデル,量子化を行われた8Bitモデル、4Bitモデルが公開されています。
https://huggingface.co/weblab-GENIAC/Tanuki-8B-dpo-v1.0

学習させるデータについて

Bertについての検証の際と同じデータを使用しました。
https://zenn.dev/rounda_blog/articles/8ea816a5a4bc58

具体的には
・wrime-sentiment
 ・感情極性 0,1,2を誹謗中傷ではないデータとして使用しました。
https://huggingface.co/datasets/shunk031/wrime

・japanese-toxic-dataset
 ・annotation_num4,5を誹謗中傷のデータとして使用しました。
https://github.com/inspection-ai/japanese-toxic-dataset/tree/main

・その他クローリング + アノテーション
 ・約1000件ほどを某SNSなどからクローリング、主に誹謗中傷が多め
 ・数人でのアノテーション、かつそのフラグで誹謗中傷度合を機械的にスコア化

学習させるデータにはlabelとして"誹謗中傷である"、"誹謗中傷ではない"の2種類を与えました。

初めは「誹謗中傷である」「誹謗中傷とも誹謗中傷でないともいえない」「誹謗中傷ではない」の3種類のlabelに分割して学習させましたが、誹謗中傷要素が含まれている文章を誹謗中傷でない可能性がある、と判断させることが難しく中間の応答をすることが少なかったため、最終的に2種類での分類に落ち着きました。

プロンプトについて

学習させる際に用いたプロンプトでは以下の形式を用いました。

以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。
### 指示:
以下のSNSへの投稿が他者に対する直接的な"誹謗中傷"か"誹謗中傷でない"か選んで返してください。
### 入力:
SNSの文章
### 応答: 
label:"誹謗中傷である"

学習後に出力させる際は以下の形式を用いました。

以下は、タスクを説明する指示と、文脈のある入力の組み合わせです。要求を適切に満たす応答を書きなさい。
### 指示:
以下のSNSへの投稿が他者に対する直接的な"誹謗中傷でない"か"誹謗中傷"か選んで返してください。
また、誹謗中傷度合いを「軽度な誹謗中傷,中度の誹謗中傷,強い誹謗中,過激な誹謗中傷,非常に過激な誹謗中傷」の中から選んでscoreとして返してください。
### 入力:
SNSの文章
### 応答:
label :

もともとのプロンプトでは、label だけでなく誹謗中傷の度合いも知りたいため、「0~100点の間で誹謗中傷度合いのスコアを返せ」と入力していました。しかし、返答が0と100ばかりになってしまったため、「5,20,45,60,75,95の中から~」といったように数値を細かく刻ませるようにしました。
その後、数値を使うよりも日本語を用いたほうが精度が高いと判断し、次のように変更しました。

「軽度な誹謗中傷,中度の誹謗中傷,強い誹謗中,過激な誹謗中傷,非常に過激な誹謗中傷」の中から選んでscoreとして返してください。

このようにプロンプトを調整することで、よりバランスの取れた返答を得られるように工夫しました。

数値でスコアを出させたい場合、最大最小である0や100を入れると結果に偏りが発生してしまいます。
それは80,85といった高スコアの場合でも同じような結果が見受けられました。
低スコアである5,20では起こらなかったので、元の学習データにSNSや口コミで使われやすい0や100といった数値が多いのではないかと思われます。

上記図における応答時のプロンプトの順序について、"誹謗中傷でない"か"誹謗中傷"かの順序を逆にすると応答が大きく変わります。前にした方の答えが多くなります。Tanuki-8B-dpo-v1.0は誹謗中傷に厳しめなので"誹謗中傷でない"を前にすることをお勧めします。

応答: label:をつけるなど応答を補助しないと以下のように質問文を連呼するエラーが発生することが多かったです。また、json形式を指定することでもこの問題を回避可能ですが、毎回json形式で返してくれるわけではないので注意が必要です。

命令文に点数の基準などを入力するとSNSへの投稿との区別がつかなくなることがあるので基準などは入れないほうがよさそうです。

結果

学習前と学習後で結果が変わっています。学習前は誹謗中傷に対し厳しすぎましたが、誹謗中傷と判断することが減り一般的な感覚に近づいたのではないでしょうか。

応答時はこのようになぜそのような判断をしたのかについての補足をしてくれます。

scoreに関しては最も誹謗中傷度の高い応答になることがかなり多かったです。学習データに誹謗中傷度のscoreを含めていないでscoreを含んだデータを用意すればある程度scoreも良くなると思います。

考察

生成AIを用いた誹謗中傷判定は判定結果になぜその判断をしたのかの解説がつくため、人間がSNSの投稿を行う前に問題のある文章でないかをチェックする際等に有用である可能性が高いと思います。

逆にjson形式で返すよう指定しても回答フォーマットを毎回揃えることが難しく、一見そろったように見えても稀に間違ったフォーマット(最後に}をつけ忘れるなど)で返すことがあります。

人間が使うならば生成モデル、システムに組み込むならばbert等の自然言語処理がよいのではないでしょうか。

過学習について

epoch数を増やすことで解答から説明を省けますが、回答がlabelのみになるまでepoch数を増やすと過学習となり、すべてに対して誹謗中傷であるもしくは誹謗中傷でないとしか返さなくなります。

よくあるエラーについて

google colabを使用する場合、unslothをimportする際及びfunslothからFastLanguageModelをimportする際に以下のようなバージョンによるコンフリクトが起こる場合があります。

一番初めにpipのupgradeを行い、torch,transformer,unslothの順でimportすることでコンフリクトを解消できました。

!pip install --upgrade pip
!pip install -U bitsandbytes
import numpy as np
import pandas as pd
import torch
!pip install -q transformers fugashi[unidic-lite]
from transformers import (
        AdamW,
        Trainer,
        BitsAndBytesConfig,
)
!pip install datasets
import datasets
!pip install unsloth
from unsloth import FastLanguageModel

Discussion