# Program Name: transformer_positional_encoding_full_demo.py
# Creation Date: 20251111
# Overview: Full explanation + visualization of Transformer sinusoidal positional encoding.
# Usage: Run on Jupyter/Colab to print theory and plot results.
!pip install numpy matplotlib
import numpy as np
import matplotlib.pyplot as plt
#──────────────────────────────
# 1. 理論説明(print関数で詳細出力)
#──────────────────────────────
print("""
──────────────────────────────
Transformerの位置エンコーディング(Positional Encoding)
──────────────────────────────
【背景】
TransformerはRNNやCNNと異なり、「系列順序」を内部的に持たない。
すべてのトークンを並列で処理するため、順序情報を外部から付与する必要がある。
そのため、各単語埋め込みE(token)に「位置エンコーディングPE(pos)」を加算する:
Input = E(token) + PE(pos)
このPEは、位置ごとに異なるsin波・cos波を組み合わせて表現される。
──────────────────────────────
【定義式】
PE(pos, 2i) = sin(pos / 10000^(2i / d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i / d_model))
ここで:
pos : トークン位置(0, 1, 2, ...)
d_model : 埋め込み次元数
i : 次元インデックス
→ 各次元は異なる周波数のsin, cosを担当する。
──────────────────────────────
【直感的意味】
・低次元:ゆっくり変化(長周期)
・高次元:高速に振動(短周期)
これにより、すべての位置がユニークな波の組み合わせで表現される。
例:
pos=0 → sin,cosともに1周期の基点
pos=1 → 各次元でわずかに位相シフト
pos=10 → 高周波成分が目立つ
──────────────────────────────
【設計意図】
1. 位置pと位置p+kの差が線形変換として表現可能
→ 相対位置を自然に学習できる
2. 学習不要・任意長に一般化可能
→ RNNのように順次処理しなくても順序を理解
3. 周期構造は「時間」「回転」「位相」を表す
→ 三角関数=周期の言語
──────────────────────────────
""")
#──────────────────────────────
# 2. Positional Encoding 関数定義
#──────────────────────────────
def positional_encoding(max_len=200, d_model=64):
pe = np.zeros((max_len, d_model))
position = np.arange(0, max_len)[:, np.newaxis]
div_term = np.exp(np.arange(0, d_model, 2) * (-np.log(10000.0) / d_model))
pe[:, 0::2] = np.sin(position * div_term)
pe[:, 1::2] = np.cos(position * div_term)
return pe
#──────────────────────────────
# 3. データ生成
#──────────────────────────────
max_len = 200
d_model = 64
pe = positional_encoding(max_len, d_model)
print(f"Positional Encoding Matrix Shape: {pe.shape}")
print("例: 位置0と位置1のベクトル差(位相変化):")
print(pe[1] - pe[0])
#──────────────────────────────
# 4. カラーマップで可視化(全体構造)
#──────────────────────────────
plt.figure(figsize=(10, 6))
plt.imshow(pe, aspect='auto', cmap='plasma')
plt.title("Transformer Positional Encoding (sin+cos pattern)")
plt.xlabel("Embedding Dimension")
plt.ylabel("Token Position")
plt.colorbar(label="Encoding Value")
plt.tight_layout()
plt.show()
print("""
──────────────────────────────
【図1:全体構造】
縦軸:位置(トークン順序)
横軸:埋め込み次元
色:符号化値(sin, cos)
→ 縦方向の縞模様は「周波数の違い」を示す。
低次元は長周期、高次元は短周期。
これにより全ての位置が固有のベクトルで表される。
──────────────────────────────
""")
#──────────────────────────────
# 5. 各次元の波形をプロット(低周波~高周波)
#──────────────────────────────
plt.figure(figsize=(9, 5))
for i in range(0, 12, 2):
plt.plot(pe[:, i], label=f"dim {i}")
plt.title("Sine Wave Components (various frequencies)")
plt.xlabel("Position (token index)")
plt.ylabel("Value")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
print("""
──────────────────────────────
【図2:波形解析】
低次元(dim 0,2,4):緩やかな波 → 長期依存表現
高次元(dim 10+) :細かい波 → 局所変化検出
sin, cosの直交性により、各次元は「異なる角度の基底ベクトル」として機能。
これはフーリエ基底と同様に、信号の周期・位相情報を圧縮的に保持する。
──────────────────────────────
""")
#──────────────────────────────
# 6. 特定位置のベクトル構造を棒グラフ表示
#──────────────────────────────
plt.figure(figsize=(9, 4))
plt.bar(np.arange(d_model), pe[10], color='steelblue')
plt.title("Positional Encoding Vector at pos=10")
plt.xlabel("Dimension index")
plt.ylabel("Encoding value")
plt.tight_layout()
plt.show()
print("""
──────────────────────────────
【図3:pos=10のベクトル形状】
横軸:埋め込み次元
縦軸:sin, cos値
→ 各次元が異なる周波数で振動していることが分かる。
Transformerはこのベクトルを単語埋め込みに加えることで、
系列の「位置信号」を識別できる。
──────────────────────────────
""")
#──────────────────────────────
# 7. まとめ
#──────────────────────────────
print("""
──────────────────────────────
まとめ
──────────────────────────────
・位置エンコーディングは「sin」「cos」で系列順序を符号化。
・各次元は異なる周波数=フーリエ的座標系。
・順序情報を持たないSelf-Attentionに、時間的位相を与える。
・相対位置の差は線形変換として表現でき、学習に有利。
・AIの中では「時間を波で表す数学的言語」として機能する。
応用分野:
- 自然言語処理(文中位置の認識)
- 音声・時系列分析
- 画像(Vision Transformer:パッチ位置)
──────────────────────────────
""")
このスクリプトは、print()で理論→式→直感→応用を段階的に解説し、
matplotlibで3種類の図(全体構造・波形・ベクトル形状)を可視化する。
教育・教材・AI講義用の完全版構成。