1
1

More than 1 year has passed since last update.

GPT-2を使おうとしてエラーが出た話

Last updated at Posted at 2023-05-21

やりたかったこと

PythonでFlaskを使い、リクエストを送るとGPT-2の推論結果を返してくるWebAPIを作りたかった

問題が発生したコード
gpt-2WebAPI.py
from transformers import T5Tokenizer, AutoModelForCausalLM
import torch
from flask import Flask, request

print('モデルを読み込みます。数十秒お待ちください。')

model_name = 'rinna/japanese-gpt2-medium'
# model_name = 'rinna/japanese-gpt-1b'
# model_name = 'rinna/japanese-gpt2-medium'
# model_name = 'rinna/japanese-gpt-neox-small'
tokenizer = T5Tokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)
print('モデル読み込み完了。')
app = Flask(__name__)
@app.route('/', methods=['GET'])
def process_data():
    print("読み込みました。処理を開始します。")
    # GPUが利用可能かどうかを確認
    if torch.cuda.is_available():
        device = torch.device("cuda")          
        print('GPUを使用しています')
    else:
        device = torch.device("cpu")
        print('CPUを使用しています')

    data = request.args.get('data')
    print(data + " => ")

    def generate_text(input_message):
        input_ids = tokenizer.encode(
            input_message,
            add_special_tokens=False,
            return_tensors="pt"
        )

        with torch.no_grad():
            output_sequences = model.generate(
                input_ids.to(model.device),
                max_length=150,
                min_length=10,
                temperature=0.7,
                top_k=40,
                top_p=0,
                no_repeat_ngram_size=2,
                do_sample=True,
                num_return_sequences=1,
                pad_token_id=tokenizer.pad_token_id,
                bos_token_id=tokenizer.bos_token_id,
                eos_token_id=tokenizer.eos_token_id
)

        output_sequence = output_sequences.tolist()[0]
        text = tokenizer.decode(
            output_sequence,
            clean_up_tokenization_spaces=True
            )
        input_ids_length = len(tokenizer.decode(
            input_ids[0],
            clean_up_tokenization_spaces=True
            ))
        total_text = (text[input_ids_length:])
        return total_text
    enddata = generate_text(data)
    print(enddata)
    return enddata

if __name__ == '__main__':
    app.run(port=3000)

これを実行すると、

エラーコード
RuntimeError: probability tensor contains either `inf`, `nan` or element < 0
(IPアドレス) - - [21/May/2023 15:24:35] "GET /?data=人類の発展のために、私たちはAI技術を HTTP/1.1" 500 -

スクリーンショット 2023-05-21 152657.png
こんな感じでエラーが起きる。
これに何日も頭を悩まされた......😢

解決するためにやってみたこと

とりあえずエラーコードをDeepL翻訳にかけたら、「ランタイムエラー:確率テンソルには inf, nan または要素 < 0 のいずれかが含まれます」とのこと。ふむ.......(まったくわからん)
ChatGPTに頼ってみるか。
スクリーンショット 2023-05-21 154728.png
まとめると、
・計算するときにミスってるかも。
・入力した文字の前処理に問題があるかも。
・Pythonライブラリに問題あるかも。
ってことか。

とりまモデル変えてみるか。

変更前
model_name = 'rinna/japanese-gpt2-medium'
変更後
model_name = 'rinna/japanese-gpt-1b'

で、失敗します。とりあえずモデルには問題がないってことか~

次。モデルに設定してる生成パラメータを見直してみます。

生成パラメータ設定
with torch.no_grad():
            output_sequences = model.generate(
                input_ids.to(model.device),
                max_length=150, #最大長
                min_length=10, #最小長
                temperature=0.7,
                top_k=40,
                top_p=0,
                no_repeat_ngram_size=2, #繰り返しペナルティ
                do_sample=True, #サンプリング
                num_return_sequences=1, #出力文の個数
                pad_token_id=tokenizer.pad_token_id,
                bos_token_id=tokenizer.bos_token_id,
                eos_token_id=tokenizer.eos_token_id
        )

パラメータが足りてないわけじゃないし、よくわかんないけどよさそうに見える。そういえば、top_kとtop_pって何だろ?まあいっか。(ここが今回の過ち)

...めんどくさいな。
......
.........
............

よし。全部消そう。

とりあえずライブラリを消すことにしました。

pip freeze > uninstall.txt
pip uninstall -y -r uninstall.txt

んでライブラリを入れなおしてみると、直らない。......でしょうね。

結局どうやったら直ったのか

その後cudaのバージョン確認したり、ドライバ入れなおしたり、インターネットの海を漂ったり......何しても効果がなかった。

そこで、とりあえず余計な処理を省いてみることにした。

ChatLite.py
from transformers import T5Tokenizer, AutoModelForCausalLM 
# 接頭辞(Prefix) 
PREFIX_TEXT = "人工知能を勉強することは、"
# トークナイザーとモデルの準備 
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium") 
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium") 
# 推論 
input = tokenizer.encode(PREFIX_TEXT, return_tensors="pt") 
output = model.generate(input, do_sample=True, max_length=150, num_return_sequences=3) 
print(tokenizer.batch_decode(output))

【Python】GPT-2で日本語文章を自動で生成するよりプログラムをお借りしました。

そしたら

出力
The attention mask and the pad token id were not set. As a consequence, you may observe unexpected behavior. Please pass your input's `attention_mask` to obtain reliable results.
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
A decoder-only architecture is being used, but right-padding was detected! For correct generation results, please set `padding_side='left'` when initializing the tokenizer.
['人工知能を勉強することは</s>aiの仕組みプログラムの仕組みを理解するため に必修だからですですから 人工知能の仕組みを学習する意味があります 人工知能は今から100万年ほど前に誕生したという説があります コンピュータに頼ることなく 電気信号で機械を動かそうという考え方をプログラミングしたものです 人工知能はすでに100万年も前に存在していましたそれが今になってようやく人工知能が人間にできるということが認識されるようになってきたのです このように昔の人は今と同じような言葉を使っていましたね 昔の方が意味が分かりませんでした ですから今の人に比べて理解できるはずがありませんね', '人工知能を勉強することは</s>自分の力で学習でき るようになるということです では具体的にいくつ知ればいいかいくつか例を挙げてご紹介してみたいと思います 今回は実際に人工知能を使うときに役立つ人工知能の活用 術をまとめたいと思います 人工知能の活用シーンはいろいろありますが今回は機械学習についてです 機械学習とはコンピューターが人間が行うよりも正確に学習できる 技術の総称です よくディープラーニングという用語が使用されることが多いですがディープラーニングは人間の脳と同じようにニューロンが大量に生まれる(ニューロン メモリ)ので人工知能(ai)でも自然言語の分析機能は人間とほぼ同じ役割をすることになります 人間の脳のような高度な知能を持っている', '人工知能を勉強することは</s> かが進歩していることの証拠である 人工知能研究の最前線を走っている今の東大生の考え方は まだまだ研究の最先端にいる大学生たちの世界とはほど遠いものです 人工知能というのはこれまで人間がやっていた仕事を代わりにやる技術なので 今後はその仕事人工知能に代替される可能性があります 例えば人工知能の分野において すでに最先端の人たちが 人工知能の技術が人間ではなく、「機械同士に奪われる可能性について書いている 人間の能力を超えることはあまりに急激な変化でもはや 不可能なのかもしれません 人工知能コンピューターロボットを人類の発展に活用することは 人類の知的創造']

動いた。つまりライブラリに問題はないってことか。
次に、パラメータを問題が起きたのと同じにしてみる。

ChatLite.py
from transformers import T5Tokenizer, AutoModelForCausalLM 
# 接頭辞(Prefix) 
PREFIX_TEXT = "人工知能を勉強することは、"
# トークナイザーとモデルの準備 
tokenizer = T5Tokenizer.from_pretrained("rinna/japanese-gpt2-medium") 
model = AutoModelForCausalLM.from_pretrained("rinna/japanese-gpt2-medium") 
# 推論 
input = tokenizer.encode(PREFIX_TEXT, return_tensors="pt") 
output = model.generate(input_ids.to(model.device),
                max_length=150,
                min_length=10,
                temperature=0.7,
                top_k=40,
                top_p=0,
                no_repeat_ngram_size=2,
                do_sample=True,
                num_return_sequences=1,
                pad_token_id=tokenizer.pad_token_id,
                bos_token_id=tokenizer.bos_token_id,
                eos_token_id=tokenizer.eos_token_id) 
print(tokenizer.batch_decode(output))

動かすと、

エラーコード
RuntimeError: probability tensor contains either `inf`, `nan` or element < 0

同じエラーが出た!
問題はパラメータか。多分......top_kかtop_pのどっちかだな。

ってことで調べると、
 ・top_kはその数字分の文章を保持する
 ・top_pは上位top_p%の単語から選択する
ってことらしい。
......ここやん。

生成パラメータ設定
top_k=40
top_p=0

top_kはよさそうだけど、top_pがおかしい。
上位0%って0単語じゃん。
ってことで修正。

生成パラメータ設定
top_k=40
top_p=0.95

実行すると、

出力
読み込みました。処理を開始します。
GPUを使用しています
人類の発展のために、私たちはAI技術を =>
応用し、より良い製品を創造しています。 私たちの仕事は、お客様のニーズに合った製品を生み出すことから始まります。そのためには、「開発」「設計」「製造」「品質管理」「納期管理」という工程があり、製品が完成するまで、この工程を何度も繰り返しながら、完成まで製品を作り上げていきます 当社はおかげさまで創業55年を迎え、これまで様々な製品を生み出してきました。当社の製品は「おもしろい」「かっこいい」といった感覚を大切にして、開発され、多くのお取引先様からの高い評価をいただいています 今後も当社では「よりよい製品づくり」をモットーに、さまざまな開発に取り組

動いたよぉぉぉぉぉぉぉぉぉ

まとめ

今回のエラーの原因は「top_pの設定ミス」だった。
GPTのパラメータ設定はミスるとエラーがでて動かなくなる。
しっかりとサイトを見て、解説を見ながらやりましょう。
また、今回学んだこととしては、動く最小のプログラムを作って問題の原因の切り分けをしていくと解決につながる。ということ。
横着しないで冷静に考えましょう。

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