# 埋め込みと位置符号化：正弦波と回転位置埋め込み（RoPE）

> トークン id をベクトルにする埋め込み行列と、位置をモデルに伝える正弦波位置符号化・回転位置埋め込み（RoPE）を定義し、位置のずれが回転で表せること、RoPE の内積が相対位置だけで決まることを 2 次の回転行列と加法定理から証明する。
> https://rikai.mugen-giken.com/computer-science/llm-architecture/embeddings-and-positional-encoding

## 0. この記事の要点

文章を機械に読ませるとき、単語に振った番号をそのまま計算に使うことはできません。番号の大小に意味が無いからです。さらに、「犬が猫を追う」と「猫が犬を追う」では、同じ単語が並んでいても意味が逆になります。この章では、番号を計算に使える数の組に置き換える方法と、語順を数の中に書き込む方法を説明します。読み終えると、位置を「足す」やり方と「回す」やり方で何が違うのかを、式で説明できるようになります。

- トークン id は名前にすぎないので、モデルに入れる前に $d$ 次元のベクトルに置き換えます。これは $|V| \times d$ の行列 $E$ の行を取り出す操作で、one-hot ベクトル（1 か所だけ 1 で残りが 0 のベクトル）を掛けることと同じです（<Ref to="prop-embedding-lookup" />）。
- 次章で示すとおり、自己注意（文中の各語が他の語をどれだけ見るかを決める仕組み）は入力の並べ替えを区別できません。語順を伝えるには、位置の情報を外から与える必要があります。この章ではその与え方を 2 通り用意します。
- 正弦波位置符号化 $\mathrm{PE}(p)$ は、位置を $k$ ずらすと、$p$ に依らない直交行列 $M_k$ を掛けたものになります（<Ref to="thm-sinusoidal-shift" />）。内積 $\langle \mathrm{PE}(p), \mathrm{PE}(q)\rangle$ は $p - q$ だけの関数です（<Ref to="prop-sinusoidal-inner-product" />）。
- ただし位置ベクトルを入力に**足す**方式では、内容と位置の交差項が残り、内積は相対位置だけの関数になりません（<Ref to="prop-absolute-additive-not-relative" />）。
- 回転位置埋め込み（RoPE）は、内積を取る直前にクエリとキーを位置に応じて**回します**。このとき内積は内容と相対位置 $n - m$ だけで決まり、ノルムは変わりません（<Ref to="thm-rope-relative" />）。
- 証明はすべて、2 次の回転行列の性質 $R(\alpha)R(\beta) = R(\alpha + \beta)$、つまり加法定理に帰着します。

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

- **内積とノルム**: 2 つのベクトルの対応する成分の積の和が内積で、自分自身との内積の平方根が長さ（ノルム）です。→ [内積空間](/mathematics/linear-algebra/inner-product-spaces)
- **直交行列**: かけてもベクトルの長さと内積が変わらない行列のこと。回転はその例です。→ [内積空間](/mathematics/linear-algebra/inner-product-spaces)
- **三角関数の加法定理**: $\sin(x+y)$ や $\cos(x+y)$ を、$x$ と $y$ それぞれの $\sin$、$\cos$ で表す公式です。→ [指数・対数・三角関数](/mathematics/hs-analysis/elementary-functions)
- **トークンと語彙**: 文字列を区切った単位がトークンで、その全体の集合が語彙です。→ [トークン化](/computer-science/llm-architecture/tokenization-bpe#def-alphabet-vocab)

</Aside>

## 1. 動機：id の列をベクトルの列にする

[前章](/computer-science/llm-architecture/tokenization-bpe)で、文字列はトークン id の列 $(t_1, \ldots, t_n)$、$t_i \in V$ になりました。id は整数ですが、その大小や差に意味はありません。id が 300 のトークンと 301 のトークンが似ているわけではないからです。ニューラルネットワークは実数のベクトルに対する関数なので、まず各 id を「学習で調整できるベクトル」に置き換えます。これが埋め込みです。

埋め込みだけでは足りないものがあります。同じトークンは列のどこにあっても同じベクトルになるので、ベクトルの列を見ても、もとの順番は「何番目の行か」という添字にしか残っていません。次章の <Ref to="computer-science/llm-architecture/self-attention#thm-attention-equivariance" /> は、自己注意がこの添字を使わない（行を並べ替えると出力も同じように並べ替わるだけである）ことを示します。そこで、位置の情報をベクトルの値そのものに書き込む必要があります。

書き込み方は大きく 2 つあります。

| 方式 | どこで位置を入れるか | この章での扱い |
|---|---|---|
| 絶対位置を足す | 入力のベクトルに、位置ごとのベクトルを足す（正弦波・学習する表） | 4 節・5 節 |
| 相対位置を内積に入れる | 注意の内積を取る直前に、クエリとキーを位置に応じて回す（RoPE） | 6 節 |

Vaswani らの Transformer は前者の正弦波を使い（[1]）、Su らは後者の RoPE を提案しました（[2]）。どちらも三角関数でできているので、同じ道具で性質を証明できます。

## 2. 埋め込み

この章では、ベクトルは列ベクトル、内積は $\langle \boldsymbol{x}, \boldsymbol{y} \rangle = \sum_j x_j y_j$、ノルムは $\|\boldsymbol{x}\| = \sqrt{\langle \boldsymbol{x}, \boldsymbol{x}\rangle}$ とします（<Ref to="mathematics/linear-algebra/inner-product-spaces#def-inner-product" />、<Ref to="mathematics/linear-algebra/inner-product-spaces#def-norm" />）。

<Definition id="def-embedding" title="one-hot ベクトル・埋め込み行列・重み共有">

語彙 $V$ の元に $1, \ldots, |V|$ の番号を付け、トークンをその番号と同一視する。トークン $v$ の **one-hot ベクトル** $\boldsymbol{e}_v \in \mathbb{R}^{|V|}$ とは、第 $v$ 成分が 1、ほかの成分が 0 のベクトルである。

行列 $E \in \mathbb{R}^{|V| \times d}$ を**埋め込み行列**、$d$ を**埋め込みの次元**という。$E$ の第 $v$ 行を列ベクトルとみなしたもの $E_v \in \mathbb{R}^{d}$ を、トークン $v$ の**埋め込み**という。トークン列 $(t_1, \ldots, t_n)$ に対し、第 $i$ 行が $E_{t_i}^{\mathsf{T}}$ である行列 $X \in \mathbb{R}^{n \times d}$ を、その列の埋め込みという。

モデルの最後で、ベクトル $\boldsymbol{h} \in \mathbb{R}^{d}$ から各トークン $v$ の点数（ロジット）を $z_v := \langle \boldsymbol{h}, U_v \rangle$（$U \in \mathbb{R}^{|V| \times d}$、$U_v$ はその第 $v$ 行）で作るとき、$U = E$ と取ること、すなわち入力側の埋め込み行列と出力側の行列に同じパラメータを使うことを**重み共有**という。

</Definition>

重み共有は Press と Wolf が言語モデルについて調べ（[5]）、Vaswani らも埋め込みと出力の線形変換で同じ行列を共有しています（[1] 3.4 節）。パラメータの数え方に効くので、第 4 章で改めて使います。

<Proposition id="prop-embedding-lookup" title="埋め込みは行の取り出しで、勾配は現れた行だけに入る">

$E \in \mathbb{R}^{|V| \times d}$ とする。

1. 任意のトークン $v$ について $\boldsymbol{e}_v^{\mathsf{T}} E$ は $E$ の第 $v$ 行である。
2. トークン列 $(t_1, \ldots, t_n)$ の埋め込みを $X \in \mathbb{R}^{n\times d}$ とし、損失が全微分可能な関数 $g : \mathbb{R}^{n \times d} \to \mathbb{R}$ によって $\mathcal{L} = g(X)$ と書けるとする（$E$ は $X$ を通してだけ $\mathcal{L}$ に入るとする）。このとき
$$
\frac{\partial \mathcal{L}}{\partial E_{vj}} = \sum_{i \,:\, t_i = v} \frac{\partial g}{\partial X_{ij}}(X) \qquad (1 \le v \le |V|,\ 1 \le j \le d)
$$
が成り立つ。とくに、列に現れないトークン $v$ の行については $\partial \mathcal{L} / \partial E_{vj} = 0$ である。

</Proposition>

<Proof of="prop-embedding-lookup">

1. 行列の積の定義より、$\boldsymbol{e}_v^{\mathsf{T}} E$ の第 $j$ 成分は $\sum_{u=1}^{|V|} (\boldsymbol{e}_v)_u E_{uj}$ です。$(\boldsymbol{e}_v)_u$ は $u = v$ のときだけ 1 で、ほかは 0 なので、和は $E_{vj}$ です。

2. $[t_i = v]$ を、$t_i = v$ のとき 1、そうでないとき 0 とします。1 より $X_{ij} = E_{t_i j} = \sum_{u} [t_i = u]\, E_{uj}$ で、これは $E$ の成分の 1 次式なので全微分可能で、$\partial X_{ij'} / \partial E_{vj} = [t_i = v]\,[j' = j]$ です。連鎖律（<Ref to="computer-science/math-for-ml/backpropagation#thm-chain-rule" />）を合成 $E \mapsto X \mapsto g(X)$ に使うと
$$
\frac{\partial \mathcal{L}}{\partial E_{vj}} = \sum_{i=1}^{n}\sum_{j'=1}^{d} \frac{\partial g}{\partial X_{ij'}}(X)\, \frac{\partial X_{ij'}}{\partial E_{vj}} = \sum_{i=1}^{n} \frac{\partial g}{\partial X_{ij}}(X)\,[t_i = v]
$$
で、これが主張の式です。$v$ が列に現れなければ、すべての $i$ で $[t_i = v] = 0$ なので和は 0 です。

</Proof>

1 は、実装で one-hot ベクトルとの積を実際に計算する必要がないことを言っています。$|V| \times d$ の積を計算する代わりに、表の 1 行を読むだけです。2 は、同じトークンが列に複数回現れると、その行の勾配は現れた位置の勾配の**和**になること、そして 1 回の更新で動くのは入力に現れた行だけであることを言っています。重み共有をしている場合は、$E$ が出力側でも使われるので仮定「$E$ は $X$ を通してだけ入る」が外れ、出力側からの勾配がすべての行に加わります。

<Example id="ex-tied-logits" title="重み共有のもとでのロジット">

$|V| = 3$、$d = 2$ とし、埋め込み行列を

$$
E = \begin{pmatrix} 1 & 0 \\ 0 & 1 \\ 1 & 1 \end{pmatrix}
$$

とします。トークン列 $(3, 1)$ の埋め込みは、$E$ の第 3 行と第 1 行を並べた $X = \begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}$ です。モデルの最後のベクトルが $\boldsymbol{h} = (2, 1)$ だったとすると、重み共有のもとでのロジットは $z_v = \langle \boldsymbol{h}, E_v\rangle$ なので

$$
\boldsymbol{z} = E\boldsymbol{h} = (2,\ 1,\ 3)
$$

で、いちばん大きいのはトークン 3 です。重み共有をすると、「入力でトークン $v$ を表すベクトル」と「出力でトークン $v$ らしさを測るベクトル」が同じ $E_v$ になります。最後のベクトル $\boldsymbol{h}$ がどのトークンの埋め込みと同じ向きを向いているかで、次のトークンの点数が決まります。パラメータは $E$ の $|V|d = 6$ 個だけで、共有しない場合の $2|V|d = 12$ 個の半分です。

</Example>

<Remark id="rem-embedding-scale" title="埋め込みと位置ベクトルの大きさ">

4 節で見るとおり、正弦波位置符号化のノルムは位置に依らず $\sqrt{d/2}$ です（<Ref to="prop-sinusoidal-inner-product" />）。一方、埋め込み $E_v$ のノルムは学習と初期化で決まります。位置ベクトルを足す方式では、この 2 つの大きさの比によって、足したあとのベクトルに占める内容と位置の割合が変わります。Vaswani らは、埋め込み層では重みに $\sqrt{d}$ を掛けると述べています（[1] 3.4 節）。大きさの比をどう取るのが良いかは設計と経験の問題で、この章の命題はどの比でも成り立ちます。

</Remark>

埋め込みの空間では、内積やコサイン類似度（<Ref to="computer-science/ai-era/relearning-mathematics#def-cosine" />）が「近さ」の尺度になります。次元 $d$ が大きいと、互いにほぼ直交する方向を非常にたくさん取れる（<Ref to="computer-science/ai-era/relearning-mathematics#cor-almost-orthogonal" />）ので、数万個のトークンに、互いに干渉しにくい方向を割り当てる余地があります。この章の残りでは、内容を表すこのベクトルに、位置をどう組み合わせるかを扱います。

## 3. 準備：回転行列とブロック対角の回転

<Definition id="def-rotation" title="2 次の回転行列とブロック対角の回転">

実数 $\alpha$ に対し

$$
R(\alpha) := \begin{pmatrix} \cos\alpha & -\sin\alpha \\ \sin\alpha & \cos\alpha \end{pmatrix}
$$

を角 $\alpha$ の**回転行列**という。$d$ を正の偶数とし、$\boldsymbol{\varphi} = (\varphi_0, \ldots, \varphi_{d/2 - 1}) \in \mathbb{R}^{d/2}$ に対して、$d$ 次の正方行列

$$
R[\boldsymbol{\varphi}] := \begin{pmatrix} R(\varphi_0) & & \\ & \ddots & \\ & & R(\varphi_{d/2-1}) \end{pmatrix}
$$

（対角に $2 \times 2$ のブロックが並び、ほかは 0）を**ブロック対角の回転**という。

</Definition>

この章では、$d$ 次元のベクトルの成分を $x_0, x_1, \ldots, x_{d-1}$ と 0 から数え、$(x_{2i}, x_{2i+1})$ を第 $i$ の**対**と呼びます（$i = 0, \ldots, d/2 - 1$）。$R[\boldsymbol{\varphi}]\boldsymbol{x}$ は、第 $i$ の対を平面のベクトルとみなして角 $\varphi_i$ だけ回したものです。

<Lemma id="lem-rotation" title="回転行列の性質">

$\alpha, \beta \in \mathbb{R}$、$\boldsymbol{\varphi}, \boldsymbol{\psi} \in \mathbb{R}^{d/2}$、$\boldsymbol{x}, \boldsymbol{y} \in \mathbb{R}^{d}$ とする。

1. $R(\alpha) R(\beta) = R(\alpha + \beta)$、$R(0) = I$、$R(\alpha)^{\mathsf{T}} = R(-\alpha)$。
2. $R[\boldsymbol{\varphi}]\, R[\boldsymbol{\psi}] = R[\boldsymbol{\varphi} + \boldsymbol{\psi}]$、$R[\boldsymbol{0}] = I$、$R[\boldsymbol{\varphi}]^{\mathsf{T}} = R[-\boldsymbol{\varphi}]$。
3. $R[\boldsymbol{\varphi}]^{\mathsf{T}} R[\boldsymbol{\varphi}] = I$（直交行列）。
4. $\langle R[\boldsymbol{\varphi}]\boldsymbol{x}, \boldsymbol{y} \rangle = \langle \boldsymbol{x}, R[-\boldsymbol{\varphi}]\boldsymbol{y} \rangle$、$\langle R[\boldsymbol{\varphi}]\boldsymbol{x}, R[\boldsymbol{\varphi}]\boldsymbol{y} \rangle = \langle \boldsymbol{x}, \boldsymbol{y} \rangle$、$\|R[\boldsymbol{\varphi}]\boldsymbol{x}\| = \|\boldsymbol{x}\|$。

</Lemma>

<Proof of="lem-rotation">

1. 積を計算します。
$$
R(\alpha)R(\beta) = \begin{pmatrix} \cos\alpha\cos\beta - \sin\alpha\sin\beta & -(\cos\alpha\sin\beta + \sin\alpha\cos\beta) \\ \sin\alpha\cos\beta + \cos\alpha\sin\beta & \cos\alpha\cos\beta - \sin\alpha\sin\beta \end{pmatrix}
$$
加法定理（<Ref to="mathematics/hs-analysis/elementary-functions#thm-addition-formulas" />）より、対角の成分は $\cos(\alpha+\beta)$、左下は $\sin(\alpha + \beta)$、右上は $-\sin(\alpha+\beta)$ なので、$R(\alpha+\beta)$ に等しくなります。$\cos 0 = 1$、$\sin 0 = 0$ より $R(0) = I$。$\cos(-\alpha) = \cos\alpha$、$\sin(-\alpha) = -\sin\alpha$（<Ref to="mathematics/hs-analysis/elementary-functions#thm-sin-cos-derivatives" /> の 2）より、$R(-\alpha)$ は $R(\alpha)$ の非対角成分の符号を入れ替えたもの、すなわち $R(\alpha)^{\mathsf{T}}$ です。

2. ブロック対角行列どうしの積は、対応するブロックの積を対角に並べたものです。実際、$A, B$ がブロック対角のとき、$(AB)_{jl} = \sum_{k} A_{jk}B_{kl}$ で $A_{jk} \ne 0$ となりうるのは $k$ が $j$ と同じ対にあるときだけ、$B_{kl} \ne 0$ となりうるのは $l$ が $k$ と同じ対にあるときだけなので、$j, l$ が違う対にあれば 0、同じ対にあればその対のブロックの積の成分です。転置も対ごとに取れます。よって 1 を各ブロックに使えば 2 が出ます。

3. 2 より $R[\boldsymbol{\varphi}]^{\mathsf{T}} R[\boldsymbol{\varphi}] = R[-\boldsymbol{\varphi}]R[\boldsymbol{\varphi}] = R[\boldsymbol{0}] = I$。

4. 任意の正方行列 $A$ について $\langle A\boldsymbol{x}, \boldsymbol{y}\rangle = \sum_{j}\sum_{k} A_{jk}x_k y_j = \sum_k x_k \sum_j (A^{\mathsf{T}})_{kj} y_j = \langle \boldsymbol{x}, A^{\mathsf{T}}\boldsymbol{y}\rangle$ です。$A = R[\boldsymbol{\varphi}]$ とし 2 を使うと 1 つ目の式が出ます。2 つ目は、1 つ目で $\boldsymbol{y}$ を $R[\boldsymbol{\varphi}]\boldsymbol{y}$ に置き換えて $\langle R[\boldsymbol{\varphi}]\boldsymbol{x}, R[\boldsymbol{\varphi}]\boldsymbol{y}\rangle = \langle \boldsymbol{x}, R[-\boldsymbol{\varphi}]R[\boldsymbol{\varphi}]\boldsymbol{y}\rangle = \langle \boldsymbol{x}, \boldsymbol{y}\rangle$。3 つ目は 2 つ目で $\boldsymbol{y} = \boldsymbol{x}$ として平方根を取ります。

</Proof>

4 の「内積とノルムを保つ」は、直交行列（実のユニタリ行列）の一般的な性質です（<Ref to="mathematics/linear-algebra/spectral-theorem#prop-unitary" /> の条件 1 から 2・3）。2 次の直交行列で行列式が 1 のものは回転行列に限ること（<Ref to="mathematics/hs-geometry/congruence-and-similarity#lem-orthogonal-2x2" />）も知られていますが、以下で使うのは上の補題だけです。

## 4. 位置を足す方式：正弦波と学習する表

<Definition id="def-position" title="絶対位置・相対位置・位置符号化">

列の中でのトークンの番号 $p$ を**絶対位置**、2 つのトークンの絶対位置 $m, n$ の差 $n - m$ を**相対位置**という。$d$ を正の偶数とし、$i = 0, \ldots, d/2 - 1$ について**角周波数**を

$$
\omega_i := 10000^{-2i/d}
$$

と置く。実数 $p$ に対し、成分が

$$
\mathrm{PE}(p)_{2i} := \sin(p\,\omega_i), \qquad \mathrm{PE}(p)_{2i+1} := \cos(p\,\omega_i) \qquad (i = 0, \ldots, d/2-1)
$$

であるベクトル $\mathrm{PE}(p) \in \mathbb{R}^{d}$ を**正弦波位置符号化**という。位置 $p$ のトークンの埋め込み $\boldsymbol{x}$ を $\boldsymbol{x} + \mathrm{PE}(p)$ に置き換えてモデルに入れる。

これに対し、行列 $P \in \mathbb{R}^{L_{\mathrm{ctx}} \times d}$ をパラメータとして持ち、位置 $p \in \{1, \ldots, L_{\mathrm{ctx}}\}$ のトークンの埋め込み $\boldsymbol{x}$ を $\boldsymbol{x} + P_p$（$P_p$ は $P$ の第 $p$ 行）に置き換える方式を、**学習する位置埋め込み**という。

</Definition>

$\omega_0 = 1$ が最大で、$\omega_{d/2-1} = 10000^{-(d-2)/d}$ が最小です。つまり $\omega_i$ は 1 から $1/10000$ に近い値まで、桁を揃えて並んだ値で、1 周する速さの違う時計の針を $d/2$ 本用意することに当たります（10000 という値そのものは設計上の選択です）。第 $i$ の対 $(\sin p\omega_i, \cos p\omega_i)$ は、$p$ が進むにつれて単位円の上を角速度 $\omega_i$ で回ります。速く回る対は近くの位置の違いを、ゆっくり回る対は遠くの位置の違いを表します。時計の秒針・分針・時針に似た仕組みです。

<Theorem id="thm-sinusoidal-shift" title="位置のずれは直交行列で表せる">

任意の実数 $k$ に対し、$d$ 次の直交行列

$$
M_k := R[(-k\omega_0, \ldots, -k\omega_{d/2-1})]
$$

は $p$ に依らず、すべての実数 $p$ について

$$
\mathrm{PE}(p + k) = M_k\, \mathrm{PE}(p)
$$

を満たす。

</Theorem>

<Proof of="thm-sinusoidal-shift">

$M_k$ の定義に $p$ は現れません。直交行列であることは <Ref to="lem-rotation" /> の 3 です。

等式を対ごとに確かめます。$M_k$ の第 $i$ のブロックは

$$
R(-k\omega_i) = \begin{pmatrix} \cos k\omega_i & \sin k\omega_i \\ -\sin k\omega_i & \cos k\omega_i \end{pmatrix}
$$

です（$\cos(-t) = \cos t$、$\sin(-t) = -\sin t$ を使いました）。これを $\mathrm{PE}(p)$ の第 $i$ の対 $(\sin p\omega_i, \cos p\omega_i)^{\mathsf{T}}$ に掛けると

$$
\begin{pmatrix} \cos k\omega_i \sin p\omega_i + \sin k\omega_i \cos p\omega_i \\ -\sin k\omega_i \sin p\omega_i + \cos k\omega_i \cos p\omega_i \end{pmatrix}
= \begin{pmatrix} \sin\big((p+k)\omega_i\big) \\ \cos\big((p+k)\omega_i\big) \end{pmatrix}
$$

となります。等号は加法定理（<Ref to="mathematics/hs-analysis/elementary-functions#thm-addition-formulas" />）を $x = p\omega_i$、$y = k\omega_i$ に使ったものです。右辺は $\mathrm{PE}(p+k)$ の第 $i$ の対です。$M_k$ はブロック対角なので、対ごとの等式から全体の等式が従います。

</Proof>

Vaswani らは正弦波を選んだ理由として、固定したずれ $k$ について $\mathrm{PE}(p+k)$ が $\mathrm{PE}(p)$ の線形な関数で表せることを挙げています（[1] 3.5 節）。上の定理はその線形写像を具体的に書き、それが回転（直交行列）であることまで示したものです。

<Proposition id="prop-sinusoidal-inner-product" title="正弦波位置符号化の内積とノルム">

任意の実数 $p, q$ について

$$
\langle \mathrm{PE}(p), \mathrm{PE}(q) \rangle = \sum_{i=0}^{d/2-1} \cos\big(\omega_i (p - q)\big), \qquad \|\mathrm{PE}(p)\|^2 = \frac{d}{2}
$$

が成り立つ。とくに内積は相対位置 $p - q$ だけの関数である。

</Proposition>

<Proof of="prop-sinusoidal-inner-product">

内積を対ごとに計算します。

$$
\langle \mathrm{PE}(p), \mathrm{PE}(q) \rangle = \sum_{i=0}^{d/2-1} \big( \sin p\omega_i \sin q\omega_i + \cos p\omega_i \cos q\omega_i \big)
$$

加法定理（<Ref to="mathematics/hs-analysis/elementary-functions#thm-addition-formulas" />）で $x = p\omega_i$、$y = -q\omega_i$ と置き、$\cos(-y) = \cos y$、$\sin(-y) = -\sin y$ を使うと $\cos(p\omega_i - q\omega_i) = \cos p\omega_i \cos q\omega_i + \sin p\omega_i \sin q\omega_i$ です。よって各項は $\cos(\omega_i(p - q))$ です。$q = p$ とすると各項は $\cos 0 = 1$ で、$d/2$ 項あるので $\|\mathrm{PE}(p)\|^2 = d/2$ です。

</Proof>

<Proposition id="prop-sinusoidal-injective" title="範囲つきの単射性">

$\omega_{\min} := \omega_{d/2-1} = 10000^{-(d-2)/d}$ とする。区間 $0 \le p < 2\pi/\omega_{\min}$ の上で、写像 $p \mapsto \mathrm{PE}(p)$ は単射である。

</Proposition>

<Proof of="prop-sinusoidal-injective">

$0 \le p, q < 2\pi/\omega_{\min}$ で $\mathrm{PE}(p) = \mathrm{PE}(q)$ とします。最後の対を比べると $(\cos p\omega_{\min}, \sin p\omega_{\min}) = (\cos q\omega_{\min}, \sin q\omega_{\min})$ です。$p\omega_{\min}$ と $q\omega_{\min}$ はどちらも $[0, 2\pi)$ にあり、$\theta \mapsto (\cos\theta, \sin\theta)$ は $[0, 2\pi)$ の上で単射（<Ref to="mathematics/hs-analysis/elementary-functions#thm-unit-circle-param" />）なので、$p\omega_{\min} = q\omega_{\min}$、$\omega_{\min} > 0$ より $p = q$ です。

</Proof>

区間の長さは $2\pi \cdot 10000^{(d-2)/d}$ です。$d = 4$ なら $2\pi \cdot 100 \approx 628$、Vaswani らの基本の構成 $d = 512$（[1]）なら約 $6.06 \times 10^{4}$ で、整数の位置がこの個数だけ区別できます。証明に使ったのはいちばん遅い対だけです。この範囲を超えると最後の対は 1 周して戻りますが、ほかの対も合わせて見れば区別できる位置はもっと多くなります。ただし「すべての整数の位置で単射である」という主張には $\pi$ が無理数であることが要るので、ここでは範囲つきの形だけを述べました。

<Example id="ex-sinusoidal-d4" title="d = 4 の数値例">

$d = 4$ のとき $\omega_0 = 1$、$\omega_1 = 10000^{-1/2} = 0.01$ です。

$$
\mathrm{PE}(0) = (0,\ 1,\ 0,\ 1), \quad
\mathrm{PE}(1) = (0.8415,\ 0.5403,\ 0.0100,\ 1.0000), \quad
\mathrm{PE}(2) = (0.9093,\ -0.4161,\ 0.0200,\ 0.9998)
$$

（$\sin 1 = 0.8415$、$\cos 1 = 0.5403$、$\sin 0.01 = 0.0100$、$\cos 0.01 = 0.99995$）。ずらす行列は

$$
M_1 = \begin{pmatrix} 0.5403 & 0.8415 & & \\ -0.8415 & 0.5403 & & \\ & & 0.99995 & 0.0100 \\ & & -0.0100 & 0.99995 \end{pmatrix}
$$

で、$M_1 \mathrm{PE}(1)$ の最初の 2 成分は $0.5403 \times 0.8415 + 0.8415 \times 0.5403 = 0.9093$、$-0.8415 \times 0.8415 + 0.5403 \times 0.5403 = -0.4161$ となり、$\mathrm{PE}(2)$ に一致します。内積は <Ref to="prop-sinusoidal-inner-product" /> より $\langle \mathrm{PE}(p), \mathrm{PE}(p+1)\rangle = \cos 1 + \cos 0.01 = 1.5403$、$\langle \mathrm{PE}(p), \mathrm{PE}(p+2)\rangle = \cos 2 + \cos 0.02 = 0.5837$ で、$p$ に依りません。ノルムの 2 乗は常に $d/2 = 2$ です。

</Example>

<Proposition id="prop-learned-position-table" title="学習する位置埋め込みのパラメータ数と定義域">

長さ $L_{\mathrm{ctx}}$ の学習する位置埋め込みは $L_{\mathrm{ctx}}\, d$ 個のパラメータを持ち、位置 $p > L_{\mathrm{ctx}}$ に対しては位置ベクトルが定義されない。したがってこの方式のモデルは、長さが $L_{\mathrm{ctx}}$ を超える列を入力に取れない。一方、正弦波位置符号化 $\mathrm{PE}(p)$ と、6 節の回転 $R_m$ は、パラメータを持たず、すべての実数（とくにすべての整数の位置）に対して定義される。

</Proposition>

<Proof of="prop-learned-position-table">

<Ref to="def-position" /> より、学習する位置埋め込みのパラメータは行列 $P \in \mathbb{R}^{L_{\mathrm{ctx}} \times d}$ の成分で、その個数は $L_{\mathrm{ctx}}\,d$ です。位置 $p$ のベクトルは $P$ の第 $p$ 行で、$P$ には第 $L_{\mathrm{ctx}}$ 行までしか無いので、$p > L_{\mathrm{ctx}}$ では定義されません。入力の第 $p$ トークンに足すベクトルが無ければ、モデルへの入力が定まりません。$\mathrm{PE}(p)$ は $\sin$ と $\cos$ の値で、6 節の $R_m$ も $\cos$ と $\sin$ の値を成分とする行列で、どちらも任意の実数に対して定義されており、学習するパラメータを含みません。

</Proof>

<Remark id="rem-extrapolation" title="定義できることと、うまく働くことは別">

<Ref to="prop-learned-position-table" /> が言っているのは「定義できるかどうか」だけです。学習時より長い列でモデルがうまく働くかどうかは、定義からは分かりません。Vaswani らは、正弦波と学習する位置埋め込みでほぼ同じ結果が得られたと報告したうえで、正弦波を選んだ理由を「学習時より長い列へ外挿できるかもしれないから」と述べています（[1] 3.5 節）。これは著者らの見込みであって、証明された性質ではありません。位置符号化の外挿の良し悪しは、モデルとデータに依る経験的な問題として扱ってください。

</Remark>

## 5. 足す方式では相対位置だけの関数にならない

次章の注意は、2 つの位置のベクトルの内積（に線形変換を挟んだもの）で「どの位置をどれだけ見るか」を決めます。言語では「3 つ前の語」のような相対位置が意味を持つことが多いので、この内積が相対位置で決まると都合がよいのですが、位置ベクトルを足す方式ではそうなりません。

<Proposition id="prop-absolute-additive-not-relative" title="足す方式の内積の 4 項分解">

位置 $m, n$ のトークンの埋め込みを $\boldsymbol{x}_m, \boldsymbol{x}_n \in \mathbb{R}^{d}$、位置ベクトルを $\boldsymbol{p}_m, \boldsymbol{p}_n \in \mathbb{R}^{d}$ とする。

1. $\langle \boldsymbol{x}_m + \boldsymbol{p}_m,\ \boldsymbol{x}_n + \boldsymbol{p}_n \rangle = \langle \boldsymbol{x}_m, \boldsymbol{x}_n \rangle + \langle \boldsymbol{x}_m, \boldsymbol{p}_n \rangle + \langle \boldsymbol{p}_m, \boldsymbol{x}_n \rangle + \langle \boldsymbol{p}_m, \boldsymbol{p}_n \rangle$。
2. $\boldsymbol{p}_m = \mathrm{PE}(m)$ のとき、第 4 項は $n - m$ だけの関数だが、全体はそうではない。すなわち、内容 $\boldsymbol{x}_m = \boldsymbol{x}_n = \boldsymbol{x}$ を固定しても、相対位置が同じ 2 組 $(m, n)$、$(m', n')$ で値が異なる例がある。

</Proposition>

<Proof of="prop-absolute-additive-not-relative">

1 は内積の双線形性（<Ref to="mathematics/linear-algebra/inner-product-spaces#def-inner-product" />）による展開です。

2 の前半は <Ref to="prop-sinusoidal-inner-product" /> です。後半の例を作ります。$d = 2$ とすると $\omega_0 = 1$ で $\mathrm{PE}(p) = (\sin p, \cos p)$ です。$\boldsymbol{x} = (1, 0)$ と置くと、$\langle \boldsymbol{x}, \boldsymbol{x}\rangle = 1$、$\langle \boldsymbol{x}, \mathrm{PE}(p) \rangle = \sin p$、$\langle \mathrm{PE}(m), \mathrm{PE}(n)\rangle = \cos(m - n)$ なので、1 より

$$
\langle \boldsymbol{x} + \mathrm{PE}(m),\ \boldsymbol{x} + \mathrm{PE}(n) \rangle = 1 + \sin n + \sin m + \cos(m - n)
$$

です。$(m, n) = (0, 1)$ では $1 + \sin 1 + 0 + \cos 1$、$(m, n) = (1, 2)$ では $1 + \sin 2 + \sin 1 + \cos 1$ で、どちらも相対位置は 1 ですが、差は $\sin 2$ です。

$\sin 2 \ne 0$ を確かめます。$3.14 < \pi < 3.15$（<Ref to="mathematics/hs-analysis/elementary-functions#thm-pi-bounds" />）より $\pi/2 < 2 < \pi$ です。$[\pi/2, \pi]$ では $\sin x = \cos(x - \pi/2)$ で、$x = 2$ のとき $x - \pi/2 \in [0, \pi/2)$、そこでは $\cos > 0$ です（<Ref to="mathematics/hs-analysis/elementary-functions#thm-periodicity" /> の 3）。よって $\sin 2 > 0$ で、2 組の値は異なります。数値では $2.3818$ と $3.2911$ です。

</Proof>

交差項 $\langle \boldsymbol{x}_m, \boldsymbol{p}_n\rangle$ は「内容と絶対位置の相性」を表す項で、これが残るかぎり、同じ 2 語が同じ間隔で並んでいても、列のどこにあるかで点数が変わります。実際の注意では内積の間に学習する行列が挟まりますが（次章）、双線形な式を 4 項に展開できることは同じです。Shaw らは、絶対位置を足す代わりに、相対位置ごとの表現を注意の計算の中に入れる方法を提案しました（[4]）。次節の RoPE は、同じ狙いを回転だけで実現します。

## 6. 回転位置埋め込み（RoPE）

<Definition id="def-rope" title="回転位置埋め込み">

$d$ を正の偶数とし、$\theta_i := 10000^{-2i/d}$（$i = 0, \ldots, d/2-1$）、$\boldsymbol{\theta} := (\theta_0, \ldots, \theta_{d/2-1})$ と置く。実数 $m$ に対し

$$
R_m := R[m\boldsymbol{\theta}] = R[(m\theta_0, \ldots, m\theta_{d/2-1})]
$$

と定める。位置 $m$ のクエリ $\boldsymbol{q} \in \mathbb{R}^{d}$ と位置 $n$ のキー $\boldsymbol{k} \in \mathbb{R}^{d}$ の内積 $\langle \boldsymbol{q}, \boldsymbol{k}\rangle$ の代わりに

$$
\langle R_m \boldsymbol{q},\ R_n \boldsymbol{k} \rangle
$$

を使う方式を**回転位置埋め込み**（RoPE）という。

</Definition>

クエリとキーは次章で定義します（直感的には、クエリは「いま注目している語が探しているもの」、キーは「各語が持っている目印」で、2 つの内積が大きいほど強く結びつくと考えます）。ここでは「位置 $m$ にあるベクトル $\boldsymbol{q}$ と位置 $n$ にあるベクトル $\boldsymbol{k}$ の相性を内積で測る」とだけ理解しておけば十分です。足す方式との違いは、位置の情報を入力に 1 回足すのではなく、内積を取るたびにその直前で掛けることです。

<Proposition id="prop-rotation-group" title="位置の回転の合成">

任意の実数 $m, n$ について、$R_m$ は直交行列で、

$$
R_m R_n = R_{m+n}, \qquad R_0 = I, \qquad R_m^{\mathsf{T}} = R_{-m} = R_m^{-1}
$$

が成り立つ。

</Proposition>

<Proof of="prop-rotation-group">

<Ref to="lem-rotation" /> の 2 と 3 を $\boldsymbol{\varphi} = m\boldsymbol{\theta}$、$\boldsymbol{\psi} = n\boldsymbol{\theta}$ に使います。$R_m R_n = R[m\boldsymbol{\theta}]R[n\boldsymbol{\theta}] = R[(m+n)\boldsymbol{\theta}] = R_{m+n}$、$R_0 = R[\boldsymbol{0}] = I$、$R_m^{\mathsf{T}} = R[-m\boldsymbol{\theta}] = R_{-m}$。直交性 $R_m^{\mathsf{T}}R_m = I$ は 3 で、これと $R_{-m}R_m = R_0 = I$、$R_m R_{-m} = I$ より $R_{-m}$ は $R_m$ の逆行列です。

</Proof>

<Theorem id="thm-rope-relative" title="RoPE の内積は相対位置だけで決まる">

$\boldsymbol{q}, \boldsymbol{k} \in \mathbb{R}^{d}$、$m, n \in \mathbb{R}$ とする。

1. $\langle R_m \boldsymbol{q}, R_n \boldsymbol{k} \rangle = \langle \boldsymbol{q}, R_{n-m} \boldsymbol{k} \rangle$。したがってこの値は $\boldsymbol{q}$、$\boldsymbol{k}$ と相対位置 $n - m$ だけで決まり、任意の実数 $s$ について $\langle R_{m+s} \boldsymbol{q}, R_{n+s} \boldsymbol{k} \rangle = \langle R_m \boldsymbol{q}, R_n \boldsymbol{k} \rangle$。
2. $\|R_m \boldsymbol{q}\| = \|\boldsymbol{q}\|$。
3. 第 $i$ の対を複素数 $\hat q_i := q_{2i} + \mathrm{i}\, q_{2i+1}$、$\hat k_i := k_{2i} + \mathrm{i}\, k_{2i+1}$ と書くと（$\mathrm{i}$ は虚数単位）
$$
\langle R_m \boldsymbol{q}, R_n \boldsymbol{k} \rangle = \mathrm{Re} \sum_{i=0}^{d/2-1} \hat q_i\, \overline{\hat k_i}\; e^{\mathrm{i}(m-n)\theta_i} .
$$

</Theorem>

<Proof of="thm-rope-relative">

1. <Ref to="lem-rotation" /> の 4（1 つ目の式）と <Ref to="prop-rotation-group" /> より
$$
\langle R_m \boldsymbol{q}, R_n \boldsymbol{k} \rangle = \langle \boldsymbol{q}, R_{-m} R_n \boldsymbol{k} \rangle = \langle \boldsymbol{q}, R_{n-m}\boldsymbol{k}\rangle
$$
です。右辺に現れるのは $\boldsymbol{q}$、$\boldsymbol{k}$、$n - m$ だけです。$(m, n)$ を $(m+s, n+s)$ に替えても $(n+s) - (m+s) = n - m$ なので値は変わりません。

2. <Ref to="lem-rotation" /> の 4（3 つ目の式）です。

3. まず 1 つの対について示します。$\boldsymbol{u} = (u_0, u_1)$、$\boldsymbol{w} = (w_0, w_1) \in \mathbb{R}^2$ に対し $\hat u = u_0 + \mathrm{i}u_1$、$\hat w = w_0 + \mathrm{i}w_1$ と置くと
$$
\hat u\, \overline{\hat w} = (u_0 + \mathrm{i}u_1)(w_0 - \mathrm{i}w_1) = (u_0 w_0 + u_1 w_1) + \mathrm{i}(u_1 w_0 - u_0 w_1)
$$
なので $\mathrm{Re}(\hat u\, \overline{\hat w}) = \langle \boldsymbol{u}, \boldsymbol{w}\rangle$ です。次に、オイラーの公式 $e^{\mathrm{i}\alpha} = \cos\alpha + \mathrm{i}\sin\alpha$（<Ref to="mathematics/complex-analysis/complex-numbers#thm-euler" />）より
$$
e^{\mathrm{i}\alpha}\, \hat u = (\cos\alpha + \mathrm{i}\sin\alpha)(u_0 + \mathrm{i}u_1) = (u_0\cos\alpha - u_1\sin\alpha) + \mathrm{i}(u_0 \sin\alpha + u_1\cos\alpha)
$$
で、実部と虚部は $R(\alpha)\boldsymbol{u}$ の 2 成分です。つまり $R(\alpha)\boldsymbol{u}$ に対応する複素数は $e^{\mathrm{i}\alpha}\hat u$ です。

したがって第 $i$ の対の内積への寄与は
$$
\mathrm{Re}\Big( e^{\mathrm{i}m\theta_i}\hat q_i\; \overline{e^{\mathrm{i}n\theta_i}\hat k_i} \Big)
= \mathrm{Re}\Big( \hat q_i\, \overline{\hat k_i}\; e^{\mathrm{i}m\theta_i}\, \overline{e^{\mathrm{i}n\theta_i}} \Big)
$$
です。$\overline{e^{\mathrm{i}\beta}} = \cos\beta - \mathrm{i}\sin\beta = \cos(-\beta) + \mathrm{i}\sin(-\beta) = e^{-\mathrm{i}\beta}$ で、$e^{\mathrm{i}\alpha}e^{-\mathrm{i}\beta}$ は「$R(\alpha)R(-\beta) = R(\alpha - \beta)$ に対応する複素数」なので $e^{\mathrm{i}(\alpha - \beta)}$ です（<Ref to="lem-rotation" /> の 1。直接には、積を展開して加法定理を使っても同じです）。$\alpha = m\theta_i$、$\beta = n\theta_i$ として $e^{\mathrm{i}m\theta_i}\,\overline{e^{\mathrm{i}n\theta_i}} = e^{\mathrm{i}(m-n)\theta_i}$。内積は対ごとの内積の和なので、$i$ について足し、実部を取る操作と和を入れ替えて主張の式を得ます。

</Proof>

なお、証明の 3 は 1 と 2 の言い換えで、各対を複素数とみなして書き直したものです。本筋は 1 と 2 だけで追えるので、複素数に馴染みが無ければ飛ばしても構いません。

1 と <Ref to="prop-absolute-additive-not-relative" /> を比べてください。足す方式では内容と絶対位置の交差項が残りましたが、RoPE では $m$ と $n$ が $n - m$ の形でしか現れません。2 は、回してもベクトルの長さが変わらないので、位置の情報を入れることで内容の大きさが乱されないことを言っています。3 は Su らが RoPE を導いた形で（[2]）、各対を複素数とみなすと「位置 $m$ では $e^{\mathrm{i}m\theta_i}$ を掛ける」という 1 行の規則になります。

<Example id="ex-rope-d2" title="d = 2 の数値例">

$d = 2$ で、説明のために角度を $\theta_0 = \pi/6$ と取ります（<Ref to="def-rope" /> の値 $\theta_0 = 1$ の代わりです。<Ref to="thm-rope-relative" /> の証明は $\boldsymbol{\theta}$ の値に依りません）。$\boldsymbol{q} = (1, 2)$、$\boldsymbol{k} = (3, 1)$ とします。

$(m, n) = (1, 3)$ のとき、$R_1\boldsymbol{q} = R(\pi/6)\boldsymbol{q} = (-0.1340,\ 2.2321)$、$R_3\boldsymbol{k} = R(\pi/2)\boldsymbol{k} = (-1,\ 3)$ で、内積は $(-0.1340)\times(-1) + 2.2321 \times 3 \approx 6.8301$ です。

$(m, n) = (5, 7)$ のとき、$R_5\boldsymbol{q} = (-1.8660,\ -1.2321)$、$R_7\boldsymbol{k} = (-2.0981,\ -2.3660)$ で、内積はやはり $6.8301$ です（丸める前の値で計算）。ベクトルはどちらも大きく回っていますが、相対位置がともに 2 なので内積は一致します。

<Ref to="thm-rope-relative" /> の 3 で確かめます。$\hat q\,\overline{\hat k} = (1 + 2\mathrm{i})(3 - \mathrm{i}) = 5 + 5\mathrm{i}$、$e^{\mathrm{i}(m-n)\theta_0} = e^{-\mathrm{i}\pi/3} = \tfrac12 - \tfrac{\sqrt3}{2}\mathrm{i}$ なので、実部は $\tfrac52 + \tfrac{5\sqrt3}{2} = 6.8301$ です。

相対位置を 3 に変えた $(m, n) = (1, 4)$ では $e^{-\mathrm{i}\pi/2} = -\mathrm{i}$ で、$\mathrm{Re}\big((5 + 5\mathrm{i})(-\mathrm{i})\big) = 5$ となり、値が変わります。

</Example>

<Figure caption="d = 2、θ₀ = π/6 の RoPE。左は (m, n) = (1, 3)、右は (5, 7)。実線が回したクエリ、破線が回したキー。2 本のなす角は相対位置 n − m = 2 だけで決まるので、左右で同じになる。">
<svg viewBox="0 0 600 300" width="100%" role="img" aria-label="位置を変えても、回したクエリとキーのなす角が変わらないことを示す図">
  <g stroke="currentColor" stroke-width="1" opacity="0.4" fill="none">
    <line x1="40" y1="150" x2="260" y2="150" />
    <line x1="150" y1="40" x2="150" y2="260" />
    <line x1="340" y1="150" x2="560" y2="150" />
    <line x1="450" y1="40" x2="450" y2="260" />
    <circle cx="150" cy="150" r="62.6" />
    <circle cx="150" cy="150" r="88.5" />
    <circle cx="450" cy="150" r="62.6" />
    <circle cx="450" cy="150" r="88.5" />
  </g>
  <g stroke="var(--sl-color-accent)" stroke-width="2.2" fill="var(--sl-color-accent)">
    <line x1="150" y1="150" x2="146.2" y2="87.5" />
    <circle cx="146.2" cy="87.5" r="4" />
    <line x1="450" y1="150" x2="397.8" y2="184.5" />
    <circle cx="397.8" cy="184.5" r="4" />
  </g>
  <g stroke="currentColor" stroke-width="2" stroke-dasharray="6 4" fill="currentColor">
    <line x1="150" y1="150" x2="122" y2="66" />
    <line x1="450" y1="150" x2="391.3" y2="216.2" />
  </g>
  <g fill="currentColor">
    <circle cx="122" cy="66" r="4" />
    <circle cx="391.3" cy="216.2" r="4" />
  </g>
  <g fill="currentColor" font-size="14">
    <text x="160" y="84">R₁q</text>
    <text x="82" y="58">R₃k</text>
    <text x="352" y="178">R₅q</text>
    <text x="350" y="238">R₇k</text>
    <text x="150" y="286" text-anchor="middle">(m, n) = (1, 3)　内積 6.8301</text>
    <text x="450" y="286" text-anchor="middle">(m, n) = (5, 7)　内積 6.8301</text>
  </g>
</svg>
</Figure>

## 7. 数値実験

正弦波位置符号化、$M_k$、RoPE を NumPy で実装し、この章の命題を数値で確かめます。乱数種は 0 に固定しています。

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

def omegas(d):
    return 10000.0 ** (-2.0 * np.arange(d // 2) / d)

def pe(pos, d):
    """正弦波位置符号化。偶数番目が sin、奇数番目が cos。"""
    out = np.empty(d)
    out[0::2] = np.sin(pos * omegas(d))
    out[1::2] = np.cos(pos * omegas(d))
    return out

def shift_matrix(k, d):
    """PE(pos + k) = M_k PE(pos) となるブロック対角行列。"""
    M = np.zeros((d, d))
    for i, w in enumerate(omegas(d)):
        c, s = np.cos(k * w), np.sin(k * w)
        M[2 * i:2 * i + 2, 2 * i:2 * i + 2] = [[c, s], [-s, c]]
    return M

def rope(x, m, thetas):
    """ベクトル x の第 (2i, 2i+1) 成分を角度 m * thetas[i] だけ回す。"""
    out = np.empty_like(x)
    c, s = np.cos(m * thetas), np.sin(m * thetas)
    out[0::2] = c * x[0::2] - s * x[1::2]
    out[1::2] = s * x[0::2] + c * x[1::2]
    return out

if __name__ == "__main__":
    np.set_printoptions(precision=4, suppress=True)
    for pos in range(3):
        print("PE(%d) =" % pos, pe(pos, 4))
    print("M_1 PE(1) =", shift_matrix(1, 4) @ pe(1, 4))

    d = 64
    err_shift = max(np.abs(shift_matrix(k, d) @ pe(p, d) - pe(p + k, d)).max()
                    for p in range(200) for k in (1, 7, 100))
    M = shift_matrix(7, d)
    err_orth = np.abs(M.T @ M - np.eye(d)).max()
    err_norm = max(abs(pe(p, d) @ pe(p, d) - d / 2) for p in range(200))
    err_inner = max(abs(pe(p, d) @ pe(q, d) - np.cos(omegas(d) * (p - q)).sum())
                    for p in range(0, 200, 7) for q in range(0, 200, 11))
    print("shift %.1e  orth %.1e  norm %.1e  inner %.1e" % (err_shift, err_orth, err_norm, err_inner))

    rng = np.random.default_rng(0)
    thetas = omegas(d)
    q, k = rng.standard_normal(d), rng.standard_normal(d)
    err_rel, err_len = 0.0, 0.0
    for m in range(0, 60, 3):
        for n in range(0, 60, 4):
            lhs = rope(q, m, thetas) @ rope(k, n, thetas)
            err_rel = max(err_rel, abs(lhs - q @ rope(k, n - m, thetas)))
            err_rel = max(err_rel, abs(lhs - rope(q, m + 500, thetas) @ rope(k, n + 500, thetas)))
        err_len = max(err_len, abs(np.linalg.norm(rope(q, m, thetas)) - np.linalg.norm(q)))
    print("rope relative %.1e  norm %.1e" % (err_rel, err_len))
```

```text
PE(0) = [0. 1. 0. 1.]
PE(1) = [0.8415 0.5403 0.01   1.    ]
PE(2) = [ 0.9093 -0.4161  0.02    0.9998]
M_1 PE(1) = [ 0.9093 -0.4161  0.02    0.9998]
shift 2.8e-14  orth 2.2e-16  norm 7.1e-15  inner 3.6e-14
rope relative 1.4e-13  norm 8.9e-16
```

最初の 4 行は <Ref to="ex-sinusoidal-d4" /> の値です。5 行目は $d = 64$ での最大誤差で、順に <Ref to="thm-sinusoidal-shift" />（$\mathrm{PE}(p+k) = M_k\mathrm{PE}(p)$）、$M_7$ の直交性、<Ref to="prop-sinusoidal-inner-product" /> のノルムと内積です。6 行目は RoPE で、<Ref to="thm-rope-relative" /> の 1（$\langle R_m\boldsymbol{q}, R_n\boldsymbol{k}\rangle = \langle \boldsymbol{q}, R_{n-m}\boldsymbol{k}\rangle$ と、両方の位置を 500 ずらしても値が変わらないこと）と 2（ノルムの保存）の最大誤差です。どれも倍精度の丸め誤差の大きさに収まっています。`rope` は $d \times d$ の行列を作らず、成分 1 個につき 2 回の乗算と 1 回の加減算（対ごとに 4 回の乗算と 2 回の加減算）で回しているので、計算量は $O(d)$ です。

## 8. 次章へ

この章で用意したのは、(1) トークン id の列を $n \times d$ の行列 $X$ にする埋め込み、(2) 位置を $X$ に足す正弦波と学習する表、(3) 内積の直前でクエリとキーを回す RoPE、の 3 つです。次章の[自己注意](/computer-science/llm-architecture/self-attention)では、$X$ の行どうしの内積から「どの位置をどれだけ見るか」の重みを作ります。そこで示す同変性の定理は、(2) か (3) のどちらかが無ければモデルが語順を区別できないことを意味します。この章の内容は、その穴を埋める部品です。

## 9. 演習

<Exercise id="exr-lookup-gradient" difficulty="易">

$|V| = 6$、$d = 3$ とし、トークン列 $(2, 5, 2)$ の埋め込みを $X$（行が $\boldsymbol{x}_1, \boldsymbol{x}_2, \boldsymbol{x}_3$）とする。固定したベクトル $\boldsymbol{u} \in \mathbb{R}^3$ に対して $\mathcal{L} = \langle \boldsymbol{x}_1, \boldsymbol{u}\rangle + 2\langle \boldsymbol{x}_2, \boldsymbol{u}\rangle + 3\langle \boldsymbol{x}_3, \boldsymbol{u}\rangle$ とするとき、$\mathcal{L}$ の $E$ についての勾配（$6 \times 3$ の行列）を求めよ。

<Solution>

$g(X) = \sum_i c_i \langle \boldsymbol{x}_i, \boldsymbol{u}\rangle$（$c = (1, 2, 3)$）なので $\partial g/\partial X_{ij} = c_i u_j$ です。<Ref to="prop-embedding-lookup" /> の 2 より、第 $v$ 行の勾配は $\sum_{i: t_i = v} c_i\, \boldsymbol{u}^{\mathsf{T}}$ です。トークン 2 は位置 1 と 3 に現れるので第 2 行は $(1 + 3)\boldsymbol{u}^{\mathsf{T}} = 4\boldsymbol{u}^{\mathsf{T}}$、トークン 5 は位置 2 に現れるので第 5 行は $2\boldsymbol{u}^{\mathsf{T}}$、第 1・3・4・6 行は 0 です。

</Solution>
</Exercise>

<Exercise id="exr-shift-group" difficulty="標準">

<Ref to="thm-sinusoidal-shift" /> の $M_k$ について、$M_k M_l = M_{k+l}$ と $M_k^{-1} = M_{-k}$ を示せ。また $\mathrm{PE}(p) = M_p\, \mathrm{PE}(0)$ であることと、$\mathrm{PE}(0)$ の成分を求めよ。

<Solution>

$\boldsymbol{\omega} = (\omega_0, \ldots, \omega_{d/2-1})$ と置くと $M_k = R[-k\boldsymbol{\omega}]$ です。<Ref to="lem-rotation" /> の 2 より $M_k M_l = R[-k\boldsymbol{\omega}]R[-l\boldsymbol{\omega}] = R[-(k+l)\boldsymbol{\omega}] = M_{k+l}$、$M_0 = R[\boldsymbol{0}] = I$ です。よって $M_k M_{-k} = M_{-k}M_k = M_0 = I$ で、$M_k^{-1} = M_{-k}$ です。

<Ref to="thm-sinusoidal-shift" /> で $p$ を 0、$k$ を $p$ に取り替えると $\mathrm{PE}(p) = M_p\,\mathrm{PE}(0)$ です。$\mathrm{PE}(0)_{2i} = \sin 0 = 0$、$\mathrm{PE}(0)_{2i+1} = \cos 0 = 1$ なので $\mathrm{PE}(0) = (0, 1, 0, 1, \ldots, 0, 1)$ です。つまり正弦波位置符号化は、1 つのベクトル $\mathrm{PE}(0)$ を、位置に比例する角度だけ対ごとに回したものです。

</Solution>
</Exercise>

<Exercise id="exr-inner-product-d4" difficulty="易">

$d = 4$ の正弦波位置符号化で $\langle \mathrm{PE}(0), \mathrm{PE}(3)\rangle$ を求めよ（$\cos 3 = -0.98999$、$\cos 0.03 = 0.99955$ を使ってよい）。この値から、位置 0 と 3 のベクトルのなす角について何が言えるか。

<Solution>

<Ref to="prop-sinusoidal-inner-product" /> より $\cos(3\omega_0) + \cos(3\omega_1) = \cos 3 + \cos 0.03 = -0.98999 + 0.99955 = 0.00956$ です。ノルムはどちらも $\sqrt{d/2} = \sqrt2$ なので、コサイン類似度は $0.00956 / 2 = 0.0048$ で、2 つのベクトルはほぼ直交しています。速く回る対（$\omega_0$）がほぼ反対向き、遅く回る対（$\omega_1$）がほぼ同じ向きで、打ち消し合った結果です。

</Solution>
</Exercise>

<Exercise id="exr-rope-direction" difficulty="標準">

$d = 2$、$\theta_0 = \pi/2$ の RoPE で、$\boldsymbol{q} = (1, 0)$、$\boldsymbol{k} = (0, 1)$ とする。相対位置 $n - m$ が $1$、$0$、$-1$ のときの $\langle R_m\boldsymbol{q}, R_n\boldsymbol{k}\rangle$ を求め、RoPE の内積が「前にあるか後ろにあるか」を区別できることを確かめよ。

<Solution>

<Ref to="thm-rope-relative" /> の 1 より、値は $\langle \boldsymbol{q}, R((n-m)\pi/2)\boldsymbol{k}\rangle$ です。

- $n - m = 1$: $R(\pi/2)\boldsymbol{k} = (-1, 0)$ で、内積は $-1$。
- $n - m = 0$: $R(0)\boldsymbol{k} = (0, 1)$ で、内積は $0$。
- $n - m = -1$: $R(-\pi/2)\boldsymbol{k} = (1, 0)$ で、内積は $1$。

相対位置の符号を変えると値が $-1$ から $1$ に変わるので、キーがクエリより 1 つ後ろにあるか 1 つ前にあるかが区別できています。<Ref to="prop-sinusoidal-inner-product" /> の $\langle \mathrm{PE}(p), \mathrm{PE}(q)\rangle = \sum_i\cos(\omega_i(p - q))$ は $p - q$ の符号を変えても同じ値でしたが、RoPE では内容のベクトル $\boldsymbol{q}, \boldsymbol{k}$ が間に入るので、向きの情報が残ります。

</Solution>
</Exercise>

## 参考文献

- [1] 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) — 3.4 節（埋め込みと重みの共有）、3.5 節（正弦波位置符号化）。
- [2] J. Su, Y. Lu, S. Pan, A. Murtadha, B. Wen, Y. Liu, "RoFormer: Enhanced Transformer with Rotary Position Embedding", 2021. [arXiv:2104.09864](https://arxiv.org/abs/2104.09864) — 回転位置埋め込みの提案。
- [3] 本サイト「[数学を学び直す意義：AI を読み解く三つの言語](/computer-science/ai-era/relearning-mathematics)」 — コサイン類似度と、高次元でほぼ直交する方向の本数。
- [4] P. Shaw, J. Uszkoreit, A. Vaswani, "Self-Attention with Relative Position Representations", NAACL 2018. [arXiv:1803.02155](https://arxiv.org/abs/1803.02155) — 相対位置の表現を注意に入れる先行研究。
- [5] O. Press, L. Wolf, "Using the Output Embedding to Improve Language Models", EACL 2017. [arXiv:1608.05859](https://arxiv.org/abs/1608.05859) — 入力と出力の埋め込みの重み共有。
