Encoder
The cat sleeps .
原文を読み、ことば同士の関係を反映した数の並び(ベクトル)に変換します。原文の各位置に、その表現が残ります。
TRANSFORMER EXPLAINER 予備知識なしで、はじめよう
まず全体をつかみ、必要な部品を学び、左右の構造をつなぐ。
8つの章を「次へ」で進むと、原論文の図を順番に読めます。
第1章 / 8
Transformerは何を受け取って、何を返す?
翻訳を例に、入口と出口だけを見ます。図の箱の名前は、このあとの章で1つずつ扱います。
The cat sleeps .
原文を読み、ことば同士の関係を反映した数の並び(ベクトル)に変換します。原文の各位置に、その表現が残ります。
開始 猫 は ?
訳文の前半を読み、Encoderの情報も参照して次の訳文トークンを予測します。出力を1つ選び、末尾に足して続けます。
上の文は翻訳の仕組みを示す例です。左と右は同時に使う2つのネットワークであり、「左が学習用・右が生成用」という分担ではありません。
最初は、この2つの役割だけつかめば大丈夫です。下の図で左右の位置を確認したら、「次へ」で入力のトークン化から始めましょう。
この章では、同じ2トークンの例を最後まで使います
第3章では、トークンごとに入力ベクトルを作りました。Attentionは、それらを使って各トークンに対応する出力ベクトルを1つずつ計算します。この出力は後続の層の計算に使う数の並びです。
第3章の8次元の数値を切り取ったものではありません。入力と重みを手で用意した、計算を追うための例です。日本語の意味を学習したモデルではありません。
Q・K・Vを作る → 点数を作る → 係数に変える → Vを掛けて足す、という一連の計算を行う経路を、ヘッド(head)と呼びます。
Q・K・Vを作る は、学習する3つの重み行列です。ヘッド1はヘッド1用の3つ、ヘッド2はヘッド2用の別の3つを持ちます。「ヘッド専用の重み」とは、このことです。同じヘッド内では、全トークンに同じ3つの行列を使います。
同じ入力を、別々の重みを持つ複数のヘッドで並列に計算するのがMulti-Head Attentionです。1単語につき1ヘッドではありません。1つのヘッドが、全トークンの出力を計算します。この章では、そのうち1ヘッドの「眠る」の出力を拡大して追います。
同じ入力から、各Vに掛ける割合が異なる複数の出力を作れるようにするためです。Q用・K用の重みが違えば点数と割合を変えられ、V用の重みが違えば足し合わせるベクトル自体も変えられます。これが、複数のヘッドで表現力を増やす仕組みです。
各ヘッドの重みは通常、それぞれ別の乱数で初期化し、最終予測の誤差から一緒に学習します。もし全ヘッドで3つの重みをすべて同じにすれば、同じ入力に同じ計算をして、同じ出力を繰り返すだけになります。
各ヘッドに「主語用」「動詞用」などの担当をあらかじめ決めるわけではなく、必ず別の役割に分かれる保証もありません。原論文では各ヘッドを小さい次元にして、単一の大きなヘッドと同程度の計算量に抑えています。単に重みの総数を増やすだけの工夫ではありません。
「眠る」という単語を予測する計算ではありません。「猫」「眠る」はすでに入力にあり、それぞれの行に新しいベクトルを計算する段階です。
各入力に、3種類の重み行列を掛けます。 はQ用、 はK用、 はV用です。Wはweight(重み)を表します。これらはAttention内部の線形層の重みで、通常は乱数から学習で調整します。
Q = Query:出力を計算する行のQを使う。今回は「眠る」のQ。
K = Key:そのQとの内積で、トークンごとの点数を作る。
V = Value:点数から決めた係数を掛け、最後に足すベクトル。
入力
入力
ここから先は「眠る」のQを1つと、両方のK・Vを使います。Qを作った行と、出力を計算する行は同じです。
すべて1行目=猫、2行目=眠るです。小文字qは1トークンのベクトル、大文字Qは2行をまとめた行列を指します。
この例の重みは次の3つです。同じ行列を猫・眠る両方の入力に掛けます。Qの操作を行った場合、この表と計算式も連動して変わります。
入力は 。入力の各数字に重みを掛け、Qの各成分を作ります。下の図は、現在の重みと連動しています。
線に付いた係数を行列にまとめたものが です。行が入力の成分、列がQの成分に対応します。
入力の第1・第2成分を 、Qの第1・第2成分を と書きます。 は のi行j列の1つの数です。
、。ここでは行ベクトルに右から行列を掛けます。
同じ「眠る」の入力から、KとVも次のように計算します。
同じ「眠る」のQで、猫のK・眠るのKとの点数を1つずつ計算します。その2つの点数から、猫のV・眠るのVに掛ける係数を決めます。
Qの1つ目を増やすと、Kの1つ目の数字を点数に強く反映します。この操作では2つ目を同じだけ減らします。
実際のQには負の数も使え、合計1という制約もありません。この図では変化を追いやすくするため、[0, 1]と[1, 0]の間だけで動かします。
この操作ではQ用の重みを変え、上のQ行列・重みの計算式・下の出力まで、すべて同じ状態で再計算します。
眠るのQ × 猫のK
点数:
この点数は、眠るの出力を計算するときの猫のVの係数を決めるために使う。
眠るのQ × 眠るのK
点数:
この点数は、眠るの出力を計算するときの眠るのVの係数を決めるために使う。
まず、Q・Kの成分が2個なので点数を で割ります。次にSoftmaxを使います。割り算後の各点数sを という正の数に変え、2つの合計で割る計算です()。
平方根で割るのは、成分数が大きくなったときに内積の振れが大きくなり、Softmaxが極端に偏ることを抑えるためです。
使ったQは「眠る」のQ。猫のVと眠るのVを、上で決めた係数で足した結果です。
これは点数でも、入力から作ったVそのものでもありません。複数のVの加重和です。このベクトルを と呼びます。2つの数字は第1・第2成分で、「猫・眠るの点数」ではありません。
次は、ほかのヘッドが計算した「眠る」の出力と横に連結し、出力側のLinearに渡します。
表示は小数を丸めています。内部の計算には丸める前の値を使います。ここで計算しているのはAttentionの1ヘッドの出力で、次の単語の予測ではありません。
猫のQと両方のKから、猫の出力を計算。眠るのQと両方のKから、眠るの出力を計算。それを行に並べたものがZです。実際には行列の掛け算で、全行をまとめて計算できます。単語に当たる計算単位は、厳密にはトークンです。
下の青い行は、すべて「眠る」の出力用です。点数・係数の列は、左が猫のV用、右が眠るのV用。最終出力の列は、ベクトルの第1・第2成分です。
はKの行と列を入れ替えたものです。Qの各行と、転置したKの各列を掛けて足すと、全組み合わせの点数が一度に求まります。
点数を√2で割り、
各行にSoftmax
点数の2行目・1列目は、眠るのQと猫のKの内積。その点数から作った係数を猫のVに掛け、出力の2行目の足し算に使います。
この例ではすべて2行×2列ですが、列の意味は異なります。トークン数をT、Vの成分数を とすると、点数と係数Aは 、Vと出力Zは 。出力にはトークンごとに1行ずつ、Vと同じ成分数のベクトルが残ります。
2ヘッドの場合を図にすると、次の順番です。上で計算したZを、ここでは と書き、もう一方のヘッドの出力を と書きます。下付き数字はヘッド番号です。それぞれの行列には、猫・眠るの両方の行があります。
入力にこの3つの行列を掛ける
→ Q・K・V → 点数 → 係数 → Vの加重和
入力にこの3つの行列を掛ける
→ Q・K・V → 点数 → 係数 → Vの加重和
連結という操作だけを確かめる例(上の実験とは別の説明用の数値)
上の連結例の続きを、説明用に手で決めた で計算します。実モデルでは、この行列の数字も学習します。
第1成分は 。第2成分は 。連結で並べた4つの成分から、新しい2つの成分を計算しました。
原論文のベースモデルでは、64成分×8ヘッドを連結して512成分にし、512行×512列の で512成分へ変換します。出力側のLinearは、必ず成分数を減らすわけではありません。
は、すべて学習する重みです。モデルを作るときに行列を用意し、通常は乱数で初期化します。学習では、最終的な予測と正解のずれから、それぞれの重みの更新量を計算します。 をQ・K・V用の重みやConcatの結果から生成するわけではありません。学習後の通常の推論では、これらの重みを固定して使います。
原論文のベースモデルは8ヘッドです。上のスライダーで動く計算は1ヘッドのZまでです。ここで示した連結・出力側のLinearの数値例は、操作を説明するための固定の例です。
Kの1つ目の数字だけが点数になる。
Kの2つ目の数字だけが点数になる。
は、1つのKベクトルの1つ目・2つ目の数字です。この例では、Kの各成分に「主語」「動詞」などの意味は割り当てていません。
「探す条件」と呼んでいたのは、QがKの成分への係数となって、各Vを足す割合を決めることです。たとえばQ = [1, 0]では猫のVを約59%、Q = [0, 1]では猫のVを約33%使います。上の図の「Qの係数を動かす」を開くと、この変化を試せます。
「眠る」の入力 は固定し、説明用の の2行目を変えています。Qは毎回 で再計算しています。K用・V用の重みは固定です。
これは手で重みを動かす実験です。実際の学習では、最終的な予測と正解のずれから重みの更新量を計算します。
最初から役立つ係数を作れるわけではありません。学習では、上の図の計算を含めてモデル全体を動かし、最後に予測した単語の確率を、正解と照らし合わせます。
Qは「Kの成分への係数」を作る側、Kは「その係数を掛けられる数字」を作る側です。QとKを違う側につなぐ設計は最初から決まっています。その両方を、予測の誤差を減らすように学習します。Qの中に日本語の質問文ができる、という意味ではありません。
Self-Attentionでは、入力は同じで、掛ける行列が違います。どちらの重みも最初は乱数です。QとKが別の役割を持つのは、作った後の使い方を、モデルの設計で分けているからです。
出力の2行目(眠る)を計算するときは、眠るのQを使います。出力の1行目(猫)を計算するときは、猫のQを使います。一方、猫のKは、どちらの行を計算するときにも、猫のVに掛ける係数を決める計算に使います。
| 点数の表 | 猫のK | 眠るのK |
|---|---|---|
| 猫のQ | 0 | 1 |
| 眠るのQ | 1 | 0.5 |
眠るのQだけを変えると、青い行の点数が変わり、出力の2行目を計算するときのVの係数が変わる。
| 点数の表 | 猫のK | 眠るのK |
|---|---|---|
| 猫のQ | 0 | 1 |
| 眠るのQ | 1 | 0.5 |
猫のKだけを変えると、茶色の列の点数が変わる。出力の1行目・2行目を計算するときの、猫のVの係数に影響する。
表の各マスは、行のQと列のKの内積です。ここでは、そのベクトル以外を固定して影響を見ることにしています。実際には重みを全トークンで共有するため、 を更新すれば複数のQが、 を更新すれば複数のKが変わります。
この行と列の区別は、学習を始める前からあります。各行の点数を割合に変え、その割合をVに掛けて足し、同じ行番号の出力ベクトルとする、という計算が決まっているためです。QとKは、その計算で担当する側に付けた名前です。
学習では、最終的な予測の間違いから「どの点数をどう動かすと、間違いが減るか」を計算します。その点数はQとKからできているので、さらにQとK、それを作った重みへと、変化の影響を逆にたどれます。
そのため、同じ形の「入力 × 重み」でも、Q用とK用では重みの更新内容が異なります。予測の間違いを減らすように両方を調整すると、各行の出力を計算するときに、どのVへどれだけの係数を掛けるか、その係数を決める点数の付け方を学習できます。
設計で決めるもの:QとKの担当する側。
学習で獲得するもの:その担当で、予測に役立つ点数を出す能力。
ランダムな数列が自然に「質問」や「鍵」という別種類のデータに変化するわけではありません。Qの数列だけを見て、そこに日本語の質問文が入っていると解釈することもできません。
出力ベクトルの行番号をi、係数を掛けるVの行番号をjとします。見通しのため、√dで割る前の点数を と書きます。予測の誤差をL、その点数を少し変えたときの誤差の変わり方を と置くと:
Q側には、同じ出力行で使ったすべての点数からの影響が足されます。
K側には、同じVの係数を決めたすべての点数からの影響が足されます。この違いが、それぞれを作った重みへも伝わります。Softmax・Vの足し算・後続の層・スコアのスケーリングを通じた影響は、ここでのgに含めています。
Xは入力ベクトルをトークン順に並べた行列です。入力行列をSと書く資料もあります。式の隣り合った文字の間は行列の掛け算です。
はKの行と列を入れ替えた行列(転置)。 の1マスが、行のQと列のKの内積になります。Kを転置することで、この組み合わせを行列の掛け算で計算できます。
はQ・Kの成分数です。ここでは2。Softmaxを各行に適用して係数に変え、その行の係数でVを足します。
Wは学習する重み行列です。一方、Softmaxの結果も「Attentionの重み」と呼ばれますが、こちらは入力から毎回計算する係数です。
Figure 1のMulti-Head Attentionの箱を開くと、Figure 2に描かれた3つのLinearがあります。入力に重みを掛けてQ・K・Vを作る部分です。
原論文では、ヘッドiのQ用の重みを と書きます。ここでは1ヘッドに注目して と表記しています。Figure 2の入口のQ・K・Vは射影前の材料を指し、このページでは射影後をQ・K・Vと呼んでいます。
層・ヘッド・Attentionの種類ごとに、別の重みがあります。DecoderのCross-AttentionのK・VはEncoderの出力から作りますが、その変換の重みはDecoderのCross-Attentionに属します。左右の材料の違いは第6章で扱います。
第5章では、ずっと「眠る」の数列を追います
第4章では各ヘッドの出力を計算しました。ここからは、同じ「眠る」の出力を連結して、Encoderの1層の終わりまで進めます。各カードの最後の数列が、次のカードの入力です。
2ヘッドの出力を と とした、小さな例です。入力・重み・ヘッド出力は手で用意しており、第4章のスライダーの結果や512次元モデルの一部ではありません。以下の5段階は、この例の数値でつながっています。
↓ ヘッド1の2成分の後ろに、ヘッド2の2成分を置く
この段階では足したり平均したりしません。ヘッドごとの結果を、次の掛け算で一緒に使えるよう1行に並べます。
この例では、説明用の を下の数値に設定しています。1や−0.5は、入力から突然出てきた数ではなく、この行列の中の重みです。実モデルでは、これらの数字を学習で調整します。
式が収まらない場合は、式の上を横にスクロールできます。
出力の第2成分には、色を付けた第2列を上から順に使います。4つの入力 に、4つの重み を1つずつ掛け、すべて足します。他の出力成分も、使う列が変わるだけです。
どの出力成分も「4回掛けて、4項を足す」計算です。この例の第2列には0でない重みが2つあるので、第2成分では2つの項が0にならずに残ります。第2成分だけ別の計算ルールがあるわけではありません。
連結では数字を並べただけでした。Linearでは、学習する係数を使ってヘッドの成分を組み合わせます。この例では第2成分に、両ヘッドの数 を使っています。
Attentionの計算結果を元の入力に足す経路を残差接続と呼びます。元の入力が、Attentionの計算を通らずに足し算へ届く経路を作ります。
「眠る」の4成分だけを足して、4で割ります。平均は 2。別のトークンの数は使いません。
平均より小さい数はマイナス、大きい数はプラスになります。これで数列の中心が0にそろいます。
平均との差を同じ数で割り、数列の広がりをそろえます。Softmaxのように合計を1にする処理ではありません。
平均との差をそれぞれ2乗すると、次の数になります。
その平均が 2。0で割ることを防ぐ小さな数0.00001を足し、平方根を取ると 1.414 です。この値で各成分を割っています。
数の大きさの変動を抑え、学習を進めやすくする処理です。LayerNormには、成分ごとに掛ける係数 (ガンマ)と足す数 (ベータ)もあります。各Normが別々に持つ学習パラメータで、通常はガンマを1、ベータを0から学習します。この章の2か所のNormでは、すべて に固定しているため、上の数列はそのままです。
途中の6成分は、元の4成分から作る6通りの計算結果です。それぞれ別の係数で掛けて足し、ReLUで負の結果を0にします。この複数の結果を組み合わせることで、単なる1回の行列の掛け算より複雑な変換を学習できます。
6は、この説明用に選んだ内部の成分数です。必ず6にする必要も、必ず増やす必要もありません。内部を広くするほど、ReLUを通す計算を多く持てますが、重みの数と計算量も増えます。
最後に4へ戻すのは、次のAddで、FFNに入る前の4成分と1対1で足すためです。戻すのは成分数で、数字を元に戻す処理ではありません。原論文では同じ考え方で512 → 2048 → 512にしています。
FFNはFeed Forward Networkの略です。このEncoder層のFFNには、Attentionとは別に、次の2組の学習パラメータがあります。Wは掛ける重み行列、bは掛け算の後に足すベクトル(バイアス)です。添字の1・2はFFN内での順番で、ヘッド番号やEncoderの層番号ではありません。
掛ける行列:(4行×6列)
足す数:(6成分)
掛ける行列:(6行×4列)
足す数:(4成分)
も、通常は別々の乱数で初期化して学習します。 も学習対象ですが、初期値は実装によって0や乱数です。最終的な予測の誤差から、Attentionの重みと一緒に更新します。同じ層内の全トークンに同じFFNを使い、別の層のFFNは別の重みを持ちます。
ここからの数字は、計算を追うために手で設定した値です。学習済みの値でも、このページで学習させた結果でもありません。
この例の1つ目の重み行列とバイアスは、次の数値です。行列の1列が、出力1成分の掛ける係数を決めます。6列あるので、6成分を作れます。
式が収まらない場合は、式の上を横にスクロールできます。
例えば第5成分には、 の第5列 を掛け、 の第5成分である1を足します。
0以上の数はそのまま残します。下の各列で、変化の前後を比べてください。
「負なら0にする」という分岐を挟むことで、行列の掛け算だけでは作れない変換ができます。すべてLinearだけなら、何段重ねても1つのLinearにまとめられてしまいます。
前のReLUを通った6つの数を、そのまま次の掛け算に使います。上で説明した はこのLinearの掛ける重み、 は足すバイアスです。どちらも学習対象で、ここでは下の数値を手で設定しています。
式が収まらない場合は、式の上を横にスクロールできます。
6行あるので入力の6成分をすべて使い、4列あるので4成分を作ります。6成分のうち4つを選んで残す処理ではありません。
例えば出力の第2成分は、色を付けた第2列 を掛け、 の第2成分0を足して求めます。「第5成分の半分」になるのは、この列の5番目が0.5だからです。
この間、使ったのは「眠る」の1行の数だけです。FFNは、1トークン内の成分を組み合わせて変換します。他のトークンのVを使ったAttentionとは、計算の範囲が違います。
FFNに入る前の1トークンのベクトルを と置きます。括弧の内側から、1つ目のLinear → ReLU → 2つ目のLinearの順で計算します。
ここで足すのは、カード3の最後に得たFFNに入る前の数列です。Attentionに入る前の とは異なります。
「眠る」の4成分だけを足して、4で割ります。平均は 1.509。別のトークンの数は使いません。
平均より小さい数はマイナス、大きい数はプラスになります。これで数列の中心が0にそろいます。
平均との差を同じ数で割り、数列の広がりをそろえます。Softmaxのように合計を1にする処理ではありません。
平均との差をそれぞれ2乗すると、次の数になります。
その平均が 1.148。0で割ることを防ぐ小さな数0.00001を足し、平方根を取ると 1.072 です。この値で各成分を割っています。
ここでPositional Encoding(位置情報)をもう一度足すことはありません。原論文では、埋め込みに位置情報を足すのは、最初のEncoder層に入る前の1回だけです。2層目以降は、前の層の出力をそのまま入力にします。
各層の処理:Multi-Head Self-Attention → Add & Norm → FFN → Add & Norm
Nは、最初の層も含めた合計の層数です。原論文ではN=6なので、いまの計算が1層目なら、続けて2〜6層目の残り5層を通します。各層の処理の構成は同じですが、重みは層ごとに別です。
次の層は、この数列にその層の を掛け、新たなQ・K・Vを作ります。同じ処理を「猫」などすべてのトークンの行にも行います。Linear・FFNの重みは同じ層内で共通、Normの平均とばらつきは各行で別々に計算します。
原論文の図1では、Positional Encodingの足し算が「N×」の枠の外にあります。位置情報を加えた入力を各層が順に変換するので、後の層の計算もその入力に基づいています。出典:§3.5 Positional Encoding。
説明用の例は2ヘッド×2成分を連結して4成分、FFNは4 → 6 → 4成分です。原論文のベースモデルは8ヘッド×64成分を連結して512成分、FFNは512 → 2048 → 512成分です。
ここでは全トークンの行をまとめた行列で書きます。入力をX、各ヘッドの出力を 、出力側のLinearの結果をO、最初のAdd & Normの結果をH、このEncoder層の最終結果を と呼びます。
この章は原論文の「足してから正規化する」順序です。Dropout(学習時だけ、処理結果の成分を一定確率で0にして過度な依存を抑える処理)は省略しています。出典:Transformer §3.1・§3.3、Layer Normalization §3。
表示は小数第3位までに丸めています。後続の計算は丸める前の値を使います。下の任意の8次元実験は別のモデルです。
第4章の計算を、Decoderの2つのAttentionにつなぐ
第4章では、QとKから点数を作り、Softmaxで係数に変え、その係数でVを足しました。Decoderでも同じ計算を使います。新しく見るのは、どの位置を隠すかと、Q・K・Vをどちらの文から作るかです。
4トークンの最終出力を保存しておく。Decoderは、この4行を参照する。
今回は2行目の「猫」を追う。この行から次の「は」を予測するので、3行目の「は」は隠す。
学習時は、正解を右にずらした列をまとめて入力できます。上はその先頭3位置です。「猫」の行が使えるのは「開始・猫」まで。生成時に「は」をまだ選んでいなければ、入力自体が「開始・猫」までです。右シフトと生成の繰り返しは第8章で詳しく見ます。
入力と重みは手で用意しています。第4章の操作結果・第5章の4次元出力・下の8次元実験とは別の例です。各Attentionを1ヘッドにし、出力側のLinearは数値を変えない行列に固定して、2種類のAttentionの間も同じ数値でつなぎます。
表や長い数式が画面に収まらないときは、その部分を左右にスクロールして読めます。
第1層なら、埋め込みに位置情報を足した行列が入力Xです。この例では、その段階の数値を次のように決めます。Q・K・Vはすべて同じXから作りますが、掛ける重みは3種類です。Selfは「同じ列を使う」という意味で、Q・K・Vが同じ数値という意味ではありません。
| 訳文側の行 | 入力X | Q | K | V |
|---|---|---|---|---|
| 1:開始 | ||||
| 2:猫 | ||||
| 3:は |
今回使うQは「猫」の 。このQで各Kとの点数を計算し、「猫」の出力ベクトルを1つ作ります。「開始」「は」のQは、それぞれの行の出力を作るときに使います。
下の3行列がこのSelf-Attention用の重みです。同じヘッド内では、3トークンすべてに同じ行列を掛けます。バイアス(掛け算後に足す数)は0です。
「猫」の入力は [0, 1]。行ベクトルと行列の掛け算なので、結果の第1成分には行列の第1列、第2成分には第2列を使います。
実際のモデルでは、この行列も学習で調整します。下で計算する「Attentionの重み」は、入力から毎回作る係数であり、ここでの重み行列とは別のものです。
まず「猫」のQ = [1, 0]と各Kの内積を取ります。Q・Kは2成分なので√2で割ります。ここまでは第4章と同じです。そのあと、「猫」より後ろにある「は」の点数を −∞(負の無限大)に置き換えます。
| 参照する位置 | QとKの内積 | √2で割る | マスク後 | Softmax |
|---|---|---|---|---|
| 開始 | 1×1 + 0×0 = 1 | 0.7071 | 0.7071 | 58.7% |
| 猫 | 1×0.5 + 0×1 = 0.5 | 0.3536 | 0.3536 | 41.3% |
| は(未来) | 1×1.5 + 0×1 = 1.5 | 1.0607 | −∞ | 0.0% |
各点数sを正の数 に変え、合計で割ります。 なので、「は」は合計にも加わりません。
合計は約3.4522。「開始」の係数は2.0281 ÷ 3.4522 ≈ 0.5875、「猫」は1.4241 ÷ 3.4522 ≈ 0.4125、「は」は0です。
点数を0にするだけでは隠せません。 なので、0の点数にも割合が残るためです。マスクは、Softmaxの前に適用します。
第1成分は0.5875×2 ≈ 1.175、第2成分は0.4125×4 ≈ 1.6501。
これがMasked Self-Attentionの1ヘッドの「猫」の出力です。「は」のVは係数0なので、足し算の結果に入りません。
行は「どのQの出力を作るか」、列は「どのK・Vを参照するか」です。自分自身の位置も参照できます。
| 出力の行 ↓ / 参照先 → | 開始 | 猫 | は |
|---|---|---|---|
| 開始 | 使える | 隠す | 隠す |
| 猫 | 使える | 使える | 隠す |
| は | 使える | 使える | 使える |
このマスクで計算した係数の行列は次のとおりです。各行の合計は1で、右上の未来の位置は0です。
「は」が猫より高い点数1.5を持っていても、猫の行からは使えません。比較のため猫の行のマスクを外すと、係数は 、出力は に変わります。未来の情報が混ざった結果です。
第5章で見たAdd & Normです。本来は各ヘッドの出力を連結し、出力側のLinearを通してから足します。この例は1ヘッドで、 を に固定しているので、出力は変わりません。
平均は約1.9125。各成分から平均を引くと 。分散に小さな数0.00001を足し、平方根を取った約0.7376で割ります。
この例では、正規化後に掛ける係数γを1、足す数βを0に固定しています。−1と1に見える値も実際には少し違い、後続には丸める前の値を渡します。
Cross-AttentionのQの材料は、この新しい です。元の入力 [0, 1] や、先ほどのSelf-AttentionのQ [1, 0] をそのまま使うのではありません。訳文の前半を読んだ結果から、次のQを作り直します。
原文を参照するAttentionを、Cross-Attentionと呼びます。出力を作りたい行は訳文側の「猫」のまま、参照先が原文の4位置へ変わります。左のEncoderから渡すのは、原文の各トークンが最後のEncoder層まで通ったベクトルです。
直前のAdd & Normの「猫」の行
↓ Cross-Attention用の を掛ける
このQを、原文の4つのKと比べる。
Encoderの最終出力を並べた行列
行は上から The・cat・sleeps・.。K用・V用の重みを別々に掛ける。
原文側の数値も、説明のためにここで用意した値です。catの行 [1, 0] などに英語の意味を学習させているわけではありません。Theと「.」を [0, 0] にしたのは、掛け算を追いやすくするためです。
| 原文の位置 | Encoderの最終出力 | K | V |
|---|---|---|---|
| 1:The | |||
| 2:cat | |||
| 3:sleeps | |||
| 4:. |
このCross-Attentionの重みは次の3つです。Self-Attentionの3つとは別のパラメータで、学習対象になります。説明用に同じ数値を置いた行列も、実際には別々に学習できます。
たとえば、丸めて書いた「猫」の行 [−1, 1] から作るQは、次の掛け算です。
原文catの [1, 0] にはK用・V用の行列を掛けます。Kは [1, 0]、Vは [2, 0] です。sleepsの [0, 1] からは、K = [0, 1]、V = [0, 4] を作ります。
Encoder内部で使ったK・Vを持ってくるのではありません。Encoderの最終出力から、このDecoder層のCross-Attention用のK・Vを新しく作ります。
使うQは約 [1, 0]。計算手順は第4章と同じです。各Kとの内積 → √2で割る → Softmax → Vの加重和、と進みます。原文は最初から全文が与えられているので、原文の後ろの位置を隠す因果マスクは使いません。
| 原文の参照先 | QとKの内積(概算) | √2で割る | Vに掛ける係数 |
|---|---|---|---|
| The | 1×0 + 0×0 = 0 | 0 | 19.9% |
| cat | 1×1 + 0×0 ≈ 1 | 0.7071 | 40.3% |
| sleeps | 1×0 + 0×1 = 0 | 0 | 19.9% |
| . | 1×0 + 0×0 = 0 | 0 | 19.9% |
指数を取ると約 。合計は約5.0281なので、catの係数は2.0281 ÷ 5.0281 ≈ 0.4034。ほかの3位置はそれぞれ1 ÷ 5.0281 ≈ 0.1989です。
Theと「.」は点数0ですが、係数は0になっていません。先ほどの「未来を隠す −∞」との違いです。
× 0.1989
× 0.4034
× 0.1989
× 0.1989
第1成分は0 + 0.8067 + 0 + 0。第2成分は0 + 0 + 0.7955 + 0。
4つの原文位置を参照しても、できるのは訳文側の「猫」に対応する1本のベクトルです。2つの成分は語彙候補の点数ではありません。また、catの割合が大きいことだけで「正しく翻訳できた」とは判断できません。
「開始」「は」の行でも、それぞれのAdd & Normの結果からQを作り、同じ原文4位置のK・Vを使います。小文字sが1行のベクトル、大文字Sが全行を並べた行列です。
Kを転置して掛けると、点数は3行×4列です。各行でSoftmaxを使い、次の係数Aを作ります。
| 訳文 ↓ / 原文 → | The | cat | sleeps | . |
|---|---|---|---|---|
| 開始 | 0.2863 | 0.1412 | 0.2863 | 0.2863 |
| 猫 | 0.1989 | 0.4034 | 0.1989 | 0.1989 |
| は | 0.1989 | 0.4034 | 0.1989 | 0.1989 |
青い2行目が、上で追った「猫」の係数です。この行の4つの係数でVの4行を足すと、「猫」の出力2成分ができます。
出力の行数はQ側、成分数はV側にそろいます。原文と訳文のトークン数が同じでなくても、QとKの成分数がそろっていれば点数を計算できます。
Cross-Attentionのあとにも、連結 → 出力側のLinear → Add & Normがあります。この例はここも1ヘッド・数値を変えないLinearです。足す元の入力は、Cross-Attentionに入る直前の「猫」のベクトルです。Encoderの原文ベクトルを直接足すわけではありません。
に を足すと、。これを同じ方法で正規化した がFFNの入力です。
2成分だけの例では、Normの結果がどちらも約 [−1, 1] になります。これはこの数値例の性質です。実モデルで、原文を参照しても表現がいつも同じになるわけではありません。
| 図の場所 | Qの材料 | K・Vの材料 | 参照できる範囲 |
|---|---|---|---|
| 左:Self-Attention | Encoderの現在の入力表現 | 同じEncoderの現在の入力表現 | 原文の全位置 |
| 右下:Masked Self-Attention | Decoderの現在の入力表現 | 同じDecoderの現在の入力表現 | 訳文の自分の位置と、それ以前 |
| 右中央:Cross-Attention | 直前のAdd & Normの結果 | Encoderの最終出力 | 原文の全位置 |
「全位置」は有効なトークンの範囲です。長さをそろえる詰め物(padding)は、未来を隠す因果マスクとは別のマスクで隠します。この例にはpaddingはありません。
Cross-Attentionの材料を、訳文側は 、原文側は と書くと、次の式になります。添字のdecとencは、材料の出どころを区別する印です。
Masked Self-AttentionはQ・K・Vを同じ入力Xから作り、Softmaxの前にマスク行列Mを足します。Mは使える位置が0、未来の位置が−∞です。
原論文のベースモデルは各Attentionが8ヘッドです。SelfとCrossは、それぞれのヘッドにQ・K・V用の重みを持ち、連結後の出力側の重みも別々に持ちます。この例は各1ヘッドでDropoutを省略しています。
参照できます。sleepsは原文の3位置目ですが、原文は最初から全文が与えられています。隠すのは、訳文側で「猫」より後ろにある「は」です。原文と訳文の位置番号を比べて隠すのではありません。
数値は小数第4位まで、割合は小数第1位までに丸めています。計算には丸める前の値を使います。下の任意の数値実験は別の8次元モデルです。
同じ「眠る」の行で、横の計算と縦の計算を追う
第4章では1ヘッドの出力、第5章ではAttentionのあとの処理、第6章ではDecoderの2種類のAttentionを見ました。この章では、それらがいくつあり、何を次へ渡すのかを整理します。
同じ層の入力から、別々のQ・K・Vを作って計算する。結果は横に連結して、1つのAttentionの出力にまとめる。
AttentionだけでなくAdd & Norm・FFNまで通した出力を、次の層へ渡す。次の層は、その新しい入力で計算を始める。
「猫」「眠る」の入力と重みを手で用意しました。各ヘッドのQ・K・Vは2成分です。第4〜6章の数値を引き継いだものではありません。Encoderの1層を計算し、その結果から次の層のQを作るところまで追います。
横長の表や数式は、その部分を左右にスクロールして読めます。
入力Xは、トークンごとのベクトルを行に並べたものです。この例では1行目が猫、2行目が眠る。第1層の手前で、すでに埋め込みと位置情報を足した段階の値だと考えます。
このヘッド用の
猫・眠るの両方の行を計算する
このヘッド用の
猫・眠るの両方の行を計算する
「猫用のヘッド」と「眠る用のヘッド」に分けるのではありません。どちらのヘッドも同じ2行を受け取り、それぞれ2行分の出力を作ります。ヘッド2の入力に、ヘッド1の出力を渡すこともありません。
入力は同じでも、掛ける重みが違えばQ・K・Vは変わります。下は実際に掛け算した結果です。今回追う「眠る」の出力には、各ヘッドの「眠る」のQを使います。
| 行 | Q | K | V |
|---|---|---|---|
| 猫 | |||
| 眠る |
| 行 | Q | K | V |
|---|---|---|---|
| 猫 | |||
| 眠る |
ヘッド1の「眠る」のQは [0, 1]、ヘッド2は [1, 0] です。Kのどの成分を点数に反映するかが違うので、Vを混ぜる割合も変わります。V自体も、別の重みから作った数値です。
各ヘッドはQ用・K用・V用の3行列を持ちます。2ヘッドなら合計6行列。ここではすべて4行×2列で、4成分の入力を2成分へ変換します。
たとえばヘッド2のQは、次のように計算します。
第1成分は0×0 + 1×0 + 0×0 + 1×1 = 1。第2成分は0×0 + 1×0 + 0×1 + 1×0 = 0です。ここでは計算を見やすくするため0の多い行列を使いました。実モデルでは、全入力成分を混ぜる重みを学習できます。
使う手順は第4章と同じです。「眠る」のQと両方のKで点数を作り、Q・Kが2成分なので√2で割り、Softmaxを使います。Encoderの例なので、猫・眠るの両方を参照できます。
0と1/√2を指数にすると、約1と2.0281です。合計3.0281で割ると、1 ÷ 3.0281 ≈ 0.3302、2.0281 ÷ 3.0281 ≈ 0.6698。ヘッド2では点数の順が逆なので、係数の順も逆になります。
どちらのヘッドでも、係数の順は「猫・眠る」です。出力の2成分の順は「第1成分・第2成分」で、トークン別の確率ではありません。
「眠る」の出力同士を横に並べる操作がConcatです。2成分 + 2成分で4成分になります。足し算や平均はせず、順に並べます。猫の出力を眠るの行に混ぜることはありません。
左の2成分がヘッド1、右の2成分がヘッド2です。
次に、このAttentionが持つ出力側の重み を掛けます。Q・K・V用の重みとは別の行列で、両ヘッドの結果を混ぜて、層の入力と同じ4成分へ整えます。
第1成分は、連結した第1成分と第3成分を足した0.6605 + 0.6698 ≈ 1.3302。第2成分は1.3395 + 0.9907 ≈ 2.3302。第3・第4成分は、そのまま残る重みにしました。
まだ1層が終わったわけではありません。ここまでで終わったのは、その層にあるMulti-Head Attentionの計算です。
第5章の処理を、いま計算した4成分に続けます。最初のAddで足すのは元の「眠る」の入力 [0, 1, 0, 1]。FFN後のAddでは、FFNに入る直前の値を足します。
FFNの重みは第5章の説明例と同じものを使い、今回の新しい入力で再計算しています。前半のLinearではバイアスを足し、ReLUで負の成分を0にし、後半のLinearとバイアスで4成分へ戻します。
前半のバイアスは 、後半は です。Normは各行で平均を引き、分散 + 0.00001の平方根で割ります。γ = 1、β = 0、Dropoutなしの説明例です。
| 行 | 成分1 | 成分2 | 成分3 | 成分4 |
|---|---|---|---|---|
| 猫 | 1.308 | 0.6344 | -0.9712 | -0.9712 |
| 眠る | -1.2624 | 1.27 | 0.626 | -0.6337 |
猫の行も同じ1層の手順で計算しました。入力と同じ2行×4成分を保っているので、次の層へそのまま渡せます。
第2層には、上の最終出力が入力されます。第1層の入力Xや、ヘッドごとの出力をそのままもう一度使うのではありません。位置情報をここで再び足すこともありません。
この例では、入力の第1・第2成分を入れ替えてQを作る行列を用意しました。第1層のヘッド1とは別の行列です。
新しい入力の第2成分がQの第1成分、第1成分がQの第2成分になります。
第1層のQ [0, 1] とは違う値で、次のAttentionを始めます。
次は第2層のK・Vも作り直し、全ヘッドを計算 → 連結 → Linear → Add & Norm → FFN → Add & Norm、と進みます。この章で数値を追うのは、第2層の入口のQまでです。
「同じ構造をN層」は、「同じ重みをN回使う」ではありません。各層の各ヘッドに独自のQ・K・V用の重みがあり、出力側のLinear・FFN・Normのパラメータも層ごとに持ちます。
原論文のベースモデルでは、1ヘッドのQ・K・Vは64成分、8ヘッドを連結すると512成分です。出力側のLinearも512成分を出すので、元の入力に足せます。
Self-Attention → FFN
各処理のあとにAdd & Norm
Masked Self-Attention → Cross-Attention → FFN
各処理のあとにAdd & Norm
Decoderの1層には、8ヘッドのMasked Self-Attentionと、別の8ヘッドのCross-Attentionがあります。各Decoder層のCross-Attentionは、同じEncoderの最終出力を、その層専用の重みでK・Vに変えます。
Encoderは6層×各層1個で、Attentionの箱は6個。Decoderは6層×各層2個で12個。合計18個の箱が、それぞれ8ヘッドを持ちます。18×8 = 144はヘッドの総数で、144層という意味ではありません。
同じ各層の重みを使って、猫も眠るも、別の入力文も計算します。一方、別の層・別のヘッドには別の重みがあります。ヘッド数が入力の単語数によって増減するわけではありません。
別の重みがあるので、異なる割合やVを使う表現を学習できます。ただし「主語用」「動詞用」と人が担当を決めるわけではなく、必ず違う役割になる保証もありません。原論文ではヘッドを増やすときに各ヘッドの成分数を小さくして、全体の計算量を抑えています。
表示は小数第4位までに丸め、後続の計算は丸める前の値を使っています。次の章では、最後のDecoder層の出力を語彙の確率に変える計算へ進みます。
最後のベクトルから、次の1トークンを選ぶまで
第7章までで、各トークンのベクトルが層を通って更新される流れを見ました。ここでは、最後のDecoder層を出たあとを追います。ベクトルの数値が、そのまま文字になるわけではありません。候補ごとの点数を作り、確率に変え、トークンを1つ選びます。
開始猫は
原文は The cat sleeps .。訳文は「猫 は」までできています。次に使うのは、入力の最後にある「は」の行です。
この2成分から、次の「眠る」などの候補に点数を付ける。2成分は2つの単語の点数ではありません。
最後のDecoderベクトルと出力用の重みは手で用意しています。第6・7章の出力を引き継いだ計算ではありません。この例のベクトルから先のLinear・Softmax・選択は、表示どおりに計算しています。
候補は「猫・は・眠る・。・終了」の5つに絞りました。「開始」は入力を始めるための専用トークンです。この5候補表には含めません。実モデルの語彙はもっと大きく、単語より小さな単位も含みます。
横長の表や数式は、その部分を左右にスクロールして読めます。
最後のベクトルをh、出力用の重みを と呼びます。vocabは語彙を表す印です。1候補につき1列の重みがあり、hとの掛け算と足し算で、その候補の点数を1つ作ります。
| 入力成分 ↓ / 候補 → | 猫 | は | 眠る | 。 | 終了 |
|---|---|---|---|---|---|
| 成分1に掛ける | 1 | 1 | 0 | -1 | 0 |
| 成分2に掛ける | 0 | 1 | 1 | 0 | -1 |
| 候補 | 第1成分の分 + 第2成分の分 | logit |
|---|---|---|
| 猫 | (−1)×1 + 2×(0) | -1 |
| は | (−1)×1 + 2×(1) | 1 |
| 眠る | (−1)×0 + 2×(1) | 2 |
| 。 | (−1)×-1 + 2×(0) | 1 |
| 終了 | (−1)×0 + 2×(-1) | -2 |
この点数をlogit(ロジット)と呼びます。負でもよく、合計1である必要もありません。今回の点数は 。順序はずっと「猫・は・眠る・。・終了」です。
1行×2列のhに、2行×5列の重みを掛け、1行×5列の点数を作ります。実モデルなら512成分を語彙数V個の点数へ変えるので、重みは512行×V列です。
この重みは学習対象です。この例では掛け算後のバイアスを0にしています。Attentionの連結後に使った とは置かれる場所も役割も違います。
第4章では、Softmaxで各Vに掛ける係数を作りました。ここでは語彙の5候補に対する確率を作ります。計算方法は同じでも、列が何を表すかが違います。
| 候補 | logit | 指数を取る | 合計で割る | 確率 |
|---|---|---|---|---|
| 猫 | -1 | 0.3679 | 0.0276 | 2.8% |
| は | 1 | 2.7183 | 0.2039 | 20.4% |
| 眠る | 2 | 7.3891 | 0.5544 | 55.4% |
| 。 | 1 | 2.7183 | 0.2039 | 20.4% |
| 終了 | -2 | 0.1353 | 0.0102 | 1.0% |
55.4%です。ただし、これはこの例の重みと入力から計算された値です。「その文が正しい確率」や「モデルが理解した割合」ではありません。
ℓはlogit、jは注目する候補、kは合計に入れる全候補の番号です。実装では、指数を取る前に全logitから最大値を引くと、同じ確率のまま大きすぎる数を避けられます。このページの計算もそうしています。
温度Tを使う場合は、logitをTで割ってからSoftmaxを使います。正のTを小さくすると高い点数に確率が集中し、大きくすると平らになります。この主例はT = 1です。下の8次元実験で変化を試せます。
Softmaxは確率を作るだけです。実際にどのトークンを出すかは、次の選択処理で決めます。ここでは最大確率の候補を選ぶ方法(greedy、貪欲法)で「眠る」を選びます。
開始猫は
最後の「は」の行で次を予測する。
開始猫は眠る
次は、最後の「眠る」の行で続きを予測する。
追加するのは「眠る」のトークンIDです。確率ベクトルやhを、そのまま文字列に足すわけではありません。次の計算では、そのIDの埋め込みと新しい位置の情報を使い、Decoderの各層を通します。
確率に従ってランダムに選ぶサンプリングなら、今回も「眠る」以外を選ぶ可能性があります。複数の候補列を残して比較するbeam searchもあります。選び方によって文章が変わるので、確率を作る処理と、トークンを決める処理を分けて考えます。
下の「次の1トークン」で、入力の末尾が増える様子を追えます。各回のlogitは、上と同じ出力用の重みから計算します。変わるのは、最後のDecoderベクトルです。
5回の生成を順に追う
原文はずっと The cat sleeps .。Encoderの最終出力を各回のCross-Attentionで参照します。
各回の最終Decoderベクトルは、生成の手順を示すために用意した固定値です。翻訳モデル全体を動かして得た値ではありません。そこから先の点数・確率・最大候補の選択は実際に計算しています。3回目が上で追った [−1, 2] の例です。
「終了」を選んだら、この例の生成は終わりです。開始・終了の専用トークンは、表示する訳文「猫 は 眠る 。」には含めません。実際の生成システムでは、終了が出なくても最大トークン数などの条件で止めます。
| 対象 | 生成を1つ進めたとき |
|---|---|
| 原文とEncoderの最終出力 | 同じ原文なので再利用できる |
| 学習したモデルの重み | 通常の生成中は固定。毎回学習し直さない |
| Decoderへの入力 | 選んだトークンが末尾に1つ増える |
| 予測に使う最後の行 | 新しい末尾の位置へ移る |
| logit・確率 | その行のベクトルから新しく計算する |
実装では過去位置のK・Vを保存するキャッシュなどで計算を省けます。「毎回、長くなった入力から次を予測する」という依存関係は同じです。
学習では正解の訳文が分かっています。正解が「猫 は 眠る 。」なら、開始・終了の専用トークンを使って次の2列を作ります。
| 位置 | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| Decoderへの入力 | 開始 | 猫 | は | 眠る | 。 |
| 当てたい正解 | 猫 | は | 眠る | 。 | 終了 |
入力「は」の位置で、次の「眠る」を当てます。同じ位置に答えそのものを入れないための工夫が右シフトです。ただし入力の4位置目には「眠る」があるので、ずらすだけでは答えが見えてしまいます。
開始:使える猫:使えるは:使える眠る:隠す。:隠す
「は」のQからは、自分の位置までの3つのK・Vだけを使えます。右シフトで入力をずらし、マスクで後ろを隠す。この2つで、次の正解を見ずに予測させます。
全位置の正解があるので、学習時にはこの5行の予測をまとめて計算できます。各行に違うマスクを使い、それぞれの「次」を当てます。生成時は次の入力トークンがまだ決まっていないため、選択と追加を1回ずつ進めます。
上の「は」の位置の正解が「眠る」なら、注目するのは「眠る」に付けた確率0.5544です。基本の交差エントロピーでは、この1位置の損失を で計算します。logは自然対数です。
正解の確率が0.9なら損失は約0.1054、0.1なら約2.3026。正解に低い確率を付けるほど、損失が大きくなります。
通常の学習では、選んだ単語を正解と比べるだけではなく、正解の確率そのものを使います。最大候補を選ぶ前の、連続した数値から重みの更新量を求めます。
これは基本の交差エントロピーを示した例です。原論文では、正解だけに確率1を割り当てる目標を少しなだらかにするlabel smoothingも使っています。上の損失はその追加処理を省略しています。
埋め込み表Eは「語彙数×成分数」で、トークンIDを指定して1行取り出す表でした。出力側は「成分数×語彙数」の行列を掛け、全候補の点数を一度に作ります。原論文では、埋め込みと出力用の重みの数値を共有しています。
転置で行と列を入れ替えると、入力では表の1行を取り出し、出力では全候補のベクトルと内積を取れます。この章は出力用の行列だけを用意し、埋め込みから最後のhまでの計算は省略した例です。
通常の生成では、重みは固定したままです。変わる入力から、新しいベクトル・点数・確率を計算します。正解の訳文を使って損失を計算し、重みを更新するのは学習の段階です。
表示は小数第4位まで、割合は小数第1位までに丸めています。計算は丸める前の値を使います。選択方法・学習の補足:原論文 §5.4(label smoothing)、§6.1(beam search)。
構造・次元・計算式の出典:Vaswani et al., Attention Is All You Need, Figure 1・Figure 2・3.1–3.5節。上の翻訳例・2次元と4次元の数値例は、仕組みの説明のために作成しました。
ここでは「猫 は 庭 で 眠る」を使います。8次元・未学習のDecoderモデルで、EncoderとCross-Attentionは含みません。上の翻訳例とは別の、計算を確かめる実験です。
スペースで区切って、1〜8個まで入力できます。登録されていないことばは「未知のことば」として計算します。
この章の数値実験
「見方」は別々の重みを使う計算経路(ヘッド)。切り替えて、混ぜる割合を比べられます。
この章で扱う部分を緑で示しています。図は下から上へ読みます。
狭い画面では図を横にスクロールできます。左がEncoder、右がDecoderです。
第1章と原論文の対応
箱を迂回する矢印は残差接続。元のベクトルを処理結果に足します。Add & Normは、その加算とLayerNormを表します。
この表は各章の8次元実験についてです。第4章の2次元例・第5章の4次元例は、別に手で設定した説明用の計算です。
| 項目 | 論文のベースモデル | 8次元の数値実験 |
|---|---|---|
| 構成 | Encoder + Decoder | Decoder側を簡略化 |
| 繰り返し N | 各6層 | 1層 |
| 埋め込み次元 | 512 | 8 |
| ヘッド数 | 8 | 2 |
| FFN内部次元 | 2048 | 16 |
| 学習 | 翻訳データで学習 | 固定乱数・未学習 |
この8次元実験はEncoderとEncoder–Decoder Attention(Cross-Attention)を省略しています。以下の式のd_modelはベクトルの成分数です。また、原論文の埋め込みへのの乗算、埋め込みと出力射影の重み共有、Dropoutは再現していません。この実験のLinearで掛け算の後に足すベクトル(バイアス)は0です。LayerNormで正規化した後に掛ける係数をγ、足す数をβと呼び、この実験ではです。
Encoderは原文を読み、Decoderはその情報を参照しながら訳文を作る。
全8章を読み終えました。原文を読む → 訳文から原文を参照する → 次を選ぶ、という流れを、図の箱とつなげて振り返れます。
この実験の読み方 色はベクトルの値、線の太さはAttentionの重みを表します。Attentionの大きさだけで、意味の理解や予測の原因がわかるわけではありません。実際のモデルは学習した重みと多数のブロックを使います。
さらに読む:Q・K・Vの実験 · 位置情報の実験 · Attention Is All You Need ↗