はじめに
LLMを一度も使わない日はないと言えるほど、すっかりLLMに入り浸っているにも関わらず、思えば一度もTransformerについてきちんと腰を据えて学んだことがなかったと思い出し調べた備忘録を残しておきます。
若輩者がなんとか理解しようと奮闘した記録になります。誤りや理解が及んでいない点が多々あると思いますが、温かい目で見守ってやってください。
Notionにメモしたものをそのままコピペしている箇所が多いので、ですます調が揃っておらず読みづらいですが、その点もご容赦ください。
今回学ぶTransformerについて
最初期のTransformerといえば、かの有名な論文”Attention Is All You Need”(Ashish Vaswani et al., 2017)で紹介されていたものが思い浮かびます。
現在のLLMで採用されているTransformerはより複雑な仕組みになっていることは想像に難くないですが、まずは基本理解からしていきたいので、今回はこれをもとに学んでいきます。
[Ashish Vaswani et al., 2017]より引用
トークン化
文章として与えられた入力を各単語・接頭辞・接尾辞・句読点などに分けて、一意に対応する数値を与える。
具体的には単語ごと、もしくはサブワードごとに分割をし、それを事前準備された語彙表に対応させている。
トークン埋め込みと位置埋め込み
機械学習モデルが文章を理解するために、それを構成するトークンの種類と位置関係を数値で表す必要があり、それを行うのがトークン埋め込み(token embedding)と位置埋め込み(positional embedding)であり、これらはいずれも多次元の数値ベクトルだが、その次元数は言語モデルによって異なる。
トークン埋め込みでは、Word2VecやGloVeなどと同様に、トークン同士の共起情報を用いて数値化される。2つのテキストが似た意味のものである場合、これらは互いに近い場所にマッピングされる。
位置埋め込みでは文章中でのトークンの位置の情報を数値化し、語順の違いを数値で表現している。
Transformerでは以下のように位置埋め込みを定義している。これを各単語の埋め込みに足し込むことで位置情報を付与している。
\displaylines{PE_{(pos,2i)}=\sin(\frac{pos}{10000^{\frac{2i}{d_{model}}}}),\\
PE_{(pos,2i+1)}=\cos(\frac{pos}{10000^{\frac{2i}{d_{model}}}})}
※pos: 位置 (トークンの順番), i: その単語がどこの次元に埋め込まれているか, d_model: 埋め込みベクトルの次元数
最近のモデルでは、正弦や余弦ではなく、学習可能なパラメータとして位置埋め込みを扱っているようです。
Self-Attention・Multi-head Attention
いよいよTransformerの肝とも言えるAttentionに関する部分です。
Transformerは多数のTransformer Blockの連結からなり、それぞれのTransformer BlockはAttention機構とFeedforward層(ニューラルネットワーク)からなる。
トークンの種類・位置関係からそれらの依存関係を把握することが重要。その依存関係を表現する(文脈を追加する)ために用いられるのが、Attention機構。
ここまでの埋め込みでは、異なる意味で捉えられる同じ字面の単語を区別することができない。
ex. Sentence 1: The bank of the river., Sentence 2: Money in the bank.
ここでのbankは前者が土手、後者が銀行を意味するが同じembeddingがなされてしまう。
そこでAttention機構は、関連する単語同士のembeddingを近づけることによって、文脈理解を実現している。
Attentionは、各単語がそれぞれもつQueryとKeyとValueの3つのベクトルで計算される。文中にある単語の意味を理解する際に、文中の単語のどれに注目すれば良いかを表すスコア。
QueryとKeyでAttentionスコアを算出し、そのAttentionスコアを用いてValueを加重和するとAttentionを適用した単語の潜在表現が手に入る。
ここでQ (Query), K (Key), V (Value)はそれぞれ、入力単語EmbeddingXに重みWをかけたもの。
Q = XW^Q, K = XW^K, V = XW^V
このようにして求められたQ, K, Vを用いて縮小付き内積Attentionは算出される。
\displaylines{score_{ij} = \frac{QK^T}{\sqrt{d_k}} \\
Attention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})V}
上式の意味としては、単語Aのクエリと単語A以外の単語のキーの内積により単語Aとその他の単語との関連度を計算する(単語Aがほかの単語iにどの程度注目すべきか)
次にこれを√d_kでスケールした後に、softmax関数で正規化することで、縮小付き内積Attentionスコアが得られる。
※ここでのsoftmax関数は全トークンに対してどれにどのくらい注目すべきかを表す確率分布として解釈するために用いられている。
クエリとキーによる掛け算でAttentionを算出する方法を内積Attention、クエリとキーを入力とした1層の全結合層でAttentionを算出する方法を加法Attentionという。
√d_kでスケールしているのはd_kが大きい際に、こうしないと内積Attentionは加法Attentionの性能を下回ってしまうからとのことでした。
各単語に1組のQuery, Key, Valueを持たせるのではなく、比較的小さいQuery, Key, Valueをヘッドの数分だけ作り、それぞれのヘッドで潜在表現を計算し、最終的に一つのベクトルに落とすことによって得られた潜在表現をその単語の潜在表現とするのが、Multi-Head-Attention。
\displaylines{MultiHead(Q, K, V) = Concat(head_1, head_2, ...\ ,head_h)W^Q \\
where \ head_i= Attention(QW^Q_i, KW^K_i, VW^V_i)}
フィードフォワード層(Feed Forward Network, FNN)
フィードフォワード層は1つの中間層と出力層をもつ2層の順伝播型ニューラルネットワーク。
中間層には活性化関数が配置されており、ReLU関数やGeLU関数がよく用いられる。トークン内の非線形変換を補っている。
一般に中間層は入力層の4倍の次元数になることが多いようです。
フィードフォワード層のパラメータ数はTransformer全体のパラメータの3/4を占めているが、情報がどのように扱われているか詳しいことは不明。
各トークンごとで学習が完結するため、他のトークンから干渉を受けることはない。
FFN(x_t)=f(x_tW_1+b_1)W_2+b_2
線形変換により各特徴を別の高次元空間にマッピングし、それらの関係を活性化関数により非線形化。最後に元の次元に戻して出力。
Add & Norm
AddとはResidual Connection (残差接続) のことであり、NormとはLayer Normalization (レイヤー正規化) のことである。
ともに各Attention, FFNの直後に行われる処理であるが、AttentionやFFNの出力をf(x)としたとき、Residual Connectionは以下のような処理を行う。
y = x + f(x)
出力値に入力値を加えることで勾配消失[爆発]問題に対してアプローチしたものである。
勾配消失[爆発]問題とは、Neural Networkが深くなることによって勾配が減衰・発散し学習が止まってしまう問題
残差接続を入れることによって、勾配が直接入力側から逆伝播されるため、勾配消失問題を緩和し、効果的な学習が可能となる。
一方でLayer Normは以下のような処理を行う。
y=\frac{x−E[x]}{\sqrt{Var[x]+ϵ}}γ+β
AttentionやFFNの出力は層ごとに分布が異なるため、それを上式によって正規化することで、出力を安定させることができる。
Cross-Attention
Decoder側にのみある機構。仕組みとしてはSelf-Attentionとほとんど同じであるが、違いとしてはEncoderとDecoderの両方からの情報が入力となること。
DecoderのSelf-Attentionからの出力をクエリに、Encoderからの出力をバリューとキーに変換し、そこからSelf-Attentionと同様にしてAttentionスコアの算出を行う。
次トークン予測
以上の機構からなるTransformerからの出力ベクトルをもとに、実際に出力する次トークン予測を行う。
まずTransformerが学習したすべてのトークンをベクトル化したものの集合Vを考える。そして予測するトークンの直前のトークンのベクトルと集合Vの各トークンとの内積を計算し、それをSoftmax関数に通すことで[0,1]の範囲で正規化する。
ここで予測したいトークンの直前のトークンのみを計算に用いているのは、Attentionによりこのトークン埋め込みには、それまでのトークンの情報もまた十分に含まれていると考えることができるからだそうです。
これにより次トークンとして出力するトークンの候補を確率のように扱うことが可能となる。
なお、LLMのAPI利用でしばしば考慮するTemperatureやtop_k, top_pといったハイパーパラメータはここでの次トークンの選び方に寄与しています。
- Temperature
この段階で通すSoftmax関数を以下のようにすることにより、出力として得られる確率分布の概形をより尖った(偏った)ものにするか、なだらかなものにするかを調整する。(TがTemperature)
なお、T=0の場合はSoftmax関数で算出された数値のうち最大のものを単純に次トークンとする貪欲法になる。
p(v∣z_t)=\frac{e^{\frac{logits_v}{T}}}{\sum\nolimits_{v} e^{\frac{logits_v}{T}}}
- top_k
Softmax関数で正規化した数値のうち、上位k個のトークンを次トークン候補とする。 - top_p
Softmax関数で正規化した数値のうち、累積値がpを超えない範囲でとったトークンを次トークン候補とする。
Transformerの分類について
今まで読んできた論文や資料でしばしば目にしてきた以下のようなTransformerベースのモデルの分類に関して、??と思うことが多かったです。
- Decoder Only Model
- Encoder Only Model
- Encoder Decoder Model
これはさまざまな場所で見られる分類ですが、GPTやLLaMAのようなモデルはDecoder Only Modelに分類され、BERTやRoBERTaはEncoder Only Model、T5やBARTはEncoder Decoder Modelになるとのこと。
しかし数ベクトルで出力されるBERTなどがEncoder Only Modelであるのはわかるが、Decoder OnlyってDecoderしかないのなら、どうやって計算しているの?とまるでよくわかりませんでした。
Decoder Only Modelでは、エンコーダとのCross-Attention機構がなくなり、Decoderに入力されるのはこれまでの出力文のみとなり、自分のこれまでの出力を参照して次の出力を生成するという仕組みをとっています。(自己回帰モデル)
そのため、ユーザーからの入力はすべて過去の出力としてモデルに渡され、その後になにが続くのか?ということから次の出力は計算されるようです。そういった意味で、明確に入力文をエンコードして内容理解をしているわけではないため、Decoder Onlyと呼ばれているようでした。
参照したサイト・論文
