
本記事ではよくAIなどをプログラムに使用する時に登場するTransformerの基本的な仕組みを、筆者が学んだこと含めて纏めていきます。
ただTransformerの基本的な部分に絞ってもかなり複雑なので複数回に分けており、本記事では第1回目として、1番最初の入力部分【Input Embedding】とその入り口である【Scaled Dot-Product Attention 】についてご紹介します。
仕組みや概略を理解するのを最優先としているので、間違っている箇所があるかもしれないことにご注意ください。
より詳細な仕組みやコードを知りたい場合は、参考記事に掲載しているリンク先をご覧ください。
全体の流れ
まずはTransformerの簡単な流れを、原文から引用したものが下記です。
そして上図のオレンジ部分である『Multi-Head Attention』部分を図にしたものが下図です。
さらに上図の『Scaled Dot-Product Attention』を分解したものが下図となります。
そのためTransformerを理解するためには、Multi-Head Attentionを理解する必要があります。
そしてMulti-Head Attentionを理解するために、Scaled Dot-Product Attentionも理解する必要があるのです。
Input Embedding
早速Scaled Dot-Product Attentionの解説をと行きたいところですが、そもそもどのようなデータが入力されているのか理解しないと、以降の内容もかなり曖昧になります。
そのためまずは上図の赤枠部分について詳細にご紹介していきます。
トークン化
まずインプットされた文章がプログラムでも理解できるよう、事前に定義された語彙(ボキャブラリー)を元に分割していきます。
本記事でサンプルとしてインプットする文章は、【トムはサッカーが好き】とします
例)
”トムはサッカーが好き”→[123, 13, 6861, 9, 312]
あくまで例なので実際にこのようにトークン化されない可能性がありますが、サンプルとして上記のものをトークン化されたものとします。
ただこれだけだとどのような処理を行われたのか全く分からないため、もう少し詳細に処理を表現したのが下記です。
”トムはサッカーが好き”→["トム”,"は","サッカー","が","好き"]
["トム”,"は","サッカー","が","好き"]→[123, 13, 6861, 9, 312]
【トム:123】【は:13】【サッカー:6861】【が:9】【好き:312】とIDを割り振る処理をしました。
これは一度文章を全て単語に分け、事前に定義されたIDに割り振っただけのとても簡単な処理をしています。
まとめるとトークンIDは使用するトークナイザーで事前に定義された語彙に対応したIDです。
あくまで上記のトークン化した時のIDは、本記事内だけのサンプルとしてご覧ください。
Embedding(エンベディング)
次にトークン化されたものをベクトルに変換するEmbeddingをしていきます。
全てのトークンに対して行われますが、サンプルとして”トム”に絞って記載します。
例)
トム(ID:123)→[0.12,0.87,-0.5......](768次元)
Embeddingすると、上記のようにかなり高次元なベクトルになりますが、何次元になるかは使用するモデルによって異なります。
ここで”トム”という単語が、なぜここまで768次元という想像もしにくい高次元なベクトルになるかというと、"トム"という単語が示す特徴を全て含んでいるからです。
ここで分かりやすくするため例を用います。
例えば、”トム”と”マリー”と”車”の3つのトークンがあり、Embeddingするとします。
トム = [0.6 , 0.4]
マリー = [0.8 , 0.3]
車 = [-0.9 , 0.8]
この時、1つ目の要素を【生物的であるか】で判断し、2つ目の要素を【重量】とした場合、2次元のベクトルは下図のようになります。

上図を見ればハッキリと、人名を示す”トム”と”マリー”のベクトルと、無機物である”車”のベクトルが向かう向きは違うと分かるでしょう。
ですが、ここで”チンパンジー”というトークンを追加すると、”トム”や”マリー”と同じようなベクトルになりますが、人とチンパンジーを類似度の高い言葉と見なすの生物学的な意味以外では大変失礼です。
そうならないよう、要素に【知能指数】や【平均寿命】などを追加しなくてはならず、それが最初にご紹介した”トム”が768次元もある理由となります。
言い換えるならばベクトルの要素は言葉が示すプロファイリングとも言え、次元数はどれくらいその言葉を精密に捉えているかを示すと言えるでしょう。
どうしてベクトルなのか
ベクトルの要素が言葉のプロファイリングだと納得できたと思いますが、どうしてベクトルなのかと疑問に思った方も多いでしょう。
この答えは簡潔に自然言語を数学的に扱えるようにするためです。
筆者は最初、下記のようにした方が正確に比較できると考えていました。
”トム”=["性別" : 0 , "年齢" : 20 , "身長" : 170 ...]
そして各ラベルごとに比較を行い、類似度を計算するという考えでしたが、Transformerのラベルは重要視しません。
各要素ごとに比較するのではなく、出力されるベクトルが類似するかどうか、これを最も重要視しているのです。
こうすることで例えば例え年齢や性別、身長が大きく違っていても高次元のベクトルでは大した違いにはなりにくいです。
また他にはベクトルを使うことで意味の操作や勾配計算ができるなどのメリットがあるらしいですが、筆者の理解はそこまで追いついていないので今はこれで納得してください。
Positional Encording
複雑な処理に見えて、ただトークンをベクトル化したものに、位置情報ベクトルを加算しています。
この位置情報を埋め込んでおかないと、ベクトル化したトークンの文章がぐちゃぐちゃに処理されてしまうため、簡単ですが必要な処理となっています。
概念的には、文字情報が集まったベクトルに、位置情報のベクトルを加算させ、文字と位置情報が集まったベクトルになったという理解で問題ありません。
Scaled Dot-Product Attention
次にベクトル化された各トークンたちの中から入力するベクトルを作成するわけですが、いくつかの工程があるため分割して説明していきます。
上記が処理の流れとなっており、詳しく見ていきます。
ただしモデルを可能な限り簡略化し理解しやすいようにするため、本記事では【Mask(opt)】の部分を一旦無視してご紹介します。
QKVを作る
まずは全トークン内で、最も注目すべきベクトルはを作り出していきます。
そのベクトルとは下記の3つ。
Query:質問(一体どのような情報が欲しいのか)
Key:特徴(持っている情報の特徴)
Value:実際の情報(渡される情報の中身)
このQKVが特に分かりにくく、概念や感覚に近いものになります。
例えば【トム】のベクトル(以下Xトム)を使った場合、Query(以下Qトム)は一体どんな情報を持っているのかという形にベクトルを作ります。
本記事の例だと、【トム】という情報で一体何を言いたいのか、どのような単語と繋がりがあるのかをQトムで示そうとしているのです。
次に【トム】のKey(以下Kトム)は、このトークンが文章中でどのような意味合いを含んでいるのかを示すベクトルになります。
本記事の例だと、以下Kトムは主語であり人名だと示すベクトルになるでしょう。
最後に【トム】のValue(以下Vトム)は、トムがという意味そのものが出力されます。
本記事の例だとVトム、は、人物名であることは恐らく人間の男性、固有名詞らしいというベクトルが入るわけです。
そしてこのQトムやKトム、Vトムの作り方は、学習結果を使って得ます。
具体的な計算式は下記。
Qトム= Xトム × WQ
Kトム= Xトム × WK
Vトム= Xトム × WV
Xトム:【トム】のベクトルであり、WQとWKとWVは学習結果で作られた重み付き行列で、線形変換と呼ばれる処理をしています。
行列は高校の学習指導要領の変更で復活したり廃止したりしているので、場合によっては習っていない人もいるかもしれません。
習っていない人、もしくは復習したい人は下記の記事をご参照ください。
この処理を全てのトークンに対して行っていきます。
つまり本記事の例だと”トム”、”は”、”サッカー”、”が”、”好き”、の5つのトークンにそれぞれQKVを計算します。
関係値を算出
次にどのトークンがどのトークンと深いかを算出していきます。
【注意】【Attention係数】【Attentionスコア】などと呼ばれている値の事です。
まずは分かりやすいよう、”トム”を参考にして各トークンとの関係値を求めるとします。
この場合、Qトムと各ベクトルのKを内積して取得します。
そもそもQはどのような意味なのか質問するようなベクトルであり、Kは特徴を表すベクトルであるため、QとKのベクトルの内積が高い=類似していると見なせます。
似たような処理としてコサイン類似度が挙げられ、こちらは仕事などで活用するので馴染みやすいかもしれません。
知らない人も参考程度にはなるため、詳細は下記の記事をご参照ください。
ただし、Transformerで行っているのはコサイン類似度ではないので、処理の意味程度を掴む程度に留めてください。
この類似度を全てのトークンに対して行うのを、簡潔に記したのが原文にも登場する【QKT】となります。
本記事の流れを理解している方は、ここでQとKと書かれてもどのトークンのものか分からなくなるため、分かりやすくすると【QAllKAllT】です。
ここでのAllは名前の通り”全て”であり、Tは転置行列を示すものです。
転置行列については下記の記事をご参照ください。
つまり、QAllKAllTをちゃんと示すと下記のようになっています。
計算結果まで含めると記事の横幅を超過したため、QAllKAllTのみとなります。
実数しか使用できませんが、行列の計算の仕組みなどは下記のサイトを使って試してみてください。
これで全トークンの関係値、コサイン類似度を計算することができました。
スケーリング
次にこのまま計算にしようしたいところですが、このままだと非常に扱いにくいです。
なぜなら内積の結果にかなりばらつきがあり、データ処理をする上で勾配が強すぎるからです。
そのため内積のばらつきを一定値以内に抑えるため、QKTの次元数を使って分散を減らしていきます。
分散を減らす計算処理が下記。
上記のは、QKTの次元数に平方根を付けたもので、多くの場合Embeddingした時の次元数になります。
※のkはQKVのKではありません
ただし、使用する WQやWK、WVによって次元が変わるため絶対ではありません。
これで必要以上に大きくなった内積の値をスケーリングした後、Softmaxでさらに正規化します。
Softmax関数については下記の記事をご参照ください。
ここまでの処理を1つに纏めたのが、原文にも出てくる下記の式となります。
線形変換
さてここまで複雑な指揮が出てきましたが、これでやっと一息付けます。
ここまでで出してきたものを使っていなかったQKVのVと掛け合わせて線形変換を行い、それが下記の式となります。
上記の式が原文も出てきますが、これで理解できる人はかなり少ないでしょう。
そのため、もっと分かりやすくするため、下記のように分解してみてください。
上記の式を更に処理内容などの概念的なものとしてとらえると、下記のようになります。
正規化 ( スケーリング × 関係値をまとめた行列 ) × 実際の情報が入ったベクトル
つまり難しく書いていますがやっていることは、関係が深そうなものを0から1の値に正規化した行列と、実際の情報が入ったベクトルを掛け合わせて線形変換をしているだけです。
Matmulとは
流れの図にある【Matmul】ですが、これは行列の積なので実は既にしてあるため気にする必要はありません。
ただどのようなものなのか気になった人は、下記の記事をご参照ください。
参考記事
Transformerを提唱した原論文は上記から見られます。
原論文を解説してくださっている記事が上記。
Attention Is All You Needの簡単な概略は、上記のWikipediaを参照
Transformerの基本については上記を参照
自己注意(Self-Attention)についての解説は上記2つの記事を参照
Scaled Dot-Product Attentionの説明は上記を参照
本記事の内容は以上となります。
今回はガッツリと概念や計算式などが出てきたので、高校や大学にかするようなレベルの数学を勉強し直す必要があります。
次回もTransformerの動作について学んだことを書こうと思っていますので、気になった人は気長にお待ちください。
本記事は以上です。お疲れさまでした。



