第4章 位置エンコーディング:語順の情報を加える
こんにちは。ゆうせいです。
第3章では、トークンIDが768次元の埋め込みベクトルに変換されることを確認しました。ここで、重大な問題が残っています。埋め込みだけでは、単語がどの順番で並んでいたかという情報が、完全に失われてしまうのです。「犬が猫を追いかけた」と「猫が犬を追いかけた」は、含まれるトークンがまったく同じであるため、埋め込みの集まりとしては区別できません。しかし、この二つの文は、意味が正反対です。第4章では、この失われた語順の情報を、どのようにしてベクトルに埋め込むのかを解説します。Transformer Explainerで埋め込みの表示を見たとき、実は二種類のベクトルが足し合わされていることに気づいたでしょうか。その、もう一つのベクトルがこの章の主題です。
なぜ語順の情報が失われるのか
まず、問題の構造を正確に把握します。
第3章までの処理を振り返ると、各トークンは、独立に埋め込みベクトルへ変換されました。「犬」というトークンは、文のどこにあっても同じベクトルになります。
そして、第5章以降で扱う自己注意という仕組みは、すべてのトークンを同時に、並列に処理します。この並列処理こそが、Transformerが高速に学習できる理由なのですが、同時に、順序という概念を持たない原因にもなっています。
RNNとの対比で理解する
Transformerの前に主流だったRNN(再帰型ニューラルネットワーク)は、トークンを一つずつ、順番に処理していました。
1番目のトークンを処理し、その結果を持ったまま2番目のトークンを処理し、さらにその結果を持ったまま3番目を処理する、という流れです。
この構造では、順序の情報が、処理の順番そのものに自然に含まれています。位置情報を別途与える必要がありません。
一方で、この逐次処理には欠点がありました。1番目の処理が終わらなければ2番目に進めないため、並列化ができず、学習に時間がかかるのです。
Transformerは、この逐次処理をやめることで、大幅な高速化を実現しました。しかし、その代償として、順序の情報を失いました。そこで、順序の情報を明示的に与える仕組みが必要になったのです。
これが、位置エンコーディング(Positional Encoding)です。
位置エンコーディングの基本的な考え方
位置エンコーディングの発想は、単純です。
各位置(1番目、2番目、3番目…)に対して、その位置を表すベクトルを用意します。そして、そのベクトルを、トークンの埋め込みベクトルに足し合わせます。
足し算という点が、初学者にとって意外に感じられる部分かもしれません。位置の情報と意味の情報を、別々の場所に置くのではなく、同じ768次元のベクトルの中に、重ね合わせて格納するのです。
なぜ連結ではなく加算なのか
「意味のベクトル768次元と、位置のベクトル768次元を、横につなげて1536次元にすればよいのではないか」と考える人もいます。これを連結(concatenation)と呼びます。
連結にしない理由は、主に二つあります。
一つ目は、次元数が増えると、以降のすべての計算量が増えるためです。1536次元にすれば、パラメータ数も計算量も、おおよそ倍増します。
二つ目は、加算でも十分に機能することが、実験的に確認されているためです。768次元という空間は十分に広く、意味の情報と位置の情報を、干渉を抑えながら重ね合わせて表現できます。
イメージとしては、音の重ね合わせに近いものです。二つの音を同時に鳴らしても、人間の耳は、そこに含まれる二つの音を聞き分けられます。ベクトルの加算も、これに似た性質を持っています。
GPT-2が採用している方式:学習される位置埋め込み
位置エンコーディングには、大きく二つの方式があります。GPT-2が採用しているのは、後者です。
方式1:固定的な位置エンコーディング(sin/cos方式)
Transformerを最初に提案した論文では、三角関数を使った固定的な位置エンコーディングが使われていました。
posは位置、iは次元のインデックス、dは埋め込み次元です。
この式は複雑に見えますが、やっていることは、位置ごとに異なる周期の波を組み合わせて、固有のパターンを作ることです。
次元によって波の周期が異なるように設計されており、低い次元では波長が短く(位置がわずかに変わっても値が大きく変わる)、高い次元では波長が長く(広い範囲の位置の違いを表す)なっています。これにより、近い位置は似たベクトル、遠い位置は異なるベクトルという性質が実現されます。
この方式の利点は、学習が不要であり、学習時に見たことのない長さの系列にも、そのまま対応できる点です。
方式2:学習される位置埋め込み(GPT-2の方式)
GPT-2では、より単純な方式が採られています。
位置ごとの埋め込みベクトルを、トークン埋め込みと同じように、学習によって獲得するのです。
具体的には、位置埋め込み行列を用意します。
行数:1024(扱える最大の位置の数)
列数:768(埋め込み次元)
1番目の位置には1行目のベクトル、2番目の位置には2行目のベクトル、という具合に割り当てます。この行列の中身は、ランダムな初期値から始まり、学習の過程で最適な値へと調整されていきます。
第3章で扱ったトークン埋め込み行列と、まったく同じ仕組みです。違いは、参照するインデックスが、トークンIDではなく位置番号である、という点だけです。
パラメータ数を確認する
位置埋め込み行列のパラメータ数を計算します。
約78万6千個です。トークン埋め込み行列の約3860万個と比べると、はるかに小さい値です。位置の種類は1024通りしかないため、語彙数50257通りと比べて、必要な行数が少なくて済むのです。
1024という数字の意味
位置埋め込み行列の行数が1024である、という点は、実務上、重要な意味を持ちます。
これは、GPT-2が一度に扱えるトークン数の上限が1024であることを意味しています。この上限を、コンテキスト長、または最大系列長と呼びます。
1025番目の位置に対応するベクトルは、行列に存在しません。したがって、1024トークンを超える入力は、そのままでは処理できないのです。
実務への影響
第2章で、日本語は英語よりトークン数が多くなりやすいと説明しました。この二つを合わせると、次のことが分かります。
1024トークンという上限は、英語であれば、おおよそ700から800単語程度に相当します。日本語では、これよりかなり短い文章量しか扱えません。
長い文書を要約したい、長い会話履歴を保持したいといった用途では、この制約が直接の障害になります。
近年のモデルでは、このコンテキスト長を大幅に拡張する工夫が行われています。学習される位置埋め込みではなく、より柔軟な方式(RoPE、回転位置埋め込みなど)が採用されているモデルも多くあります。
GPT-2の方式は、実装が単純で理解しやすい一方、拡張性に制約があるという特徴を持っている、と押さえておいてください。
Transformer Explainerで観察できること
Transformer Explainerの埋め込みの部分では、トークン埋め込みと位置埋め込みが、それぞれ表示され、それらが足し合わされる様子が可視化されています。
次の点を確認してみてください。
一つ目は、同じ単語を文章の異なる位置に2回入れたとき、トークン埋め込みは同じでも、位置埋め込みが異なるため、足し合わせた結果は異なるベクトルになるという点です。
第3章の最後で、同じ単語は同じ埋め込みになると説明しました。位置エンコーディングを加えることで、初めて、同じ単語でも位置によって異なる表現になります。
二つ目は、位置埋め込みの値の大きさです。トークン埋め込みと比べて、極端に大きくも小さくもない、同程度のスケールになっていることが分かります。
もし位置埋め込みの値が極端に大きければ、意味の情報が位置の情報にかき消されてしまいます。逆に極端に小さければ、位置の情報がほとんど効かなくなります。学習を通じて、両者のバランスが取れた値に調整されているのです。
初学者がつまずきやすい点
つまずき1:位置エンコーディングだけで語順が完全に扱えると考える
位置エンコーディングは、あくまで「このトークンは何番目にある」という情報を付与するだけです。
「AがBより前にある」という相対的な関係を、モデルが直接受け取るわけではありません。その関係は、自己注意の計算を通じて、モデルが間接的に学習します。
この点は、後の章で扱う相対位置エンコーディングという発展的な手法の動機にもつながります。
つまずき2:加算によって情報が混ざって壊れないのかという疑問
「意味のベクトルに位置のベクトルを足したら、意味が変わってしまうのではないか」という疑問は、非常に自然なものです。
答えとしては、変わります。ただし、モデル全体が、この足し合わされた状態を前提として学習されているため、問題にならないのです。
モデルは、足し算される前の純粋な意味ベクトルを見たことがありません。最初から、意味と位置が重ね合わされたベクトルを入力として学習しています。したがって、モデルにとっては、この重ね合わされた状態こそが「正常な入力」なのです。
つまずき3:sin/cos方式が現在も主流だと思い込む
多くの入門記事では、最初のTransformer論文にならって、三角関数による位置エンコーディングが説明されます。数式が印象的であるため、記憶に残りやすいのですが、実際のモデルでは、別の方式が使われていることが多くあります。
GPT-2は学習される位置埋め込みを使い、より新しい多くのモデルはRoPEなどを使っています。学習した知識が、目の前のモデルにそのまま当てはまるとは限らない、という点に注意してください。
演習
演習1:位置埋め込みのパラメータ数を計算する
次の条件のモデルについて、位置埋め込み行列のパラメータ数を計算してください。
最大系列長が4096、埋め込み次元が4096のモデル。
また、この値は、GPT-2の位置埋め込み行列の何倍になるでしょうか。
演習2:位置埋め込みの効果を確認する
同じ単語が異なる位置にあるとき、最終的な入力ベクトルが異なることを、実際に確認してみてください。
from transformers import GPT2Tokenizer, GPT2Model
import torch
tokenizer = GPT2Tokenizer.from_pretrained("gpt2")
model = GPT2Model.from_pretrained("gpt2")
# 位置埋め込み行列の形を確認
position_matrix = model.wpe.weight
print(f"位置埋め込み行列の形: {position_matrix.shape}")
# 位置0と位置1のベクトルを比較
pos0 = position_matrix[0]
pos1 = position_matrix[1]
pos500 = position_matrix[500]
cos = torch.nn.CosineSimilarity(dim=0)
print(f"位置0と位置1の類似度: {cos(pos0, pos1):.4f}")
print(f"位置0と位置500の類似度: {cos(pos0, pos500):.4f}")
# 同じ単語が異なる位置にある場合の入力ベクトルを比較
token_id = tokenizer.encode(" cat")[0]
token_vec = model.wte.weight[token_id]
input_at_pos0 = token_vec + position_matrix[0]
input_at_pos5 = token_vec + position_matrix[5]
print(f"\n同じ単語 cat の、位置0と位置5での入力ベクトルの類似度: {cos(input_at_pos0, input_at_pos5):.4f}")
演習の解答例と解説
演習1の解答は、次の通りです。
約1678万個です。GPT-2の位置埋め込み行列が約78万6千個ですから、およそ21.3倍になります。
この計算から、コンテキスト長を伸ばすには、位置埋め込み行列を大きくする必要があり、パラメータ数がその分だけ増えることが分かります。学習される位置埋め込み方式のコストが、ここに現れています。
演習2では、位置0と位置1の類似度が、位置0と位置500の類似度より高くなる傾向が期待されます。近い位置どうしのベクトルが似ているという性質が、学習によって獲得されているかを確認してみてください。
また、同じ単語であっても、位置が異なれば入力ベクトルが完全には一致しないことが確認できます。ただし、類似度は依然として高い値になるはずです。これは、位置の違いによる変化が、単語の意味を完全に上書きしてしまわない程度に抑えられていることを示しています。
講師向けの補足
この章で最も効果的な導入は、「犬が猫を追いかけた」と「猫が犬を追いかけた」の対比です。
受講者に、まず「この二つの文は、トークンの集合として見ると同じである」という点を確認させてください。そのうえで、「では、モデルはどうやって区別しているのか」と問いかけると、位置情報の必要性が、自然な疑問として立ち上がります。
三角関数の式を示す際は、式そのものの導出には深入りしないことを推奨します。「次元によって異なる周期の波を重ねることで、位置ごとに固有のパターンを作っている」という直感的な説明で十分です。数式の詳細に時間をかけると、より重要な「なぜ位置情報が必要か」という論点が薄れます。
理解度を確認する問い
第4章の内容を、次の問いで確認してみてください。
Transformerで位置エンコーディングが必要になる理由を、RNNとの構造の違いを踏まえて説明してみてください。
位置の情報を、連結ではなく加算によって埋め込みに組み込む理由は何でしょうか。
GPT-2の位置埋め込み行列の行数が1024であることは、実務上どのような制約を生むでしょうか。
まとめ
位置エンコーディングとは、埋め込みだけでは失われる単語の並び順の情報を、ベクトルとして加える仕組みです。
Transformerは、すべてのトークンを並列に処理するため、順序の情報を構造的に持ちません。RNNのように逐次処理をしないことで高速化を実現した代償として、位置情報を明示的に与える必要が生じました。
位置の情報は、トークン埋め込みに足し合わせる形で組み込まれます。連結ではなく加算とすることで、次元数の増加を避けています。
GPT-2では、三角関数による固定的な方式ではなく、学習によって獲得される位置埋め込みが使われています。行列の大きさは1024行768列であり、この1024という行数が、扱えるトークン数の上限を決めています。
位置エンコーディングを加えることで、同じ単語であっても、文中の位置によって異なる入力ベクトルになります。これが、以降の処理の出発点です。
次の第5章から、いよいよTransformerの中核である自己注意の説明に入ります。第5章では、その第一歩として、Query、Key、Valueという三つのベクトルを扱います。同じ入力ベクトルから、なぜ三種類の異なるベクトルを作る必要があるのか、それぞれがどのような役割を持つのかを解説します。
第5章に進む前に、Transformer Explainerで、入力した文章のトークン埋め込みと位置埋め込みが足し合わされる部分の表示を、あらためて確認しておいてください。ここまでで作られたベクトルが、次章以降の処理の入力になります。
セイ・コンサルティング・グループでは新人エンジニア研修のアシスタント講師を募集しています。
投稿者プロフィール

- 代表取締役
-
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
海外放浪の末、2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。
学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。
最新の投稿
新人エンジニア研修講師2026年8月10日第14章 出力層:ロジット、Softmax、そして温度パラメータ
新人エンジニア研修講師2026年8月10日第13章 MLP層とGELU:トークンごとの情報を加工する
新人エンジニア研修講師2026年8月10日第12章 レイヤー正規化:値のばらつきを揃えて学習を安定させる
新人エンジニア研修講師2026年8月10日第11章 残差接続:入力をそのまま足し合わせる仕組み
