GPT-1
o1
https://openai.com/ja-JP/index/learning-to-reason-with-llms/
GPTの層
- Embedding
- Self attension
- Feed foward
- 出力Soft Max
Embeddingについて
入力文章をトークン化する "The cat sat" → [101, 22, 390] 各単語に該当する単語のID(index)に変換される。 次に変換された各数字(単語のid)をEmbedding層が持っている辞書のような行列から対応する行を取り出す
単語にidがあってそのidに単語を分解するというのはわかるが、それを使って対応する行をとりだすというのがわからない。ここでいう行とは何?どんな数値が入っているの? ここの辞書のような行列 = ベクトル = 意味空間?
各ベクトル(例:[ 0.14, -0.22, 0.03, … ])の中の数値は、 「この単語が持つ抽象的な意味の“特徴の強さ”」
学習の過程で、モデルが自動的にこうした潜在的意味の方向を見つけ出します。 だから「catと「dog」は多くの次元で似た値を持ち、「cat」と「car」は異なる値を持つようになるんです。
なるほど、768の次元に単語としての特徴を数値化して入れているわけか。"生き物っぽさ"を表す次元(列)で行がcatやdogであれば1に近くなるみたいな感じかな?なのでさっきもった疑問「次元に入力された数値は何を表している?」という点への答えはその次元に対応する意味っぽさという感じかな?
ぽっさ(特徴)は人間が決めるものではなく、モデルが自動的に見つける
Embedding層とは「単語ID → 意味ベクトル」を対応づけた巨大な表(行列)であり、 各“行”がその単語の意味を数値的に表す“点”になっている。
行列全体が「意味空間」であり、そこに単語たちが位置づけられている。
各単語は次のようなベクトルです: vcat=[v1,v2,...,v768]
そして単語間の意味の近さは、 コサイン類似度(cosine similarity) で計算されます: similarity(cat, dog)=∣∣vcat∣∣∣∣vdog∣∣vcat⋅vdog similarity(cat, dog)=vcat⋅vdog∣∣vcat∣∣ ∣∣vdog∣∣\text{similarity(cat, dog)} = \frac{\mathbf{v}{cat} \cdot \mathbf{v}{dog}}{||\mathbf{v}{cat}|| , ||\mathbf{v}{dog}||}similarity(cat, dog)=∣∣vcat∣∣∣∣vdog∣∣vcat⋅vdog
Embedding空間は「線形代数のベクトル空間」
負の値があることで、GPTは“意味の強さ”だけでなく“意味の方向(反対概念)”まで表現できる。 0は「ない」、負は「逆」を表す。 この“逆方向の表現”こそが、Embeddingを「意味空間」にしている本質です。
gptが入力された単語を辞書から取り出す操作の時に使用する式 xi=Wembed[idi] vector("king")−vector("man")+vector("woman")≈vector("queen") 男 : 王様と女:女王が対応している強い近似を示していると言える式
Embeddingの前はWord2Vecという技術が使われていた。
Word2Vec は、単語をその文脈から意味的に学び、「似た意味の単語を近い場所に配置する」ことで自然言語の意味を数値ベクトルとして表現す手法。 GPTやBERTの“Embedding層”の原点とも言える存在です。
Embedingのまとめ
EmbedingはTransformer層の最初に位置する層で、入力された文字列をトークン化(サブワード単位への分割)され、各トークンがIDに変換された後、IDの配列になり、そのIDを元に意味空間上から事前学習の時に生成された意味空間から意味を取り出す役割を担っている。
意味空間は語彙数 * 768以上の次元からなる表のようなものになっていて、ここでいう次元はその単語の意味っぽさを表している 【次元の例】
- 一次元:生き物っぽさ
- 二次元:動詞っぽさ
- 三次元:概念っぽさ
各次元の数値は負の値から正の値が入力されており、単語の意味を距離で表すことで、各単語の意味を数値として、相対的に扱えるようにしている。ここでの数値の開き際の大きさが意味の方向性となる。
つまり、Embedingは入力された単語の概念の類似性・関係性を捉える役割を担っている。 人間にとって「解釈」があるとおり、TransformerにっとてEmbedding層は「意味理解の入り口」である。このそうによって文字列が数値的に意味を持った信号に変換される。
💡 Embedding層まとめ(AIフィードバック統合版)
Embedding層はTransformerの最初に位置し、入力された文字列をトークン化してトークンIDに変換し、そのIDをもとに「意味空間」から対応するベクトルを取り出す役割を担う。
意味空間は「語彙数 × ベクトル次元(例:768)」の行列として表され、各次元はその単語の意味的特徴(生き物っぽさ・動詞っぽさ・抽象性など)を表している。各値は正負の両方向をとり、その符号と大きさが意味の方向性と強さを示す。距離が近い単語ほど意味的に似ており、これにより言葉の類似性や関係性を数値的に扱うことができる。
Embedding層は人間にとっての「解釈」に近い機能を果たしており、Transformerが“言葉の意味”を理解する最初のステップである。
Positional Encoding
役割。
Transformerが“文章の中での単語の順序”を理解するために存在する仕組み
Self Attentionは全単語の関係を見る役割を担っているが、単語の順番を知らないというのが欠点。
- 犬が人を噛んだ
- 人が犬を噛んだ 上記の文章の意味は全然違う。この意味の相違は、単語の語順で決まっている。単語自体に違いはないからだ。犬、人、噛んだ。この単語に順番を付与するのがpositional encodeing なのでEmbeddingで単語の意味はとりだすことができるが、それはあくまで単語の意味であって、文章の意味でしかないからPositional encodingが必要になる 実際の文章も単語の意味と文法から構成されているように
入力文字列(テキスト) ↓ トークン化(subword単位) ↓ トークンIDの配列 ↓ Embedding層(単語を意味ベクトルに変換) ↓ Positional Encoding(位置情報を足し込む) ←★ここ! ↓ Self-Attention層(単語間の関係を学習) ↓ Feed Forward層(文脈を非線形変換) ↓ Softmax(次の単語を出力)
PE(pos,2i)=sin(100002i/dmodelpos) PE(pos,2i+1)=cos(pos100002i/dmodel)PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{\text{model}}}}\right)PE(pos,2i+1)=cos(100002i/dmodelpos)
Positional Encodingでsin・cosを使うのは、 位置を“波のズレ(位相差)”として表現することで、 単語同士の距離や順序を、どんな長さの文でも安定して扱えるようにするためです。
なぜ単語の順番ではなく位置を教えるのか? 単語の順番だ気を教えてしまうとその順番の数が大きくなればなるほど重要な単語と解釈ししまう。
https://www.nomuyu.com/positional-encoding/ この記事がわかりやすかった。
順番に加算して順番の情報を渡してしまうとベクトルの大きさが変わってしまう。位置のベクトルは意味のベクトルと足し合わせて、self attentionの時に使用されるので、位置のベクトルが大きくなりすぎるとEmbeddingの時に得た意味を失ってしまうつまり、Suisoidal Positional Encodingに必要なのは順番に関わらず大きさが変わらないことである。されど、順番が変化しても、付与するベクトルが変わらないのは意味がない。入力するシーケンス長がどれだけ伸びても発散せずに、しかし値は絶えず変化するようなもの。。というわけで、周期関数であるsinやcosに白羽の矢が立つわけである。 sinを使うことでその値を-1から1の間に制限できる。 しかし、周期関数なので定期的に同じ値が返されてしまう。 そこで、文章量が多くなっても同じ値が繰り返されないほど低い周波数を与えたらいい感じなのではないだろうか? だが、周波数を低くしたことによる弊害が発生する。それは勾配が小さいところでは低周波ゆえに順番が変わってもほとんど数値が変化しない区間があるということである。 そこでcosを組み合わせるのである。
Self Attention
入力文の中で、各単語が“他のどの単語に注目すべきか”を自動で学ぶ仕組みです。
(=文の中の「関係性」「依存関係」を数値的に表す方法)
Self-Attentionは、「意味」と「順番」が与えられた単語たちの関係性を分析する層です。
Embedding+Positional Encodingの出力から作られたQ(Query), K(Key), V(Value)のみいつのベクトルを使って計算する
- Query : 注目する側
- Key:注目される側
- Value:実際に情報を運ぶ側
Step 1. 単語をベクトルに変換 各単語は Embedding → Positional Encoding を経て、 ベクトル(例:3次元に簡略化)になります: |単語|ベクトル(意味+位置)| |---|---| |The|[0.2, 0.5, 0.1]| |cat|[0.9, 0.1, 0.3]| |sat|[0.4, 0.7, 0.8]|
Step 2. Q, K, V を作る 各単語ベクトルにそれぞれ別の重み行列を掛けて、
Query(Q), Key(K), Value(V)を生成します。 Q=XWQ,K=XWK,V=XWVQ = XW_Q,\quad K = XW_K,\quad V = XW_VQ=XWQ,K=XWK,V=XWV (Wは学習によって決まるパラメータ行列) こうすることで、
「この単語がどの単語に注目するか」「注目されるか」を表現できるようになります。 Step 3. QとKで「関連度(Attention重み)」を計算 「cat」が他の単語にどれだけ注目するかを計算するとき:
- “cat”の Q(Query) と
- “The”, “cat”, “sat” それぞれの K(Key)
の内積を取ります。 AttentionScore=Qcat⋅Kother\text{AttentionScore} = Q_{cat} \cdot K_{other}AttentionScore=Qcat⋅Kother → 値が大きいほど、「関係が強い」「注目すべき」と判断されます。
意味ベクトルと位置ベクトルを足し合わせる。 意味ベクトルはEmbeddingの時に作られたもので、位置ベクトルはPosition Encodingの時に作られたもの。
Self-Attentionとは、各単語が文全体の中で“自分にとって重要な単語”を選び、
その情報を取り込んで意味を再構築する仕組み。
Transformerが「全体を見渡して理解できる」理由はここにあります。
Self Attentionは文中の単語同士の依存関係を計算すること どうやって?Positional EncodingとEmbeddingで得た位置ベクトルと意味ベクトルを足し合わせて、それと学習時に獲得している重みW_Q, W_K, W_Vをつかって計算する なぜ?
Q・K・Vは、各単語の「意味+位置」ベクトルに対して
学習された行列を掛けて作られる3つの特徴空間であり、
Transformerが「どの単語がどの単語に注目すべきか」を
自動的に学ぶための基礎的な変換です。
Attentionの一般式は:Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)VAttention(Q,K,V)=softmax(dkQKT)V
soft maxとは?
softmax は “値を確率のように正規化する関数” です 入力された複数の数値の「相対的な大きさ」をもとに、全体で 1 になるように重みを割り当てます。 softmax(xi)=∑jexjexi
Attentionのスコア算出 たとえば「cat」が注目している時:
Q_cat · K_The = 0.3Q_cat · K_cat = 0.1Q_cat · K_sat = 1.6Q_cat · K_on = 0.4Q_cat · K_the = 0.2Q_cat · K_mat = 0.1→ この「数値(スコア)」は、どの単語とどれくらい意味的に関連が強いかを表す。SoftMaxの役割 上記で算出したスコアをそのまま使うと、単位や範囲がバラバラなので比較しにくい そこでsoftmaxを使って、「相対的な重み(確率的な注目度)」に変換する |単語|スコア|softmax後(重み)| |---|---|---| |The|0.3|0.10| |cat|0.1|0.05| |sat|1.6|0.70| |on|0.4|0.10| |the|0.2|0.03| |mat|0.1|0.02|
Self Attentionのまとめ
Self-Attentionは入力文中の各単語がどの単語に注目すべきかという依存関係を計算する仕組みで、Embeddingから得た意味ベクトルとPositional Encodingから得た位置ベクトルを足し合わせたものに学習時に習得した重み(W_Q, W_K, W_V)を使用してQ, K, Vを算出し、それを使ってどの単語に注目すべきかを計算します。 この計算の利点として以下のような点が挙げられる
- 文脈の理解:全単語を一度に見て依存関係を学ぶことができる
- 並列処理することができる:全単語を同時に処理することが可能に
- 長距離依存:遠く離れた単語同士も簡単に紐づけることができる
- 柔軟な関連:主語-動詞や形容詞-名詞など多様な関係を自動で学習することができる 計算の結果以下のような表が完成して入力した文章中の単語がそれぞれどのように関連するのか数値の対応表が作られる
|i\j|The|cat|sat|on|the|mat| |---|---|---|---|---|---|---| |The|0.1|0.2|0.1|0.05|0.1|0.05| |cat|0.1|0.1|0.7|0.05|0.03|0.02| |sat|0.05|0.8|0.1|0.05|0.02|0.03| |on|0.1|0.05|0.05|0.1|0.4|0.3| |...|...|...|...|...|...|...| 各行は1つの単語が「他の単語にどれだけ注目しているか」を示し、
各行の合計は 1 になる(確率分布になっている)。 📘補足例: たとえば「cat」の行の合計は1になるようにSoftmax正規化され、
0.7(sat)という値は「catがsatに最も注目している」確率的重みを意味する。Attention行列を使って、各単語のValue(V)ベクトルを加重平均することで、各単語が「文全体の文脈を反映した新しいベクトル(文脈表現)」に変換される。
- Q(Query):探す側(どんな情報を求めているか)
- K(Key):持っている側(自分がどんな特徴を持っているか)
- V(Value):実際の情報本体
Self-Attention は、同じ文(系列)の中で「自分自身の他の単語」に注意を向ける仕組みである。
つまり、外部の文(例:翻訳先など)ではなく「自分の文脈内」で関係を学習する。実際のTransformerでは、Self-Attentionを複数並列(Multi-Head Attention)で行い、 各ヘッドが異なる「関係の視点(意味的・構文的など)」を学習する。
Self-Attentionのまとめ(改訂)
Self-Attentionは、入力文中の各単語が他のどの単語に注目すべきかという
依存関係を自動で学習する仕組みである。
Embeddingから得た意味ベクトルとPositional Encodingによる位置ベクトルを加算し、
学習済みの重み行列(W_Q, W_K, W_V)を掛けてQ, K, Vを算出する。
- Q(Query):どんな情報を探しているか
- K(Key):自分がどんな情報を持っているか
- V(Value):実際に保持している情報
これらを使って各単語同士の関連度を計算し、
Softmaxで正規化することで「どの単語をどれだけ重視するか」を確率的に決定する。
この結果、各単語が他の単語の情報を加重平均した新しい文脈ベクトルを得る。
主な利点
- 文脈理解:全単語を一度に見て依存関係を学べる
- 並列処理:全単語を同時に処理可能
- 長距離依存:遠い単語同士の関係も容易に捉えられる
- 柔軟な関連:主語–動詞・形容詞–名詞など多様な関係を自動学習
Attentionスコア行列(Softmax後の例)
| i\j | The | cat | sat | on | the | mat | | ------- | ---- | ------- | ------- | ---- | ---- | ------- | | The | 0.1 | 0.2 | 0.1 | 0.05 | 0.1 | 0.05 | | cat | 0.1 | 0.1 | 0.7 | 0.05 | 0.03 | 0.02 | | sat | 0.05 | 0.8 | 0.1 | 0.05 | 0.02 | 0.03 | | on | 0.1 | 0.05 | 0.05 | 0.1 | 0.4 | 0.3 |
各行は1つの単語が他の単語にどれだけ注意を向けているかを示し、
行の合計は1(確率分布)となる。 実際のTransformerでは、このSelf-Attentionを複数の「ヘッド」に分けて
異なる視点で文脈を捉える Multi-Head Attention を構成している。
Feed Forward Network(FFN)
これは Transformer ブロックの後半にあたる部分で、Attentionが得た「文脈情報」を整理・変換して次の層に渡す役割を担っています。
Self-Attention → FFN
は「関係性の理解」→「意味の再構成」という流れ。
🧠 直感的にいうと…
- Self-Attention は「単語と単語の関係」を見て 文脈 を理解します。
- しかし、その出力は「どこと関係があるか」の情報に特化しています。
- Feed Forward はそれを使って「最終的にどんな意味を持つ単語か」を再構成します。 つまり:
Attention:この単語は誰と関係がある?
Feed Forward:関係を踏まえて、私は最終的にどんな意味になる?🧩 なぜ “Feed Forward” と呼ぶのか?
「前向き(順伝播)」に情報を流すネットワークだから。
つまり、RNNのようなループ構造はなく、単純に入力 → 出力へ流すだけ。💬 一文でまとめると:
Feed Forward Network(FFN) は、Self-Attentionが捉えた「文中の関係情報」をもとに、各単語ごとの「意味・特徴表現」を再構成する層。
各単語を独立に処理し、非線形変換によってモデルの表現力を高める。
疑問
「前向き(順伝播)」に情報を流すネットワークとは? b1とかb2のバイアス項も学習によって獲得したもの? ReLU 非線形変換関数とは?ReLUを訳さず書くとどうなるかも気になる
また、各単語の位置ごとに独立して計算します。
(ここがSelf-Attentionと大きく違う!)
という箇所もうまく理解できないので開設して欲しいです
- 「前向き(順伝播)」に情報を流すネットワークとは?
- ニューラルネットワークの基本的な仕組みのこと
- 機械学習・ニューラルネットワークの基本構造は「入力→計算→出力」の一方向の流れになっている
- この流れを 順伝播(Forward Propagation) という。情報が前に(出力方向)進むから Feed Forward(前に流す)
- 構造:入力 → 重み行列 → 非線形変換 → 出力
- 目的:Attentionの出力を整理・再構成して次の層へ渡す
- 特徴:各単語を独立に処理・並列計算が可能
- 順伝播の逆で逆伝播(Back Propagation)もある
- 出力から入力に受かって重みを更新する
- 順伝播で出力された結果を評価して、その評価の結果をモデルに反映させるのが逆伝播
- どうやってfeed forwardはattentionからの出力を整理、再構成している?
- 前提
- Self Attentionの出力は「文全体を見渡した各単語の文脈ベクトル」
- 各単語はすでに他の単語の情報を混ぜている
- でもその混ぜ方は関係の強さに基づいているだけ
- また情報として混ざっているだけで、意味として整理されていない
- 疑問:なぜ各単語の情報がまざっているのに意味として整理されていない状態と言えるの?
- 回答:関係性はわかるがどのような関係かがわかっていない
- 例:catとsatが関係していることはわかる。しかしそれが、主語と動詞の関係なのか、形容詞と名詞の関係なのかがわからない
- FNN(feed forward)
- 以下の方法で意味の再構成を行う
- 線形変換:特徴を拡張(768次元 → 3072次元)
- 疑問:なぜ次元を拡張するのか
- 回答:関係は数値になっているが、具体的な関係はわからない(主語と動詞 / 名詞と形容詞)から次元を拡張して表現の幅を広げる
- ReLU(非線形変換):重要な特徴を強調、不要な特徴を0に
- どんな情報を残すか選別する
- 線形変換:次元をもとに戻す(3072次元→768次元)
- 抽象化された情報を整理して出力するため
- 線形変換:特徴を拡張(768次元 → 3072次元)
- 次元の数は固定
- 各次元が何を表すのかは学習によって自動で変わる
- 人間の直感では「1軸=動物っぽさ」「2軸=感情っぽさ」などと1次元=1意味と考えたくなりますが、実際は違います。
- 1つの次元が「1つの意味」を持っているわけではない
- 各次元は「多数の意味の混合」
- 意味は「方向(ベクトルの組み合わせ)」として現れる
- 1つの次元が「猫っぽさ」だけを表すわけではない
- 100次元目が少し「動物の文脈」+「名詞的」+「ポジティブな文」などいくつもの要素が混ざっています。
- 768個の値が作る全体のベクトル(方向) が「意味」を表します。
- ベクトル間の距離と角度(方向の違い)が、意味の違いを表します。
- 「位置(点)」ではなく「方向(ベクトル)」が意味を持つ
- 意味空間は、言語全体をマッピングした巨大な地図のようなものです
- GPTにおいては各次元が「人間が理解できる特徴量(=意味)」ではない
- GPTなどの言語モデルにおける「次元」は、一種の「抽象的な特徴量」と考えられる
- ただしそれは、人間が理解できるような“意味を持つ特徴”ではなく、モデルが文脈を表すために自動で形成した多次元の表現軸
- 一般的な意味においては次元=特徴料と言ってもいい
- ReLUの働き
- 正の値(意味的に重要な特徴) → 残す
- 負の値(不要または無関係な特徴) → 0に潰す
- 以下の方法で意味の再構成を行う
- 前提
残差接続(Residual Connection)
残差接続は、層の出力に「元の入力」を足し戻す仕組みです。 たとえば:
-
Self-Attention の出力に、元の入力ベクトルを足す
-
Feed Forward の出力にも、同じように元の入力を足す
-
なぜ必要?
- 勾配消失を防ぐ
- 深いネットワークでは、勾配が途中でちいさくなって伝わらなくなる問題があります。入力を足しておくことで、「元の情報の流れ」が残り、勾配が下層まで届きやすくなります。
- 情報の破壊を防ぐ
- 新しい層で情報を変換しすぎたことによって元の意味から乖離してしまうことを防ぐ
- 微調整がしやすい構造
- 出力を「入力 + 少しの修正」として扱えるため、モデルが既存の知識を保持しつつ細部だけ調整するように学習できる
- 勾配消失を防ぐ
-
例
- 「犬が吠えている」という文章があった時に
- すでにモデルが犬=動物であると学習している場合「吠える」という要素を足すために、元の犬という単語に「吠える」という要素を足す
- 式:出力 = 元の意味(dog) + 文脈での変化(吠える)
正規化(Layer Normalization)
- Layer Normalization(LayerNorm)は、 各単語ベクトルの中の値のばらつきを整える仕組み
- なんで必要?
- 学習の安定化
- AttentionやFeedForwardの出力は値のスケールがバラバラになる
- そのまま次の層に送ると学習が安定的に
- LayerNormで「平均0、分散1」に整えて安定化させる
- 情報のスケールを揃える
- -10, 0.3, 8, -5, 2 などバラバラ
- -0.9, 0.1, 0.8, -0.5, 0.5 のように整う
- 情報のスケールを揃える
- Self Attentionでは多くのベクトルが混ざり合うため
- 各単語のベクトルのスケールが揃っていることが重要
- AttentionやFeedForwardの出力は値のスケールがバラバラになる
- 勾配爆発・消失を防ぐ
- 層が深くなるほど、値の大小が暴れやすくなるため、LayerNormがブレーキの役割を果たします。
- 学習の安定化
発火タイミング
Transformerでは、各サブレイヤー(Attention・FFN)の後に必ず👇を実行する。
x = x + Sublayer(x) # 残差接続
x = LayerNorm(x) # 正規化
この二つを実行することで、いかが両立する
- 情報を壊さずに強化(Residual)
- スケールを整えて安定化(LayerNorm)