0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

マルチモーダルLLMの個人メモ①Postional Encoding

0
Posted at

はじめに

この記事はAIで作成されています。multi-modal LLM関連のメモを記載しています。

目次

Positonal Encoding

Transformer の Self-Attention は、トークンの順序をそのままでは捉えられないため、位置情報を与える仕組みが必要になる。代表的な方式には、次の3つがある。

方式 位置情報の扱い 学習可能な位置パラメータ 特徴
①Sinusoidal Positional Encoding 位置ベクトルをトークン埋め込みに加算 なし 固定された sin / cos の数式で位置を表現する
②Relative Position Encoding 相対距離に応じた情報を Attention に組み込む あり(代表的な方式) トークン同士の距離や前後関係を直接扱う
③RoPE Query と Key を位置に応じて回転 なし Attention の内積に相対位置の情報を反映する

現在の主流

近年の大規模言語モデル(LLM)では、RoPE が広く採用されている代表的な方式である。例えば、Llama 系列などで使われている。

ただし、すべてのモデルが RoPE を採用しているわけではない。学習済みの絶対位置埋め込みや、RoPE 以外の位置情報の扱いを採用するモデルもある。

①Sinusoidal Positional Encoding

論文名: Attention Is All You Need
URL: https://arxiv.org/abs/1706.03762
発表日: 2017-06-12

✅ ポイント

  • Transformer の Self-Attention には、トークンの順序を直接表す仕組みがないため、位置情報をトークン埋め込みに加算する。
  • 位置情報には、異なる周波数の sin 関数と cos 関数を使用する。各位置が異なるベクトルで表現される。
  • 位置情報は学習可能なパラメータではなく、固定された数式で計算する。学習時も推論時も同じ方法で生成できる。

🧪 学習の疑似コード

# トークン埋め込みと位置情報を準備
initialize(token_embedding, transformer)

while not converged:
    token_ids, targets = sample_from_dataset()

    # トークンの意味をベクトル化
    X = token_embedding(token_ids)

    # 各位置の位置エンコーディングを計算
    PE = sinusoidal_encoding(sequence_length, d_model)

    # トークン埋め込みに位置情報を加算
    X = X + PE

    # Transformer で予測
    predictions = transformer(X)

    # 損失を計算してモデルを更新
    loss = compute_loss(predictions, targets)
    update(loss)

位置エンコーディング自体は学習せず、トークン埋め込みや Transformer のパラメータを学習する。

🔎 推論時の疑似コード

token_ids = input_sequence()

# トークン埋め込みを取得
X = token_embedding(token_ids)

# 入力系列の位置情報を計算
PE = sinusoidal_encoding(sequence_length, d_model)

# 位置情報を加算して Transformer に入力
X = X + PE
output = transformer(X)

🧮 位置エンコーディングの計算式

位置 pos と次元 i に対して、次の式で位置情報を計算する。

$$
PE(pos, 2i) = \sin\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)
$$

$$
PE(pos, 2i+1) = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)
$$

偶数次元には sin、奇数次元には cos を使用する。次元ごとに周波数が異なるため、位置ごとに異なるパターンのベクトルが生成される。

❓ よくある質問

Q. なぜ sin と cos を使うの?

  • 周波数の異なる波を組み合わせることで、各位置を異なるベクトルで表現できる。
  • sin と cos の組み合わせには、位置のずれを相対的な変化として扱いやすいという性質もある。

Q. 位置エンコーディングも学習するの?

  • 学習しない。位置と次元から数式で計算する固定値である。
  • 一方、トークン埋め込みや Transformer の重みは通常どおり学習する。

Q. なぜトークン埋め込みに加算するの?

  • トークンの意味情報と位置情報を同じ次元のベクトルにまとめ、Transformer に入力するため。
  • これにより、Self-Attention がトークンの内容と位置の両方を利用できるようになる。

Q. 学習時より長い系列にも対応できるの?

  • 固定された数式から位置情報を計算するため、学習時に使っていない位置についても生成できる。
  • ただし、学習時より長い系列で十分な性能が得られるとは限らない。

Q. Relative Position Encoding との違いは?

  • Sinusoidal Positional Encoding は、各トークンの絶対位置を表すベクトルを入力埋め込みに加算する。
  • Relative Position Encoding は、トークン同士の相対位置を Attention のスコア計算や出力の集約に直接組み込む。

②Relative Position Encoding

論文名: Self-Attention with Relative Position Representations
URL: https://arxiv.org/abs/1803.02155
発表日: 2018-03-06

✅ ポイント

  • Sinusoidal Positional Encoding ではトークンの絶対位置を使うが、Relative Position Encoding ではトークン同士の相対距離を使う。
  • 相対位置ごとに学習可能なベクトルを用意し、Attention のスコア計算と出力の集約に組み込む。
  • 相対距離が一定の範囲を超えた場合は同じ距離として扱い、学習するパラメータ数を抑える。

🧪 学習の疑似コード

# 相対位置ごとの学習可能なベクトルを初期化
initialize(relative_key, relative_value)

while not converged:
    x, targets = sample_from_dataset()

    # Query / Key / Value を計算
    Q, K, V = compute_qkv(x)

    # トークン間の相対距離を計算
    relative_positions = clip(
        positions_j - positions_i,
        -max_distance,
        max_distance
    )

    # 相対位置に対応する学習可能なベクトルを取得
    R_key = relative_key[relative_positions]
    R_value = relative_value[relative_positions]

    # Key に相対位置ベクトルを加えてスコアを計算
    scores = Q @ (K + R_key).T / sqrt(d_k)
    attention = softmax(scores)

    # Value にも別の相対位置ベクトルを加えて出力を集約
    output = attention @ (V + R_value)

    # 損失を計算してモデル全体を更新
    loss = compute_loss(output, targets)
    update(loss)

🔎 推論時の疑似コード

x = input_sample()

Q, K, V = compute_qkv(x)

# トークン間の相対距離を計算
relative_positions = clip(
    positions_j - positions_i,
    -max_distance,
    max_distance
)

# 相対位置に対応する学習済みベクトルを取得
R_key = relative_key[relative_positions]
R_value = relative_value[relative_positions]

# Key に相対位置ベクトルを加えてスコアを計算
scores = Q @ (K + R_key).T / sqrt(d_k)
attention = softmax(scores)

# Value にも相対位置ベクトルを加えて出力を集約
output = attention @ (V + R_value)

relative_key と relative_value は別々の学習可能なパラメータであり、相対位置に応じたベクトルをそれぞれ Key と Value に加える。学習時には誤差逆伝播によって更新し、推論時には学習済みの値を使用する。

❓ よくある質問

Q. なぜ絶対位置ではなく相対位置を使うの?

  • Attention では、トークン同士の距離や前後関係が重要になるため。
  • 相対位置を直接組み込むことで、「1つ前のトークン」や「3つ後ろのトークン」といった関係を利用できる。

Q. 相対位置ベクトルは Key と Value の両方に必要なの?

  • 論文では、Key 側で Attention のスコア計算に相対位置を反映し、Value 側でも出力の集約に相対位置を反映する。
  • ただし、相対位置を組み込む方法はモデルの設計によって異なる。

Q. なぜ相対距離をクリップするの?

  • 距離ごとに異なるベクトルを用意すると、必要なパラメータ数が増えるため。
  • 一定以上の距離をまとめることでパラメータ数を抑えられるが、遠い位置同士の距離の違いは区別できなくなる。

Q. Sinusoidal Positional Encoding との違いは?

  • Sinusoidal Positional Encoding は、絶対位置を表すベクトルをトークン埋め込みに加算する。
  • Relative Position Encoding は、トークン同士の相対位置を Attention のスコア計算や出力の集約に直接組み込む。

③RoPE(Rotary Position Embedding)

論文名: RoFormer: Enhanced Transformer with Rotary Position Embedding
URL: https://arxiv.org/abs/2104.09864
発表日: 2021-04-20

✅ ポイント

  • Sinusoidal Positional Encoding は位置情報をトークン埋め込みに加算するが、RoPE は Query と Key のベクトルを位置に応じて回転させる。
  • 回転角度はトークンの位置と次元ごとの周波数によって決まる。Attention の内積に、トークン同士の相対位置の情報が自然に反映される。
  • 位置情報を固定された数式で計算するため、位置エンコーディング自体の学習は不要。ただし、学習時より長い系列での性能が保証されるわけではない。

🧪 学習の疑似コード

# RoPE の回転角度を計算するための周波数を準備
initialize_frequencies()

while not converged:
    token_ids, targets = sample_from_dataset()

    # トークン埋め込みから Query / Key / Value を計算
    X = token_embedding(token_ids)
    Q, K, V = compute_qkv(X)

    # 各トークンの位置に応じて Query と Key を回転
    Q_rot = apply_rope(Q, positions)
    K_rot = apply_rope(K, positions)

    # 回転後の Query と Key で Attention を計算
    scores = Q_rot @ K_rot.T / sqrt(d_k)
    attention = softmax(scores)

    # Value を重み付きで集約
    output = attention @ V

    # 損失を計算してモデルを更新
    loss = compute_loss(output, targets)
    update(loss)

RoPE 自体は学習可能なパラメータを持たず、位置に応じた回転を計算する。学習対象となるのは、主にトークン埋め込みや Query / Key / Value の射影などのモデルパラメータである。

🔎 推論時の疑似コード

token_ids = input_sequence()

# トークン埋め込みから Query / Key / Value を計算
X = token_embedding(token_ids)
Q, K, V = compute_qkv(X)

# 位置に応じて Query と Key を回転
Q_rot = apply_rope(Q, positions)
K_rot = apply_rope(K, positions)

# Attention を計算
scores = Q_rot @ K_rot.T / sqrt(d_k)
attention = softmax(scores)

# Value を集約
output = attention @ V

🧮 回転の計算式

RoPE では、ベクトルの隣り合う2次元を1組として扱い、位置 pos に応じて回転させる。

x'_{2i} = x_{2i}\cos(pos\theta_i) - x_{2i+1}\sin(pos\theta_i)
x'_{2i+1} = x_{2i}\sin(pos\theta_i) + x_{2i+1}\cos(pos\theta_i)

ここで、$x$ は回転前のベクトル、$x'$ は回転後のベクトル、$\theta_i$ は次元ごとに設定される周波数である。

各次元ペアは異なる周波数で回転するため、位置に応じた情報をベクトル全体に反映できる。この回転を Query と Key に適用することで、Attention のスコアに相対位置の情報が反映される。

❓ よくある質問

Q. なぜベクトルを回転させるの?

  • 位置に応じて Query と Key の向きを変えることで、Attention の計算に位置情報を反映するため。
  • 2つの回転後ベクトルの内積には、それぞれの絶対位置だけでなく、トークン同士の相対位置が反映される。

Q. Value にも RoPE を適用するの?

  • 基本的な RoPE では、Query と Key に回転を適用する。
  • Attention のスコア計算を通して位置情報を反映するため、Value には通常、RoPE を適用しない。

Q. Sinusoidal Positional Encoding との違いは?

  • Sinusoidal Positional Encoding は、位置を表すベクトルをトークン埋め込みに加算する。
  • RoPE は、Query と Key を位置に応じて回転させ、Attention の内積に相対位置の情報を反映する。

Q. Relative Position Encoding との違いは?

  • Relative Position Encoding は、相対距離ごとの学習可能なベクトルを Attention の計算に加える。
  • RoPE は、位置に応じた回転によって相対位置の情報を反映する。相対距離ごとの学習可能なベクトルを用意する必要がない。

Q. 学習時より長い系列にも対応できるの?

  • 回転角度は位置から計算できるため、学習時に登場しなかった位置にも適用できる。
  • ただし、長い系列での性能が保証されるわけではなく、実際のモデルでは系列長に応じた工夫が必要になる場合がある。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?