RoPEとは?回転位置埋め込みの仕組みとコンテキスト長拡張・実装判断を実装者向けに解説
いま自社で動かせるオープンウェイトのLLMは、ほぼ例外なくRoPE(Rotary Position Embedding、回転位置埋め込み)で位置情報を持っています。ところが、この方式が実装者の前に姿を見せるのは、たいてい「学習時より長い入力を投げたら出力が崩れた」「設定ファイルの rope_scaling を書き換えたのに効かない」といった不具合の側からです。本記事では、RoPEが何を回転させて何を解いているのかを処理単位まで分解し、設定キーの実体、コンテキスト長を伸ばす4方式の選び分け、そして拡張に手を出してよい条件までを2026年7月時点の一次情報で整理します。QKの内積そのもの、つまりTransformerの自己注意の仕組みは別記事で扱っているため、本記事は位置情報の与え方に絞ります。
まとめ:RoPEの仕組みとコンテキスト長拡張・採用判断の結論
RoPEは、トークンの位置を「ベクトルに足す値」ではなく「ベクトルを回す角度」として与える位置エンコーディングです。クエリとキーの各ヘッド次元を2つずつペアにし、位置mのトークンならペアごとに角度 m·θ を掛けて回す。それだけの操作です。
この形にした見返りが、内積の性質に出ます。位置mのクエリと位置nのキーの内積を展開すると、回転角の差 (m−n)·θ だけが残り、mとnの絶対値は消える。絶対位置を入力しているのに、注意スコアには相対距離しか効かないという構造になります。RoFormer論文(arXiv:2104.09864、2021年公開、Neurocomputing 568巻に2024年掲載)が示したのがこの点です。
実装上の触りどころは3か所しかありません。回転の細かさを決める base(設定キーは rope_theta、既定は10,000)、回転を掛ける対象(クエリとキーのみ、値ベクトルには掛けない)、そして学習長を超えて使うときの拡張方式(rope_type)です。Hugging Face transformers では 5.14.1 時点で設定が rope_parameters という辞書に統合され、従来の rope_scaling は非推奨エイリアスとして読み替えられます。
判断の起点は、伸ばしたい倍率と精度の許容幅の2つ。2倍前後までなら学習なしの dynamic(NTK-aware)で足り、8倍を超えるなら YaRN のように短時間の追加学習を伴う方式でなければ品質が保てません。そして、どの方式でもコンテキスト長に比例してKVキャッシュが膨らむため、伸ばした長さを本当に使うのかをメモリ側から先に確かめるのが安全な順序です。
RoPEが解く問題|位置情報を加算する方式から回転方式へ移った理由
まず、この方式が何を置き換えたのかを確定させます。
絶対位置を足し込む方式が長い文脈で崩れてしまう仕組み上の理由
初期のTransformerは、トークン埋め込みに位置ベクトルを加算していました。正弦波で作る方式(Sinusoidal PE)でも、位置ごとに学習する方式(Learned PE)でも、入り口で足すという点は共通です。この設計には2つの弱点があります。
1つは、位置情報が入力層で1度だけ注入され、層を重ねるうちに他の特徴と混ざって薄まること。もう1つは、学習した位置までしかベクトルが存在しないことです。学習を2,048トークンで行えば2,049番目の位置ベクトルは未定義で、学習型なら参照そのものができません。正弦波型は数式上いくらでも伸ばせますが、その領域は学習で1度も見ていない値であり、注意スコアが不安定になります。
相対位置を直接埋め込む方式(Relative PE)はこの弱点に対処しましたが、注意スコアの計算にトークン対ごとの項が加わり、実装と計算コストが重くなりました。RoPEはこの2系統の間を通します。入力に足すのをやめ、注意を計算する直前のクエリとキーに対して、位置に応じた回転を掛ける。それだけで相対位置の性質が手に入る、という筋です。
2次元ペアの回転で内積に相対距離だけが残る中核の性質を数式で確認
回転の対象はヘッド次元(head_dim)です。仮に128次元なら、これを (0,1)(2,3)…(126,127) のように2つずつのペアに分け、各ペアを2次元平面上のベクトルとみなします。位置mのトークンなら、i番目のペアを角度 m·θ_i だけ回す。回転行列の適用そのものです。
ここで効いてくるのが、回転行列の積の性質です。角度αの回転の転置と角度βの回転を掛けると、角度 β−α の回転になる。クエリ(位置m)とキー(位置n)の内積を取ると、この差だけが残ります。
score(m, n) = q_m · k_n
= (R(m·θ) q) · (R(n·θ) k)
= q · R((n − m)·θ) k # 絶対位置 m, n は消える
結果として、モデルは「50番目と55番目」ではなく「5つ離れている」という情報だけを見ることになります。同じ距離のペアなら文書のどこにあっても同じ扱いになり、位置ベクトルを別途学習する必要もありません。この性質が、パラメータを1つも増やさずに得られる点がRoPEの効率です。
もう1つ、距離が開くほど内積の期待値が下がるという副次的な性質もあります。ペアごとに回転速度が違うため、遠いトークン同士では位相がばらけて打ち消し合う。近いものほど強く結びつくという自然な減衰が、明示的な減衰項なしに生まれます。LLMという枠組み全体での位置づけや企業導入の判断軸はLLM(大規模言語モデル)の仕組みと導入判断で扱っています。
波長を決める base(rope_theta)と次元ごとの周波数の割り当て
ペアごとの回転角 θ_i は、次の式で決まります。base は既定で10,000です。
inv_freq = 1.0 / (base ** (arange(0, head_dim, 2) / head_dim))
freqs = position_ids * inv_freq # 形状 [系列長, head_dim ÷ 2]
cos, sin = freqs.cos(), freqs.sin()
先頭のペアほど θ が大きく、1トークン進むだけで大きく回ります。末尾のペアは θ が極端に小さく、数千トークン進んでようやく1周する。つまり、低次元側が「隣接語の並び」を、高次元側が「文書内の大まかな位置」を担う周波数分解になっています。
base を上げるとすべての周波数が下がり、波長が伸びます。長い文脈を扱うモデルが base を大きく取るのはこのためで、Llama 3 は事前学習の段階で base を10,000から500,000へ引き上げました。低周波側のペアが1周し切らないまま長い系列を表現できるようになり、後付けの拡張に頼らずに長さを稼げます。
実装で実際に触る場所|QとKへの適用位置と設定キーの対応関係
数式より先に、コードのどこに現れるかを押さえておくほうが実務では早く済みます。
rotate_half と cos・sin の掛け方=Vには適用しないという原則
実装は回転行列を組み立てず、要素ごとの積と符号反転で済ませます。Hugging Face 実装の骨格は次の通りです。
def rotate_half(x):
x1, x2 = x.chunk(2, dim=-1)
return cat((-x2, x1), dim=-1)
q = q * cos + rotate_half(q) * sin
k = k * cos + rotate_half(k) * sin
# v には掛けない
押さえる点は2つあります。第一に、回転を掛けるのはクエリとキーだけで、値ベクトル(V)には掛けません。位置に依存させたいのは「どこを見るか」であって「何を運ぶか」ではないためです。ここを取り違えた自作実装は、短文では動くのに長文で急に壊れるという分かりにくい壊れ方をします。
第二に、ペアの取り方が原論文と実装で異なります。原論文とGPT-J系は隣接する次元 (0,1)(2,3) を組にしますが、Hugging Face のこの書き方は前半と後半を組にする(0と64、1と65…)GPT-NeoX系です。回転としては次元の並べ替えを挟めば等価ですが、別実装から重みを移植するときは、この並べ替えを入れないと出力が壊れます。変換スクリプトが permute 処理を持っているのは、この差を吸収するためです。
5系transformersのrope_parametersと旧rope_scaling
設定の置き場所は2026年7月時点で移行の途中にあります。transformers 5.14.1 の modeling_rope_utils.py を読むと、RoPE関連の設定は rope_parameters という1つの辞書に統合済みで、base も rope_theta としてこの辞書の中に入ります。従来トップレベルに置いていた rope_scaling は convert_rope_params_to_dict によって rope_parameters へ読み替えられる非推奨エイリアスという扱いです(辞書内の旧 type フィールドも rope_type と等価に処理されます)。
"rope_parameters": {
"rope_type": "yarn",
"rope_theta": 10000.0,
"factor": 8.0,
"original_max_position_embeddings": 4096
}
実務上の注意はここです。4系の記事やスクリプトをそのまま持ち込み、config.json のトップレベルに rope_scaling を書いた場合、読み替えは効いても、コード側で config.rope_scaling を直接参照している自作の前処理は空を掴みます。「設定を書き換えたのに挙動が変わらない」という症状の多くは、読み替え後の rope_parameters を見ていないことが原因です。設定を変えたら、モデルを読み込んだ状態で config.rope_parameters を出力し、意図した値が入っているかを確かめてから評価に進んでください。
partial_rotary_factorの部分適用とhead_dimの対応関係
すべての次元を回す必要はありません。partial_rotary_factor は、head_dim のうち何割にRoPEを適用するかを 0 から 1 の範囲で指定するパラメータで、GPT-NeoX系やPhi系のモデルが 0.25 や 0.4 といった値を採ります。残りの次元は回転を受けず、位置に依存しない特徴としてそのまま通ります。
この設計の狙いは、位置に縛られない意味的な特徴を確保しておくことにあります。一方で、拡張方式の計算式は適用対象の次元数を前提に組まれているため、partial_rotary_factor を設定したまま factor だけを触ると、意図した波長にならないことがあります。既存モデルの設定を書き換えるときは、この値が1未満かどうかを最初に確認するのが確実です。
コンテキスト長を伸ばす方式の違い|PI・NTK・YaRN・LongRoPEの整理
学習長を超えた入力をどう扱うかが、RoPEを実務で触る最大の理由になります。
事前学習の段階で base を上げる方法とLlama 3の500,000という選択
後付けの拡張より先に押さえるべきは、そもそも base を大きくして長い文書で学習してしまう手です。Llama 3 が base を500,000へ引き上げたのがこの方針で、低周波側の波長が最初から長いため、モデルは長距離の位置差を学習の中で直接見ることになります。
この方法が使えるのは、自前で事前学習または大規模な継続学習を回せる場合に限られます。学習済みモデルを配布物として受け取る立場なら、選べるのは次に挙げる後付けの4系統です。
後付け拡張の4系統と rope_type 指定値の対応を一覧で整理する
transformers v5.14.1 の ROPE_INIT_FUNCTIONS に登録されている値は、linear・dynamic・yarn・longrope・llama3・proportional の6種類で、無指定なら default(拡張なし)です。主要な4系統の性格は次のように分かれます。
| rope_type | 元になる手法 | 追加学習 | 向く倍率 |
|---|---|---|---|
| linear | Position Interpolation | 短時間の追加学習が前提 | 2〜4倍 |
| dynamic | NTK-aware 動的スケール | 不要(そのまま推論) | 2倍前後まで |
| yarn | YaRN | 短時間の追加学習で効く | 8〜32倍 |
| longrope | LongRoPE | 探索と追加学習が必要 | 数十倍以上 |
linear は位置インデックスを factor で割って既存の範囲に押し込む素直な補間です(arXiv:2306.15595)。隣接トークンの分解能まで一律に潰れるため、無学習では近距離の精度が落ちます。dynamic は割るのではなく、入力長に応じて base を動的に持ち上げる方式で、学習なしで使える代わりに倍率を上げると崩れます。
yarn(arXiv:2309.00071)は、周波数帯ごとに扱いを変えるのが要点です。高周波側は隣接語の分解能を守るため補間せず、低周波側だけを補間し、その中間は beta_fast と beta_slow で決まる区間でなだらかに切り替える。加えて attention_factor で注意ロジットの温度を補正します。高倍率でも品質が落ちにくいのはこの作り分けによるもので、その分パラメータの指定項目が増えます。
longrope(arXiv:2402.13753)は、次元ごとに別々のスケール係数を探索で決める方式で、短い入力用の short_factor と長い入力用の long_factor を持ちます。200万トークン級まで伸ばした報告があるのはこの系統です。llama3 は low_freq_factor と high_freq_factor で低周波側だけを補間する専用式で、Llama 3.1系の配布設定に現れます。
推論エンジン側の設定とKVキャッシュ量への跳ね返りを見積もる
設定を書き換えるとき、config.json だけを見ていると足をすくわれます。推論エンジンは自身の最大長設定を別に持ち、モデル設定と食い違うと、位置が壊れるか、そもそも起動を拒否するかのどちらかになります。vLLMの仕組みと使い方・起動オプションの決め方で扱っている最大長やオーバーライドの指定と、config 側の rope_parameters を必ず突き合わせてください。
そして、伸ばした長さは丸ごとメモリ請求書として返ってきます。KVキャッシュはコンテキスト長に比例して増えるため、4kから32kへ8倍にすれば、1リクエストあたりのキャッシュも8倍です。同時実行数を保ったまま長さだけ伸ばすと、バッチが組めなくなって実効スループットが落ちます。見積もりの手順はKVキャッシュの仕組みとメモリ削減の考え方にまとめてあります。
拡張後にも精度検証を実施する必要があります。長文の中に1文だけ手がかりを埋めて回収させる形式の評価(needle-in-a-haystack)と、実務のプロンプトを用いた回帰確認を、拡張前後で同じ条件で比べる。困るのは、短い入力では差が出ないのに、想定した長さの8割あたりから静かに精度が落ちるという壊れ方をする点で、短文のスモークテストだけでは検出できません。
RoPE拡張を採用してよい3条件と、見送るべき場面の判断基準
ここからは判断の話です。設定を1行足せば動いてしまうため、採否の線引きを先に決めておかないと、壊れているのに気づかないまま本番へ出ます。
拡張採用の第1条件は必要なコンテキスト長の要求が実測に基づくこと
1つ目の条件は、必要な長さが実測で決まっていることです。「念のため128kまで」ではなく、実際の入力トークン分布の95パーセンタイルを測り、その値の少し上に置く。分布を測らずに上限を取ると、使わない長さのためにKVキャッシュとGPU台数を払い続けることになります。
2つ目は、長さを使う目的が検索・要約・参照といった「広く浅く読む」処理であること。文書横断の参照や長い議事録の要約は、拡張後の精度低下が許容範囲に収まりやすい用途です。逆に、長文の隅にある1つの数値を厳密に取り出して判断に使う処理は、拡張の劣化がそのまま業務の誤りになります。
3つ目は、拡張前後を比べる評価セットを自前で持てること。公開ベンチマークの数値ではなく、自社の実データで作った20〜50件程度の回帰セットがあれば十分です。これを持てない体制なら、倍率を上げる判断を下す根拠がありません。
拡張を見送るべき3場面=精度保証・低レイテンシ・短文中心の用途
1つ目は、出力の正しさを契約や規程で保証する必要がある場面。拡張は学習時に見ていない位置での外挿であり、品質が保たれる保証は原理的にありません。この場合は、長文をそのまま投げるのではなく分割して処理する設計か、初めから長いコンテキストで学習されたモデルを選ぶほうが筋が通ります。
2つ目は、応答時間の上限が厳しい場面。長いコンテキストは入力処理(プリフィル)の時間を押し上げ、KVキャッシュの増加でバッチも組みにくくなります。P99レイテンシを守る用途では、長さを伸ばすより入力側を絞り込む設計のほうが確実に効きます。
3つ目は、入力の大半が数千トークン以内で収まっている場面です。長い入力が全体の数パーセントなら、その数パーセントのために全リクエストのメモリ設計を犠牲にする理由はありません。長い入力だけを別経路へ回し、分割して処理するほうが総コストで有利です。拡張は、いわば全員分の座席を広げる工事であって、たまに来る大柄な来客のための対応としては割高だと考えてください。
長文対応の実装を外部へ委託するとき見積書で確認すべき5項目の基準
委託時に見積もりの精度を左右するのは、次の5点です。第一に、対象モデルの学習時コンテキスト長と base(rope_theta)の実値、そして目標長と倍率が明記されているか。倍率が書かれていない見積書は、方式の選定が済んでいない可能性があります。
第二に、採用する rope_type と、追加学習の有無・データ量・計算資源。yarn や longrope を選ぶなら追加学習の工数が乗るはずで、そこが空欄なら無学習の dynamic を想定している見積もりです。第三に、KVキャッシュを含めたVRAM試算と、想定同時実行数での必要GPU台数。第四に、拡張前後の回帰評価の設計(評価セットの件数・作成主体・合格基準)。第五に、推論エンジン側の設定変更とデプロイ手順が範囲に含まれるか。
この5点が曖昧なまま進むと、構築後に「長さは通るのに、長い入力での精度が業務水準に届かない」という形で表面化します。委託先を選ぶ際は、機械学習モデル開発のようにモデル構造の選定と基盤実装を一体で扱える体制かを確認してください。
よくある質問
RoPEの検討時に問い合わせが多い論点を5つ挙げます。
RoPEと従来の位置エンコーディングは何が違うのですか?
足すか、回すかの違いです。従来方式はトークン埋め込みに位置ベクトルを加算し、入力層で1度だけ位置情報を注入していました。RoPEは注意計算の直前にクエリとキーを回転させるため、層ごとに位置情報が作用し、内積には相対距離だけが残ります。学習可能なパラメータを増やさない点と、系列長を後から伸ばす余地がある点も差になります。
RoPEを使えば学習した長さを超えても動くのですか?
形式上は動きますが、品質は保たれません。位置インデックス自体は上限なく計算できるので、学習長の10倍を投げてもエラーにはならず、出力だけが崩れます。この「静かに壊れる」性質が実装者にとっての落とし穴で、拡張方式を指定せずに長い入力を通していないかは、本番投入前に確認しておく価値があります。
rope_scaling を後から書き換えるだけで長文に対応できますか?
倍率次第です。2倍前後までなら dynamic の無学習指定で実用に足りることが多い一方、8倍を超える拡張では yarn などの方式と短時間の追加学習を伴わないと精度が落ちます。加えて transformers 5系では設定が rope_parameters に統合されているため、書き換えた値が読み込み後の config に反映されているかを先に確かめてください。
RoPEはKVキャッシュとどのように関係しますか?
Hugging Face の一般的な実装では、回転を適用した後のキーをキャッシュします。したがってキャッシュ済みの内容は特定の絶対位置に紐づいており、プロンプトの前方を差し替えると位置がずれて再利用できません。拡張の設定を変えた場合も、以前の設定で作られたキャッシュは無効になると考えて扱ってください。
画像や音声を扱うモデルでもRoPEは使えますか?
画像や音声を扱うモデルでの利用例は公表済みです。テキストの1次元の位置を、時間・高さ・幅といった複数の軸へ分解して割り当てる多次元の派生が公表されており、マルチモーダルモデルの位置表現として採られています。基本の考え方は同じで、軸ごとに次元のブロックを割り当て、それぞれの位置に応じて回転させる形になります。
関連記事
- LLM推論とは?仕組みと高速化の手法・推論基盤の選び方を実装視点で解説【2026年】:RoPE拡張を載せる推論基盤側の全体像
- LoRA(低ランク適応)とは?仕組み・使い方・QLoRAなど派生手法を解説:YaRNなどで必要になる短時間の追加学習の手段
- LLM量子化とは?仕組みとGPTQ・AWQ・GGUFの違い・企業の採用判断を解説【2026年版】:長文化で膨らむメモリを別方向から抑える手法
- DeepSeek V4とは|CSA・HCAの仕組みとPro/Flashの性能・料金・移行期限を解説:長文アテンションを構造側から軽くする実例
- ニューラルネットワークとは?仕組み・種類・学習方法を実装目線で解説:回転を掛ける対象である埋め込み表現の基礎