Skip to content
Published on

位置エンコーディングの完全理解 — 正弦波からRoPEまで

Authors

はじめに — なぜ位置情報が必要か

self-attentionは入力トークンの集合を見て加重平均を取ります。ところがアテンション演算そのものは順序を知りません。「私はあなたが好き」と「あなたは私が好き」は同じ単語の集合ですが意味は正反対なのに、位置情報がなければモデルは両者を区別する手がかりが不足します。数学的に言えば、self-attentionは順列同変(permutation equivariant)であり、入力順序を変えると出力も同じように変わるだけで、順序そのものを認識できません。

そこでTransformerはトークンの位置情報を明示的に注入しなければなりません。本記事はその方法の進化をたどります。最も単純な正弦波エンコーディングから出発し、学習型、相対位置を経て、今日事実上の標準となったRoPEとALiBiまで見渡し、学習より長い入力を扱う長さの外挿手法で締めくくります。

1. Sinusoidal — 固定された正弦波エンコーディング

原論文の方式です。各位置ごとに異なる周波数の正弦/余弦値を作り、トークン埋め込みに足します。

PE(pos, 2i)   = sin( pos / 10000^(2i / D) )
PE(pos, 2i+1) = cos( pos / 10000^(2i / D) )

pos = 位置インデックス
i   = 次元インデックス (0 .. D/2-1)
D   = モデル次元

低い次元は速い周波数、高い次元は遅い周波数を担当し、位置ごとに固有のパターンが生まれます。利点は学習パラメータがなく、理論上は学習長より長い位置でも値を計算できることです。ただし実際には、学習長を大きく超えると性能が落ちる場合が多いです。

import torch

def sinusoidal_encoding(n_positions, d_model):
    pe = torch.zeros(n_positions, d_model)
    pos = torch.arange(n_positions).unsqueeze(1).float()
    i = torch.arange(0, d_model, 2).float()
    denom = torch.pow(10000, i / d_model)
    pe[:, 0::2] = torch.sin(pos / denom)
    pe[:, 1::2] = torch.cos(pos / denom)
    return pe  # (n_positions, d_model)

2. Learned — 位置を学習する方式

正弦波の代わりに、位置ごとに学習可能な埋め込みベクトルを置く方式です。初期のBERT、GPTなどが使いました。データに合わせて位置表現を最適化できる利点がありますが、決定的な欠点があります。学習時に見たことのない位置(最大長を超える入力)には埋め込みがそもそも存在しません。つまり外挿が原理的に不可能です。

learned PE:
 位置 0..max_len-1 それぞれに対して (D,) ベクトルを学習
 max_len 超過の位置 -> 対応するベクトルなし -> 処理不可

この制約のため、長コンテキストが重要になった最近では、learned絶対位置エンコーディングの人気は下がりました。

3. 相対位置 — 絶対より相対が自然

文の意味は「このトークンが文書の何番目か」よりも「このトークンがあのトークンからどれだけ離れているか」に依存する場合が多いです。相対位置エンコーディングは、二つのトークン間の距離(相対位置)をアテンションスコアに反映します。

絶対位置を埋め込みに足す代わりに、アテンションスコア段階でqueryとkeyの距離に応じた項を加える方式です。こうすると、同じ距離関係が文書のどの位置にあっても同一に扱われ、汎化と外挿に有利です。RoPEとALiBiはどちらもこの相対位置の哲学に従います。

4. RoPE — 回転で相対位置をエンコード

核心アイデア

RoPE(Rotary Position Embedding)は、今日Llama、Qwenなど大半のオープンLLMが使う方式です。発想は優雅です。位置情報を足さずに、QueryとKeyのベクトルを位置に比例した角度だけ回転させます。

2次元の部分空間で位置mのベクトルを角度m かける thetaだけ回転させると、QueryとKeyの内積が自然と二つの位置の差(m - n)だけに依存するようになります。つまり絶対位置で回転をかけたのに、結果的に相対位置がエンコードされるのです。

RoPEの核心的性質:

位置mのqueryをR(m)で回転、位置nのkeyをR(n)で回転すると
 dot( R(m) q, R(n) k ) = 関数( q, k, m - n )

-> 内積が絶対位置m, nではなく相対距離 (m - n) だけに依存

回転行列

D次元をD/2個の2次元ペアにまとめ、各ペアを異なる周波数で回転します。

各2次元ペア (x_a, x_b) を角度 theta で回転:

 [ x_a' ]   [ cos(theta)  -sin(theta) ] [ x_a ]
 [ x_b' ] = [ sin(theta)   cos(theta) ] [ x_b ]

位置mでのj番目のペアの角度:
 theta_j = m / base^(2j / D)    (baseは通常10000)

低い次元のペア: 速い回転(高周波)
高い次元のペア: 遅い回転(低周波)
import torch

def apply_rope(x, positions, base=10000):
    # x: (..., N, D)  D は偶数
    *_, N, D = x.shape
    half = D // 2
    freq = 1.0 / (base ** (torch.arange(0, half).float() / half))
    angles = positions.unsqueeze(-1).float() * freq  # (N, half)
    cos = torch.cos(angles)
    sin = torch.sin(angles)

    x1 = x[..., :half]
    x2 = x[..., half:]
    # 2次元ペアの回転
    rotated = torch.cat([x1 * cos - x2 * sin,
                         x1 * sin + x2 * cos], dim=-1)
    return rotated

RoPEが人気な理由は、(1)相対位置を自然にエンコードし、(2)追加パラメータがなく、(3)アテンションのQ, Kにだけ適用されKV cacheとも相性がよく、(4)baseを調整して外挿を扱う余地を与えるからです。

5. ALiBi — 距離に比例したアテンションペナルティ

ALiBi(Attention with Linear Biases)はより単純です。位置エンコーディングを埋め込みに入れず、アテンションスコアにqueryとkeyの距離に比例する負のバイアスを直接足します。遠いトークンほどスコアをより削るのです。

ALiBiアテンションスコア:

 score(i, j) = q_i · k_j  -  m * |i - j|

 m = ヘッドごとに異なる傾き(slope)定数
 |i - j| = 二つのトークンの距離

-> 近いトークンはペナルティ小、遠いトークンはペナルティ大

ヘッドごとに傾きmを変えて、あるヘッドは近いトークンに、あるヘッドは遠いトークンに集中するよう分化させます。ALiBiの強みは、学習よりはるかに長い入力にも比較的よく外挿することです。ただしRoPEほど普遍的には採用されておらず、モデル設計によって選択が分かれます。

6. 比較の整理

方式位置注入の場所相対/絶対追加パラメータ外挿代表的な使用
Sinusoidal埋め込みに足す絶対なし限定的原論文
Learned埋め込みに足す絶対あり不可初期BERT/GPT
相対位置アテンションスコア相対方式による良好Transformer-XLなど
RoPEQ, K の回転相対なし外挿手法と結合Llama, Qwenなど
ALiBiアテンションスコアのバイアス相対なし良好一部のモデル

7. 長さの外挿とコンテキスト拡張

問題

モデルを4Kコンテキストで学習したのに32K入力を入れるとどうなるでしょうか。RoPEの場合、学習時に見たことのない大きな回転角が現れ、アテンションパターンが崩れて性能が急落します。これを外挿失敗と呼びます。再学習なしでコンテキストを伸ばすことが実務の大きな関心事です。

NTKスケーリング

RoPEのbase(周波数の基準値)を大きくして、回転角がゆっくり増えるようにする方式です。直観的には「位置軸を伸ばして学習範囲の中に押し込む」効果を出します。高周波情報の損失を抑えつつコンテキストを伸ばす均衡を取ります。

NTK-awareスケーリングの直観:

 RoPE base を 10000 -> より大きな値に調整
 -> 各次元の回転角が緩やかになる
 -> 学習より長い位置も学習分布の内側に近くマッピング

YaRN

YaRNはNTK系を発展させ、周波数帯域ごとに補間/外挿の強度を変えて調整し、アテンション温度まで一緒に補正する方式です。高周波(近い距離の情報)は保存し、低周波(遠い距離)は伸ばして、より長いコンテキストでも品質を保つよう設計されています。少量の追加微調整と組み合わせると効果的です。

コンテキスト拡張戦略のまとめ:

 位置補間(PI): 位置インデックスを比率で圧縮 -> 単純だが高周波を損なう
 NTK-aware:    base調整 -> 高周波保存を改善
 YaRN:         帯域ごとの補正 + 温度調整 -> より長い拡張に有利
手法核心再学習利点注意
位置補間(PI)位置インデックスを圧縮やや推奨単純高周波情報を損なう
NTK-awarebase調整不要~わずか高周波保存大きな拡張には限界
YaRN帯域ごとの補正+温度少量推奨長い拡張に強い実装が複雑

8. マルチモーダルのM-RoPE

画像や動画を扱うビジョン言語モデル(VLM)では、位置は1次元ではありません。画像は行と列、動画は時間軸まで加わります。M-RoPE(Multimodal RoPE)はRoPEを複数の軸に分解し、時間/高さ/幅のような次元にそれぞれ回転を割り当てます。Qwen2-VLなどが任意解像度の入力を扱うために、この多軸位置エンコーディングを使います。

M-RoPEの直観:

 テキスト: 1D位置 (順序)
 画像: 2D位置 (行, 列)
 動画: 3D位置 (時間, 行, 列)

 RoPE次元を軸ごとに分け、各軸の位置で回転
 -> 一つの統一された位置エンコーディングで複数のモダリティを処理

これにより、テキストと画像のトークンが同じ位置体系の中で相対関係を保ちながら、一緒にアテンションできます。

8.5. なぜ絶対位置エンコーディングは外挿に弱いか

相対位置系(RoPE, ALiBi)が外挿に強い理由を、絶対位置エンコーディングの限界と対比して整理します。

絶対位置エンコーディングの外挿の弱点:
 sinusoidal -> 学習長の外の位置パターンは学習中に見たことがない
               理論上は値が計算できるが、モデルがそのパターンを解釈するよう
               学習されておらず、実戦性能が落ちる
 learned    -> 学習長の外の位置に埋め込み自体がない -> 外挿が原理的に不可

相対位置系が強い理由:
 同じ距離関係が位置に関係なく同一に表現される
 -> 「10マス離れている」の意味が位置5でも5000でも同じ
 -> 学習で見た距離関係を長い入力でも再利用できる

ただし相対位置も万能ではありません。RoPEでさえ学習よりはるかに長い入力では、大きな回転角が学習分布を外れて性能が落ちます。だからNTK/YaRNのような補正が必要なのです。核心の教訓は、「相対位置は外挿の出発点を良くするが、大幅な拡張にはほぼ常に追加の補正が必要だ」ということです。

8.7. 任意解像度と位置エンコーディング

マルチモーダルでは、位置エンコーディングは任意解像度の処理とも直結します。画像サイズがまちまちだと、固定された位置格子では多様な解像度を一貫して扱いにくいです。

固定位置格子の限界:
 学習時に見た解像度(例: 224x224)に合わせて位置を学習すると
 -> 別の解像度(例: 1024x768)の入力で位置の意味がずれる

多軸相対位置(M-RoPE)の利点:
 位置を (行, 列) のような座標の相対関係でエンコード
 -> 解像度が変わっても「右へ1マス」の意味が保存される
 -> 任意解像度の入力をより自然に処理

Qwen2-VLのnaive dynamic resolutionのようなアプローチは、画像を固定サイズに強制リサイズせず、元の比率と解像度を生かしたまま処理しつつ、多軸位置エンコーディングで空間関係を維持します。これはOCRや文書理解のように、細かい空間情報が重要なタスクで特に有利です。

9. 小さな例で見るRoPEの回転

RoPEが抽象的に感じるなら、2次元の1ペアを実際に回転させてみると直観がつかめます。次元D=4(つまり2次元ペアが2個)としましょう。

ベクトル x = [x0, x1, x2, x3]
2次元ペアにまとめる: (x0, x1), (x2, x3)

位置m=2, 最初のペアの角度 theta_0 = 0.5 とすると
 回転後:
  x0' = x0 * cos(2*0.5) - x1 * sin(2*0.5)
  x1' = x0 * sin(2*0.5) + x1 * cos(2*0.5)

二つ目のペアはより遅い周波数(小さなtheta_1)で回転
 -> 同じ位置でもペアごとに異なる角度で回る

核心は、同じベクトルでも位置mによって回転角が変わること、そして二つのトークンのQuery·Keyの内積を計算すると回転角の差(つまり位置差 m-n)だけが残ることです。だから絶対位置で回転をかけたのに、結果は相対位置として現れます。

import torch

def rope_dot_demo(q, k, pos_q, pos_k, base=10000):
    # q, k: (D,)  同じトークン内容でも位置が違えば内積が変わる
    qr = apply_rope(q.unsqueeze(0), torch.tensor([pos_q]), base)
    kr = apply_rope(k.unsqueeze(0), torch.tensor([pos_k]), base)
    return (qr * kr).sum()  # 位置差に依存する値

10. コンテキスト拡張を数値で感覚をつかむ

4Kで学習したモデルを16Kに伸ばしたいとしましょう。拡張倍率は4倍です。各手法がこの倍率をどう扱うかを直観的に見ます。

拡張倍率 s = 目標長 / 学習長 = 16K / 4K = 4

位置補間(PI):
 すべての位置インデックスを 1/s に圧縮 (pos -> pos / 4)
 -> 学習範囲に収まるが、隣接トークン間の角度間隔も1/4に縮み
    近い距離の解像度(高周波)がつぶれる

NTK-aware:
 baseを大きく(例: 10000 -> 10000 * s^(D/(D-2)) 付近)して高周波はほぼ保存、
 低周波だけ伸ばして外挿 -> PIより短い文脈の精度を維持

YaRN:
 周波数帯域を分けて高周波はそのまま、低周波は補間、
 中間帯域は滑らかに遷移 + アテンション温度を補正
 -> 大きな倍率でも安定、少量のファインチューニングと結合すると効果大

数値で見ると、なぜ単純な位置補間が短い文脈で損をするのかが明確になります。すべての周波数を等しく圧縮すると、近いトークンを区別する高周波情報が最も大きく損なわれるからです。NTKとYaRNは「どの周波数をどれだけ触るか」を差別化して、この損失を減らします。

11. 実務でコンテキストを伸ばす手順

実際にモデルのコンテキストを伸ばすときの一般的な順序を整理します。

1) 目標長と拡張倍率を決定 (例: 4K -> 32K, 8倍)
2) モデルの位置エンコーディング方式を確認 (RoPEか, base値はいくつか)
3) 拡張手法を選択:
   - 小幅拡張 + 再学習不可 -> NTK-aware (base調整)
   - 大幅拡張 + 少量ファインチューニング可 -> YaRN
4) 選んだスケーリングを適用して推論/ファインチューニング
5) 長コンテキスト評価:
   - needle-in-a-haystack で位置別の回収率を確認
   - 短い文脈の性能が退化していないか回帰検証
6) サービング時に paged KV cache で増えたKVメモリを管理

5段階の回帰検証が特に重要です。コンテキストを伸ばす手法はほぼ常に短い文脈の性能とトレードオフがあるので、長い文脈でよく回収するかだけを見ず、元々得意だった短いタスクが壊れていないかも併せて確認すべきです。

12. 位置エンコーディングとKV cache、アテンションのつながり

位置エンコーディングの選択は、アテンション・KV cache最適化とも噛み合います。

RoPEは Q, K にだけ適用される
 -> KV cacheに保存されるKに回転がすでに反映される
 -> GQA/MQAのようにKVヘッドを共有してもRoPEと衝突しない

ALiBiはアテンションスコアにバイアスを足す
 -> 別の位置埋め込みをKV cacheに持ち回る必要がない
 -> メモリ面で単純

長さの外挿(NTK/YaRN)はRoPEの角度計算だけを変える
 -> KV cacheの構造はそのまま -> サービングスタックと互換しやすい

このようにRoPE系が広く使われるのには、品質だけでなく、GQA/MQA・paged KV cacheのようなサービング最適化ときれいに調和するという実務的な理由も大きいです。位置エンコーディングを選ぶとき、モデル品質だけでなくサービングパイプライン全体との相性も併せて見るのがよいです。

落とし穴とトラブルシューティング

  • コンテキスト拡張時のbase未調整: RoPEモデルをそのまま長い入力に使うと、外挿失敗で品質が急落します。NTK/YaRNのような拡張手法を必ず適用してください。
  • 位置補間の高周波損傷: 単純な位置補間(PI)は、近い距離の情報を担う高周波を壊し、短い文脈の精度が落ちることがあります。
  • learned PEでの外挿の試み: 学習型の絶対位置エンコーディングは最大長を超える位置に埋め込みがなく、外挿が原理的に不可能です。長コンテキストにはRoPE/ALiBi系が適します。
  • RoPEをVにも適用: RoPEはQとKにだけ適用してこそ相対位置の性質が成り立ちます。Valueにまで回転をかけると意味が壊れます。
  • 次元の奇数問題: RoPEは次元を2次元ペアにまとめるため、ヘッド次元が偶数でなければなりません。奇数だとペア構成が崩れます。
  • マルチモーダルの軸割り当てミス: M-RoPEで時間/行/列の軸に次元を誤って割り当てると、画像の空間関係が歪みます。モデル実装の軸分割ルールに従ってください。

12.5. RoPEの適用位置とキャッシュの詳細

RoPEを推論パイプラインに入れるときによく混乱する詳細を押さえます。RoPEはQとKに適用されますが、適用の時点をどこに置くかでKV cacheの保存内容が変わります。

KV cacheに何を保存するか:
 一般にRoPEを適用した後のKをキャッシュに保存
 -> キャッシュされたKはすでに回転が反映された状態
 -> 新しいトークンのQもその位置へ回転させて内積
 -> 位置差だけが残り、相対位置が自然に機能する

注意:
 回転前のKをキャッシュに保存して毎回回転すると演算の無駄 + 一貫性のリスク
 -> 通常は回転後のKを保存する実装が標準

コンテキスト拡張手法を適用するときも、この流れは保たれます。NTKやYaRNは各位置での回転角の計算だけを変えるので、KV cacheの保存構造やアテンションカーネル自体はそのままにして、位置スケーリングだけを差し替えればよいです。この点が、RoPE系がサービングスタックとよく調和するもう一つの理由です。

13. 実務でよくある質問

位置エンコーディングを適用する際によくぶつかる質問を整理します。

Q. 学習長までしか使わないなら、どの位置エンコーディングでもよい?
A. ほぼそうだが、相対位置(RoPE/ALiBi)が汎化にやや有利な傾向。
   後でコンテキスト拡張の可能性があるならRoPE系が安全。

Q. RoPEのbase値を変えると既存の重みを再学習する必要がある?
A. 小幅調整(NTK-aware)は再学習なしでもある程度動く。
   大幅拡張は少量のファインチューニング(YaRNなど)を併用すると安定。

Q. ALiBiとRoPEのどちらを選ぶべき?
A. 大半のオープンLLMエコシステムがRoPE中心なので、ツール/互換性の面でRoPEが無難。
   特定の外挿特性が必要ならALiBiも候補。

Q. マルチモーダルなら必ずM-RoPE?
A. 多軸位置が必要な画像/動画で有利。モデル実装が定めた軸分割に従う必要がある。

14. 核心まとめチェックリスト

長い記事を1ページに圧縮すると次のとおりです。

[ ] self-attentionは順序を知らない -> 位置情報の注入が必須
[ ] sinusoidal: パラメータなし, 外挿は限定的
[ ] learned: データ適合, 外挿不可
[ ] 相対位置: 距離ベース -> 汎化/外挿に有利
[ ] RoPE: Q,Kの回転で相対位置をエンコード, 追加パラメータなし, 現在の標準
[ ] ALiBi: 距離比例ペナルティ, 外挿良好
[ ] 長さの外挿: PI < NTK-aware < YaRN (拡張幅/品質の順)
[ ] M-RoPE: RoPEを多軸に -> マルチモーダル/任意解像度
[ ] 拡張後は短い文脈の回帰検証を必ず

おわりに

位置エンコーディングは「self-attentionが順序を知らない」という根本的な限界を埋める仕掛けです。正弦波から出発し、学習型、相対位置を経て、今日では回転で相対位置を優雅にエンコードするRoPEと、距離ペナルティをかけるALiBiが主流になりました。そしてNTK、YaRNのような外挿手法は再学習なしでコンテキストを伸ばす道を開き、M-RoPEはこのアイデアをマルチモーダルへ拡張しました。

位置エンコーディングを理解すれば、「なぜこのモデルは長コンテキストで崩れるのか」「どうやってコンテキストを安全に伸ばすか」といった実務的な問いに答えられます。先の二つの記事(Transformer構造、アテンションの進化)と合わせて読めば、現代LLMの核心骨格が一つにつながるでしょう。

参考資料