こんにちは、42Tokyoにおりますyamatoといいます。
今回はTransformerとEmbeddingについてまとめました。
ざっくりいうと、Transformerは凄腕のシェフで、Embeddingは完成した料理のイメージでよいと思います。
Transformerについて
Transformerは、2017年にGoogleが発表した論文「Attention Is All You Need」で提案された、新しいニューラルネットワークのアーキテクチャです。主にNLPの分野で使われ、ChatGPTやGeminiなどで使われています。chatGPTのGPTは、Generative Pre-trained Transformerの略です。
Transformer登場以前の課題
RNNやLSTM等のニューラルネットワークは、とても素晴らしい技術です。(自分もここら辺はまだまだ勉強中です。いつか再実装とかできたら、記事書きます。)しかしながら、これらは、文章を単語の数だけ順番に処理していました。文が長くなると、最初の方の単語の意味を忘れてしまうという弱点がありました。例えば、アガサ・クリスティの名作『そして誰もいなくなった』をRNNに読ませると、「なんか10人ぐらい死んだぞ。最初に死んだ人誰だっけ?」みたいなことが起こります。迷宮入り確定です。
Transformerの登場
では、Transformerはそれらをどう解決したのか。Transformerは、文章を順番に処理するのではなく、一度に全体を見渡します。そして、文中のある単語の意味を理解するために、「文中の他の全ての単語との関連性の強さ(注目度)」を一気に計算します。この「文章全体の関係性を一発で計算する」アプローチにより、長い文章でも文脈を失うことなく、高速かつ高精度な処理が可能になったのです。
Transformerの全体像
・全体の構造
1.前処理層
1-1 トークン化 &
1-2 初期ベクトル化
入力テキストは「トークン」に分解され、各トークンはID番号に変換されます。その後、このIDは埋め込み行列(Embedding Matrix) $E$を使って初期ベクトル$Xtextembedding$に変換されます。
1-3 位置情報の付与
Transformerは語順をそのままでは理解できないため、「この単語は何番目にあるか」という位置情報をベクトル化し、足し合わせる必要があります。各単語の位置'pos'と、ベクトルの各次元'i'に基づいて、以下の**位置エンコーディング(PE)**ベクトルを計算します。
PE_(pos,2i) = \sin(pos/10000^{2i/d_{model}})
PE_(pos,2i+1) = \cos(pos/10000^{2i/d_{model}})
※ここの$d_{model}$はTransformerモデル内で一貫して使われる、基本となるベクトルのサイズのことです。例えば、「Attention Is All You Need」では、$d_{model} = 512$ に設定されています。つまり、モデル内のすべての単語は512個の数値のリストとして表現されます。
最終的にエンコーダー層への入力となるベクトル行列$X$は、以下のように表せます。
X = X_{embendding}+X_{PE}
2.エンコーダー層
ここがTransformerの心臓部です。入力ベクトル行列$X$は、このエンコーダー層を何層も(例: BERTなら12層)通過することで、文脈を深く理解していきます。
2-1 自己注意機構 (Multi-Head Self-Attention)
まず、入力$X$は、学習済みの重み行列$W^Q,W^K,W^V$を使って、Query,Key,Valueという3つの行列に変換されます。
Q = XW^Q
K = XW^K
V = XW^V
次に、これらの行列を使ってAttentionスコアを計算します。これは、「どの単語にどれだけ注目すべきか」という重みを計算する処理です。
Attention(Q,K,V) = softmax\bigg(\frac{QK^T}{\sqrt{d_k}}\bigg)V
この式の役割は以下の通りです
・ $QK^T$:QueryとKeyの内積を取り、単語間の関連性スコアを計算します
・$\sqrt{d_k}$:スコアの大きさを調整するためのスケーリング因子です。
*スケーリング因子とは?:数値の大きさをちょうど良い範囲へ調整するために使われる、 特定の定数のことです。ニューラルネットワークのような複雑な計算では、途中の計算結果が極端に大きく、または小さくなってしまうことがあります。値が大きすぎると、計算が不安定になったり、学習がうまく進まなくなる「勾配消失」という問題を引き起こしたりします。
*$d_k$:Self-Attentionの内部で使われる、QueryベクトルとKeyベクトルの次元数 を指します。$d_model$次元のベクトルから、より小さな$d_k$次元のQuery(Q)とKey(K)を生成して、単語間の関連性スコアを計算する役割を果たします。
・$softmax(...)$:正規化しています
・$...V$:Valueベクトルの加重平均を取ります。これにより、文脈を反映した新し いベクトルになります。
実際には、この計算を複数パターン(マルチヘッド)で並列実行し、より豊かな文脈を捉えます。
2-2 全結合層
自己注意機構で文脈情報が付与されたベクトル$x$は、さらに2層の全結合ニューラルネットワークで処理されます。これにより、さらに複雑な特徴表現への変換が行われます。
FFN(x) = max(0,xW_1+b_1)W_2+b_2
・$W_1,b_1,W_2,b_2$は学習済みの重み行列とバイアスベクトルです
・$max(...)$はRelu関数です
各エンコーダー層では、この2つのステップの後に、それぞれ**残差接続(Add)と正規化(Norm)**という処理が挟まれ、深く層を重ねても学習が安定するように工夫されています。
3.出力層
プーリング
文章全体を表す単一のベクトルを得るために、この複数のトークンベクトルを集約します。一般的な手法として、文頭に置かれた特殊な**'[CLS]'トークン**の最終ベクトルを、文章全体のベクトルとして採用します。
この一連の複雑な行列計算を経て、入力されたテキストは、最終的にその豊かな意味を凝縮した一つのベクトルとして出力されるのです。
Embeddingについて
一言でいうと、Embeddingとは、テキスト(単語や文章)の「意味」を、コンピュータが扱える数値の配列(ベクトル)に変換したものです。
なぜベクトルに変換する必要があるのか
コンピュータは「意味」という曖昧な概念を直接は扱えません。得意なのは数値計算だけです。そこで、単語や文章を**多次元空間上の「座標」**として表現することで、意味の計算を可能にします。
この「意味の空間」では、似た意味を持つ単語は互いに近い位置に、関係ない単語は遠い位置にプロットされるように学習されます。
「意味」を計算する:ベクトル演算の魔法
Embeddingの凄さを示す最も有名な例が、以下のベクトル演算です。
'ベクトル("王様") - ベクトル("男性") + ベクトル("女性")'
この計算を行うと、その結果はベクトル空間上で'ベクトル("女王様")'に非常に近い座標を示します。これは、ベクトル間の幾何学的な関係が、「王族」「性別」といった意味的な関係性を正確に捉えていることを意味します。
Transformerが生み出す「文脈を読んだ」Embedding
以下の二つの例文を見てみましょう
・She wrote a novel about a detective solving a mystery in ancient Rome.
・Using a drone for pizza delivery is still a novel idea in this city.
以前のEmbeddingでは、どちらのノーベルも同じ意味として計算してしまっていましたが、Transformerの登場により、文脈に応じて最適なEmbeddingを生成することができるようになりました。これが、現代のAIが非常に高い精度で言語を理解できる理由の核心です。
このEmbedding(ベクトル)こそが、RAGシステムにおける類似度検索や、あらゆるAIタスクの出発点となる、最も重要な「成果物」なのです