Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-tran...

Go言語とトイモデルで学ぶTransformerの気持ち / fukuokago23-transformer

Avatar for monochromegane

monochromegane

July 21, 2026

More Decks by monochromegane

Other Decks in Programming

Transcript

  1. Q/K/Vの役割 • 各トークンを、役割の違う3つのベクトルに変換する • Q(Query)= いま探したいこと • K(Key)= 各トークンの目印 •

    V(Value)= 取り出したい中身 • 例:「猫が寝ている。それは疲れていた」 • Q/Kが品詞的な観点を学習しているとする(実際は複数の観点を持つ=マルチヘッド) •「それ」のQ(指している名詞は? )に「猫」のK(この場合は名詞)が 最も強くヒットし、Vから猫の意味を多めに取り込む 14
  2. Q/K/Vの役割 • 各トークンを、役割の違う3つのベクトルに変換する • Q(Query)= いま探したいこと • K(Key)= 各トークンの目印 •

    V(Value)= 取り出したい中身 • 例えるなら、キーの完全一致ではなく「近さ」で引けるmap • map[K]Vは、一致したキーの値を1つだけ返す • Attentionは、QとKの近さに応じてすべてのVを混ぜて返す 15
  3. GPUの概略図 例:7Bモデル(fp16)を載せた場合 GPU SMの中身 SM SM SM モデル重み 14 GB

    7B×2バイト(fp16) 計算のたびに 読み書き CUDA core ×多数 Tensor core Tensor core 共有メモリ(SRAM):小容量 HBM/GDDR(VRAM) 24 GB 8k文脈×1リクエスト KV cache 4 GB (詳しくは後述) 一時メモリ 約2 GB 計算の途中結果の置き場 空き 4 GB Streaming Multiprocessor(SM)が計算し、 VRAM上の重み・KV cache・途中結果を読み書きする 21
  4. 毎回すべてを計算する素朴な実装 type Ctx struct{ tokens []Token; ks, vs []Vec }

    // Attention操作(関連度 → 重み → 足し合わせ) func attend(q Vec, ks, vs []Vec) Vec { w := softmax(scores(q, ks)) return weightedSum(w, vs) } // 素朴な実装(毎ステップ、全トークンから K・V を作り直す) func step(ctx *Ctx, tok Token) Vec { ctx.tokens = append(ctx.tokens, tok) ctx.ks, ctx.vs = nil, nil for _, t := range ctx.tokens { // 毎回すべて計算 ctx.ks = append(ctx.ks, projK(t)) ctx.vs = append(ctx.vs, projV(t)) } return attend(projQ(tok), ctx.ks, ctx.vs) } KV cache: Off(全部compute) 毎ステップ、過去トークン分のK・Vを作り直している 22
  5. KV cache type Ctx struct{ tokens []Token; ks, vs []Vec

    } // Attention操作(関連度 → 重み → 足し合わせ) func attend(q Vec, ks, vs []Vec) Vec { w := softmax(scores(q, ks)) return weightedSum(w, vs) } // KV cache を用いた実装 func step(ctx *Ctx, tok Token) Vec { ctx.tokens = append(ctx.tokens, tok) ctx.ks = append(ctx.ks, projK(tok)) // 新トークンぶんだけ追記 ctx.vs = append(ctx.vs, projV(tok)) // 過去は再計算しない return attend(projQ(tok), ctx.ks, ctx.vs) } KV cache: On(過去はreused) K・V生成を「追記」に変えるだけ。ブロックに流すのは最新トークンのみ 24
  6. Sliding window Attention // KV cache を用いた実装に、Sliding window を適用 func

    step(ctx *Ctx, tok Token, w int) Vec { ctx.ks = append(ctx.ks, projK(tok)) ctx.vs = append(ctx.vs, projV(tok)) if len(ctx.ks) > w { // 直近 w 件だけ残す ctx.ks = ctx.ks[len(ctx.ks)-w:] ctx.vs = ctx.vs[len(ctx.vs)-w:] } return attend(projQ(tok), ctx.ks, ctx.vs) } Window=3(直近だけ残す) KV cacheに「直近w件だけ残す」を足すだけ。容量・計算が一定に 26