WindowsでGPT-2(rinna社日本語ファインチューニングモデル)の文章生成をする方法 | 経済的生活日誌

WindowsでGPT-2(rinna社日本語ファインチューニングモデル)の文章生成をする方法

文章生成AI使い方ソフトウェア

文章生成AI GPT-2の日本語チューンモデル(rinna Japanese-gpt-1bなど)をWindows上で扱う方法について解説します。コピペで動かせる便利なpythonスクリプトも載せておいたので、ハードウェアのスペックさえ十分なら誰でも簡単に日本語文章の生成ができます。

pythonスクリプトについては、下記の通り3種類用意しました。

どれもコピペするだけで使えます。

  1. とりあえず動く簡潔なサンプル
  2. コマンドライン引数で動くちょっと便利版
  3. モデルロードを1回で済ませて何度も様々なプロンプト入力できる決定(?)版

1,必要なものをインストール

まずPython3.10をインストール

当方で動作確認が取れているのはPython3.10.7のためそれをインストールしていますが、多分マイナーバージョンまでは合わせなくても大丈夫です。

Pythonがまだインストールされていない方は以下の手順に従ってPythonをWindowsにインストールしてください。

PythonのインストールとPTATHへの追加が終わったものとして次へ進みます

では次は、必要なモジュールをいくつかpip installコマンドでインストールしていきます。

次にモジュールをいくつかpipでインストール

以下2つを1行ずつコマンドプロンプトにコピペしてエンターキーを押してください。

pip install transformers

ただし、PyTorchについてはCUDAバージョンなどに左右されるため、エラーなど出たら公式を確認してください。

https://pytorch.org/get-started/locally/

ここでは一例として当方の環境(上記画像の通り)のコマンドを載せておきます。

pip3 install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu117

コマンドプロンプトはWindowsキーを押した後、「cmd」と打ち込みエンターキーを押すと起動できます。

管理者権限は不要です。

2,GPT-2をとりあえず動かす

コピペ用コード

以下のコードをgpt.pyなど適当な名前を付けて保存して、実行してください。

import torch
from transformers import T5Tokenizer, AutoModelForCausalLM

tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt-1b")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-1b")

if torch.cuda.is_available():
    model = model.to("cuda")

text = "「とある魔術の禁書目録」の魅力1つ目は、"
token_ids = tokenizer.encode(text, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_length=100,
        min_length=100,
        do_sample=True,
        top_k=500,
        top_p=0.95,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        # bad_word_ids=[[tokenizer.unk_token_id]]
    )

output = tokenizer.decode(output_ids.tolist()[0])
print(output)

#実行画面閉じさせない用
import os
os.system("PAUSE")

初回実行時はモデルデータのダウンロードでそれなりに時間がかかります。

回線速度次第ですが大抵数分程度です。

ちなみにパラメータ最後の「# bad_word_ids=[[tokenizer.unk_token_id]]」をコメントアウトしたのは、何故かエラーが出るためです。

公式のサンプルプログラム(?)をそのままコピペしてエラーが出たのでここは、このようにコメントアウトしてみてください。

生成能力をレビュー

生成された文章

上記コードを実行すると、このような文章が生成されました。

手元の3090では生成までに掛かった時間は1分くらいですね。

初回実行時でなくともモデル読み込みにかかる時間が割りと長く文章の生成処理自体は数秒です。

太字部分が与えた文章で、残りは全部GPT-2(Japanese-GPT-1B)が生成してくれたものです。

「とある魔術の禁書目録」の魅力1つ目は、可愛くてかっこいいヒロインたちが次々と登場するバトルシーンです。特徴的なキャラクターたちも登場し、それぞれの能力がよくわかるシーンが次々と展開されます。アニメとは思えないほどのア クションに思わず引き込まれること間違いなしです。また、超能力を持った登場人物が多く登場し、彼らが主役のストー リーが展開されるのも魅力です。魔法の力を利用した戦闘シーンは美しく、思わず見入ってしまいます。能力が先天的に 備わっているがゆえに様々な悲劇を生みます。しかし、それを乗り越えようとする様子も心

そこそこそれっぽい文章が生成されました。

優れている点

まず良い点をレビュー。

  • 内容は禁書目録ガチ勢から見てもおおむね正しい(これは偶然ですが)
  • 「1つ目は、」と与えたことに応じて、文の中盤で「また、超能力を…」と2つ目の魅力も書いているのでちゃんと文脈を踏まえている
  • 悲劇を生みます。しかし、それを乗り越えようと」と、複数の文での代名詞もちゃんと対応

惜しい点

あまり良くない点。

  • 文章が途切れて終わっている
    (「 max_length=100,」を変えれば回避確率UP)
  • 「ストー リー」「先天的に 備わっている」など謎半角空白が出力(学習元にPDFでも含まれていたのか?!)
    (output.replace(” “,””)とかで解決できるのでセーフ)

3,上記コードを改良して使いやすくする

改良1、コマンドライン引数でプロンプト入力できるようにする

一々Pythonファイルを適当なテキストエディタで開いて入力文の書き換えをするのはスマートではないので、コマンドライン引数を使って命令できるようにします。

変更点はこの2箇所だけ。

import torch, sys
from transformers import T5Tokenizer, AutoModelForCausalLM

tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt-1b")
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt-1b")

if torch.cuda.is_available():
    model = model.to("cuda")

text = sys.argv[1]  # コマンドライン引数で入力
token_ids = tokenizer.encode(text, add_special_tokens=False, return_tensors="pt")

with torch.no_grad():
    output_ids = model.generate(
        token_ids.to(model.device),
        max_length=100,
        min_length=100,
        do_sample=True,
        top_k=500,
        top_p=0.95,
        pad_token_id=tokenizer.pad_token_id,
        bos_token_id=tokenizer.bos_token_id,
        eos_token_id=tokenizer.eos_token_id,
        # bad_word_ids=[[tokenizer.unk_token_id]]
    )

output = tokenizer.decode(output_ids.tolist()[0])
print(output)

import os
os.system("PAUSE")

ターミナルでこのPythonファイルを引数付きで実行すると生成文章が表示されます。

使い方

上記コードをコピペ&保存したフォルダ内で右クリック→「ターミナルで開く」を選択。

python ファイル名.py プロンプト」と入力すると結果が表示されます。

出力結果が残念なのはさておきちゃんと生成できてますね。

python GPT-2サンプルコード .py 超電磁砲の見どころ

超電磁砲の見どころについて、紹介。やっぱり、なんと言っても最後のあのシーンです。「 超電磁砲」には、そこ以外にも中々パワフルな場面やセクシーとも言えるところなども(以下意味不明なため省略)

これだと1回ごとにモデルロード時間が数十秒かかるため低速です。

そのため、次のような改良で連続して色々なプロンプトを入力できるようにしました。

改良2,一旦モデル読み込みさせた後に何度も様々なプロンプトを入力できるようにする

これを実行すると最初にモデル読み込みに30秒位かかりますが、その後は生成にかかる数秒だけで色々な文章を生成できます。

また、後に解説するいろいろなモデルのどれを使うかの選択を簡単にしました。

import torch
from transformers import T5Tokenizer, AutoModelForCausalLM

select_mode = "rinna/japanese-gpt" + "-1b"
# japanese-gpt[-1b],japanese-gpt[2-medium],japanese-gpt[2-small],japanese-gpt[2-xsmall]
tokenizer = T5Tokenizer.from_pretrained(select_mode)
model = AutoModelForCausalLM.from_pretrained(select_mode)

if torch.cuda.is_available():
    model = model.to("cuda")

x = 0
while x == 0:
    input_text = input("文章の冒頭を入力してください : ")
    if input_text == "end":
        x = 1
    else:
        token_ids = tokenizer.encode(
            input_text, add_special_tokens=False, return_tensors="pt"
        )

        with torch.no_grad():
            output_ids = model.generate(
                token_ids.to(model.device),
                max_length=200,
                min_length=50,
                do_sample=True,
                top_k=500,
                top_p=0.90,
                pad_token_id=tokenizer.pad_token_id,
                bos_token_id=tokenizer.bos_token_id,
                eos_token_id=tokenizer.eos_token_id,
                # bad_word_ids=[[tokenizer.unk_token_id]]
                num_return_sequences=1,
            )

        output = tokenizer.decode(output_ids.tolist()[0])
        output = str(output).replace("</s>", "").replace("[PAD]", "")
        print(f"{output}\n")

ちなみに「end」の3文字だけを打ち込むとプログラムが終了するようにしました。

x=0のうちはプロンプト入力→出力をループさせ、「end」の入力でx=1にしてループ終わりというクソ雑実装です…

output = str(output).replace(“</s>”, “”).replace(“[PAD]”, “”)はなぜ必要か

この1行なしで実行するとこの通り。

文章の冒頭を入力してください:とあるシリーズの魅力は次のような

とあるシリーズの魅力は次のような「心理描写」にあるのですが、アニメだとその部分が、ある、他のシリーズに比較して少し欠けて いるような感じがします。また、「心理描写」のところには、解説的またはオカルト的な考察などを交えなければならないので、声優 </S> [PAD](以下PAD連呼のため略)

「</s>」は確か文章の終わりを表しているのでその後が空白の出力[PAD]連呼になっているのでしょう。

適当にreplaceで取り除かないと見れたもんじゃないですね。

使い方

上記コードを適当な名前で保存して、ダブルクリックで起動します。

モデルロード時間がかかるのでプログラム立ち上げには数十秒かかります。

私のモデル保存場所はPCIE Gen4x4の超高速SSDなのにKONOZAMA!! Orz

あとはプロンプトを入力してエンターキーを押す度に生成されていきます。

画像では見にくいので1つだけ。

文章の冒頭を入力してください:新劇場版

新劇場版で追加されたルルの位置は以前の設定とは異なるものの、後のEVA第2号の位置はかなり近いものであり、第5・6話でもはっき りと目視できることから、パイロットと思われる。また、オケアノスの投光器周辺では、ロボットに搭載された音声認識用のマイクロ フォンからも聞き取れる。

文章生成は3090ではたった数秒です!!☆

生成中の様子はこの通り。

4,諸々の解説

各モデルのスペック

language modelparamslayers emb dim epochsdev ppltraining time*
rinna/japanese-gpt-1b1.3B24204810+13.9n/a**
rinna/japanese-gpt2-medium336M24102441845 days
rinna/japanese-gpt2-small110M1276832115 days
rinna/japanese-gpt2-xsmall37M65123284 days
https://github.com/rinnakk/japanese-pretrained-models

最も動かすのに負荷が大きいjapanese-gpt-1bでもVRAM13GB程度のため、medium/smallあたりなら誰でも動かせるでしょう。

勿論xsmallもOKです。

paramsはデータセットのデカさを表しています。

japanese-gpt-1b1.3Bとは1.3BILLION=13億パラメータという巨大なモデルということです。

japanese-gpt2-mediumの336Mは336Million=3億3600万パラメータという具合ですね。

パラメータが大きほど上位のモデルで、動かす負荷が大きい分自然な日本語を生成すると捉えておけば問題ありません。

実行時のオプションの意味

  • max_length=200, 生成する文章の最大の長さ
  • min_length=50, 生成する文章の最小の長さ
  • do_sample=True, ランダム性ON/OFF
    (Trueなら同じパラメータで異なる出力。Falselyなら結果は固定)
  • top_k=500, 予測される文章の続き候補を、確率高い順にいくつまで保持して文章生成するか
  • top_p=0.90, 予測単語の上位何%を使うか。小さいほど文章の結果がバラつきにくくなる
  • pad_token_id=tokenizer.pad_token_id, 気にしない
  • bos_token_id=tokenizer.bos_token_id, 気にしない
  • eos_token_id=tokenizer.eos_token_id, 気にしない
  • #bad_word_ids=[[tokenizer.unk_token_id]] わからない
  • num_return_sequences=1,  # 生成する文章の数

動かす上で抑えておくべきは太文字の6つだけです。

色々なプロンプトを連続して入力できる3つ目のスクリプトを改造して、プロンプトでなく最大文章長(max_length)・top_kなど好きなパラメータを可変にすれば最適な設定を探しやすいです。

3つ目のスクリプトのパラメータは当方の環境(3090パワーリミットなし)に合わせたもののため、それを参考に改変していくのが手っ取り早いです。

このサイトの他のAI関連記事

好きなキャラに好きに台詞を言わせるMoeGoeGUI

話題のNovelAIをGoogleColab無料枠で動かす方

AIのために3090を買った私が解説するAI用グラボの選び方

その他AI記事はこちら

AI
画像生成AI(NovelAI ,Waifu Diffusionなど)や、音声生成AI(MoeGoe GUI)、文章生成AI(GPT-2)に関連する情報をまとめました。
タイトルとURLをコピーしました