【論文解説】OpenAI 「GPT」を理解する

AI・機械学習

今回はOpenAIが提案するOpenAI 「GPT」を解説したいと思います。

なお、現在ではGPT2、GPT3というのがありますので、そちらが気になる方は以下の記事をご参照ください。

ただし、GPT2、GPT3の仕組みは、ほとんどこの「GPT」と同じですので、上記の記事ではモデルに関しては変更点しか解説していません。

ですので、仕組みを知りたいという方は、まずこちらの記事を読んでいただき、そのあとに上記の記事でどこが違うかを理解していただければと思います。

OpenAI GPTとは

OpenAI GPTは2018年に以下の論文で提案されたモデルで、基本的にはTransformerをベースに、事前学習-ファインチューニングをすることで非常に高い精度を達成したモデルです。

特に文章生成で非常に良好な結果を残しているようです。

https://s3-us-west-2.amazonaws.com/openai-assets/research-covers/language-unsupervised/language_understanding_paper.pdf

BERTも事前学習の方法が少し違うだけでほぼ同じ仕組みなので、このモデルを理解しておけばBERTの理解も難しくないと思います。

またOpenAI GPTもTransormerベースなので、Transformerと事前学習-ファインチューニング、特にULMFiTがわかっていれば、それほど難しくありません。
むしろ自然な発展と考えられると思います。

GPTの仕組みを理解するにはTransformerをしっかりと理解していた方が良いと思いますので、Transformerがよくわからないという方は以下のTransformerの記事を読んでいただければと思います。(逆にTransformerがわかっていればGPTもあまり難しくありません)

また、ULMFiTはこちらです。

ULMFiTが文書分類に特化していたのに対し、OpenAI GPTではQuestion Answeringなどでも良好な結果を残しています。

OpenAI GPTの仕組み

OpenAI GPTの大きな特徴は以下です。

OpenAI GPTの特徴
  • モデルにTransformerを使う。
  • ラベルなしデータで言語モデルの事前学習、それをラベル付きデータで言語モデルのファインチューニングと教師あり学習による分類器等のファインチューニングを同時に行う。

では、これらを詳しく見ていきたいと思います。

Transformer

Transformerは以下のようなオリジナルのTransformerとそれほど変わりません。

まずは、Positional Encodingです。もとのTransformerと同じで、単語の埋め込み表現にを位置情報を足します。

$$\begin{align}
h_0 = UW_e + W_p
\end{align}$$

\(W_e\)がword embedding matix、\(W_p\)がposition embedding matrixです。

ただし、OpenAI GPTでは、\(W_p\)はオリジナルのTransformerの論文のように\(\sin\)・\(\cos\)を使った方法ではなく、\(W_p\)もデータから学習します。

次のレイヤーですが、Transformerと言っても、ここではencoder-decoderを使ったTransformerではなく、decoderのみのいわゆるTransformer blockを使います。つまり、

$$h_l=\text{transformer_block}\left(h_{l-1}\right)$$

だけになります。\(l=(1,\cdots, n)\)です。そして、softmaxレイヤーで求めます。

$$P(u)=\text{softmax}\left(h_nW_e^T\right)$$

Pretraining, Fine-tuning

Pretraining

まずは、言語モデルの事前学習です。
事前学習は直前の\(k\)個の単語を使って対数尤度を最大化させるように次の単語を求めます。
\(\mathcal{U}\)はラベルなしデータを意味します。

$$L_1\left(\mathcal{U}\right)=\sum_i \log P\left(u_i| u_{i-k}, \cdots, u_{i-1}; \Theta\right)$$

Fine-tuning

次に言語モデルのファインチューニングと分類器のファインチューニングを行います。
ULMFiTではこれらを順番に行っていましたが、OpenAI GPTでは同時に行うようです。

両方ともラベル付きデータを使って行います。
ラベル付きデータの入力単語を\(x_1, \cdots, x_m\)とすると、ラベル\(y\)の予測は最後のtransformer blockの最後の時点の出力\(h_l^m\)のベクトルを使ってsoftmaxレイヤーにより求めます。

$$P\left(y|x^1, \cdots, x^m\right)=\text{softmax}\left(h_l^m W_y\right)$$

そして、ラベル付きデータを\(\mathcal{C}\)とすると、対数尤度

$$L_2\left(\mathcal{C}\right)=\sum_{(x, y)}\log P\left(y|x^1, \cdots, x^m\right)$$

が最大になるようにパラメータを調整します。
さらに、単純に\(L_2\)を最大化させるのではなく、同時に言語モデルのファインチューニングを行います。
その尤度を\(L_3\)とすると、

$$L_3(\mathcal{C})=L_2(\mathcal{C})+\lambda*L_1(\mathcal{C})$$

を最大化するように、言語モデルと分類器のファインチューニングを同時に行います。
\(L_1(\mathcal{C})\)は ラベル付きコーパスを使った言語モデル(Pretrainingのところの式)の学習を意味しています。
この目的関数をauxiliary objectiveと呼んでいます。

インプット

さて、モデルはこれで大丈夫そうです。

あとは、これらをテキスト分類やtextual entailment、question answeringなど色々なタスクに適用できるようにインプットを調整してあげます。

テキスト分類はシンプルです。
テキストの初めにStartトークンをテキストの終わりにExtractトークンを入れてあげます。
Extractトークンの位置にある最後のTransformer blockの出力を分類に使います。

textual entailmentは2つの文章の意味を読み取って、それらの関係を予測するので、Startトークン、Extractトークンに加えて、2つのテキストの間にDelimiter用のトークンを追加します。

類似度を求めるタスクでは、1つ目のテキストと2つ目のテキストの順番は関係ありません。
ですので、1つ目のテキストの次にDelimeter用のトークンを追加し、そのあとに2つ目のテキストをつなげたサンプルと、その逆にしたもをインプットとしたサンプルを2つ同時に作成します。
そして、2つのTransformerのアウトプットをくっつけて処理します。

question answeringなどのタスクで複数の答えがある場合も同様に、複数のTransformerを使って処理します。

こういった処理により、ELMoのようにタスクに特化した処理を少なくすることで、汎用性を高めています。

実験

論文では、BooksCorpusデータセットを使って事前学習しています。
このコーパスは7,000を超える未発表の本からなっています。1B Word Benchmarkというデータセットも使っています。

モデルのセッティング

12個のTransformer block をつなげていて、各blockの隠れ層の次元は768次元、multi-head attentionのhead数は12個です。

position-wise feed-forwardレイヤーの次元は3,072次元です。

オプティマイザーはAdamですが、学習率の最大値を2.5e-4とし、ゼロから2,000 iterationまではその最大値まで増加し、それ以降は、cosineスケジュールにしたがって、ゼロに近づくようにします。

ミニバッチ数は64でエポック数は100、512単語をインプットとします。

単語はBytepair Encodingというのを使っています。
ざっくり言うと、語彙数を減らすため、高頻度の単語は単語そのものを使い、低頻度の単語は文字単位などもう少し細かく分けるというものです。
Bytepair Encodingについては、こちらが非常に参考になります。

Sentencepiece : ニューラル言語処理向けトークナイザ - Qiita
少し時間が経ってしまいましたが、Sentencepiceというニューラル言語処理向けのトークナイザ・脱トークナイザを公開しました。MeCabやKyTeaといった単語分割ソフトウエアとは趣旨や目的が異なるソフトウェアですので、少し丁寧に...

そして、残差結合、embeddingレイヤー、attentionレイヤーにドロップアウト率0.1のドロップアウトを適用し、ウェイト、バイアスにL2正則化を施しています。

活性化関数は以下のGaussian Error Linear Unit(GELU)を使っています。
\(\Phi(\cdot)\)は標準正規分布の分布関数を表します。

$$\begin{align}
\text{GELU}(x)&=x\Phi(x)\\
&\sim0.5x\left(1+\tanh\left[\sqrt{2/\pi}\left(x+0.044715x^3\right)\right]\right)
\end{align}$$

ちなみに、ReLUが0以下の領域で傾きがゼロになるのに対して、GELUはゼロ以下でも一定の領域では傾きがゼロにならないように設計されています。

出所:Gaussian Error Linear Units(GELUs)

GELUについては以下の投稿で少し詳しくみています。

ファインチューニングについては、ドロップアウト率0.1、学習率6.25e-5、バッチサイズ32としています。
これで3エポックぐらいで収束しているとのことです。
なお、\(\lambda\)は0.5です。

結果

では、結果をいくつか順に見てみましょう。

まず、textual entailmentですが、どのデータセットでも精度が上がっています。
1段目は複数モデルのアンサンブルなので単独モデルと比較すると大幅に精度が改善していることがわかります。
ただ、一番小さいRTEというデータセットは2,490サンプルしかなく、そのデータセットでは改善が見られていません。

次に、Question Answeringです。かなり精度が改善していますね。
RACE-mはミドル・スクール、RACE-hはハイ・スクールの英語の試験問題です。

そして、 文書分類 とSemantic similarityです。
Semantic similarityは、2つの文書が意味的に同じものかを判定します。このタスク3つのうち2つでSoTAを達成しています。
QQPデータセットではELMoの結果を大きく超えています。

まとめ

ということで、今回はOpenAI GPTの論文を読んでみました。

Transformer + ULMFiTという感じで、Transformerの扱いやすさとULMFiTの事前学習+ファインチューニングという強力な手法の組み合わせで良好な結果を残しています。

そして、ここからGPT-2、GPT-3と改良されていくことになります。

いつかその辺りも投稿できればと思います。




mm0824

システム開発会社や金融機関で統計や金融工学を使ったモデリング・分析業務を長く担当してきました。

現在はコンサルティング会社のデータ・サイエンティストとして機械学習、自然言語処理技術を使ったモデル構築・データ分析を担当しています。

皆様の業務や勉強のお役に立てれば嬉しいです。

mm0824をフォローする
AI・機械学習 自然言語処理
mm0824をフォローする
楽しみながら理解する自然言語処理入門

コメント

タイトルとURLをコピーしました