Encoder-DecoderやらTransformerやらGPTの内部がどうなってるのかを理解する
何がしたい?
Encoder-Decoderから現在まで続くGPTモデルに至るまで何がしたかったのか?
入力(単語列)を言語モデルに突っ込んで次に予測される出力(単語列)を得ること 翻訳タスクの場合、例えば
入力: x1,x2,....xn(This is a pen)
言語モデル: (RNNSearch / Transformer 等)
出力: y1,y2,...ym(これはペンです)
正確には単語列を出力するというよりはy1,y2,..y(i-1)に対してyiは何になるか?の確率分布を出力
Encoder-Decoder
入力をGRU(長期記憶を捉えるのに適したRNNの一種。前の入力までの状態ht-1から次の状態tを求める時に良い感じに選択更新できる)で処理していき、入力全体の状態=文脈を表す1つの固定長のベクトル(c)として出力。その情報を元にDecoderで推論したい結果を出力するモデルのこと 大雑把な処理の流れ
Encoder
入力(This is a pen) -> encoding(GRU) -> 一つにまとまった文脈ベクトルc
Decoder
入力(これ) + c -> decoding-> 確率分布(これの次に何が来そうか) -> BeamSearch -> は
入力(これ は) + c -> decoding-> 確率分布(これはの次に何が来そうか) -> BeamSearch -> ペン
入力(これ は ペン) + c -> decoding-> 確率分布(これはペンの次に何が来そうか) -> BeamSearch -> です
入力(これ は ペン です) + c -> decoding-> 確率分布(これはペンですの次に何が来そうか) -> BeamSearch -> EOS(終了)
課題
encoding結果のベクトルの長さが固定 == 学習により理解できる量や複雑度に限界がある == 未知の語句や長い文章の推論に弱い
RNN Search
Encoder-Decoder + Attention
入力の各単語からBiGRU(順方向と逆方向でGRU)で前後の意味情報を加味した単語ベクトルh1,h2,...hnを求めてもっておく。h1,h2,...hnに色々やって重み付けして文脈ベクトルci(=Attention)を生成する。そのAttentionをDecoderにインプットしてあとは普通のDecoderと同様に推論していく。
異なる点は
全ての単語のstepの状態を使うところ
Attentionを使うところ
単語ベクトルの中でどこに注目すべきか?を求めたAttentionを推論で用いると、固定長の文脈ベクトルcしか使えなかった場合に比べて(扱える情報が増えるから)精度が上がる
てかAttentionとは?
Attention自体はNNによる自然言語処理の手法の一つ(モデルではない)。文脈情報をより重要な部分に集中させる(重み付けする)ことでより精度の高い推論を実現するための技術。
あるタスクに対して単語ごとにどの単語が重要かを表現する仕組みと言っても良い。例えば、
入力「猫は可愛い」から作ったAttentionを元に「cat is」に続く単語を予測させる場合は可愛い(cute)に注目されてほしい
RNN SearchでもTransformerでもAttentionの求め方(数式)は異なっている
Transformer
https://scrapbox.io/files/64326e1e5a937f001b47d13b.png
RNNを取っ払ったAttentionだけのEncoder-Decoderモデル。逐次処理する必要なくなった。
タスク:
機械翻訳の場合: 入力(英語) -> 出力(独語の次の単語予測)
以下英独翻訳の場合で話を進める
Encoder
入力: 英語の単語列, 出力: 文脈ベクトル
Input Embedding
Embedding Layer
単語列を行列(単語特徴量)に変換する
猫,は,可愛い -> 3(単語数)dim x 512dim
Positional Encoding
単語特徴量に時系列情報を付与する(時系列情報の行列を付与してsin/cosで-1~1の値に慣らす処理をする)
RNNと違いモデル側で時系列情報を保持してないので特徴量側で時系列情報を扱っている
時系列情報を保持してないというのはそれぞれの単語ベクトルqが同時にEncoderに突っ込まれて処理されていくということ(RNNでは逐次処理されていたので順番情報が次の状態に都度反映されてた)
Multi-Head Attention
Scaled Dot-Product Attention: Multi-Head Attention内で使われているAttention
式
Attention(Q,K,V) = softmax(QK^T / sqrt(dk))V
Q(Query): 入力。これに関連するものをAttentionする(関連度を求める)のが目的。
※Qはq(横ベクトル)を縦に並べたやつ。
K(Key): memory(=元データ)の特徴量。
V(Value): memoryの値(大体K = V)
√dk: 埋め込みベクトルの次元数
確率が低い部分の勾配情報を保持したい
Qに対してK^Tをかけて√dkで割ってsoftmaxしてそれにVをかけたもの
scaling factorを用いた内積(=類似度)
QueryとKeyの類似度を内積で計算し、それに応じた重みでValueを足してる
Multi-Head Attention: 本体
式
MultiHead(Q,K,V) = Concat(head_1,...,head_h) W^O
where
head_i = Attention(QW_i^Q, KW_i^K, VW_i^V)
Attention(Q,K,V) = softmax(QK^T / sqrt(d_k)) V
WiはそれぞれQ,K,Vに対する重み。これを元にAttentionを計算。
Wをかけるのはさまざまな角度からベクトルを比較してどこに注目するのかを制御し出力を調整する役割
というかQ,K,Vは等しいのでWによって変化がないと多様な学習できんだろというのはそれはそう
head_h(つまりqに対するAttention。ベクトル。)を横につなげて(Concat)したものがMulti-Head Attention、ということ
Shortcut Connection, Layer Normalization, Position-wise Feedforward Network
Shortcut Connection
ResNetの要素(残差ブロックとskip connectionのあれ)。より深くlayerを増やすことが可能になる。 Layer Normalization
NNのレイヤの出力を平均0分散1に正規化するやつ
Position-wise Feedforward Network
各単語ごとに隔離された全結合層
Decoder
入力: 一つ前までの独語の単語列, 出力: 次にくると予測される独語の単語(の確率分布)
Multi-Head Attentionを計算する時の入力にEncoderの出力の文脈ベクトルを使う
Masked Multi-Head Attention
Multi-Head Attention + ある単語の次を予測することが目的なのに次以降の単語の情報が見えてるとカンニングみたいな感じになって良くないのでMaskして(0にして)隠してる
GPT
Transformer(Decoder) + PreTraining + FineTuning
Transformer
Decoderのみ
12個積み重なる
PreTraining
背景
学習データを用意するのめちゃきつい。数十億個のデータのラベル付けとかやってられん
どうするか?
ラベル無しのデータを使って学習すれば良い
文章の一部を穴抜けにして、その穴抜け部分を予測させるようなタスクを解くように学習させる
穴抜けの文章とその答えのセット(タスク)は簡単に大量に作れる
大規模なテキストデータセット(数十億個)を用いてこれを行った
結果
単語や文法や文脈理解などの基礎的な言語能力を得られるようになった
FineTuning
PreTrainingしたモデルを使って学習させる
PreTrainingで基本的な学習は終わってるので必要なデータ(1000件くらい)が少なくて良いので楽
GPT2
中身はGPTとほぼ同じ。Transformerを48個積み重ねてる。
学習データをクソデカくして学習させたらどうなるのか?
学習データを自作した
量・質・種類を重視したい->Redditの3karma以上の投稿から収集
15億パラメータ
GPT3
GPT2 + Sparse Transformer / Transformerを96個積み重ねてる。
Sparse Transformer
Multi-Head Attentionを軽量化させた版
元のMulti-Head Attentionでは前の情報を全て参照してたが、Sparse Multi-Head Attentionでは前の情報を一定間隔でまとめて、そのまとめたものを参照するようにしてる
Few-shot / One-shot / Zero-shot
FineTuningよりも学習データを少なくしたい
言語モデルの方を追加学習することすらしない
言語モデルに0件~数件学習データを与えて、その続きを生成させるだけ
This is a pen -> これはペンです, This ia a cat -> XXXでXXXを生成させる
これがOne-Shot学習。2つ以上だとFew-Shotで1つもなしで推論させるならZero-Shot。
In Context Learning
学習データをGPT2よりもっとクソデカくして学習させたらどうなるのか?
データを自作。色んなコーパスから3000億単語くらい。
1750億パラメータ
その他
各種論文
Encoder-Decoder関連
Transformer関連
PyTorchでTransformerを自作する記事
GPT関連
深く理解するにはまず自作するのが良かろうということで色々やってる人がおり、その中でもリファレンス的に参照されているリポジトリがこれ。
上記minGPTの解説記事の日本語訳
X-Shot Learningがなぜうまく機能するのかについての解説
関連知識
BERTとかGPTとかが登場した時系列がまとまってる
スペシャルサンクス
AIcia Solid Projectの動画がわかりやすすぎる
GPTにGPTのことを聞いたりしてた