Level 1概要役割と処理の流れ
何をする機能か
[B, S, D] の各位置のベクトルに、「これは系列の何番目か」という情報を加えます。
形は変わらず、入力も出力も [B, S, D] です。
原典 Transformer では、位置ごとに決まった値を持つ固定のベクトルを作り、 埋め込みベクトルに加算します。
なぜ必要か
Self-Attention は、すべてのトークンどうしの関係を同時に計算します。 その計算式には位置の概念が入っていません。 そのため、位置情報を加えないと次の 2 文はモデルにとって区別できません。
- 共通例文そのもの(
The keys on the table are lost.) keysとtableを入れ替えた文(The table on the keys are lost.)
RNN は前から順に処理するので語順が自然に反映されますが、 Transformer は並列処理のためにその性質を捨てています。捨てた分を明示的に補うのが、この工程です。
全体の中でいつ呼ばれるか
入力埋め込み の直後、最初の Attention 層の直前です。 原典の構成では1回だけ加算され、その後の各層では再度加算しません。
Level 2内部処理Tensor形状・内部ステップ・設計上の意味
前段から受け取るもの
入力埋め込み の出力 hidden_states [B, S, D]。
後段へ渡すもの
同じ形の hidden_states [B, S, D]。
Encoder では マルチヘッド自己注意 へ、
Decoder では マスク付き自己注意 へ渡されます。
例文での処理
共通例文
The keys on the table are lost.
概念上のトークン列(S = 8): [The, keys, on, the, table, are, lost, .]
- The
- keys
- on
- the
- table
- are
- lost
- .
on the table という句を理解するには、on(位置2)→ the(位置3)→ table(位置4)が
連続していることが手がかりになります。位置情報がなければ、この「隣り合っている」という関係を
Attention が捉える足がかりがありません。
位置情報の付加前
the と、別の場所にある the は同じベクトル付加後
原典の方式(Sinusoidal)
位置 、次元 に対して、sin と cos を交互に使った固定値を割り当てます。 学習パラメータを持たないため、学習時に見た系列長より長い入力にもそのまま値を計算できます。
EncoderとDecoderでの違い
方式は同じで、Encoder は [B, S, D]、Decoder は [B, T, D] に対して適用します。
Decoder の推論時は 1 トークンずつ伸びていくため、
その時点の位置に対応する値を使います。
入力と出力
入力
| 項目名 | データの意味 | データ型 | Tensor形状 | 記号の意味 | 具体例 | 次の渡し先 |
|---|---|---|---|---|---|---|
hidden_states | 埋め込み済みのベクトル列(位置情報なし) | float32 Tensor | [B, S, D] | B = バッチサイズ(同時に処理する文の数) / S = 入力系列長(Encoder側のトークン数) / D = モデル内部のベクトル次元(d_model) | [1, 8, 512] | 位置エンコーディングを加算 |
positional_encoding | 位置ごとの固定ベクトル(学習しない) | float32 Tensor | [S, D] | S = 入力系列長(Encoder側のトークン数) / D = モデル内部のベクトル次元(d_model) | [8, 512]。バッチ方向へブロードキャストされる | 加算 |
出力
| 項目名 | データの意味 | データ型 | Tensor形状 | 記号の意味 | 具体例 | 次の渡し先 |
|---|---|---|---|---|---|---|
hidden_states | 位置情報を含むベクトル列 | float32 Tensor | [B, S, D] | B = バッチサイズ(同時に処理する文の数) / S = 入力系列長(Encoder側のトークン数) / D = モデル内部のベクトル次元(d_model) | [1, 8, 512](形は変わらない) | Self-Attention(Encoder)/Masked Self-Attention(Decoder) |
B- バッチサイズ(同時に処理する文の数)
S- 入力系列長(Encoder側のトークン数)
D- モデル内部のベクトル次元(d_model)
このサイトでは Tensor 形状を PyTorch の `batch_first=True` 相当、つまり `[B, S, D]`(バッチ次元が先頭)で統一しています。実装によっては `[S, B, D]` を採用するものもあります。
よくある誤解
Level 3数式・Python数式・疑似実装・計算量・実装差
数式(Sinusoidal Positional Encoding)
位置を 、次元インデックスを ()として、
次元が大きくなるほど波長が長くなるので、 低い次元は細かい位置差を、高い次元は大まかな位置を表します。
この形の利点は、任意のオフセット に対して が の線形変換で書けることです。相対的な位置関係を扱いやすくなります。
Pythonで表したインターフェース
import math
import torch
from torch import Tensor
def build_sinusoidal_encoding(seq_len: int, d_model: int) -> Tensor:
"""原典の sin/cos 位置エンコーディングを作る。
Args:
seq_len: 系列長 S。
d_model: モデル次元 D(偶数を想定)。
Returns:
[S, D] の固定値テーブル。学習パラメータではない。
"""
position = torch.arange(seq_len).unsqueeze(1) # [S, 1]
index = torch.arange(0, d_model, 2) # [D/2]
div_term = torch.exp(-math.log(10000.0) * index / d_model) # [D/2]
encoding = torch.zeros(seq_len, d_model) # [S, D]
encoding[:, 0::2] = torch.sin(position * div_term)
encoding[:, 1::2] = torch.cos(position * div_term)
return encoding
def add_positional_information(hidden_states: Tensor) -> Tensor:
"""[B, S, D] へ位置情報を加え、同じ形状を返す。
Args:
hidden_states: [B, S, D]。Token Embedding の出力。
Returns:
[B, S, D]。位置情報が加算されたベクトル列。
"""
_, seq_len, d_model = hidden_states.shape
encoding = build_sinusoidal_encoding(seq_len, d_model) # [S, D]
# [S, D] は [B, S, D] へブロードキャストされる
return hidden_states + encoding.to(hidden_states.device)
# 最小使用例
hidden_states = torch.zeros(1, 8, 512) # [B=1, S=8, D=512]
out = add_positional_information(hidden_states)
print(out.shape) # torch.Size([1, 8, 512]) == [B, S, D]
print(torch.equal(out[0, 0], out[0, 3])) # False(位置0と位置3で値が異なる)この例で単純化している点
- キャッシュや最大長の事前計算を省き、毎回計算しています。
- Dropout(原典では加算後に適用)を省略しています。
- RoPE や Learned Position Embedding は含めていません(下の「派生」を参照)。
型と Tensor 形状の見え方を掴むための擬似実装です。そのまま学習・推論に使えるものではありません。
計算量
テーブル作成が 、加算が です。 Attention の に比べて小さく、実行時間にはほとんど影響しません。
派生:現代のLLMで使われる方式
| 方式 | 概要 | 主な採用例 |
|---|---|---|
| Sinusoidal(原典) | sin/cos の固定値を入口で加算 | 原典 Transformer |
| Learned Position Embedding | 位置ごとのベクトルを学習する。最大長を超えられない | BERT、GPT-2 |
| RoPE (Rotary Position Embedding) | Query と Key を位置に応じて回転させる。各層の Attention 内部で適用 | Llama、Qwen など多数 |
| ALiBi | Attention スコアに距離に比例したバイアスを加える | BLOOM など |
RoPE や ALiBi は相対位置を直接扱えるため、 学習時より長い系列への外挿がしやすいという利点があります。 現在の Decoder-only LLM では RoPE が主流です。