こんにちは。音声認識エンジンの研究開発をしている大橋です。
今回はGPT3の一世代前のアーキテクチャであるGPT2を使ってGPT3ライクなクエリを試してみました。
GPT3とは
ディープラーニング界の今年一番の発表は何と言ってもGPT3でしょう。
GPT3はパラメータ数175Bという超巨大アーキテクチャにスクレイピングしまくったウィキペディアのダンプが小さく見える超巨大データを約5億円とも6億円とも言われる費用をクラウドGPUに突っ込んで学習させたモデルです。
GPT3って何?っていう方は前回のブログを参照して頂けますでしょうか。
以前GPT3については多少触れましたが、一番の面白さはその使い方です。どんなデータをインプットするかによって、アウトプットされる型が変わります。インプットするデータの形式を工夫することで一つのモデルで文章生成、要約、質問に対してイエス/ノーで回答、質問に対して文章で回答、算数、プログラム生成など何でもできてしまいます。まだ特定の目的のためにチューニングされたモデルにはやや劣りますが、それでも凄い事です。
ただ、英語がわからないとイマイチ、その凄さが理解しにくいのが難点でした。そこでふと思いました。
GPT-2とGPT-3はパラメータの数が違うだけで仕組みとしてはほとんど同じ。っていうことはGPT2を日本語向けに学習させたら似たようなことができるのでは?
という事でやってみました
GPT-2はGithubにいくつかプロジェクトがありますが、自然言語処理関連ではhuggingfaceがベストです。GPTのみならずBertなど、有名なアーキテクチャの多くは実装済みで、全てオープンソースで公開されています。
ちょっと洗練されすぎていてハックしにくいのが玉に瑕ですが、安心して使える代物です。
データセットは日本語のウィキペディアのダンプを使いました。一部TwitterのAPIからのデータを取得しましたがせいぜい数万件なので、事実上はウィキペディアオンリーですね。
データセットが決まったら、次はトークナイズ(単語分割)です。
NLPではテキストを単語分割する必要があるのですが、日本語の場合は単語分割が一意ではないため、選択肢が多く迷います。
有名なSentence pieceを使おうかとも思ったのですが、今回はhuggingfaceとの相性を考え、huggingfaceのレポジトリにあるtokenizerを使うことにしました。
と、ここで問題が。
日本語ウィキペディアのダンプは6000万行くらいデータがあるのですが、そのボリュームだと途中でメモリが足りなくなってしまい、トークナイザーの学習がエラーになってしまいました。僕のマシンは64Gのメモリを積んでいるので決してショボいマシンではないのですが、それでも足りなくなってしまいました。
Huggingefaceのフォーラムで質問をしてみたところ、「今のコードだと日本語や中国語のようにスペースの無い言語だと死ぬほどメモリが必要になっちゃうんですよ。遠からず直すつもりなので、良かったら待っててね。もしくは自分で修正してください。」と言われてしまいました。
ということで、残念ですが、今回は6000万行から300万行を抽出し、300万行で作成しました。
さて、学習です。
今回はhuggingfaceの言語モデル学習用のスクリプトをそのまま使わせてもらう事にしました。
GPU2枚で2週間以上かかってやっと 2 epoch 回りました。
結果を評価
では早速評価をしてみましょう。
1 2 |
# import convenient library from transformers import pipeline |
1 2 3 4 5 6 |
# TokenizerとModelのWeightsをロード text_generation = pipeline( "text-generation", model="./gpt2-checkpoint", tokenizer="./my_tokenizer", ) |
まずは普通にテキスト生成をやってみます。
1 |
text_generation("豊臣秀吉とは") |
1 |
[{'generated_text': '豊臣秀吉とは、江戸時代から続く仲間で友好関係を築いていたが、関ヶ原の戦いでは豊臣秀吉が家康軍に敗走したため、豊臣氏の本拠地としての役割を担った。|サムネイル|250x250ピクセル|徳川家康の養女・毛利元就室(徳川家康'}] |
1 |
text_generation("トランプ大統領は") |
1 |
[{'generated_text': 'トランプ大統領は「自由を、自由と平等の両方、自由と自由は、すべての自由に対して支配することが約束された。」( 自由、自由は、全て自由、自由と平等、自由は、自由である)が、この自由は'}] |
出力された文章の意味は全く不明ですが、紛れもなく日本語が出力されています。
では、今回のテーマである、答えのフォーマットを指定してみたらどうなるかを試してみましょう。
目標は「誰々は:」と人の名前を入れて質問したら「男」もしくは「女」と性別を返してくれる事にしましょう。
1 2 |
# Zerp shots text_generation("性別を教えて。小泉純一郎は:") |
1 |
[{'generated_text': '性別を教えて。小泉純一郎は: 「「女」が嫌い」とは何かとダメだから。小泉純一郎本人は「家族で、今、家族がいる、家族であるのですか?」と返答しているが、小泉純一郎は「'}] |
まぁ、普通に文章が紡ぎ出されています。それはそうですよね。ちなみにフォーマットに関するヒントを与えないやり方を「Zero shot」を呼びます。Zero shotではGPT3でも中々欲しい回答は得られません。
では、「One shot」にしたらどうでしょうか。
1 2 |
# One shots text_generation("性別を教えて。小泉純一郎は:男。小池百合子は:") |
1 |
[{'generated_text': '性別を教えて。小泉純一郎は:男。小池百合子は:女。 私が僕の結婚であったら…?????????????????????????'}] |
「小泉純一郎は:男。」と正解の例を与え、それに続けて小池百合子は:をインプットしています。ちなみに正解例を1個与えるやり方を「One shot」と呼びます。
なんと「女。」が返ってきました。凄いですね。「。」で終わらず文章がどんどん続いてしまっているのはデコーダーの問題ですから、GPT2のせいではありません。huggingfaceのtext_generationはデフォルトで50個とか決められた数の文字を生成します。正解の型がわかっているのなら、「女。」ときたところで、次の文字の推論を止めれば良いだけで、これはエンジニアの仕事です。
もうちょっとやってみましょう。
1 2 |
# Two shots text_generation("性別を教えて。小泉純一郎は:男。小池百合子は:女。マツコデラックスは:") |
1 |
[{'generated_text': '性別を教えて。小泉純一郎は:男。小池百合子は:女。マツコデラックスは:男。大人は。泣きた! 笑っているから。泣きた! 私は、何とか笑ってるけど ちょっとごめん'}] |
今回は「性別を教えて。小泉純一郎は:男。小池百合子は:女。」と正解例を2つ入れてみました。ちゃんとマツコデラックスは「男。」と回答しています。
たったの2 epochしか回せていないのに中々のものです。では算数はどうでしょうか。
1 |
text_generation("計算して。1+3=4。4+3=") |
1 |
[{'generated_text': '計算して。1+3=4。4+3=7 の「値」は統計的な時間(すなわち「時間」)における値が、2,3,4,3,-+3-}という値。 を '}] |
計算もできてますね。これは面白いですね。
1 |
text_generation("計算して。1+3=4。4+3=7。10+5=") |
1 |
[{'generated_text': '計算して。1+3=4。4+3=7。10+5=12個…=7,004,9,08%=8++10=9,000,000=0,800,500'}] |
10+5=12と間違えてしまっていますね。
これはGPT3で遊んだ方々も指摘されている事ですが、学習データにあった情報を何らかの方法で記憶してパターンに合うように出力しているだけで論理は理解できていないようですね。
1 |
text_generation("性別を教えて。小泉純一郎は:男。小池百合子は:女。IKKOは:") |
1 |
[{'generated_text': '性別を教えて。小泉純一郎は:男。小池百合子は:女。IKKOは:女。Yahoo!は:女。FAXは:aに。FAXはカッコ良い。IK'}] |
また、IKKOさんは女と回答してしまっています。ウィキペディアの中で女という漢字がたくさんでてきたから女と回答してしまっているのかな。やっぱり論理は理解できていないっぽいですね。
いずれにせよ、「要約してください。<長文1>: <要約1>。<長文2>:」などとインプットすれば長文2の要約が、「回答してください。<質問1>: <回答1>。<質問2>:」などとインプットすれば回答2がアウトプットされてくれる、これは面白いですね。
今回は日本語でGPT-2の学習を行い、GPT-3で紹介されていたようなクエリの投げ方を試してみました。GPT-3と比較するとアーキテクチャの規模もデータセットのボリュームも小さいですが、GPTシリーズの面白さは垣間見れた気がしますね。
Pre-trainedのウェイトはHuggingFaceに登録してみました。
下記ウェブサイトで検索(geekfeed/gpt_ja)できます。
また、下記 jupyter notebooksで試すこともできます。
https://github.com/kouohhashi/mytutorials/blob/master/nbs/gpt_ja_example.ipynb
登録したウェイトをダウンロードして試してみると実行する度に結果が異なりますね。事実を事実として記憶、回答することができていないようです。データ量、パラメータ量、学習に使った時間(epoch数)ともに足りないので仕方ないですかねー。
ところで、ギークフィードではディープラーニングを学びたい、AIエンジニアになってみたいプログラマの方を募集しています。興味のある方は弊社採用ページよりお問い合わせください。
https://www.geekfeed.co.jp/recruitment
また、もくもく会(テック勉強会)の一環でプログラマ向けディープラーニング講座を開催しています。
https://geekfeed.connpass.com/
https://geekmokumoku.slack.com/
講義内容はYoutubeで公開させて頂いておりますので、ご興味のある方は是非。
https://www.youtube.com/channel/UC0IJyUzHlG6zUGz1SaavySA
- Simple AWS DeepRacer Reward Function Using Waypoints - 2023-12-19
- Restrict S3 Bucket Access from Specified Resource - 2023-12-16
- Expand Amazon EBS Volume on EC2 Instance without Downtime - 2023-09-28
- Monitor OpenSearch Status On EC2 with CloudWatch Alarm - 2023-07-02
- Tokyo’s Coworking Space Hidden Gem: AWS Startup Loft Tokyo - 2023-05-24