Dance with Agents

Attentionは、クエリとキーを突き合わせて、どの語からどれだけ情報を取り込むかを決めている。その割合はモデルの中に保存されていない

アドバンスド比喩で止めず、実際の数値で計算を追ったり、部品ごとの差分まで踏み込みます。同じ題材の一段手前の記事を読んだ前提です

LLMの中では、1つの語の意味が、周りの語の情報を取り込みながら定まっていきます。「川に架かるはし」の「はし」が橋を指すと分かるのは、「川」「架かる」の情報が混ざるからです。

このとき、どの語からどれだけ取り込むかという割合が必要になります。この記事ではこれを配分と呼びます。

『LLMの中でやっていることは2つだけ』では、この配分を「その場で計算される」とだけ書きました。その計算を、実際の数で追いかけます。

例として、1語を3個の数値(ベクトル)で表す、実物より小さいモデルを用意する

LLMは文章をそのまま扱いません。まず短い断片に切り、その断片1つ1つを数値の並びに置き換えてから計算します。切り分けられた断片1つをトークン、置き換えた先の数値の並びをベクトルと呼びます。実物のモデルでは、1つのトークンが1024個や4096個の数値からなるベクトルになります。

トークンの切れ目は単語とは一致しません。日本語では「走る」が「走」と「る」に割れることもあります。ただしこの記事は切れ目の話には立ち入らないので、「犬が走る」が「犬」「が」「走る」の3つに切れたものとして進めます。以降、この3つは語と呼びます。

そのうえで、1つの語を3個の数値からなるベクトルで表すモデルがあるとします。1024個のままでは、この記事に数値を並べて追いかけられないからです。

「3」が2回出てきますが、数えているものが違います。

登場する「3」 何を数えているか
3語 文に入っている語の数。犬・が・走るで3つ
3個 1語のベクトルに入っている数値の個数。犬で3個、がで3個、走るで3個

3語ぶんのベクトルを並べると、こうなります。この記事に登場する数値は、説明のために仮に作ったサンプルです。実物のモデルから取り出した値ではありません。

犬   : (1, 2, 0)
が   : (0, 1, 1)
走る : (2, 0, 1)

3個のうち1個目が動物らしさ、といった対応はしていません。3個そろって初めて、1つの場所が決まります。 緯度と経度の2個で地球上の1地点が決まるのと同じです。決まる場所は、意味空間——意味の近い語どうしが近くに置かれた空間——の中の1地点。この記事では以降、この場所をその語の位置と呼びます。

各語のベクトルから、クエリ・キー・バリューの3つを作る

配分を決めるのに、語のベクトルどうしをそのまま比べるわけではありません。まず、各語のベクトルから、別のベクトルを3種類作ります。 どれも3個の数値からできています。

3種類が必要な理由は、「走る」の側から見ると分かります。「走る」が意味を定めるには、誰が走るのかを文の中から探す必要があります。探される「犬」の側には、自分は動作の主になれると掲げておく役目が必要です。そして噛み合ったあと、「走る」に実際に渡す情報が必要になる。探す・掲げる・渡すで3種類です。

この3つには、2017年の論文Attention Is All You Needが付けた名前があります。

名前 日本語にすると その語の何を表すか
Query(クエリ) 問い合わせ この語が何を探しているか。「走る」なら「誰が走るのか」
Key(キー) 鍵、あるいは索引の見出し この語が自分は何者かと掲げているもの。「犬」なら「私は動作の主になれる」
Value(バリュー) 値 この語が噛み合った相手に実際に渡す情報

この記事では以降、クエリ・キー・バリューと呼びます。 定着した日本語訳が無く、他の解説でもQuery・Key・Valueのまま書かれているからです。

作り方は3種類とも同じです。その語のベクトルに入っている3個の数値に、1個ずつ掛ける数を決めて、全部を足す。 これで数値が1個できます。同じ作業を3回繰り返すと、3個そろってベクトル1つ分になります。

掛ける数は、クエリ用・キー用・バリュー用で別々に用意されています。 元になる3個の数値は同じでも、掛ける数が違うので、違う3個ができあがる。

この掛ける数が、学習で決まって固定されている部分です。

クエリとキーを突き合わせて、語ごとの点数を計算する

「走る」のベクトルを書き換えるところをやってみます。「走る」のクエリと、3語それぞれのキーを上の作り方で計算したら、こうなったとします。

走るのクエリ : (1, 0, 2)

犬のキー     : (2, 1, 1)
がのキー     : (0, 3, 0)
走るのキー   : (1, 1, 1)

合い具合の測り方も「掛けて足す」です。 1個目どうし・2個目どうし・3個目どうしを掛けて、全部を足します。

犬  : 1×2 + 0×1 + 2×1 = 2 + 0 + 2 = 4
が  : 1×0 + 0×3 + 2×0 = 0 + 0 + 0 = 0
走る: 1×1 + 0×1 + 2×1 = 1 + 0 + 2 = 3

点数が決まりました。犬が4、がが0、走る自身が3。

向きがそろっているほど大きな値になる計算なので、「探しているもの」と「掲げているもの」が噛み合った語ほど、点数が高くなります。

点数を、合計が1になるように割り振る

点数のままでは使えません。合計が1になるように割り振り直します。

犬  : 4 ÷ 7 = 0.57
が  : 0 ÷ 7 = 0
走る: 3 ÷ 7 = 0.43

これが配分です。 実際の割り振りには差を強調する専用の計算式が使われるので、点数が少し高い語が配分ではかなり多く取ります。ここでは単純な割り算にしてあります。

混ぜ込まれるのは、各語のバリュー

配分が決まったので、いよいよベクトルを書き換えます。掛けるのは、各語のバリューです。3語のバリューも、クエリやキーと同じ作り方で計算します。こうなったとします。

犬のバリュー   : (2, 5, 1)
がのバリュー   : (0, 1, 3)
走るのバリュー : (4, 0, 2)

これに配分を掛けて、足します。

犬   0.57 × (2, 5, 1) = (1.14, 2.85, 0.57)
が   0     × (0, 1, 3) = (0.00, 0.00, 0.00)
走る 0.43 × (4, 0, 2) = (1.72, 0.00, 0.86)
                  足して → (2.86, 2.85, 1.43)

この (2.86, 2.85, 1.43) が、「走る」の新しいベクトルです。 最初は (2, 0, 1) でした。2個目が0から2.85に増えたのは、配分を0.57取った「犬」のバリューの2個目が、5と大きかったからです。「走る」が「犬」の情報を強く取り込んだ、ということです。

できたのは「犬走る」という新しい語ではありません。 あくまで「走る」1語の、新しい位置です。そして同時に、「犬」も「が」も、それぞれ自分の配分で動いています。3語入れて、3語出ます。

なぜ語のベクトルどうしを直接比べず、クエリとキーを作るのか

クエリもキーも、元は同じ1つのベクトルから作られています。それなら、語のベクトルどうしを直接比べれば済みそうに見えます。

済みません。ベクトルどうしを比べて測れるのは、意味が似ているかどうかだけだからです。「走る」と「犬」は、意味としては似ていません。それでも「走る」は「犬」を強く見る必要がある。

必要なのは似ているかどうかではなく、探しているものと、掲げているものが噛み合うかです。「走る」が探すのは動作の主、「犬」が掲げるのは私は主になれる。別々の掛ける数で作った2つだから、この噛み合いを測れます。

バリューがさらに別なのも同じ理由です。「私は主になれる」という掲げ方と、実際に渡す情報は、別のものでいい。図書館で言えば、棚の背表紙と、本の中身の違いにあたります。

固定されているものと、その場で計算されるもの

ここが、この記事でいちばん大事なところです。

固定か、その場か
クエリ・キー・バリューの作り方 学習で固定。これがパラメータ
クエリ・キー・バリューそのもの その場で計算
合い具合の点数、配分 その場で計算

配分はどこにも保存されていません。 「動詞は主語を強く見る」という表が、モデルの中にあるわけではない。

だから同じモデルで「川に架かるはし」と「ご飯を食べるはし」を読ませると、同じ掛ける数から違う配分が計算されます。 入ってくるベクトルが違えば、クエリもキーも変わり、噛み合う相手が変わるからです。

ヘッドは何十個も並んでいる

ここまで、クエリを1組だけで説明してきました。実際は違います。

“In this work we employ h = 8 parallel attention layers, or heads.”

(本研究では、8組の並列な注意層、すなわちヘッドを用いる)

同じ層の中に、クエリとキーの組が8つあります。 1組をヘッドと呼びます。

1つの語が探したいものは、1つとは限らないからです。「走る」は主語も探したいし、時制も知りたい。1組のクエリでは、どちらかしか探せません。

そしてその後、ヘッドの数は大きく増えています。

1つの層のヘッド数 層の枚数 全体のヘッド数
2017年の論文 8 6 48
LLaMA 6.7B 32 32 1,024
LLaMA 65.2B 64 80 5,120

数字はLLaMA論文のTable 2からです。100倍以上に増えています。

1つのヘッドの持ち場は、増えていません

同じ表で、1語あたりの数値の個数(幅)をヘッド数で割ると、こうなります。

LLaMA 6.7B  : 4096 ÷ 32 = 128
LLaMA 13.0B : 5120 ÷ 40 = 128
LLaMA 32.5B : 6656 ÷ 52 = 128
LLaMA 65.2B : 8192 ÷ 64 = 128

4つとも128でそろいます。 2017年の論文は512 ÷ 8 = 64でしたから、64から128へ一度だけ倍になり、以降は動いていません。

つまりヘッドが賢くなったのではありません。 扱う幅が広がったぶんを128ずつで割った結果、担当するヘッドの数が増えた。増えたのは数であって、1つのヘッドが受け持つ範囲ではありません。

何を探すヘッドになるかは、決められていない

「このヘッドは主語担当」という割り当てを、設計者が指定したわけではありません。次の語を予測する訓練をした結果として、そうなっているものが見つかる、という順序です。

実際に役割が特定された例があります。AnthropicのIn-context Learning and Induction Headsが報告した誘導ヘッドです。

“The head attends back to previous tokens that were followed by the current and/or recent token.”

(そのヘッドは、現在の語や直近の語が後に続いていた、過去の語のほうへ注意を向ける)

「前に同じ並びが登場した場所を探して、その続きをまねる」という働きです。同じ論文は、この単純な仕組みが文脈内学習の大半を担っていると主張しています。

探し方そのものが、訓練の副産物として立ち上がっている。 配分の計算式は設計者が決めましたが、何と何を噛み合わせるかは、決めていません。

まとめ

  • 配分は保存されていない。 文を読むたびに計算される
  • 決め方は、その語のクエリと、各語のキーの合い具合を測って、合計1に割り振る
  • 測り方も混ぜ方も、「掛けて足す」だけ
  • 固定されているのは、クエリ・キー・バリューの作り方のほう
  • ヘッドは1つの層に何十個も並び、モデル全体では数千個にのぼる。ただし1つのヘッドの持ち場は128のまま変わっていない
  • どのヘッドが何を探すようになるかは、設計されていない

LLMの仕組みの記事

LLMの仕組みのページへ →