About

構造は回路図、重みはつまみの位置 — そしてAttentionの変形はn²を避けるための改造だ

重みが公開されればすぐ使えるのか、GQAはなぜ長い文脈で必須なのか

「重みって何?公開されればtransformersですぐ使えるの?」と「Attentionの変形って何?」は、実は1つの質問だ。短く答えると、構造は回路図、重みはその回路のつまみの位置だ。回路図は論文で公開されていて、つまみをどこに合わせるかを見つけるのに学習コストが全部かかる。この記事を読めば、公開モデルが使えるかを4つの点で確かめられ、モデル説明に出てくるGQAやSliding Windowが何を減らそうとしているのかがわかる。

モデルのファイルに入っている2つ

設計図(config.json)  層数・次元数・ヘッド数          ← Transformerの「パターン」部分。たいてい公開
重み(weights)        学習で決まった数値が数十億個    ← モデルの知識のすべて

Llama 8Bならこの数値が80億個ある。構造が同じでも、別のモデルの重みを差し替えることはできない。1つ1つのつまみが、ほかのつまみの位置を前提に合わせてあるからだ。

重みが公開されればすぐ使えるか — 4つを見る

その構造がライブラリに実装されているか。 有名な構造はたいていHF transformersにある。

tokenizerも一緒に公開されているか。 文字を数値に変えるルールがなければ、重みは使えない。

ライセンスが自分の用途を許しているか。 Llamaのように条件付きのものもあるので、ライセンス本文を読む。

動かすハードウェアがあるか。 8Bなら量子化すればノートPCでも動くが、70B級は高性能GPUが何枚も必要になる。

Claude・GPT・Geminiは重みが非公開なのでAPIでしか使えない。Llama・Qwen・Mistralは重みが公開されていて、ローカルで動く。

Attentionはなぜ改造されるのか — n²

元のAttentionは、すべてのトークンがほかのすべてのトークンを1回ずつ見る。会議の参加者全員が、互いに全員と1対1で話すようなものだ。トークンがn個ならペアはn²個。1,000トークンなら100万ペア、100,000トークンなら100億ペア。文脈が100倍長くなると、仕事は1万倍になる。

Who looks at whom (8 tokens)FullBERT, 64 pairsCausalGPT-style, 36 pairsSliding windowlast 3 only, 21 pairsRows = the token that is looking. Columns = the token being looked at.

そこで、見る量を減らす・分けて見る・同じことを速く見る、という改造が出てきた。

変形 アイデア 減らすもの 使われているところ
Multi-Head(元祖) 複数の観点(head)で同時に見る —(基本形) 元のTransformer、BERT
MQA / GQA 複数のheadがKey・Valueを共有する KV cacheのメモリ Llama 2 70B・Llama 3、Mistral 7B
Sliding Window 近くのN個だけ見る 長い入力の計算量 Mistral 7B
Sparse Attention 決まった一部の位置だけ見る 計算量 GPT-3(denseと交互)
Linear Attention n²をnに近い形で近似する とても長い入力 主に研究段階
FlashAttention 結果はそのまま、GPUメモリを読む順番を変える メモリ移動の時間 最近の学習・推論ライブラリの多く

FlashAttentionは結果を近似しない。論文のタイトルからして「Exact Attention」だ。計算を減らすのではなく、GPUメモリとの往復を減らして速くなる。

GQAがなぜ大事か — KV cacheを自分で計算してみる

生成モデルはトークンを1つ作るたびに、前のトークンたちのKey・Valueをメモリに積んでおく。これがKV cacheだ。headごとに別々に持つと、長い会話でGPUメモリがすぐに埋まる。

Llama 3 8Bのconfig.jsonの数字で計算してみた。層は32、Key・Valueを持つheadは8つ(質問側のheadは32)、headの次元は128、fp16(2バイト)。

1トークンあたり = 2 (K, V) × 32層 × 8 head × 128次元 × 2バイト = 131,072バイト = 128KB
GQAなしで32個のheadが全部別々に持つと = 512KB
8,192トークンなら → GQAありで1GB / なしで4GB

実測ではなくconfigから計算した値だ。それでも4倍の差は構造からそのまま出てくる。長い文脈のモデルでGQAがほぼ標準になった理由だ。

MVCのアプリにキャッシュやクエリ最適化を入れるのと性質は同じだ。パターンはそのままで、内側だけ手を入れる。

Transformerの構造自体があやふやならTransformerから。同じ重みをどんな箱に入れて配るかはONNXは梱包規格だにある。

公開モデルをローカルや社内サーバーに載せたいが、メモリ・ライセンス・ハードウェアをどう合わせるかで詰まっているなら、negabaroに相談してもらって構わない。

キーコンセプト

1

モデルのファイルは設計図(config.json)と重みに分かれる — 知識はすべて重みにある

2

公開された重みを使う前に、実装・tokenizer・ライセンス・ハードウェアの4つを見る

3

Attentionはn² — 文脈が100倍なら仕事は1万倍

4

KV cache = 2 × 層 × KV head × head次元 × バイト × トークン — GQAはKV headを減らす

ユースケース

公開モデルを社内サーバーに載せる前のメモリ見積もり — KV cacheの計算 モデルカードのGQA・Sliding Windowの表記を読んで長い文脈に向くか判断する
← PyTorch・Hugging Face・Ollamaを同じ棚に並べるな — AIフレームワークは3層だ