一文要約: トークン埋め込みは内容を運びますが、住所は持ちません。Positional Encoding は、標準的な Transformer が利用できる順序信号を加えます。
5.1 位置がなぜ重要なのか
前章で、次のパイプラインを手にしました。
raw text -> token IDs -> embeddings -> Transformer blocks
埋め込みは揃いました。しかし、その中には静かに潜んだ問題があります。
5.1.1 決定的なギャップ
通しの例から、2つの文を考えてみましょう。
漫画家が貸本屋を訪ねた。
貸本屋が漫画家を訪ねた。
どちらの文も同じ語からできています。もしモデルに内容の埋め込みだけを渡すと、「漫画家」も「貸本屋」も「訪ねた」も、二つの文で同じ出発ベクトルを持ちます。
内容ベクトルだけでは、それがどの並びから来たのかはわかりません。しかし、2つの文の意味は決して同じではありません。
このギャップは「位置」の欠落です。標準的な Self-Attention には、再帰も畳み込みもありません。そのためオリジナル Transformer は、入力に順序信号を明示的に注入します。生成が逐次的であることや、デコーダが因果マスクを持つことと、トークン埋め込み自体に住所があることは別の話です。
5.1.2 Positional Encoding が解決する3つのこと
Positional Encoding は、関連する3つの問題を解きます。
-
絶対位置: このトークンがシーケンス内のインデックス 0、14、あるいは別の位置にあるという信号を受け取れます。
-
相対距離: 「漫画家」と「が」は隣接し、「漫画家」と「貸本屋」の間には助詞があります。この間隔と並びは、文法的・意味的な情報を運びます。
-
一貫したパターン: 決定的な式なら、学習済みの表にない位置でも計算できます。これは外挿の可能性を与えますが、訓練長を超えて必ず正しく働くことまで保証しません。
5.2 単純なアイデアとその限界: 生の整数
Transformer が実際に何をしているかを説明する前に、最も素朴なアプローチを見て、なぜそれがうまくいかないのかを理解しておきましょう。
5.2.1 整数の位置番号を足し込む
最も単純なアイデアは、各位置に番号を割り当て、その位置のトークン埋め込みに足し込むことです。
おもちゃサイズの d_model = 4 で、トークン ["漫画家", "と", "貸本屋", "と", "編集者", "。"] の例を見てみましょう。
埋め込みベクトル(意味内容):
| token | dim0 | dim1 | dim2 | dim3 |
|---|---|---|---|---|
| 漫画家 | 0.62 | -0.51 | 0.09 | 0.85 |
| と | 0.15 | 0.73 | -0.38 | 0.46 |
| 貸本屋 | 0.07 | 0.31 | -0.44 | 0.12 |
| と | 0.15 | 0.73 | -0.38 | 0.46 |
| 編集者 | 1.30 | -0.72 | 0.55 | 0.41 |
| 。 | 0.98 | 0.03 | -0.11 | 0.74 |
整数位置ベクトル:
| position | dim0 | dim1 | dim2 | dim3 |
|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 2 | 2 |
| 3 | 3 | 3 | 3 | 3 |
| 4 | 4 | 4 | 4 | 4 |
| 5 | 5 | 5 | 5 | 5 |
| 6 | 6 | 6 | 6 | 6 |
足し合わせた後:
| token | dim0 | dim1 | dim2 | dim3 |
|---|---|---|---|---|
| 漫画家 | 0.62+1 | -0.51+1 | 0.09+1 | 0.85+1 |
| と | 0.15+2 | 0.73+2 | -0.38+2 | 0.46+2 |
| ... | ... | ... | ... | ... |
5.2.2 なぜ扱いにくいのか
生のインデックスをすべての次元に複製する方法は、数学的に不可能なわけではありません。ただし、2つの実用上の問題があります。
-
値のスケールが増え続ける:
pos = 1000では各次元に1000が加算されます。埋め込みがゼロ近辺なら、位置信号が内容を圧倒し、最適化を難しくします。これは「勾配が必ず爆発する」という意味ではなく、スケール設計が悪いということです。 -
信号が一方向だけ: すべての次元が同じスカラーを受け取ります。ネットワークがこの線形信号から何も学べないわけではありませんが、異なる距離を表す多スケールの構造は持ちません。
オリジナルの Transformer 論文には、もっと原理的な何かが必要だったのです。
5.3 Transformer の答え: Sinusoidal Encoding
5.3.1 中心となるアイデア
オリジナルの Transformer は、異なる周波数の sin・cos 波 を使って位置ベクトルを構成します。私が覚え方として使っているのは、各位置が波を積み重ねたバーコードを持つ、というイメージです。低周波の波は大まかな位置を、高周波の波は近くの位置どうしの細かい距離をエンコードします。
式は以下の通りです。
even dimensions: PE(pos, 2i) = sin(pos / 10000^(2i / d_model))
odd dimensions: PE(pos, 2i+1) = cos(pos / 10000^(2i / d_model))
式を見て怯まないでください。中身は2つのアイデアだけです。
- 偶数次元は sin、奇数次元は cos を使う。
- 次元のペアごとに異なる周波数を使う。それを制御するのが
2i/d_modelの指数です。
5.3.2 波としての可視化
シーケンスに沿って位置エンコーディングをプロットすると、各次元はひとつの波を描きます。低周波の次元は位置が変わってもゆっくり変化します。遅い時計のようなものです。高周波の次元は素早く振動します。速い時計です。たくさんの時計を並べると、シーケンスの各位置がそれぞれ固有の読み取りの組み合わせを持つことになります。これが私たちの欲しいものです。
5.3.3 具体的な数値
最初の4次元について、6トークンのシーケンス(pos = 0 から 5)の実際の値はこうなります。
| token | pos | dim0 (sin) | dim1 (cos) | dim2 (sin) | dim3 (cos) |
|---|---|---|---|---|---|
| 漫画家 | 0 | 0.00 | 1.00 | 0.00 | 1.00 |
| と | 1 | 0.84 | 0.54 | 0.01 | 1.00 |
| 貸本屋 | 2 | 0.91 | -0.42 | 0.02 | 1.00 |
| と | 3 | 0.14 | -0.99 | 0.03 | 1.00 |
| 編集者 | 4 | -0.76 | -0.65 | 0.04 | 1.00 |
| 。 | 5 | -0.96 | 0.28 | 0.05 | 1.00 |
注: 位置はゼロ始まり(
pos = 0, 1, 2, ...)です。pos = 0ではsin(0) = 0およびcos(0) = 1です。
d_model = 4 では、次元 0–1 が sin(pos) と cos(pos)、次元 2–3 が sin(pos/100) と cos(pos/100) です。そのため、後ろの2列はずっとゆっくり変化します。
ここから読み取れることは:
- すべての値が
[-1, 1]の範囲に収まっています。sin と cos の自然な範囲です。長い位置でも値が爆発しません。 - この例と実用的なコンテキスト範囲では、位置ごとに区別可能な指紋が得られます。
- パターンは滑らかに変化します。近い位置どうしは数値的にも近い値です。
5.3.4 なぜ sin と cos なのか
論文の著者が sin/cos を選んだ理由は3つあります。
-
値が有界: 常に
[-1, 1]の中にあります。pos = 10,000でも値は爆発しません。 -
式は外挿できる: 訓練長を超えてもエンコーディング自体は計算できます。訓練済みモデルが未知の位置をうまく使えるかは別問題です。
-
固定オフセットの線形関係: 固定した
kに対し、PE(pos + k)はkだけで決まる回転によってPE(pos)から得られます。原論文は、これが固定された相対オフセットの学習を容易にすると仮説を立てました。
式が無限に続くことと、訓練済みモデルが無限の長さで機能することは同じではありません。RoPE や ALiBi は相対位置や距離バイアスを Attention により直接入れますが、使えるコンテキストは訓練長、スケーリング、モデル設定に依存します。第25章で比較します。
5.4 埋め込み + 位置 = 入力
ここで、足し合わせのステップ全体を見てみましょう。
5.4.1 ベクトルの加算
3つの行列、いずれも形は [seq_len, d_model] です。
埋め込み行列(意味内容):
漫画家: [0.62, -0.51, 0.09, 0.85]
と: [0.15, 0.73, -0.38, 0.46]
貸本屋: [0.07, 0.31, -0.44, 0.12]
...
位置行列(位置):
pos 0: [0.00, 1.00, 0.00, 1.00]
pos 1: [0.84, 0.54, 0.01, 1.00]
pos 2: [0.91, -0.42, 0.02, 1.00]
...
入力埋め込み(両者の和):
漫画家 (pos 0): [0.62+0.00, -0.51+1.00, 0.09+0.00, 0.85+1.00]
と (pos 1): [0.15+0.84, 0.73+0.54, -0.38+0.01, 0.46+1.00]
...
肝心なのはこの観察です。二つの「と」は同じ埋め込みから始まりますが、位置ベクトルが異なるので合算した入力も異なります。Attention は内容と順序を組み合わせ、「漫画家が貸本屋を訪ねた」と「貸本屋が漫画家を訪ねた」を別の並びとして扱えます。
このおもちゃ例では、足し算を見やすくするため直接
Embedding + Positionとしています。オリジナル Transformer は、加算前にトークン埋め込みをsqrt(d_model)倍します:Input = sqrt(d_model) × Embedding + PE。現代のアーキテクチャでは細部が異なることがあります。
5.4.2 幾何学的な直感
2次元のスケッチでは、ベクトルの加算は平行四辺形の法則に従います。
embedding vector = [1, 3] (青い矢印: 意味の方向)
position vector = [2, 1] (赤い矢印: 位置によるシフト)
input vector = [3, 4] (結果: 平行四辺形の対角線)
得られたベクトルは、向きと大きさの中に両方の情報を符号化して持ちます。768次元や4096次元の世界では、この合成表現が破綻せずにいられる余地ははるかに大きくなります。
5.4.3 相対距離が効いてくる
多くのタスクで、モデルは絶対位置だけでなく相対距離を気にします。「ねじ」が「式」のすぐ前に来ているかどうかは大事な情報です。Sinusoidal の方式はその構造の一部を数学的に保ち、学習型の位置方式は経験的に保ちます。第25章で各アプローチの詳細を扱います。
位置だけでトークンの意味が決まるわけではありません。位置は Attention に順序と近傍を読めるようにし、その結果として曖昧さを解く手がかりになります。「ひく」という語を考えてみましょう。
- 「胡弓をひく」では、楽器を演奏する意味です。
- 「辞書をひく」では、辞書で言葉を調べる意味です。
トークンも出発点の埋め込みも同じです。位置信号によって Attention は周囲の単語がどう並んでいるかを読めます。名詞と動詞を分けるのは、位置そのものではなく、その後に作られる文脈付き隠れ状態です。
これこそが、標準アーキテクチャで Positional Encoding が重要な理由です。内容埋め込みだけには住所がないため、順序に依存する関係には別の信号が必要です。
5.5 訓練: 何が学習され、何が学習されないか
5.5.1 固定エンコーディング 対 学習可能パラメータ
オリジナルの Transformer には重要な非対称性があります。
-
埋め込み行列: 学習可能なパラメータです。勾配がルックアップを通って流れ、トークンベクトルを更新します。有用な幾何構造が現れることはありますが、意味的に関連するすべてのトークンが必ず最近傍になるというルールはありません。
-
位置行列(Sinusoidal 版): 決定的で固定です。式から計算またはキャッシュできますが、オプティマイザのパラメータではなく、パラメータ更新を受けません。
訓練中、モデルはベクトルに埋め込まれた位置信号をどう解釈するかは学びますが、信号そのものは変えません。
BERT を含む一部のモデルでは、学習型の位置埋め込みを使います。位置行列がトークン埋め込みテーブルと同様にパラメータとなり、勾配降下で更新されます。トレードオフとして、学習型の埋め込みは訓練時の文脈長を超えるとうまく一般化しないことが多く、Sinusoidal の方は原理的には外挿できる、という違いがあります。
5.5.2 アーキテクチャ内のどこにいるか
モデル全体の流れは次のようになります。
raw text
|
| tokenization
v
token IDs
|
| embedding lookup
v
embedding matrix [seq_len, d_model]
|
| + positional encoding [seq_len, d_model]
v
input embeddings [seq_len, d_model]
|
| feed into Transformer blocks
v
...
本章の加算式 Sinusoidal Encoding では、位置信号を最初の Transformer ブロックの前に加えます。RoPE 系のモデルは異なり、入力に位置ベクトルを加える代わりに、Attention 内部で Q と K を回転させます。
5.6 なぜ連結ではなく加算なのか
この質問は、私がこの章を教えるたびに必ず出てきます。直感を言葉にしておく価値があります。
5.6.1 連結 vs. 加算
連結 (Concatenation):
- 埋め込みベクトルの後ろに位置ベクトルをつなげる。
- 両方を
d_model幅のまま保つなら、結果の[embedding | position]は2 × d_model幅になる。 - 情報の分離がきれいに保たれる。
- 欠点: 後段の層がより広い行列と計算を扱うか、追加の射影で
d_modelへ圧縮する必要がある。
加算 (Addition):
- 埋め込みと位置を要素ごとに足す。
- 結果: 同じ形
[d_model]── 次元は変わらない。 - 欠点: 2つの信号が同じ次元に混ざる。
5.6.2 なぜ加算で機能するのか
有用な直感は、高次元空間は驚くほど広い、というものです。768次元や4096次元では、後段の学習された射影が、混ざった内容と位置信号を一緒に解釈できます。部分的に分離した方向が形成されることはありますが、直交性は加算自体が保証するものではありません。
ホワイトボードを2人のエンジニアが各自持つのではなく、共有していると考えてみてください。ぐちゃぐちゃに聞こえますが、ボードが十分に大きく、人が整理整頓されていれば、問題なく機能します。しかも2枚目のホワイトボードのコストを節約できます。
経験的にも、加算はうまく動きます。アーキテクチャはよりシンプルで、パラメータ数も増えません。良い工学的トレードオフです。
5.7 章のまとめ
5.7.1 重要な概念
| 概念 | 意味 |
|---|---|
| Positional Encoding | 各トークン埋め込みに加算される、シーケンス内の位置を符号化したベクトル |
| Sinusoidal Encoding | 複数周波数の sin/cos 波を使って位置ベクトルを生成する方式 |
| 加算 | embedding + position = input embedding、形は変わらず、次元数も変化しない |
| 固定 vs. 学習型 | Sinusoidal は固定。一部のモデル(BERT など)は学習型の位置パラメータを使う |
| 相対位置 | モデルは絶対インデックスだけでなく、距離の解釈を学べる |
5.7.2 データの流れ
Embedding [seq_len, d_model] <- 意味内容
+
Position [seq_len, d_model] <- sinusoidal 位置エンコーディング
=
Input [seq_len, d_model] <- 最初の Transformer ブロックへ供給
5.7.3 中心となる学び
Positional Encoding は、トークン埋め込みに欠けている住所を補います。順序信号を注入することで、Attention は内容、向き、距離を組み合わせ、「漫画家が貸本屋を訪ねた」と「貸本屋が漫画家を訪ねた」を異なる並びとして扱えます。
章のチェックリスト
この章を終えたあと、あなたは次のことができるはずです。
- Transformer がトークンを順次に処理しないからこそ、明示的な位置情報が必要である理由を説明できる。
- Sinusoidal Encoding を「複数周波数の波で作るバーコード」として描写できる。各位置が sin と cos の値の固有の組み合わせを得る、という形で。
- 式
PE(pos, 2i) = sin(pos / 10000^(2i/d_model))を再現し、その中の2つの主要なアイデアを説明できる。 - なぜ連結ではなく加算が使われるのか、そして実用上のトレードオフが何かを説明できる。
- 固定の Sinusoidal エンコーディング(オリジナル Transformer)と、学習型の位置埋め込み(BERT など)を区別できる。
次章でお会いしましょう
Positional Encoding についてはここまでで十分です。「漫画家が貸本屋を訪ねた」と「貸本屋が漫画家を訪ねた」が、同じ語を使っていてもなぜ異なるモデル出力を生むのか ── これを自分の言葉で説明できるなら、この章はあなたの中に染み込んでいます。
Transformer ブロックへの入力はこれで完成です。埋め込みからの意味情報と、Positional Encoding からの位置情報。両方が揃いました。
第6章では、Transformer の内部のいたるところに登場する、小さくて欠かせない数学の道具を2つ紹介します。LayerNorm ── 数値を扱いやすい範囲に保つ仕組み ── と、Softmax ── 生のスコアを確率分布に変える仕組みです。それでは、また次章で。