# スケーリングと文脈：文脈長・疎な注意の受容野・スケーリング則

> 文脈長を伸ばすと注意の計算量が 2 乗で増えることから出発し、窓つき注意の計算量と受容野、経路長の比較、べき則の読み方、計算量の予算のもとでのモデルとデータの最適配分を証明し、経験則として引用する部分と区別して述べる。
> https://rikai.mugen-giken.com/computer-science/llm-architecture/scaling-and-context

## 0. この記事の要点

長い文書を読ませたいとき、モデルに一度に見せる文章を長くすればよさそうですが、長くした分だけ計算は急に重くなります。この記事では、その増え方を数えたうえで、見る範囲を絞る工夫が何を失うかを確かめます。後半では、モデルを大きくしたり学習データを増やしたりすると結果がどのくらい良くなるかを、証明できる部分と観察にすぎない部分に分けて読みます。

- 全注意では、文脈長 $n$ を $c$ 倍にすると注意の計算量は $c^2$ 倍、[KV キャッシュ](/computer-science/llm-architecture/inference-and-sampling#def-kv-cache)（過去の位置のキーとバリューを保存しておく仕組み）の記憶量は $c$ 倍になります（<Ref to="prop-context-quadratic" />）。
- 各位置が直前の $w$ 個だけを見る窓つき注意は、計算量を $O(nwd)$ に下げます（<Ref to="prop-window-attention-cost" />）。代わりに、$L$ 層重ねても位置 $i$ の出力は $i - L(w-1)$ より前の入力に依存できません（<Ref to="thm-window-receptive-field" />）。全注意は 1 層で任意の位置対をつなぎ、再帰型は $n - 1$ 段、畳み込みは $O(n/k)$ または $O(\log_k n)$ 層を要します（<Ref to="prop-path-length" />）。
- 注意のパターンをどう疎にしても、下三角であるかぎり因果性は保たれ、KV キャッシュは使えます（<Ref to="prop-sparse-pattern-causality" />）。
- 損失がモデルの大きさ $N$ のべき則 $a N^{-\alpha}$ に従うなら、$N$ を $c$ 倍にすると損失は $c^{-\alpha}$ 倍になります。定数項 $L_\infty$ があると両対数で直線にならず、2 点からは指数が決まりません（<Ref to="prop-power-law" />）。
- 損失が $E + A N^{-\alpha} + B D^{-\beta}$ の形で、予算の制約が $ND = C$ なら、最適な配分はただ 1 つで $N^{\star} \propto C^{\beta/(\alpha+\beta)}$、$D^{\star} \propto C^{\alpha/(\alpha+\beta)}$ です（<Ref to="thm-compute-optimal-allocation" />）。この関数形と指数の値は経験的な当てはめで、定理が言うのは「その形を仮定したときの帰結」だけです。

<Aside type="tip" title="この記事で使う事前知識">

- **自己注意**: 各位置が、同じ列の他の位置との関係の強さ（内積）を重みにして、情報を集める計算。→ [自己注意](/computer-science/llm-architecture/self-attention#def-attention)
- **因果マスク**: 位置 $i$ が自分より後ろの位置を見ないようにする制限。重みの行列が下三角になる。→ [因果マスク](/computer-science/llm-architecture/self-attention#def-attention)
- **KV キャッシュ**: 生成済みの位置のキーとバリューを保存し、次のトークンの計算で使い回す仕組み。→ [KV キャッシュ](/computer-science/llm-architecture/inference-and-sampling#def-kv-cache)
- **自己回帰生成**: すでに出したトークンを条件に、次のトークンを 1 つずつ出していく生成。→ [自己回帰生成](/computer-science/llm-architecture/inference-and-sampling#def-autoregressive-generation)
- **O 記法**: 入力の大きさに対する計算量の増え方を、定数倍を無視して表す書き方。→ [計算量と O 記法](/computer-science/algorithms/complexity-and-big-o)

</Aside>

## 1. 動機：どこまでが証明で、どこからが観察か

ここまでの章で、デコーダのみの Transformer の入力から出力までと、その学習と推論を一通り扱いました。残っているのは「大きくするとどうなるか」という問いです。大きくする向きは 2 つあります。

1 つは**文脈長**、すなわちモデルが 1 回に参照できるトークンの数です。長い文書を読ませたい、長い会話を続けたいという要求は、文脈長を伸ばすことに直結します。しかし注意は位置の対ごとに計算するので、素直に伸ばすと計算量が 2 乗で増えます。これは仕組みから厳密に導けることで、対処の方法（見る範囲を絞る）の得失も、命題として証明できます。

もう 1 つは**モデルとデータの規模**です。重みの数を増やし、学習に使うトークンを増やすと、損失はどのくらい下がるのか。これは仕組みからは導けません。分かっているのは、実際に多数のモデルを学習して損失を測った結果を、簡単な式に当てはめたものです。Kaplan ら（2020）と Hoffmann ら（2022）の報告がその代表です。

この章は、この 2 種類の知識を混ぜないことを方針にします。計算量・受容野・経路長・「べき則を仮定したときの最適配分」は定理や命題として証明します。べき則が成り立つこと自体、その指数の値、長い文脈でモデルが実際にどう振る舞うかは、出典を付けた注意として書きます。節の見出しにも、経験則である節にはそう書きます。

## 2. 準備：記号

列の長さ（文脈長）を $n$、モデルの次元を $d$、層数を $L$、MLP の幅を $d_{\mathrm{ff}}$ と書きます。入力を $X \in \mathbb{R}^{n \times d}$（第 $i$ 行が位置 $i$ のベクトル $\boldsymbol{x}_i$）とします。計算量は、[推論](/computer-science/llm-architecture/inference-and-sampling)の章と同じく、スカラーの乗算の回数で数えます。$O$ 記法は <Ref to="computer-science/algorithms/complexity-and-big-o#def-big-o" /> のものです。

スケーリング則の節では、$N$ をモデルのパラメータ数、$D$ を学習に使ったトークン数、$C$ を学習の計算量とします。前半の $n$（文脈長）と後半の $N$（パラメータ数）は別の量です。

## 3. 文脈長と全注意のコスト

<Definition id="def-context-length" title="文脈長">
モデルが 1 回の順伝播で入力として受け取れるトークン数の上限を**文脈長**といいます。学習する位置埋め込みを使うモデルでは、表の長さが文脈長の上限になります（<Ref to="computer-science/llm-architecture/embeddings-and-positional-encoding#prop-learned-position-table" />）。そうでないモデルでも、計算量と記憶量が実用上の上限を決めます。
</Definition>

<Proposition id="prop-context-quadratic" title="全注意のコストは文脈長の 2 乗">
因果マスクつきの全注意（各位置が自分以前のすべての位置を見る）を使う $L$ 層のモデルで、長さ $n$ の列を 1 回順伝播するとします。

1. 1 層あたりの乗算は、注意（内積と重みつき和）が $2n^2 d$ 回、線形写像と MLP が $n(4d^2 + 2d\,d_{\mathrm{ff}})$ 回です。
2. KV キャッシュが保存する数は $2Lnd$ 個です。
3. $n$ を $c$ 倍（$c > 0$）にすると、注意の項は $c^2$ 倍、線形写像と MLP の項は $c$ 倍、KV キャッシュは $c$ 倍になります。
</Proposition>

<Proof of="prop-context-quadratic">
1 と 2 は <Ref to="computer-science/llm-architecture/inference-and-sampling#thm-kv-cache-cost" /> の 2（$t = n$ の場合）と 4 です。注意の計算量が $O(n^2 d)$ であることは <Ref to="computer-science/llm-architecture/self-attention#prop-attention-complexity" /> でも示されています。3 は、$2(cn)^2 d = c^2 \cdot 2n^2 d$、$cn(4d^2 + 2d\,d_{\mathrm{ff}}) = c \cdot n(4d^2 + 2d\,d_{\mathrm{ff}})$、$2L(cn)d = c \cdot 2Lnd$ です（多項式の次数と倍率の関係は <Ref to="computer-science/algorithms/complexity-and-big-o#prop-doubling" /> の 3）。
</Proof>

<Example id="ex-context-doubling" title="どちらの項が支配的か">
$d = 1000$、$d_{\mathrm{ff}} = 4d$ とすると、1 層の乗算は $2n^2 d + 12nd^2 = 2000 n^2 + 1.2 \times 10^7 n$ です。2 つの項が等しくなるのは $n = 6d = 6000$ のときです。

| $n$ | 注意 $2n^2 d$ | 線形写像・MLP $12nd^2$ | 注意の割合 |
|---|---|---|---|
| $1{,}000$ | $2.0 \times 10^9$ | $1.2 \times 10^{10}$ | $14\%$ |
| $6{,}000$ | $7.2 \times 10^{10}$ | $7.2 \times 10^{10}$ | $50\%$ |
| $100{,}000$ | $2.0 \times 10^{13}$ | $1.2 \times 10^{12}$ | $94\%$ |

文脈長が次元 $d$ と同じ程度のうちは、計算の大半は注意ではありません。注意だけをどれだけ速くしても、全体の速度向上は $1/(1 - 0.14) \approx 1.16$ 倍を超えません（<Ref to="computer-science/ai-era/engineer-survival-strategy#prop-amdahl" /> で $p = 0.14$ とすると、どんな $s \ge 1$ でも $S(p, s) < 1/(1-p)$ です）。文脈長が $d$ の数十倍になって初めて、2 乗の項が全体を決めます。以下で扱う「注意を疎にする」工夫が意味を持つのは、この領域です。
</Example>

## 4. 注意のパターンを疎にする

全注意は、すべての位置対 $(i, j)$ について重みを計算します。どの対を計算するかを 0/1 の行列で指定し、一部だけにすれば、計算量は対の数に比例して減ります。

<Definition id="def-attention-pattern" title="注意のパターン・窓つき注意・大域トークン">
$M \in \{0, 1\}^{n \times n}$ で、すべての $i$ について $M_{ii} = 1$ であるものを**注意のパターン**といいます。パターン $M$ つきの注意は、位置 $i$ のクエリ $\boldsymbol{q}_i$、位置 $j$ のキー $\boldsymbol{k}_j$ とバリュー $\boldsymbol{v}_j$ に対して

$$
\alpha_{ij} =
\begin{cases}
\dfrac{\exp(\langle \boldsymbol{q}_i, \boldsymbol{k}_j \rangle / \sqrt{d})}{\sum_{j' : M_{ij'} = 1} \exp(\langle \boldsymbol{q}_i, \boldsymbol{k}_{j'} \rangle / \sqrt{d})} & (M_{ij} = 1) \\
0 & (M_{ij} = 0)
\end{cases}
\qquad \text{出力の第 } i \text{ 行} = \sum_{j : M_{ij} = 1} \alpha_{ij} \boldsymbol{v}_j
$$

で定めます。$M_{ii} = 1$ なので分母は正です。

- $M_{ij} = 1$ ならば $j \le i$ であるとき（$M$ が下三角のとき）、パターンは**因果的**であるといいます。
- **全注意**（因果的）: $M_{ij} = 1 \iff j \le i$。
- **幅 $w$ のスライディングウィンドウ注意**（因果的、$w \ge 1$）: $M_{ij} = 1 \iff i - w < j \le i$。各位置は自分を含む直前の $w$ 個を見ます。
- **大域トークン**: 位置の集合 $\mathcal{G} \subset \{1, \ldots, n\}$ を選び、パターン $M$ を $M'_{ij} = 1 \iff (M_{ij} = 1 \text{ または } i \in \mathcal{G} \text{ または } j \in \mathcal{G})$ に広げます。すべての位置が大域トークンを見て、大域トークンはすべての位置を見ます。
</Definition>

<Figure caption="注意のパターンの例（$n = 8$）。行が見る側の位置 $i$、列が見られる側の位置 $j$ で、塗られたマスが $M_{ij} = 1$。左から全注意（因果的）、幅 3 の窓、窓に位置 4 の大域トークンを足したもの。">

<svg viewBox="0 0 720 210" width="100%" role="img" aria-label="全注意・窓つき注意・大域トークンつきの注意のパターンを 8 かける 8 の格子で示した図">
  <g>
    <rect x="40" y="40" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="88" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="88" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="104" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="88" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="104" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="120" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="88" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="104" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="120" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="136" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="56" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="72" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="88" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="104" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="120" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="136" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="152" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="40" y="40" width="128" height="128" fill="none" stroke="currentColor" stroke-width="1.2" />
    <rect x="280" y="40" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="280" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="296" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="280" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="296" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="312" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="296" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="312" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="328" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="312" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="328" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="344" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="328" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="344" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="360" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="344" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="360" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="376" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="360" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="376" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="392" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="280" y="40" width="128" height="128" fill="none" stroke="currentColor" stroke-width="1.2" />
    <rect x="520" y="40" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="40" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="520" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="536" y="56" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="56" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="520" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="536" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="552" y="72" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="72" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="520" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="536" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="536" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="552" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="552" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="568" y="88" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="584" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="600" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="616" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="632" y="88" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="552" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="104" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="584" y="104" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="120" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="584" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="600" y="120" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="136" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="584" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="600" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="616" y="136" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="568" y="152" width="15" height="15" fill="var(--sl-color-accent)" fill-opacity="0.7" />
    <rect x="600" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="616" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="632" y="152" width="15" height="15" fill="currentColor" fill-opacity="0.55" />
    <rect x="520" y="40" width="128" height="128" fill="none" stroke="currentColor" stroke-width="1.2" />
  </g>
  <g fill="currentColor" font-size="13" text-anchor="middle">
    <text x="104" y="30">全注意（因果的）</text>
    <text x="344" y="30">窓つき注意（w = 3）</text>
    <text x="584" y="30">窓 ＋ 大域トークン（位置 4）</text>
    <text x="104" y="190">下三角がすべて塗られる</text>
    <text x="344" y="190">対角のまわりの帯だけ</text>
    <text x="584" y="190">十字（強調色）が加わる</text>
  </g>
</svg>

</Figure>

層の全体は、[推論](/computer-science/llm-architecture/inference-and-sampling)の第 7 節と同じ形に書きます。層 $\ell$ の位置 $i$ の出力 $\boldsymbol{h}^{(\ell)}_i$ は、行ごとに働く写像 $\kappa_\ell, \nu_\ell, \chi_\ell, G_\ell$ によって

$$
\boldsymbol{h}^{(\ell)}_i = G_\ell\Bigl(\boldsymbol{h}^{(\ell-1)}_i,\ \sum_{j : M_{ij} = 1} \alpha^{(\ell)}_{ij}\, \nu_\ell\bigl(\boldsymbol{h}^{(\ell-1)}_j\bigr)\Bigr)
$$

と定まり、$\alpha^{(\ell)}_{ij}$ は $\boldsymbol{q}_i = \chi_\ell(\boldsymbol{h}^{(\ell-1)}_i)$ と $\boldsymbol{k}_j = \kappa_\ell(\boldsymbol{h}^{(\ell-1)}_j)$（$M_{ij} = 1$ である $j$）から上の式で決まります。$\boldsymbol{h}^{(0)}_i$ は入力 $\boldsymbol{x}_i$（と位置 $i$）だけで決まるとします。

まず、どの入力がどの出力に影響しうるかを、パターンだけから決まる集合として定めます。直感的には、1 層ごとに「自分が見る位置の、さらに 1 層前での視野」をまとめて取り込むので、層を重ねるほど視野が左へ広がっていく、ということです。次の定義はそれを式で書いたもので、あとの例の表を見ながら読むと追いやすくなります。

<Definition id="def-receptive-field" title="受容野">
パターン $M$（層ごとに違ってもよく、層 $\ell$ のものを $M^{(\ell)}$ と書きます）に対して、添字の集合 $R_\ell(i) \subset \{1, \ldots, n\}$ を

$$
R_0(i) = \{i\}, \qquad R_\ell(i) = \bigcup_{j \,:\, M^{(\ell)}_{ij} = 1} R_{\ell-1}(j)
$$

で定め、$R_L(i)$ を $L$ 層のあとの位置 $i$ の**受容野**といいます。
</Definition>

<Lemma id="lem-receptive-field" title="出力は受容野の中の入力だけの関数">
上の形の層を $L$ 個重ねたとき、各 $\ell \le L$ と各 $i$ について、$\boldsymbol{h}^{(\ell)}_i$ は $(\boldsymbol{x}_j)_{j \in R_\ell(i)}$ だけの関数です。すなわち、$R_\ell(i)$ に入らない位置の入力をどう変えても $\boldsymbol{h}^{(\ell)}_i$ は変わりません。
</Lemma>

<Proof of="lem-receptive-field">
$\ell$ についての帰納法（<Ref to="mathematics/foundations/proof-techniques#thm-induction" />）です。$\ell = 0$ では $\boldsymbol{h}^{(0)}_i$ は $\boldsymbol{x}_i$ だけで決まり、$R_0(i) = \{i\}$ です。$\ell - 1$ で成り立つとします。層の式の右辺に現れるのは、$\boldsymbol{h}^{(\ell-1)}_i$ と、$M^{(\ell)}_{ij} = 1$ である $j$ についての $\boldsymbol{h}^{(\ell-1)}_j$ だけです（$\alpha^{(\ell)}_{ij}$ もこれらだけから決まります）。$M^{(\ell)}_{ii} = 1$ なので、$i$ 自身もその $j$ に含まれます。帰納法の仮定により、各 $\boldsymbol{h}^{(\ell-1)}_j$ は $R_{\ell-1}(j)$ の中の入力だけの関数です。したがって $\boldsymbol{h}^{(\ell)}_i$ は、それらの和集合 $R_\ell(i)$ の中の入力だけの関数です。
</Proof>

受容野は「依存しうる」入力の集合で、実際に依存するかどうかは重みに依ります（たとえば $W_V = O$ なら、注意を通じた依存は消えます）。この補題は、依存の上限を与えます。

<Proposition id="prop-sparse-pattern-causality" title="因果的なパターンなら因果性は保たれる">
すべての層のパターンが因果的なら、各 $\ell$ と $i$ について $R_\ell(i) \subset \{1, \ldots, i\}$ で、$\boldsymbol{h}^{(\ell)}_i$ は $\boldsymbol{x}_1, \ldots, \boldsymbol{x}_i$ だけの関数です。したがって、パターンがどれだけ疎であっても、1 回の順伝播ですべての位置の次トークン予測が得られること、KV キャッシュが正しく使えることは、全注意の場合と同じく成り立ちます。
</Proposition>

<Proof of="prop-sparse-pattern-causality">
$R_\ell(i) \subset \{1, \ldots, i\}$ を $\ell$ についての帰納法で示します。$R_0(i) = \{i\}$ です。$\ell - 1$ で成り立つとすると、$M^{(\ell)}_{ij} = 1$ である $j$ は因果性から $j \le i$ を満たし、$R_{\ell-1}(j) \subset \{1, \ldots, j\} \subset \{1, \ldots, i\}$ なので、その和集合 $R_\ell(i)$ も $\{1, \ldots, i\}$ に含まれます。<Ref to="lem-receptive-field" /> により $\boldsymbol{h}^{(\ell)}_i$ は $\boldsymbol{x}_1, \ldots, \boldsymbol{x}_i$ だけの関数です。

因果マスクの定理（<Ref to="computer-science/llm-architecture/self-attention#thm-causal-mask" />）は全注意のパターンについてこれを述べたもので、その証明が使うのは「重みの行列が下三角である」ことだけです。KV キャッシュの正しさ（<Ref to="computer-science/llm-architecture/inference-and-sampling#thm-kv-cache-correct" />）の証明も、位置 $t$ の式に $t$ より後の添字が現れないことだけを使うので、和の範囲を $s \le t$ から「$M_{ts} = 1$ である $s$」に置き換えてそのまま成り立ちます。
</Proof>

<Proposition id="prop-window-attention-cost" title="窓つき注意の計算量">
幅 $w$ のスライディングウィンドウ注意（$1 \le w \le n$）では、$M_{ij} = 1$ である対の数は $nw - \dfrac{w(w-1)}{2}$ で、$nw$ 以下です。1 層の注意（内積と重みつき和）の乗算は $2d \bigl(nw - \frac{w(w-1)}{2}\bigr) \le 2nwd$ 回、保持する重み $\alpha_{ij}$ は $nw$ 個以下です。したがって時間計算量は $O(nwd)$、重みの記憶量は $O(nw)$ です。
</Proposition>

<Proof of="prop-window-attention-cost">
位置 $i$ が見る $j$ は $\max(1, i - w + 1) \le j \le i$ で、その個数は $\min(i, w)$ です。$i \le w$ では $i$ 個、$i > w$ では $w$ 個なので、合計は

$$
\sum_{i=1}^{w} i + (n - w) w = \frac{w(w+1)}{2} + nw - w^2 = nw - \frac{w(w-1)}{2}
$$

です。対 1 つにつき、内積 $\langle \boldsymbol{q}_i, \boldsymbol{k}_j \rangle$ に $d$ 回、$\alpha_{ij} \boldsymbol{v}_j$ に $d$ 回の乗算を使うので、乗算は対の数の $2d$ 倍です。重みは対ごとに 1 個です。
</Proof>

全注意（$w = n$）では対の数は $n(n+1)/2$ で、$n$ について 2 次です。$w$ を $n$ に依らない定数にすれば、計算量は $n$ について 1 次になります。その代償が次の定理です。窓が小さいと 1 層では近くしか見えませんが、層を重ねると視野が 1 層あたり $w - 1$ 位置ずつ左へ延びます。定理はこの延び方を正確に述べ、遠くの入力に届くには何層必要かを与えます。証明は、層の数についての帰納法で、各層の視野が切れ目のない区間になることを確かめるだけです。

<Theorem id="thm-window-receptive-field" title="窓つき注意の受容野">
すべての層が幅 $w$（$w \ge 1$）のスライディングウィンドウ注意であるとします。

1. $R_L(i) = \{\, j : \max(1,\ i - L(w - 1)) \le j \le i \,\}$ です。
2. したがって、$j < i - L(w - 1)$ である位置 $j$ の入力をどう変えても、$L$ 層のあとの位置 $i$ の出力は変わりません。
3. 位置 $i$ の出力が距離 $D \ge 1$ だけ前の入力 $\boldsymbol{x}_{i - D}$ に依存しうるためには、$w \ge 2$ かつ $L \ge \lceil D / (w - 1) \rceil$ が必要です。
4. 全注意（$M_{ij} = 1 \iff j \le i$）では $R_1(i) = \{1, \ldots, i\}$ で、1 層で自分以前のすべての位置が受容野に入ります。
</Theorem>

<Proof of="thm-window-receptive-field">
**1.** $L$ についての帰納法です。$L = 0$ では $R_0(i) = \{i\}$ で、右辺も $\max(1, i) \le j \le i$ すなわち $\{i\}$ です。$L - 1$ で成り立つとします。窓のパターンでは $M_{ij} = 1$ となるのは $\max(1, i - w + 1) \le j \le i$ のときなので

$$
R_L(i) = \bigcup_{j = \max(1,\, i - w + 1)}^{i} R_{L-1}(j) = \bigcup_{j = \max(1,\, i - w + 1)}^{i} \{\, j' : \max(1,\ j - (L-1)(w-1)) \le j' \le j \,\}
$$

です。右辺は、$j$ ごとに「左端が $\max(1, j - (L-1)(w-1))$、右端が $j$」の整数の区間です。右端 $j$ は $\max(1, i - w + 1)$ から $i$ まで 1 ずつ動き、各区間は自分の右端 $j$ を含むので、和集合は切れ目のない区間になります。その右端は $j = i$ のときの $i$、左端は $j$ が最小のときの値です。$i - w + 1 \ge 1$ なら、左端は $\max(1,\ i - w + 1 - (L-1)(w-1)) = \max(1,\ i - L(w-1))$ です。$i - w + 1 < 1$ なら、$j$ の最小は $1$ で左端は $1$ ですが、このとき $i - L(w-1) \le i - (w - 1) < 1$ なので $\max(1, i - L(w-1)) = 1$ で、やはり一致します（$L \ge 1$ を使いました）。

**2.** <Ref to="lem-receptive-field" /> と 1 です。

**3.** $\boldsymbol{x}_{i-D}$ に依存しうるには $i - D \in R_L(i)$、すなわち $i - D \ge i - L(w-1)$ が必要で、これは $L(w - 1) \ge D$ です。$D \ge 1$ なので $w - 1 \ge 1$ が必要で、そのとき $L \ge D/(w-1)$、$L$ は整数なので $L \ge \lceil D/(w-1) \rceil$ です。

**4.** 定義から $R_1(i) = \bigcup_{j \le i} R_0(j) = \{1, \ldots, i\}$ です。
</Proof>

<Example id="ex-window-table" title="n = 8, w = 3, L = 2 の受容野">
幅 $3$ の因果的な窓を $2$ 層重ねると、$L(w - 1) = 4$ なので、位置 $i$ の受容野は $\max(1, i - 4)$ から $i$ までです。

| 位置 $i$ | 1 層のあと $R_1(i)$ | 2 層のあと $R_2(i)$ | 届かない入力 |
|---|---|---|---|
| $1$ | $\{1\}$ | $\{1\}$ | なし |
| $2$ | $\{1, 2\}$ | $\{1, 2\}$ | なし |
| $3$ | $\{1, 2, 3\}$ | $\{1, 2, 3\}$ | なし |
| $4$ | $\{2, 3, 4\}$ | $\{1, \ldots, 4\}$ | なし |
| $5$ | $\{3, 4, 5\}$ | $\{1, \ldots, 5\}$ | なし |
| $6$ | $\{4, 5, 6\}$ | $\{2, \ldots, 6\}$ | $1$ |
| $7$ | $\{5, 6, 7\}$ | $\{3, \ldots, 7\}$ | $1, 2$ |
| $8$ | $\{6, 7, 8\}$ | $\{4, \ldots, 8\}$ | $1, 2, 3$ |

位置 $8$ の出力は、先頭の 3 つのトークンが何であっても同じです。位置 $8$ から位置 $1$（距離 $7$）に届かせるには $\lceil 7/2 \rceil = 4$ 層が要ります。計算量のほうは、対の数が全注意の $8 \times 9 / 2 = 36$ から $8 \times 3 - 3 = 21$ に減っています。

実際の規模で見ると、$w = 64$ の窓で $1000$ トークン前に届かせるには $\lceil 1000/63 \rceil = 16$ 層が必要です。
</Example>

<Proposition id="prop-global-token" title="大域トークンは経路を 2 層に縮める">
パターン $M$ に大域トークンの集合 $\mathcal{G}$（$g = |\mathcal{G}| \ge 1$）を足したパターン $M'$ を、すべての層で使うとします。

1. 任意の位置 $i, j$ について $j \in R_2(i)$ です。すなわち、どの 2 つの位置も 2 層でつながります。
2. $M'_{ij} = 1$ である対の数は、$M$ の対の数に $2gn$ を足したもの以下です。$M$ が幅 $w$ の窓なら対の数は $n(w + 2g)$ 以下で、注意の計算量は $O(n(w + g)d)$ です。
3. $M$ が因果的でも、$n \ge 2$ なら $M'$ は因果的ではありません。
</Proposition>

<Proof of="prop-global-token">
**1.** $\gamma \in \mathcal{G}$ を 1 つ取ります。$\gamma \in \mathcal{G}$ なので、すべての $j$ で $M'_{\gamma j} = 1$ で、$R_1(\gamma) = \bigcup_{j} R_0(j) = \{1, \ldots, n\}$ です。また、すべての $i$ で $M'_{i\gamma} = 1$ なので $R_2(i) \supset R_1(\gamma) = \{1, \ldots, n\}$ です。

**2.** $M'_{ij} = 1$ で $M_{ij} = 0$ である対は、$i \in \mathcal{G}$（高々 $gn$ 個）か $j \in \mathcal{G}$（高々 $gn$ 個）です。窓の場合は <Ref to="prop-window-attention-cost" /> から $M$ の対が $nw$ 以下なので、合計は $n(w + 2g)$ 以下です。対 1 つにつき $2d$ 回の乗算なので、$2d \cdot n(w + 2g) = O(n(w+g)d)$ です。

**3.** $\gamma \in \mathcal{G}$ とします。$\gamma < n$ なら $M'_{\gamma n} = 1$ で $n > \gamma$、$\gamma = n$ なら $M'_{1 n} = 1$ で $n > 1$ です。どちらの場合も、行の添字より大きい列の添字で $1$ になる成分があります。
</Proof>

3 は重要な但し書きです。大域トークンは、列の全体を一度に読む型のモデル（Beltagy らの Longformer はこの型で、窓つきの注意と、課題に応じて選んだ少数の位置の大域的な注意を組み合わせます）のための工夫です。左から右へ生成する因果的なモデルでは、「大域トークンがすべての位置を見る」ことは後ろを見ることになり、<Ref to="prop-sparse-pattern-causality" /> の前提が崩れます。因果的なモデルでできるのは、「すべての位置が列の先頭の数個を見る」という片側だけです。

次のコードは、パターンの行列を引数に取る注意を実装し、乱数の重みで $L$ 層重ねて、入力を 1 つずつ動かしたときに出力が変わるかどうかを実測します。

```python
# Python 3.12.14, NumPy 2.5.2
import numpy as np
rng = np.random.default_rng(20261010)
n, d = 12, 8

def pattern_window(n, w):          # 因果的な幅 w の窓: i は i-w+1, ..., i を見る
    i, j = np.indices((n, n)); return ((j <= i) & (j > i - w)).astype(int)

def layer(X, Wq, Wk, Wv, M):       # パターン M (0/1 行列) つきの自己注意 + 残差
    S = (X @ Wq) @ (X @ Wk).T / np.sqrt(d)
    S = np.where(M == 1, S, -np.inf)
    A = np.exp(S - S.max(axis=1, keepdims=True)); A /= A.sum(axis=1, keepdims=True)
    return X + A @ (X @ Wv)

def run(X, weights, M):
    for Wq, Wk, Wv in weights: X = layer(X, Wq, Wk, Wv, M)
    return X

def dependency(M, L):              # 入力 j を動かしたとき出力 i が変わるかを実測する
    weights = [tuple(rng.normal(0, 0.3, (d, d)) for _ in range(3)) for _ in range(L)]
    X = rng.normal(size=(n, d)); Y = run(X, weights, M); dep = np.zeros((n, n), dtype=int)
    for j in range(n):
        X2 = X.copy(); X2[j] += rng.normal(size=d)
        dep[:, j] = np.abs(run(X2, weights, M) - Y).max(axis=1) > 1e-12
    return dep

for w, L in [(3, 1), (3, 2), (3, 3), (12, 1)]:
    dep = dependency(pattern_window(n, w), L)
    reach = [int(i - np.flatnonzero(dep[i]).min()) for i in range(n)]   # 最も遠い依存までの距離
    print(f"w={w:2d} L={L}: farthest dependency per position = {reach}  bound L(w-1) = {L*(w-1)}")

dep = dependency(pattern_window(n, 3), 2)
print("dependency matrix for w=3, L=2 (rows: output i, cols: input j), first 8 positions:")
print(dep[:8, :8])
print("pairs in pattern: full causal =", int(pattern_window(n, n).sum()), " window w=3 =", int(pattern_window(n, 3).sum()))
```

```text
w= 3 L=1: farthest dependency per position = [0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2]  bound L(w-1) = 2
w= 3 L=2: farthest dependency per position = [0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 4]  bound L(w-1) = 4
w= 3 L=3: farthest dependency per position = [0, 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, 6]  bound L(w-1) = 6
w=12 L=1: farthest dependency per position = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]  bound L(w-1) = 11
dependency matrix for w=3, L=2 (rows: output i, cols: input j), first 8 positions:
[[1 0 0 0 0 0 0 0]
 [1 1 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0]
 [1 1 1 1 0 0 0 0]
 [1 1 1 1 1 0 0 0]
 [0 1 1 1 1 1 0 0]
 [0 0 1 1 1 1 1 0]
 [0 0 0 1 1 1 1 1]]
pairs in pattern: full causal = 78  window w=3 = 33
```

実測した依存の行列は、<Ref to="ex-window-table" /> の表と一致しています（コードの添字は $0$ 始まりです）。最も遠い依存までの距離は、どの位置でも上界 $L(w-1)$（列の先頭に近い位置では先頭までの距離）にちょうど達しています。<Ref to="thm-window-receptive-field" /> が保証するのは「これより遠くには依存しない」ことだけですが、乱数の重みでは受容野の中のすべての入力に実際に依存している、ということです。対の数 $78$ と $33$ は、$12 \times 13 / 2$ と $12 \times 3 - 3$ です。

## 5. 経路長：注意・再帰・畳み込みの比較

Vaswani らは、自己注意を選ぶ理由の 1 つとして、離れた位置の間を信号が伝わるのに通らなければならない段数が短いことを挙げ、層の種類ごとの比較を表にしています。受容野の言葉で定義を与えれば、この比較は証明できます。

<Definition id="def-path-length" title="経路長">
層ごとのパターン $M^{(1)}, M^{(2)}, \ldots$ が与えられているとき、位置 $j$ から位置 $i$ への**経路長**を、$j \in R_\ell(i)$ となる最小の $\ell$（そのような $\ell$ がなければ $\infty$）と定めます。因果的なパターンでは $j \le i$ の対だけを考え、$j < i$ の対についての経路長の最大値を**最大経路長**といいます。
</Definition>

列を左から順に処理するほかの構成も、同じ枠に入ります。

- **再帰型**: 状態を $\boldsymbol{s}_i = f(\boldsymbol{s}_{i-1}, \boldsymbol{x}_i)$ で更新します。位置 $i$ の状態が直接読むのは位置 $i - 1$ と $i$ だけなので、関数 $f$ の適用 1 回を 1 段と数えると、幅 $w = 2$ の窓のパターンと同じです。
- **畳み込み**（核の幅 $k \ge 2$、因果的）: 各層で位置 $i$ が $i - k + 1, \ldots, i$ を読みます。幅 $w = k$ の窓のパターンです。
- **拡張畳み込み**（核の幅 $k \ge 2$、層 $\ell$ の間隔 $k^{\ell-1}$）: 層 $\ell$ で位置 $i$ が $i - m k^{\ell-1}$（$m = 0, 1, \ldots, k-1$、$1$ 以上のもの）を読みます。ふつうの畳み込みが隣り合う位置を読むのに対し、読む位置を一定の間隔で飛ばして取る畳み込みのことで、層が上がるごとに間隔を $k$ 倍に広げるので、少ない層で遠くまで届きます。

<Proposition id="prop-path-length" title="最大経路長の比較">
長さ $n \ge 2$ の列について、位置 $1$ から位置 $n$ への経路長（これが最大経路長です）は次のとおりです。

1. 因果的な全注意: $1$。
2. 幅 $w \ge 2$ のスライディングウィンドウ注意、および核の幅 $k = w$ の畳み込み: $\Bigl\lceil \dfrac{n - 1}{w - 1} \Bigr\rceil$。
3. 再帰型: $n - 1$。
4. 核の幅 $k$ の拡張畳み込み: $\lceil \log_k n \rceil$。
</Proposition>

<Proof of="prop-path-length">
**1.** <Ref to="thm-window-receptive-field" /> の 4 から $1 \in R_1(n)$ で、$R_0(n) = \{n\}$ には $1$ が入らないので、経路長は $1$ です。

**2.** <Ref to="thm-window-receptive-field" /> の 1 から、$j \in R_\ell(i)$ は $i - \ell(w - 1) \le j \le i$ と同値です。$j = 1$、$i = n$ では $\ell(w-1) \ge n - 1$、すなわち $\ell \ge (n-1)/(w-1)$ で、最小の整数は $\lceil (n-1)/(w-1) \rceil$ です。$i - j$ が最大の対は $(1, n)$ なので、これが最大経路長です。畳み込みは同じパターンです。

**3.** 2 で $w = 2$ としたものです。

**4.** 位置 $i$ の $\ell$ 層のあとの受容野が $R_\ell(i) = \{\, j \ge 1 : 0 \le i - j \le k^\ell - 1 \,\}$ であることを、$\ell$ についての帰納法で示します。$\ell = 0$ では $k^0 - 1 = 0$ で $R_0(i) = \{i\}$ です。$\ell - 1$ で成り立つとします。層 $\ell$ は $i - m k^{\ell - 1}$（$m = 0, \ldots, k-1$）を読むので、$R_\ell(i)$ に入る $j$ の、$i$ からのずれ $i - j$ の全体は

$$
\bigcup_{m=0}^{k-1} \{\, m k^{\ell-1} + r : 0 \le r \le k^{\ell-1} - 1 \,\}
$$

（のうち $j \ge 1$ となるもの）です。$m$ 番目の集合は $m k^{\ell-1}$ から $(m+1)k^{\ell-1} - 1$ までの整数の全体で、$m = 0, \ldots, k-1$ について並べると $0$ から $k^{\ell} - 1$ までを隙間なく覆います。これで帰納法が進みます。なお、$i - m k^{\ell-1} < 1$ となる $m$ は読まれませんが、その先にある $j$ は $j \le i - mk^{\ell-1} < 1$ で、もともと範囲の外なので、結論は変わりません。

したがって $1 \in R_\ell(n)$ は $n - 1 \le k^\ell - 1$、すなわち $\ell \ge \log_k n$ と同値で、最小の整数は $\lceil \log_k n \rceil$ です。
</Proof>

| 層の種類 | 1 層の計算量 | 最大経路長（この記事） | Vaswani ら 表 1 |
|---|---|---|---|
| 全注意 | $O(n^2 d)$ | $1$ | $O(1)$ |
| 再帰型 | $O(n d^2)$ | $n - 1$ | $O(n)$ |
| 畳み込み（拡張） | $O(k n d^2)$ | $\lceil \log_k n \rceil$ | $O(\log_k n)$ |
| 範囲を限った注意（幅 $w$） | $O(n w d)$ | $\lceil (n-1)/(w-1) \rceil$ | $O(n/r)$（$r$ は近傍の大きさ） |

1 層の計算量の列は原論文の表の値です（再帰型と畳み込みの $d^2$ は、位置ごとに $d \times d$ の行列を掛けることによります）。原論文は本文で、核が連続している畳み込みでは $O(n/k)$ 層、拡張畳み込みでは $O(\log_k n)$ 層が要ると述べていて、2 と 4 がその内容です。

全注意は、計算量の $n^2$ と引き換えに、経路長 $1$ を得ています。窓つき注意はその逆の取引です。どちらが良いかは、扱いたい依存の距離と文脈長で決まり、この表が言えるのは取引の内容までです。経路が短いことが学習のしやすさにつながるという見立ては、原論文の動機として述べられているもので、定理ではありません。

## 6. 注意を近似する方法・速く計算する方法（一覧）

注意の計算量を下げる提案は数多くあります。ここでは代表的なものを、何を変え、何を保つかで整理します。各方法の中身は出典に譲ります。

| 方法 | 何をするか | 全注意と同じ出力か | 列の長さ $n$ についての計算量 |
|---|---|---|---|
| Longformer（Beltagy ら） | 窓つきの注意と少数の大域的な注意を組み合わせる | いいえ。パターンの違う別のモデル | 1 次 |
| Linformer（Wang ら） | 注意の行列を低階数の行列で近似する | いいえ。近似 | 時間・空間とも 1 次 |
| Performer（Choromanski ら） | softmax の核を正値の直交ランダム特徴で近似する | いいえ。不偏またはほぼ不偏な推定 | 時間・空間とも 1 次 |
| FlashAttention（Dao ら） | 計算を小さな塊に分け、記憶装置の階層の間の読み書きを減らす | はい。厳密な注意 | 2 次のまま（定数と読み書きの回数が減る） |
| 状態空間モデル（Gu–Dao の Mamba など） | 注意を使わない別の層に置き換える | 別の構成 | 1 次 |

表の中の語を簡単に補います。低階数での近似とは、大きな行列を、小さな行列の積で近似して計算を減らすことです。ランダム特徴とは、softmax の計算を、乱数で作った関数の内積で近似することです。状態空間モデルとは、過去の情報を固定の大きさの状態にまとめて、列を左から順に読んでいく型のモデルです。

この表で区別しておきたいのは、4 行目だけが「同じ関数を速く計算する」方法で、ほかは「別の関数に置き換える」方法だということです。前者は出力が変わらないので、正しさは計算の同値性として検証できます。後者は、置き換えたモデルが課題をどれだけ解けるかを、あらためて実験で確かめる必要があります。<Ref to="thm-window-receptive-field" /> のような命題は、置き換えによって原理的に失われるもの（遠い依存）を教えますが、実際の課題でそれがどれだけ効くかは教えません。

## 7. スケーリング則（経験則）とべき則の読み方

ここからは、モデルの規模の話に移ります。まず、経験則として報告されている内容を出典つきでまとめ、そのあとで、べき則という関数形について数学的に言えることを命題にします。

<Remark id="rem-kaplan" title="経験則：損失は規模のべき則に従う（Kaplan ら）">
Kaplan ら（2020）は、Transformer の言語モデルを大きさ・データ量・計算量を変えて多数学習し、テストデータでの交差エントロピー損失 $L$ が次の形でよく表されると報告しています。

- 十分なデータで収束まで学習したとき、埋め込みを除いたパラメータ数 $N$ について $L(N) = (N_c / N)^{\alpha_N}$、$\alpha_N \approx 0.076$。
- 大きなモデルを限られたデータ量 $D$（トークン数）で早期終了つきで学習したとき $L(D) = (D_c / D)^{\alpha_D}$、$\alpha_D \approx 0.095$。
- 計算量を最適に配分したとき、計算量 $C_{\min}$ について指数 $\approx 0.050$ のべき則。

これらは、著者らが調べた範囲（データセット、モデルの構成、規模）での**当てはめ**です。指数の値はデータやトークン化に依り、範囲の外へ延ばしてよい保証はありません。式の形そのものも選択の結果で、同じ論文は $N$ と $D$ の両方に依る別の形の式も使っていますし、次節の Hoffmann らは定数項のある別の形を当てはめています。以下でこの数値を使うときは、「報告された値を仮に入れるとこうなる」という意味です。
</Remark>

<Definition id="def-power-law" title="べき則">
定数 $a > 0$、$\alpha > 0$、$L_\infty \ge 0$ に対して

$$
L(N) = a N^{-\alpha} + L_\infty \qquad (N > 0)
$$

の形の関数を、指数 $\alpha$ の**べき則**といい、$L_\infty$ を**還元できない損失**と呼びます。$N \to \infty$ で $L(N) \to L_\infty$ です。
</Definition>

次の命題は、この関数形から何が読み取れるかを整理します。定数項がなければ両対数のグラフは直線で、指数は 2 点から決まります。定数項があると、グラフは途中で曲がって水平に近づくので、同じデータでも当てはめ方によって指数が変わります。そこで、定数項が未知でも指数を決められる点の取り方（等比に並んだ 3 点）を最後に示します。3 点を使うのは、隣り合う損失の差を取ると定数項が消え、残った差の比から指数が出るからです。

<Proposition id="prop-power-law" title="べき則の性質と指数の決定">
$L(N) = a N^{-\alpha} + L_\infty$（$a, \alpha > 0$、$L_\infty \ge 0$）とします。

1. $L_\infty = 0$ のとき、$\log L = \log a - \alpha \log N$ で、$\log L$ は $\log N$ の 1 次関数です。任意の $c > 0$ について $L(cN) = c^{-\alpha} L(N)$ です。
2. $L_\infty = 0$ のとき、2 点 $(N_1, L_1)$、$(N_2, L_2)$（$N_1 \ne N_2$）から $\alpha = -\dfrac{\log(L_2 / L_1)}{\log(N_2 / N_1)}$ と決まります。
3. $L_\infty > 0$ のとき、両対数での傾きは $\dfrac{d \log L}{d \log N} = -\alpha \Bigl(1 - \dfrac{L_\infty}{L(N)}\Bigr)$ で、$N$ とともに $-\alpha$ から $0$ へ変わります。$\log L$ は $\log N$ の 1 次関数ではありません。
4. $L_\infty$ が未知のとき、2 点からは $\alpha$ は決まりません。等比に並んだ 3 点 $N, cN, c^2 N$（$c > 1$）での値 $L_1, L_2, L_3$ からは
$$
\alpha = \frac{1}{\log c} \log \frac{L_1 - L_2}{L_2 - L_3}
$$
と決まります。
</Proposition>

<Proof of="prop-power-law">
**1.** $L = a N^{-\alpha}$ の両辺の対数を取ると $\log L = \log a - \alpha \log N$ です。$L(cN) = a c^{-\alpha} N^{-\alpha} = c^{-\alpha} L(N)$ です。

**2.** 1 から $L_2 / L_1 = (N_2 / N_1)^{-\alpha}$ で、対数を取ると $\log(L_2/L_1) = -\alpha \log(N_2/N_1)$ です。$N_1 \ne N_2$ なので $\log(N_2/N_1) \ne 0$ で、割ることができます。

**3.** $u = \log N$ とおくと $L = a e^{-\alpha u} + L_\infty$ で、$dL/du = -\alpha a e^{-\alpha u} = -\alpha (L - L_\infty)$ です。したがって $\dfrac{d \log L}{du} = \dfrac{1}{L} \dfrac{dL}{du} = -\alpha \dfrac{L - L_\infty}{L}$ です。$N \to 0$ で $L \to \infty$ なので傾きは $-\alpha$ に、$N \to \infty$ で $L \to L_\infty$ なので傾きは $0$ に近づきます。$L$ は $N$ について狭義単調減少なので、$L_\infty / L(N)$ は $N$ ごとに違う値を取り、傾きは一定ではありません。1 次関数の傾きは一定なので、$\log L$ は $\log N$ の 1 次関数ではありません。

**4.** 前半は例で示します。2 点 $(10^6, 2.0)$、$(10^8, 1.5)$ を通るべき則として、$L_\infty = 0$ のもの（2 から $\alpha = -\log 0.75 / \log 100 \approx 0.0625$）と、$L_\infty = 1$ のもの（$L - 1$ が $1.0$ から $0.5$ に半減するので $\alpha = \log 2 / \log 100 \approx 0.1505$）があり、指数が違います。後半は、$L_1 - L_2 = a N^{-\alpha}(1 - c^{-\alpha})$、$L_2 - L_3 = a (cN)^{-\alpha}(1 - c^{-\alpha}) = c^{-\alpha}(L_1 - L_2)$ から $(L_1 - L_2)/(L_2 - L_3) = c^{\alpha}$ で、対数を取って $\log c > 0$ で割ります。差を取った時点で $L_\infty$ が消えるのが要点です。
</Proof>

<Example id="ex-power-law-numbers" title="指数 0.076 の意味と、2 点での外挿の危うさ">
<Ref to="rem-kaplan" /> の報告値 $\alpha_N \approx 0.076$ を、$L_\infty = 0$ のべき則にそのまま入れてみます。

- パラメータ数を $10$ 倍にすると、損失は $10^{-0.076} \approx 0.839$ 倍になります。約 $16\%$ の減少です。
- $2$ 倍では $2^{-0.076} \approx 0.949$ 倍、$1000$ 倍では $0.592$ 倍です。
- 損失を半分にするには、パラメータ数を $2^{1/0.076} \approx 9100$ 倍にする必要があります。

指数が小さいべき則では、規模を何桁も増やして初めて損失が目に見えて下がります。

次に、<Ref to="prop-power-law" /> の 4 の証明の 2 つのべき則で、$N = 10^{10}$ での値を予測してみます。$L_\infty = 0$、$\alpha = 0.0625$ のほうは、$N$ が $100$ 倍になるごとに $0.75$ 倍なので $1.5 \times 0.75 = 1.125$ です。$L_\infty = 1$、$\alpha = 0.1505$ のほうは、$L - 1$ が $100$ 倍ごとに半分なので $1 + 0.25 = 1.25$ です。同じ 2 点を通っているのに、予測は違います。前者はどこまでも下がり続け、後者は $1$ で頭打ちになります。測定した範囲の中では区別のつかない 2 つの式が、外では別の答えを出します。
</Example>

次のコードは、定数項のあるべき則から作った合成データに、定数項を無視して両対数の直線を当てはめると、指数の推定がどれだけずれるかを見ます。直線の当てはめは最小二乗法で、正規方程式（<Ref to="computer-science/math-for-ml/linear-regression#thm-normal-equation" />）を解きます。

```python
# Python 3.12.14, NumPy 2.5.2
import numpy as np
rng = np.random.default_rng(20261010)

def fit_power(N, Lv):              # log L = log a - alpha log N の最小二乗（正規方程式）
    X = np.column_stack([np.ones_like(N), np.log(N)]); y = np.log(Lv)
    c = np.linalg.solve(X.T @ X, X.T @ y)
    return np.exp(c[0]), -c[1]

N = 10.0 ** np.arange(5, 10)                       # 10^5, ..., 10^9
alpha, a = 0.3, 50.0
print("true alpha = 0.3")
for L_inf in (0.0, 0.5, 1.0, 2.0):
    Lv = (a * N ** -alpha + L_inf) * np.exp(rng.normal(0, 0.01, N.size))   # 1% の乗法的な雑音
    a_hat, al_hat = fit_power(N, Lv)
    a2, al2 = fit_power(N, Lv - L_inf)             # L_inf を知っていて引いた場合
    print(f"L_inf={L_inf:3.1f}: fit ignoring L_inf -> alpha={al_hat:.4f}   fit after subtracting -> alpha={al2:.4f}")

# 雑音なしの 3 点 (N, cN, c^2 N) からの閉じた式
L3 = a * np.array([1e6, 1e7, 1e8]) ** -alpha + 1.0
print("three-point formula:", np.log((L3[0] - L3[1]) / (L3[1] - L3[2])) / np.log(10.0))
print("two-point slope    :", -np.log(L3[1] / L3[0]) / np.log(10.0), -np.log(L3[2] / L3[1]) / np.log(10.0))
```

```text
true alpha = 0.3
L_inf=0.0: fit ignoring L_inf -> alpha=0.3022   fit after subtracting -> alpha=0.3022
L_inf=0.5: fit ignoring L_inf -> alpha=0.1370   fit after subtracting -> alpha=0.3123
L_inf=1.0: fit ignoring L_inf -> alpha=0.0924   fit after subtracting -> alpha=0.2987
L_inf=2.0: fit ignoring L_inf -> alpha=0.0582   fit after subtracting -> alpha=0.3131
three-point formula: 0.29999999999999927
two-point slope    : 0.10819880190594328 0.06640883135207543
```

真の指数は $0.3$ ですが、還元できない損失が $0.5$ あるだけで、定数項を無視した当てはめは $0.137$ と半分以下に見積もります。$L_\infty = 2$ では $0.058$ です。定数項を正しく引いてから当てはめれば $0.3$ 前後に戻ります。3 点の式は雑音がなければ正確に $0.3$ を返し、2 点ごとの傾きは区間によって $0.108$、$0.066$ と変わっています（<Ref to="prop-power-law" /> の 3）。

報告されている指数を読むときは、どの関数形を当てはめたものかを確かめる必要がある、というのがこの節の結論です。定数項のない形で当てはめた指数と、定数項のある形で当てはめた指数は、同じデータでも違う値になり、直接は比べられません。

## 8. 計算量の予算をモデルとデータにどう配分するか

学習に使える計算量が決まっているとき、それを大きなモデルに使うか、多くのデータに使うかという問いがあります。損失の関数形を仮定すれば、これは 1 変数の最小化問題として厳密に解けます。

<Definition id="def-compute-budget" title="計算量の予算の模型">
学習の計算量が、パラメータ数 $N$ と学習に使うトークン数 $D$ の積に比例する、すなわちある定数 $\kappa > 0$ で $\text{計算量} = \kappa N D$ と書けるという模型を考えます。計算量の上限が決まっていることは、$C > 0$ を定数として $N D = C$ という制約で表されます（$\kappa$ は $C$ に含めます）。
</Definition>

1 トークンの順伝播と逆伝播の計算量がパラメータ数にほぼ比例するなら、この模型になります。Hoffmann らは、Kaplan らの見積もりに従って $\kappa = 6$（計算量 $\approx 6ND$）を使っています。<Ref to="prop-context-quadratic" /> で見たとおり、注意の項は文脈長にも依るので、これは近似です。

次の定理が答えるのは、予算 $C$ が増えたとき、モデルの大きさとデータの量をそれぞれどれだけ増やすのがよいかです。証明の方針は、制約 $ND = C$ で $D$ を消して 1 変数の関数にし、$u = \log N$ という変数に直すと凸関数になることを使って、微分が 0 になる点がただ 1 つの最小点であることを示す、というものです。

<Theorem id="thm-compute-optimal-allocation" title="べき則のもとでの最適配分">
$A, B, \alpha, \beta > 0$、$E \ge 0$、$C > 0$ とし、損失が

$$
L(N, D) = E + A N^{-\alpha} + B D^{-\beta} \qquad (N, D > 0)
$$

の形であるとします。制約 $ND = C$ のもとで $L$ を最小にする $(N, D)$ はただ 1 つ存在し、

$$
N^{\star} = G\, C^{\frac{\beta}{\alpha + \beta}}, \qquad D^{\star} = G^{-1} C^{\frac{\alpha}{\alpha + \beta}}, \qquad G = \Bigl(\frac{\alpha A}{\beta B}\Bigr)^{\frac{1}{\alpha + \beta}}
$$

です。このとき次が成り立ちます。

1. 最適点では $\alpha A (N^{\star})^{-\alpha} = \beta B (D^{\star})^{-\beta}$ です。
2. 最小値は $L^{\star}(C) = E + \Bigl(1 + \dfrac{\alpha}{\beta}\Bigr) A\, G^{-\alpha}\, C^{-\frac{\alpha\beta}{\alpha+\beta}}$ で、$L^{\star} - E$ は $C$ について指数 $\dfrac{\alpha\beta}{\alpha+\beta}$ のべき則です。
3. $\alpha = \beta$ なら $N^{\star}$ と $D^{\star}$ はともに $\sqrt{C}$ に比例します。予算を $4$ 倍にすると、モデルもデータも $2$ 倍にするのが最適です。
</Theorem>

<Proof of="thm-compute-optimal-allocation">
制約から $D = C/N$ を代入すると、$N > 0$ の 1 変数関数

$$
f(N) = E + A N^{-\alpha} + B C^{-\beta} N^{\beta}
$$

の最小化になります。$u = \log N$（$N > 0$ と $u \in \mathbb{R}$ は 1 対 1 に対応します）とおき、$\varphi(u) = f(e^u) = E + A e^{-\alpha u} + B C^{-\beta} e^{\beta u}$ とします。

$$
\varphi'(u) = -\alpha A e^{-\alpha u} + \beta B C^{-\beta} e^{\beta u}, \qquad \varphi''(u) = \alpha^2 A e^{-\alpha u} + \beta^2 B C^{-\beta} e^{\beta u} > 0
$$

です。$\varphi'' > 0$ なので $\varphi'$ は狭義単調増加です（<Ref to="mathematics/calculus/mean-value-and-taylor#cor-monotonicity" /> の 3）。$\varphi'(u) = 0$ は

$$
\beta B C^{-\beta} e^{\beta u} = \alpha A e^{-\alpha u} \iff e^{(\alpha + \beta) u} = \frac{\alpha A}{\beta B} C^{\beta}
$$

と同値で、右辺は正なので、解 $u^{\star} = \dfrac{1}{\alpha+\beta} \log\Bigl(\dfrac{\alpha A}{\beta B} C^{\beta}\Bigr)$ がただ 1 つあります。$\varphi'$ は狭義単調増加なので、$u < u^{\star}$ で $\varphi' < 0$、$u > u^{\star}$ で $\varphi' > 0$ です。したがって $\varphi$ は $u^{\star}$ の左で狭義単調減少、右で狭義単調増加で（同じ系の 3 を $-\varphi$ と $\varphi$ に使います）、$u^{\star}$ がただ 1 つの最小点です。これは、$\varphi$ が凸関数（<Ref to="computer-science/math-for-ml/why-math-for-ml#def-convex" />）で、凸関数の停留点が大域最小点であること（<Ref to="computer-science/math-for-ml/why-math-for-ml#thm-convex-stationary" />）の 1 変数の場合でもあります。

$N^{\star} = e^{u^{\star}} = \Bigl(\dfrac{\alpha A}{\beta B}\Bigr)^{\frac{1}{\alpha+\beta}} C^{\frac{\beta}{\alpha+\beta}} = G\, C^{\frac{\beta}{\alpha+\beta}}$ で、$D^{\star} = C / N^{\star} = G^{-1} C^{1 - \frac{\beta}{\alpha+\beta}} = G^{-1} C^{\frac{\alpha}{\alpha+\beta}}$ です。

**1.** $\varphi'(u^{\star}) = 0$ の式 $\alpha A (N^{\star})^{-\alpha} = \beta B C^{-\beta} (N^{\star})^{\beta}$ で、$C^{-\beta}(N^{\star})^{\beta} = (C/N^{\star})^{-\beta} = (D^{\star})^{-\beta}$ です。

**2.** 1 から $B (D^{\star})^{-\beta} = \dfrac{\alpha}{\beta} A (N^{\star})^{-\alpha}$ なので、$L^{\star} = E + \Bigl(1 + \dfrac{\alpha}{\beta}\Bigr) A (N^{\star})^{-\alpha}$ です。$(N^{\star})^{-\alpha} = G^{-\alpha} C^{-\frac{\alpha\beta}{\alpha+\beta}}$ を入れると主張の式です。

**3.** $\alpha = \beta$ なら $\dfrac{\beta}{\alpha+\beta} = \dfrac{\alpha}{\alpha+\beta} = \dfrac{1}{2}$ です。$C$ を $4$ 倍にすると $\sqrt{C}$ は $2$ 倍になります。
</Proof>

1 は、最適点で 2 つの項が「つり合う」ことを言っています。つり合うのは項の値 $A N^{-\alpha}$ と $B D^{-\beta}$ ではなく、それに指数を掛けたものです。モデルが小さすぎれば $A N^{-\alpha}$ の項が大きく、データが少なすぎれば $B D^{-\beta}$ の項が大きくなり、どちらかが突出しているうちは、予算を移すことで損失を下げられます。

指数の分かれ方にも注意してください。$N^{\star}$ の指数は $\beta$（データの側の指数）に、$D^{\star}$ の指数は $\alpha$（モデルの側の指数）に比例します。損失がモデルの大きさに敏感（$\alpha$ が大きい）なほど、予算が増えたときに多く増やすべきなのはデータのほうです。$\alpha$ が大きいと、モデルの項は少しの増加で十分に小さくなるからです。

<Example id="ex-allocation" title="仮の指数での最適配分">
**以下の数値は説明のための仮のものです。** $\alpha = \beta = 0.3$、$A = B = 1$、$E = 0$ とします。$G = 1$ で、$N^{\star} = D^{\star} = \sqrt{C}$ です。

| $C$ | $N^{\star}$ | $D^{\star}$ | $L^{\star}$ |
|---|---|---|---|
| $10^{12}$ | $10^6$ | $10^6$ | $0.0317$ |
| $10^{14}$ | $10^7$ | $10^7$ | $0.0159$ |
| $10^{16}$ | $10^8$ | $10^8$ | $0.0080$ |

$L^{\star} = 2 C^{-0.15}$ で、予算を $100$ 倍にすると $100^{-0.15} \approx 0.501$ 倍になります。$\alpha = \beta = 0.3$ という個々の指数に対して、予算についての指数は $\alpha\beta/(\alpha+\beta) = 0.15$ と半分です。予算を $N$ と $D$ の両方に分けなければならないからです。

$A$ だけを $2$ にすると $G = 2^{1/0.6} \approx 3.17$ で、$N^{\star}$ は $3.17$ 倍、$D^{\star}$ は $1/3.17$ 倍になります。指数は変わらず、係数だけが動きます。
</Example>

<Remark id="rem-hoffmann" title="経験則：当てはめられた指数と、報告の食い違い">
<Ref to="thm-compute-optimal-allocation" /> の損失の形 $E + A/N^{\alpha} + B/D^{\beta}$ は、Hoffmann ら（2022）が 3 通りの推定方法の 1 つで使った式です。同論文は、$400$ を超えるモデルの学習結果への当てはめとして $\alpha = 0.34$、$\beta = 0.28$、$E = 1.69$、$A = 406.4$、$B = 410.7$ を報告し、制約を計算量 $\approx 6ND$ として、定理と同じ閉じた式（$N^{\star}$ の指数が $\beta/(\alpha+\beta)$）を示しています。最適なパラメータ数の指数として報告されている値は、3 通りの方法で $0.50$、$0.49$、$0.46$ です（丸めた $\alpha, \beta$ から計算すると $0.28/0.62 \approx 0.45$ です）。著者らはこれを「モデルの大きさを 2 倍にするごとに、学習トークン数も 2 倍にするのがよい」と要約しています。

一方、Kaplan ら（2020）は別の関数形と別の実験から、最適なモデルの大きさが計算量の約 $0.73$ 乗に比例すると報告しており、Hoffmann らの表にもこの値が対比として載っています。$0.73$ なら予算の大半をモデルの大きさに回すことになり、$0.5$ なら半々です。結論が違います。

この食い違いが示しているのは、定理の側ではなく入力の側の不確かさです。<Ref to="thm-compute-optimal-allocation" /> は「損失がこの形で、指数がこの値なら、最適配分はこうなる」という条件つきの主張で、その部分は証明されています。損失が実際にその形をしているか、指数がいくつか、当てはめた範囲の外でも同じ式が成り立つかは、実験でしか分からず、実験の設計によって答えが変わりえます。新しい数値をここで作ることはしません。
</Remark>

```python
# Python 3.12.14, NumPy 2.5.2
import numpy as np

def closed_form(A, B, alpha, beta, C):
    G = (alpha * A / (beta * B)) ** (1 / (alpha + beta))
    return G * C ** (beta / (alpha + beta)), C ** (alpha / (alpha + beta)) / G

def numeric(A, B, alpha, beta, C, E=0.0):          # u = log N についての三分探索（凸関数）
    f = lambda u: E + A * np.exp(-alpha * u) + B * C ** -beta * np.exp(beta * u)
    lo, hi = 0.0, np.log(C)
    for _ in range(200):
        m1, m2 = lo + (hi - lo) / 3, hi - (hi - lo) / 3
        if f(m1) < f(m2): hi = m2
        else: lo = m1
    return np.exp((lo + hi) / 2), f((lo + hi) / 2)

for (A, B, alpha, beta) in [(1.0, 1.0, 0.3, 0.3), (2.0, 1.0, 0.3, 0.3), (1.0, 1.0, 0.4, 0.2)]:
    print(f"A={A} B={B} alpha={alpha} beta={beta}: exponents N: {beta/(alpha+beta):.4f}, D: {alpha/(alpha+beta):.4f}")
    for C in (1e12, 1e14, 1e16):
        Ns, Ds = closed_form(A, B, alpha, beta, C); Nn, fmin = numeric(A, B, alpha, beta, C)
        print(f"   C={C:.0e}  N*={Ns:.4e}  D*={Ds:.4e}  numeric N={Nn:.4e}  loss-E={fmin:.6f}  "
              f"alpha*A*N^-alpha={alpha*A*Ns**-alpha:.3e}  beta*B*D^-beta={beta*B*Ds**-beta:.3e}")
```

```text
A=1.0 B=1.0 alpha=0.3 beta=0.3: exponents N: 0.5000, D: 0.5000
   C=1e+12  N*=1.0000e+06  D*=1.0000e+06  numeric N=1.0000e+06  loss-E=0.031698  alpha*A*N^-alpha=4.755e-03  beta*B*D^-beta=4.755e-03
   C=1e+14  N*=1.0000e+07  D*=1.0000e+07  numeric N=1.0000e+07  loss-E=0.015887  alpha*A*N^-alpha=2.383e-03  beta*B*D^-beta=2.383e-03
   C=1e+16  N*=1.0000e+08  D*=1.0000e+08  numeric N=1.0000e+08  loss-E=0.007962  alpha*A*N^-alpha=1.194e-03  beta*B*D^-beta=1.194e-03
A=2.0 B=1.0 alpha=0.3 beta=0.3: exponents N: 0.5000, D: 0.5000
   C=1e+12  N*=3.1748e+06  D*=3.1498e+05  numeric N=3.1748e+06  loss-E=0.044828  alpha*A*N^-alpha=6.724e-03  beta*B*D^-beta=6.724e-03
   C=1e+14  N*=3.1748e+07  D*=3.1498e+06  numeric N=3.1748e+07  loss-E=0.022467  alpha*A*N^-alpha=3.370e-03  beta*B*D^-beta=3.370e-03
   C=1e+16  N*=3.1748e+08  D*=3.1498e+07  numeric N=3.1748e+08  loss-E=0.011260  alpha*A*N^-alpha=1.689e-03  beta*B*D^-beta=1.689e-03
A=1.0 B=1.0 alpha=0.4 beta=0.2: exponents N: 0.3333, D: 0.6667
   C=1e+12  N*=3.1748e+04  D*=3.1498e+07  numeric N=3.1748e+04  loss-E=0.047472  alpha*A*N^-alpha=6.330e-03  beta*B*D^-beta=6.330e-03
   C=1e+14  N*=1.4736e+05  D*=6.7860e+08  numeric N=1.4736e+05  loss-E=0.025690  alpha*A*N^-alpha=3.425e-03  beta*B*D^-beta=3.425e-03
   C=1e+16  N*=6.8399e+05  D*=1.4620e+10  numeric N=6.8399e+05  loss-E=0.013903  alpha*A*N^-alpha=1.854e-03  beta*B*D^-beta=1.854e-03
```

閉じた式の $N^{\star}$ と、$\log N$ についての三分探索で数値的に求めた最小点は、表示した桁で一致しています。最後の 2 列は <Ref to="thm-compute-optimal-allocation" /> の 1 のつり合いの条件で、どの行でも等しくなっています。3 番目の設定（$\alpha = 0.4$、$\beta = 0.2$）では、予算を $100$ 倍にしたとき $N^{\star}$ は $100^{1/3} \approx 4.6$ 倍、$D^{\star}$ は $100^{2/3} \approx 21.5$ 倍で、モデルの側の指数が大きいほどデータを多く増やすという、上で述べた向きが確かめられます。

## 9. 文脈を外から補う：検索拡張生成とツール利用（概観）

重みに入っていない知識をモデルに使わせる方法は、大きく 2 つあります。重みを更新する（[学習](/computer-science/llm-architecture/training-language-models)の章の微調整）か、入力に書き足すかです。後者は文脈長を使います。

<Definition id="def-retrieval-augmented-generation" title="検索拡張生成">
質問（長さ $n$ トークン）に対して、外部の文書の集まりから関連する断片を $k$ 個（各 $c$ トークン以下）検索し、それらを質問と合わせた列をモデルの入力にして生成する構成を、**検索拡張生成**といいます。Lewis ら（2020）は、事前学習済みの生成モデルと、文書の索引を引く検索器を組み合わせた構成をこの名前で提案しました。
</Definition>

<Proposition id="prop-retrieval-context-cost" title="検索した断片を入力に足すコスト">
<Ref to="def-retrieval-augmented-generation" /> の構成で、全注意のモデルを使うとします。

1. 入力の長さは高々 $n + kc$ で、1 層の注意の乗算は $2(n + kc)^2 d$ 回以下、KV キャッシュは $2L(n + kc)d$ 個以下です。断片を足さない場合に比べて、注意の項は高々 $\bigl(1 + \frac{kc}{n}\bigr)^2$ 倍、線形写像と MLP の項とキャッシュは高々 $1 + \frac{kc}{n}$ 倍です。
2. 生成の分布は $p_\theta(\cdot \mid \text{断片}, \text{質問})$ で、重み $\theta$ は断片に依りません。文書の集まりを入れ替えても $\theta$ は変わらず、出力の変化は、条件にする接頭辞が変わることだけを通じて起こります。
</Proposition>

<Proof of="prop-retrieval-context-cost">
**1.** <Ref to="prop-context-quadratic" /> で $n$ を $n + kc$ に置き換えたものです。比は $2(n+kc)^2 d / (2n^2 d) = (1 + kc/n)^2$、$(n + kc)/n = 1 + kc/n$ です。

**2.** 構成の定義から、モデルは断片と質問をつないだ列を接頭辞として受け取り、自己回帰生成（<Ref to="computer-science/llm-architecture/inference-and-sampling#def-autoregressive-generation" />）を行います。その各ステップの分布は、同じ $\theta$ のもとでの $p_\theta(\cdot \mid x_{<t})$ で、検索は $x_{<t}$ の内容を変えるだけです。
</Proof>

たとえば $n = 200$、$k = 5$、$c = 300$ なら、入力は $1700$ トークンで、注意の計算量は $(1700/200)^2 = 72.25$ 倍、線形写像と MLP の項は $8.5$ 倍です。

2 は、検索拡張生成の利点と限界の両方を言っています。利点は、知識を更新するのに学習が要らないことです。文書を差し替えれば、次の質問から新しい内容が条件に入ります。限界は、モデルが断片を正しく使う保証を、この命題が何も与えないことです。検索が関連する断片を返すか、モデルが断片の内容に沿って答えるかは、どちらも経験的な事柄で、ここでは定理を立てません。

<Remark id="rem-long-context-empirical" title="経験的な報告：文脈に入れた情報がどう使われるか">
文脈に入れたものがすべて同じように使われるわけではないことが、実験で報告されています。

- Brown ら（2020）は、課題の説明と少数の例を入力の文章として与えるだけで、勾配による更新なしに、モデルがさまざまな課題をこなせることを報告しました（文脈内学習）。重みを変えずに振る舞いを変える手段として、文脈が使えるということです。
- Liu ら（2023）は、複数の文書から答えを探す課題で、必要な情報が入力の先頭か末尾にあるときに正答率が高く、中ほどにあると大きく下がることを報告しています。受容野の意味では全注意はどの位置にも 1 層で届きます（<Ref to="prop-path-length" />）が、届くことと、使われることは別です。
- 学習時より長い列でモデルがどう振る舞うか（位置符号化の外挿）も、方式とモデルに依る経験的な問題です（<Ref to="computer-science/llm-architecture/embeddings-and-positional-encoding#prop-learned-position-table" /> のあとの注意を参照）。

これらは調べられたモデルと課題についての観察で、モデルが変われば結果も変わりえます。
</Remark>

**ツール利用**は、入力に書き足す内容を、検索に限らず外部のプログラムの実行結果に広げたものです。モデルは決められた書式で「どのツールを、どの引数で呼ぶか」を出力し、外側のプログラムがそれを実行して、結果を入力の末尾に足します。モデルは伸びた入力から生成を続けます。

<Figure caption="ツール利用の反復。モデルの側で起きているのは、これまでと同じ自己回帰生成だけである。外側のプログラムが、出力を解釈して実行し、結果を入力に足す。">

<svg viewBox="0 0 720 190" width="100%" role="img" aria-label="モデルが呼び出しを出力し、外部で実行され、結果が入力に足される反復">
  <defs>
    <marker id="sc-head" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M 0 0 L 10 5 L 0 10 z" fill="currentColor" />
    </marker>
  </defs>
  <g fill="none" stroke="currentColor" stroke-width="1.4">
    <rect x="20" y="60" width="170" height="60" rx="6" />
    <rect x="275" y="60" width="170" height="60" rx="6" stroke="var(--sl-color-accent)" />
    <rect x="530" y="60" width="170" height="60" rx="6" />
    <path d="M 190 90 L 271 90" marker-end="url(#sc-head)" />
    <path d="M 445 90 L 526 90" marker-end="url(#sc-head)" />
    <path d="M 615 120 L 615 160 L 105 160 L 105 124" marker-end="url(#sc-head)" />
  </g>
  <g fill="currentColor" font-size="13" text-anchor="middle">
    <text x="105" y="85">入力の列</text>
    <text x="105" y="105">（指示・これまでの結果）</text>
    <text x="360" y="85">モデル</text>
    <text x="360" y="105">自己回帰生成</text>
    <text x="615" y="85">外側のプログラム</text>
    <text x="615" y="105">呼び出しを実行</text>
    <text x="230" y="80">読む</text>
    <text x="487" y="80">呼び出し</text>
    <text x="360" y="178">実行結果を入力の末尾に足して、もう一度</text>
    <text x="360" y="40">呼び出しを含まない出力が出たら終了</text>
  </g>
</svg>

</Figure>

この反復について、この章までの命題から言えることが 2 つあります。1 つは、1 回ごとに入力が伸びるので、<Ref to="prop-context-quadratic" /> のコストが回を追って増え、いずれ文脈長の上限に当たることです。もう 1 つは、結果を**末尾に**足すかぎり、それまでの接頭辞は変わらないので、KV キャッシュがそのまま使えることです（<Ref to="computer-science/llm-architecture/inference-and-sampling#thm-kv-cache-correct" />）。途中を書き換えれば、その位置以降は計算し直しになります。

モデルがいつ、どのツールを呼ぶべきか、反復をどう止めるか、長くなった入力をどう縮めるかといった設計は、モデルの構造ではなく、それを囲むプログラムの問題です。その仕組みは、次のテーマの[エージェントループ](/computer-science/claude-code-internals/agent-loop)で扱います。

## 10. 演習

<Exercise id="exr-window-reach" difficulty="易">
幅 $w = 5$ のスライディングウィンドウ注意を $L = 6$ 層重ねたモデルを考えます。(1) 位置 $40$ の出力が依存しうる入力の位置の範囲を求めてください。(2) 位置 $40$ の出力が位置 $1$ の入力に依存しうるようにするには、層を何層にする必要がありますか。(3) 長さ $n = 100$ の列で、1 層の注意が計算する位置の対の数を、全注意と比べてください。
<Solution>
(1) <Ref to="thm-window-receptive-field" /> の 1 から $R_6(40) = \{\, j : 40 - 6 \times 4 \le j \le 40 \,\}$、すなわち位置 $16$ から $40$ までです。

(2) 距離は $D = 39$ なので、$L \ge \lceil 39/4 \rceil = 10$ 層です。$9$ 層では $9 \times 4 = 36$ で、位置 $4$ までしか届きません。

(3) <Ref to="prop-window-attention-cost" /> から窓では $100 \times 5 - 5 \times 4/2 = 490$ 対、全注意では $100 \times 101/2 = 5050$ 対で、約 $10$ 分の $1$ です。
</Solution>
</Exercise>

<Exercise id="exr-three-points" difficulty="標準">
パラメータ数 $10^7$、$10^8$、$10^9$ のモデルの損失が、それぞれ $3.20$、$2.56$、$2.24$ だったとします。(1) 初めの 2 点だけを使い、$L_\infty = 0$ のべき則を仮定して指数 $\alpha$ を求め、$10^{10}$ での損失を予測してください。(2) 3 点すべてを使って、$L_\infty$ のあるべき則の $\alpha$ と $L_\infty$ を求め、$10^{10}$ での損失を予測してください。(3) 2 つの予測の違いについて述べてください。
<Solution>
(1) <Ref to="prop-power-law" /> の 2 から $\alpha = -\log(2.56/3.20)/\log 10 = -\log_{10} 0.8 \approx 0.0969$ です。$10$ 倍ごとに $0.8$ 倍なので、$10^{10}$ では $2.56 \times 0.8^2 \approx 1.64$ です。ただしこの式は、3 番目の測定値を $2.56 \times 0.8 = 2.048$ と予測し、実際の $2.24$ と合いません。

(2) <Ref to="prop-power-law" /> の 4 で $c = 10$ とすると、$L_1 - L_2 = 0.64$、$L_2 - L_3 = 0.32$ から $\alpha = \log_{10}(0.64/0.32) = \log_{10} 2 \approx 0.301$ です。$L_1 - L_2 = a N^{-\alpha}(1 - c^{-\alpha})$ で $c^{-\alpha} = 1/2$ なので、$N = 10^7$ での $a N^{-\alpha} = 0.64 / 0.5 = 1.28$、$L_\infty = 3.20 - 1.28 = 1.92$ です。$10$ 倍ごとに $a N^{-\alpha}$ が半分になるので、$10^{10}$ では $1.92 + 1.28/8 = 2.08$ です。確かめると $10^8$ で $1.92 + 0.64 = 2.56$、$10^9$ で $1.92 + 0.32 = 2.24$ で、3 点を通ります。

(3) 予測は $1.64$ と $2.08$ で、大きく違います。(1) の式はどこまでも下がり続け、(2) の式は $1.92$ で頭打ちになります。3 番目の点が (1) の式に合わないことが、定数項の存在を示す手がかりでした。ただし (2) も 3 つの未知数を 3 点で決めただけなので、当てはまりの良さを検証する余地がなく、測定の誤差があれば $L_\infty$ の推定は大きく揺れます。
</Solution>
</Exercise>

<Exercise id="exr-allocation" difficulty="標準">
損失が $L(N, D) = N^{-1/2} + D^{-1/4}$ で、制約が $ND = C$ であるとします。(1) 最適な $N^{\star}$、$D^{\star}$ を $C$ の式で求めてください。(2) $C = 10^{12}$ のときの値を求めてください。(3) 予算を $8$ 倍にすると、$N^{\star}$、$D^{\star}$、$L^{\star}$ はそれぞれ何倍になりますか。
<Solution>
(1) $\alpha = 1/2$、$\beta = 1/4$、$A = B = 1$、$E = 0$ です。<Ref to="thm-compute-optimal-allocation" /> から $G = (\alpha/\beta)^{1/(\alpha+\beta)} = 2^{4/3} \approx 2.52$、$N^{\star} = 2^{4/3} C^{1/3}$、$D^{\star} = 2^{-4/3} C^{2/3}$ です。

(2) $C^{1/3} = 10^4$、$C^{2/3} = 10^8$ なので、$N^{\star} \approx 2.52 \times 10^4$、$D^{\star} \approx 3.97 \times 10^7$ です。つり合いの条件を確かめると、$\alpha (N^{\star})^{-1/2} = 0.5 / \sqrt{2.52 \times 10^4} \approx 3.15 \times 10^{-3}$、$\beta (D^{\star})^{-1/4} = 0.25 / (3.97 \times 10^7)^{1/4} \approx 0.25 / 79.4 \approx 3.15 \times 10^{-3}$ で、等しくなっています。

(3) $N^{\star}$ は $8^{1/3} = 2$ 倍、$D^{\star}$ は $8^{2/3} = 4$ 倍です。$L^{\star}$ の指数は $\alpha\beta/(\alpha+\beta) = (1/8)/(3/4) = 1/6$ なので、$8^{-1/6} = 2^{-1/2} \approx 0.707$ 倍です。モデルの側の指数が大きいので、増やした予算の多くはデータに回ります。
</Solution>
</Exercise>

<Exercise id="exr-retrieval-cost" difficulty="易">
質問が $n = 500$ トークンのとき、各 $250$ トークンの断片を $k$ 個足します。全注意のモデルで、注意の計算量が断片なしの場合の $9$ 倍になるのは $k$ がいくつのときですか。そのとき、KV キャッシュの記憶量は何倍になりますか。
<Solution>
<Ref to="prop-retrieval-context-cost" /> の 1 から、$(1 + 250k/500)^2 = 9$、すなわち $1 + k/2 = 3$ で $k = 4$ です。入力は $1500$ トークンになります。KV キャッシュは長さに比例するので $3$ 倍です。注意の計算量は 2 乗で、記憶量は 1 乗で増えます。
</Solution>
</Exercise>

## 参考文献

- A. Vaswani, N. Shazeer, N. Parmar, J. Uszkoreit, L. Jones, A. N. Gomez, Ł. Kaiser, I. Polosukhin, "Attention Is All You Need" (2017), [arXiv:1706.03762](https://arxiv.org/abs/1706.03762) — §4 と表 1（層の種類ごとの計算量と最大経路長）。
- I. Beltagy, M. E. Peters, A. Cohan, "Longformer: The Long-Document Transformer" (2020), [arXiv:2004.05150](https://arxiv.org/abs/2004.05150)
- S. Wang, B. Z. Li, M. Khabsa, H. Fang, H. Ma, "Linformer: Self-Attention with Linear Complexity" (2020), [arXiv:2006.04768](https://arxiv.org/abs/2006.04768)
- K. Choromanski ほか, "Rethinking Attention with Performers", ICLR 2021, [arXiv:2009.14794](https://arxiv.org/abs/2009.14794)
- T. Dao, D. Y. Fu, S. Ermon, A. Rudra, C. Ré, "FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness" (2022), [arXiv:2205.14135](https://arxiv.org/abs/2205.14135)
- A. Gu, T. Dao, "Mamba: Linear-Time Sequence Modeling with Selective State Spaces" (2023), [arXiv:2312.00752](https://arxiv.org/abs/2312.00752)
- J. Kaplan, S. McCandlish, T. Henighan, T. B. Brown, B. Chess, R. Child, S. Gray, A. Radford, J. Wu, D. Amodei, "Scaling Laws for Neural Language Models" (2020), [arXiv:2001.08361](https://arxiv.org/abs/2001.08361) — §1.2（べき則の要約と指数）、§6（計算量の最適配分）。
- J. Hoffmann ほか, "Training Compute-Optimal Large Language Models" (2022), [arXiv:2203.15556](https://arxiv.org/abs/2203.15556) — §3.3（損失の式と閉じた形の最適配分）、表 2、付録 D.2（当てはめた係数と指数の値）。
- P. Lewis ほか, "Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks", NeurIPS 2020, [arXiv:2005.11401](https://arxiv.org/abs/2005.11401)
- T. B. Brown ほか, "Language Models are Few-Shot Learners" (2020), [arXiv:2005.14165](https://arxiv.org/abs/2005.14165)
- N. F. Liu, K. Lin, J. Hewitt, A. Paranjape, M. Bevilacqua, F. Petroni, P. Liang, "Lost in the Middle: How Language Models Use Long Contexts" (2023), [arXiv:2307.03172](https://arxiv.org/abs/2307.03172)
