ChatGPTの仕組みから学ぶG検定対策講座④

未来の単語を見せない仕組みとは?マスクとSoftmax

こんにちは。ゆうせいです。

前回は、TransformerのSelf-Attentionで使われるQuery、Key、Valueについて説明しました。

QueryとKeyを比較すると、トークン同士の関係の強さを表すAttention Scoreが得られます。

しかし、文章生成AIでは、Attention Scoreをそのまま使うことはできません。

文章の続きを予測する際に、まだ生成していない未来のトークンが見えてしまうと、正しい学習にならないためです。

そこで、文章生成用のTransformerでは、未来のトークンを参照できないようにするマスクを使用します。

今回は、Transformer Explainerの「Masked Self-Attention」を操作しながら、次の処理を確認します。

  1. QueryとKeyの内積
  2. Attention Scoreのスケーリング
  3. 未来のトークンを隠すマスク
  4. Softmaxによる確率化
  5. Valueの重み付き平均

Masked Self-Attentionを開く

Transformer Explainerを開き、「Transformer Block」の中にある「Multi-Head Self-Attention」までスクロールしてください。

さらに「Attention」を開くと、次の処理が順番に表示されます。

  • QueryとKeyの内積
  • ScalingとMask
  • Softmax
  • Valueとの乗算

Transformer Explainerでは、GPT-2 smallの一つのAttention Headについて、これらの計算を視覚的に確認できます。

ステップ1:QueryとKeyの内積を求める

最初に、各トークンのQueryと、各トークンのKeyを比較します。

比較には内積を使います。

例えば、QueryとKeyが次の3次元ベクトルだったとします。

Query = [1, 2, 1]

Key   = [2, 1, 0]

内積は、同じ位置の数値を掛けてから、すべて足し合わせます。

1 × 2 + 2 × 1 + 1 × 0
= 2 + 2 + 0
= 4

この計算結果が、QueryとKeyの関連度を表す点数になります。

Transformerでは、すべてのQueryとKeyの組み合わせについて内積を計算します。

行列で表すと、次の計算です。

Attention Score = Q × Kの転置

数式では、次のように表します。

QKᵀ

入力が6トークンの場合、QueryとKeyの組み合わせは6×6通りあります。

したがって、Attention Scoreは6行6列の正方行列になります。

Attention Scoreの行と列は何を表すのか

Attention行列では、各行が「現在処理しているトークン」を表し、各列が「参照するトークン」を表します。

例として、次の6個のトークンがあるとします。

  1. Data
  2. visualization
  3. em
  4. powers
  5. users
  6. to

Attention行列は、次のような構造になります。

処理するトークンDatavisualizationempowersusersto
Data関連度関連度関連度関連度関連度関連度
visualization関連度関連度関連度関連度関連度関連度
em関連度関連度関連度関連度関連度関連度
powers関連度関連度関連度関連度関連度関連度
users関連度関連度関連度関連度関連度関連度
to関連度関連度関連度関連度関連度関連度

例えば、「users」の行を見ると、「users」が、それ以前にある各トークンをどの程度重視するかを確認できます。

ステップ2:Attention Scoreをスケーリングする

QueryとKeyの内積は、ベクトルの次元数が大きくなるほど、絶対値も大きくなりやすくなります。

値が大きすぎる状態でSoftmaxを適用すると、確率が一つの候補に極端に集中しやすくなります。

そこで、内積の値を、Keyベクトルの次元数の平方根で割ります。

スケーリング後のAttention Score
= QKᵀ ÷ √dₖ

dₖは、一つのAttention Headで使用するKeyベクトルの次元数です。

GPT-2 smallでは、768次元を12個のAttention Headに分割します。

768 ÷ 12 = 64

したがって、一つのHeadが扱うKeyは64次元です。

√64 = 8

GPT-2 smallの各Headでは、QueryとKeyの内積を8で割ることになります。

この処理は、Softmaxへ入力する値が極端に大きくなるのを抑え、学習を安定させる役割を持ちます。

【G検定対策コラム①:Scaled Dot-Product Attention(スケール化内積注意)】

QueryとKeyの内積をKeyの次元数の平方根(√dₖ)で割る処理を含むAttentionを、Scaled Dot-Product Attention(スケール化内積注意)と呼びます。G検定でも問われる正式名称です。なぜ割るのかというと、本文にあるとおり、次元数が大きいほど内積の絶対値も大きくなりやすく、そのままSoftmaxに入れると確率が一つの候補へ極端に集中し、勾配が小さくなって学習が不安定になるためです。GPT-2 smallでは1Headが64次元なので√64=8で割ります。「なぜ√dで割るのか」は元論文「Attention Is All You Need」由来の頻出ポイントなので、理由とセットで押さえましょう。

なぜ未来のトークンを隠す必要があるのか

文章生成AIは、ここまでに与えられた文章から、次のトークンを予測します。

例えば、次の文章を学習するとします。

私は今日学校へ行きました。

モデルには、次のような予測を学習させます。

入力として見せる部分予測させるトークン
私は今日
私は今日学校
私は今日学校
私は今日学校へ行きました

「学校」を予測するときに、モデルがあらかじめ「学校」を見ていたら、答えを見ながら問題を解いていることになります。

また、「今日」を処理するときに、後ろにある「学校」や「行きました」を参照できてしまうと、本来の次トークン予測にはなりません。

そこで、現在位置より後ろにある未来のトークンを参照できないようにします。

この仕組みをCausal Maskまたは因果マスクと呼びます。Transformer Explainerでは、Attention行列の右上部分にマスクを設定し、未来のトークンを参照できないようにしています。

【G検定対策コラム②:Causal Mask(因果マスク)と自己回帰モデル】

Causal Mask(因果マスク)は、現在位置より後ろにある未来のトークンを参照できないようにする仕組みです。文章生成では「ここまでの文章から次のトークンを予測する」ため、答えにあたる未来のトークンが見えてはいけません。このように直前までの出力を使って次を予測していくモデルを自己回帰モデル(Autoregressive Model)と呼び、G検定の重要用語です。GPTは因果マスクを使う自己回帰型(デコーダ型)、一方BERTは前後両方向を参照するため因果マスクを使わない(エンコーダ型)、という対比が頻出です。GPTが「一方向(左から右)」、BERTが「双方向」と表現される理由がここにあります。

三角形のマスクが作られる

6個のトークンがある場合、それぞれの位置から参照できる範囲は次のようになります。

現在の位置参照できるトークン
1番目1番目だけ
2番目1番目と2番目
3番目1番目から3番目まで
4番目1番目から4番目まで
5番目1番目から5番目まで
6番目1番目から6番目まで

行列で表すと、参照できない部分が右上の三角形になります。

○ × × × × ×
○ ○ × × × ×
○ ○ ○ × × ×
○ ○ ○ ○ × ×
○ ○ ○ ○ ○ ×
○ ○ ○ ○ ○ ○

○は参照できる場所、×は参照できない未来のトークンです。

最初のトークンは、自分自身しか参照できません。

2番目のトークンは、1番目と自分自身を参照できます。

最後のトークンは、すべてのトークンを参照できます。

参照できない場所をマイナス無限大にする

マスクを設定する際は、参照できない場所のAttention Scoreをマイナス無限大に置き換えます。

マスク前

[2.1, 1.4, 3.2, 0.8]


マスク後

[2.1, 1.4, -∞, -∞]

この例では、最初の二つのトークンだけを参照できます。

3番目と4番目は未来のトークンなので、Attention Scoreをマイナス無限大にします。

なぜ0ではなく、マイナス無限大にするのでしょうか。

その理由は、次にSoftmaxを適用するためです。

ステップ3:Softmaxで確率に変換する

Softmaxは、複数の数値を、合計が1になる確率へ変換する関数です。

例えば、次の三つの点数があるとします。

[2, 1, 0]

Softmaxを適用すると、おおよそ次の確率になります。

[0.665, 0.245, 0.090]

合計を計算すると、1になります。

0.665 + 0.245 + 0.090 = 1

元の点数が大きい要素ほど、高い確率になります。

Softmaxでは、それぞれの数値を指数関数へ入力します。

e⁰ = 1

0をSoftmaxへ入力すると、計算途中では1になります。

そのため、参照させたくない場所へ単純に0を設定しても、最終的な確率は0になりません。

一方、マイナス無限大の場合は次のようになります。

e⁻∞ = 0

したがって、マスクされた場所の確率を0にできます。

Softmax([2, 1, -∞])

≒ [0.731, 0.269, 0]

未来のトークンに対応する確率が0になり、情報を取り込まなくなります。

Transformer Explainerでは、マスクされた右上の領域がSoftmax適用後に0になり、各行の確率の合計が1になる様子を確認できます。

【G検定対策コラム③:ソフトマックス関数(Softmax)と指数関数】

Softmaxは、複数の数値を合計が1になる確率分布へ変換する関数で、G検定の機械学習分野で頻出です。本文のポイントは、各値を指数関数(eˣ)に通してから正規化するため、e⁰=1となり「0を入れても確率は0にならない」こと。だからマスクには0ではなくマイナス無限大を使い、e⁻∞=0で確率を0にします。この「マスク=−∞」の理屈は仕組みの理解を問う良問になりやすい部分です。多クラス分類の出力層で使うSoftmaxと、2クラス分類で使うシグモイド関数を対比で覚えておくと万全です。

Softmaxの結果がAttention Weightになる

Softmaxで得られた確率を、Attention Weightと呼びます。

Attention Weightは、各トークンの情報をどの程度取り込むかを表します。

例えば、あるトークンに対して、次のAttention Weightが得られたとします。

参照先のトークンAttention Weight
トークン10.10
トークン20.60
トークン30.30

この場合、トークン2の情報を最も重視します。

トークン1の情報は少しだけ取り込み、トークン3の情報は30%程度の重みで取り込みます。

Attention Weightの合計は1です。

0.10 + 0.60 + 0.30 = 1.00

ステップ4:Attention WeightとValueを掛ける

QueryとKeyは、どのトークンをどの程度重視するかを決めるために使われました。

実際に取り込む情報はValueが持っています。

そこで、Attention Weightと、それぞれのValueを掛け合わせます。

出力
= 0.10 × Value1
+ 0.60 × Value2
+ 0.30 × Value3

この計算をValueの重み付き平均と考えることができます。

Attention Weightが大きいトークンのValueほど、出力へ大きな影響を与えます。

数式では、Scaled Dot-Product Attention全体を次のように表します。

Attention(Q, K, V)
= Softmax(QKᵀ ÷ √dₖ + Mask) × V

処理の流れを分解すると、次のようになります。

  1. QueryとKeyの内積を求める
  2. 次元数の平方根で割る
  3. 未来のトークンへマスクを設定する
  4. SoftmaxでAttention Weightへ変換する
  5. Attention WeightとValueを掛ける

Attentionの出力は、ValueをAttention Weightで重み付けして足し合わせたものです。

【G検定対策コラム④:Attention Weightと重み付き平均】

Softmaxを適用して得られる、合計が1になる確率をAttention Weight(注意の重み)と呼びます。これは各トークンの情報をどれだけ取り込むかを表します。最終的なAttention出力は、このAttention Weightを重みとしてValueを足し合わせた「重み付き平均」です(出力=Σ Attention Weight × Value)。関連度が高いトークンのValueほど出力に強く反映される、という仕組みを本文の「この商品は性能が高い/価格が高い」の例で確認しましょう。同じ「高い」でも、どのトークンのValueを多く取り込むかで文脈依存の表現が変わる点がSelf-Attentionの本質です。

文章の文脈がトークンへ取り込まれる

次の文章を考えてみましょう。

この商品は性能が高い。

「高い」というトークンを処理するとき、「商品」や「性能」といったトークンに高いAttention Weightが付けば、それらのValueが多く取り込まれます。

その結果、「高い」というトークンは、単独の辞書的な意味だけでなく、周囲の文脈を反映した数値表現へ変化します。

別の文章も考えてみましょう。

この商品は価格が高い。

今度は「価格」のValueが強く取り込まれます。

同じ「高い」というトークンでも、Self-Attentionを通過した後の表現は異なります。

Self-Attentionは、周囲のトークンから必要な情報を集め、それぞれのトークンを文脈に応じた表現へ更新する仕組みです。

12個のAttention Headで同じ処理を行う

ここまで説明した処理は、一つのAttention Headで行われます。

GPT-2 smallには12個のAttention Headがあります。

それぞれのHeadが、別々のQ、K、Vを使ってAttentionを計算します。

各Headは、文章中の異なる関係を捉えられます。

  • 近くにあるトークン同士の関係
  • 主語と述語の関係
  • 動詞と目的語の関係
  • 代名詞と名詞の関係
  • 文章全体の意味的な関係

12個のHeadから得られた出力は、最後に連結されます。

Head 1の出力
Head 2の出力
Head 3の出力
……
Head 12の出力
        ↓
すべてを連結
        ↓
線形変換
        ↓
768次元の出力

Transformer Explainerでは、各Headの出力が結合され、線形変換を通してSelf-Attention全体の出力になる流れを確認できます。

マスクは入力文を削除する処理ではない

マスクについて、未来のトークンそのものを文章から削除する処理だと考えてしまうことがあります。

しかし、実際にはトークンを削除しているわけではありません。

Attention Scoreの一部をマイナス無限大にして、そのトークンへ割り当てられるAttention Weightを0にしています。

処理結果
未来のトークンを削除する行わない
未来のトークンとのAttention Scoreを無効化する行う
Softmax後のAttention Weightを0にする行う

学習時にすべての位置をまとめて計算できる

因果マスクを使うことで、Transformerは文章中の複数の位置について、次トークン予測の計算をまとめて実行できます。

例えば、次の文章があるとします。

私は猫が好きです。

学習時には、次の予測を並行して計算できます。

参照できる範囲予測対象
私は
私は猫
私は猫が好き
私は猫が好きです

行列としてまとめて計算しながらも、各位置から未来のトークンは見えないようにできます。

これが、因果マスクを使用する大きな利点の一つです。

【G検定対策コラム⑤:並列計算とTransformerの学習効率】

因果マスクを使うと、1つの文章に対して「私→は」「私は→猫」…といった複数位置の次トークン予測を、行列演算でまとめて並列計算できます。これはRNNが持たなかった大きな利点です。RNNはトークンを1つずつ順番に処理するため並列化が難しく学習に時間がかかりますが、Transformerは系列全体を一度に処理できるため大規模データでの学習に向きます。G検定では「RNNに対するTransformerの優位性」として、①長距離依存を捉えやすい ②並列計算できる、の2点が頻出です。この並列化のしやすさが、大規模言語モデル(LLM)の巨大化を支えた技術的背景であることも押さえておきましょう。

Transformer Explainerで確認するポイント

Transformer ExplainerのMasked Self-Attentionを操作し、次の点を確認してください。

  1. QueryとKeyの内積から正方形のAttention行列が作られる
  2. Attention ScoreがKeyの次元数の平方根で割られる
  3. 右上の三角形にマスクが設定される
  4. マスクされた値がマイナス無限大になる
  5. Softmax後はマスク部分が0になる
  6. 各行のAttention Weightの合計が1になる
  7. Attention WeightとValueを掛けて出力を作る
  8. トークンへマウスポインターを合わせると、対応する参照関係が強調される

今回のまとめ

  • QueryとKeyの内積によってAttention Scoreを求める
  • 入力が6トークンなら、Attention Scoreは6行6列になる
  • 内積はKeyの次元数の平方根で割ってスケーリングする
  • GPT-2 smallの1 Headは64次元なので、内積を8で割る
  • 文章生成では、未来のトークンを参照できないように因果マスクを使う
  • 参照できない場所のAttention Scoreをマイナス無限大にする
  • Softmaxによって、各行の合計が1になるAttention Weightへ変換する
  • マスクされた場所のAttention Weightは0になる
  • Attention WeightとValueを掛けて、必要な情報を取り込む
  • 複数のAttention Headの出力を連結し、最終的なSelf-Attentionの出力を作る

次回は、Self-Attentionの後に置かれているMLPについて解説します。

Transformer Explainerを操作しながら、768次元を3072次元へ拡張する理由、GELU活性化関数、残差接続の役割を見ていきます。

投稿者プロフィール

山崎講師
山崎講師代表取締役
セイ・コンサルティング・グループ株式会社代表取締役。
岐阜県出身。
海外放浪の末、2000年創業、2004年会社設立。
IT企業向け人材育成研修歴業界歴20年以上。
すべての無駄を省いた費用対効果の高い「筋肉質」な研修を提供します!
この記事に間違い等ありましたらぜひお知らせください。

学生時代は趣味と実益を兼ねてリゾートバイトにいそしむ。長野県白馬村に始まり、志賀高原でのスキーインストラクター、沖縄石垣島、北海道トマム。高じてオーストラリアのゴールドコーストでツアーガイドなど。現在は野菜作りにはまっている。