一文でまとめると: ニューラルネットワーク層とは、行列の掛け算と非線形性によってベクトルを変換する、学習された関数のことです。Transformer を理解するためには、それを「形を変えるブラックボックス」として扱うだけでも十分にやっていけます。
7.1 ニューラルネットワークの専門家になる必要はありません
先に率直に言わせてください。Transformer を理解するために、ニューラルネットワークを深く理解する必要はありません。
各 Transformer ブロックの内部にある Feed Forward Network (FFN) はニューラルネットワーク層の一種です。しかし、アーキテクチャ上の役割はとてもシンプルです。ベクトルを受け取り、それを変換して、同じサイズのベクトルを返す。Transformer 全体の動作を理解するという目的では、FFN を「形がわかっている学習済み関数」として扱えば十分です。
最低限知っておくべきことは次の3つだけです。
- どのような形のベクトルが入るのか。
- どのような形のベクトルが出てくるのか。
- 学習可能なパラメータがどこに住んでいるのか。
もう少し深い絵が見たい方のために、本章ではその先まで踏み込みます。ただし目標はあくまで「使えるメンタルモデル」を提供することであり、皆さんを誤差逆伝播の専門家に仕立てることではありません。
7.2 生物学的なたとえ話 (とその限界)
7.2.1 生物のニューラルネットワーク
大まかな数量で見ると、成人の脳には次のような規模の構造があります。
- 約860億個のニューロン: 丸い比喩ではなく、実験から得られた推定値
- 10¹⁴ 個ほどのシナプス: 約100兆の接続。ただし推定には大きな幅がある
ニューロンは上流のニューロンから電気信号を受け取り、入力の合計があるしきい値を超えると「発火」して下流に信号を送ります。
7.2.2 人工ニューラルネットワーク
人工ニューラルネットワークは、語彙だけ生物学から借りてきていますが、生物学そのものを写し取っているわけではありません。
- ノード: ニューロンに相当
- 重み: シナプスの強さに相当
- 活性化関数: 重み付き結果に非線形変換を加える。必ずしも硬いしきい値ではない
ここで重要な但し書きがあります。人工ニューラルネットワークはあくまで数学的なモデルであり、脳のシミュレーションではありません。名前と大まかな比喩を借りているだけで、実際の計算は「行列の掛け算 + 非線形関数」です。
「ニューラル」という言葉に引きずられて神秘的に感じる必要はありません。これは少しひねりを加えた線形代数なのです。
7.3 ニューラルネットワークが学習することの正体
7.3.1 自動的な特徴の発見
ニューラルネットワークの面白い性質は、特徴の規則を一つひとつ手書きしなくても、有用な表現を学べるところにあります。
古典的なデモンストレーションは、MNIST の数字分類器です。各画像は 28×28 ピクセル、つまり 784 次元です。隠れ表現を t-SNE や UMAP などで 2 次元へ射影すると、同じクラスの例が近くに現れることがあります。ただし正確な地図はモデル、レイヤー、射影方法で変わり、この図は特定の実行結果ではなく概念図です。
分類器のラベルは、どの画像が「3」かをもちろん教えます。人間が手で書かないのは、「この画素の並びなら必ず3」という規則です。ネットワークは訓練信号から、区別に役立つ表現を学びます。
7.3.2 言語にも同じことが起きる
同じ原理は言語にも当てはまります。十分なテキストで訓練すれば、
- どの単語同士が共起しやすいかを学習します。
- 分布パターンから文法構造を学習します。
- 「エージェント」と「レビュアー」が似たような構文上の位置を占めることを学習します。
訓練後の内部表現には、意味や構文の構造が現れることがあります。ただし「この2つの語句は常に近い」という固定規則ではありません。表現は文脈、レイヤー、モデルによって変わります。
7.4 ニューラルネットワークの基本構造
7.4.1 3つのレイヤー
教科書でよく使う図は、3つの部分から成ります。
- 入力層: 生のデータを受け取ります。本書の文脈ではトークンのベクトルです。
- 隠れ層: 中間の変換を行います。
- 出力層: 結果を返します。
「隠れ」というのは、入力でも出力でもなく、計算の途中で外から直接観測しない、という意味にすぎません。隠れ層のないネットワークも、多数あるネットワークもあり、隠れ変換と出力変換のどちらにも学習可能な重みを持てます。
7.4.2 具体的な特徴量で考える例
入力ベクトルが商品リスティングを表しているとしましょう。隠れ層は、たとえば次のような内部特徴を学ぶかもしれません。
- 防水性
- 保温性
- 重さ
そこから出力層が、雨具や冬物といったカテゴリを予測できます。
ネットワークが学ぶのは次の2点です。
- 各特徴量を作るために、どの入力次元を組み合わせるか。
- どの特徴量の組み合わせが、どのラベルを予測するか。
中間特徴量を人間が手作業で設計したわけではありません。訓練データ上の予測誤差を最小化する過程で、ネットワーク自身が発見したのです。
7.5 数学的な核: 行列の掛け算
7.5.1 1つの全結合層 = 1つのアフィン変換
1つの全結合層 (dense layer) の核となる計算は、次の式で書けます。
y = xW + b
ここで、
xは入力ベクトル。Wは重み行列。これが学習可能なパラメータです。bはバイアスベクトル。これも学習可能です。yは出力ベクトル。
行ベクトル表記で、入力も出力も 2 次元の例を見てみましょう。
input vector × weight matrix = output vector
[0.54, 0.84] × [w₁ w₃] + [b₁, b₂] = [0.91, 0.90]
[w₂ w₄]
形は [1, 2] @ [2, 2] = [1, 2] です。出力の i 番目は、入力と W の i 列目との内積になります。列ベクトル表記も使えますが、その場合は W @ x の順です。[2,1] @ [2,2] は計算できません。
7.5.2 複数レイヤー
レイヤーを重ねると、次のようになります。
layer 1 -> layer 2 -> layer 3 -> layer 4
学習される矢印はアフィン変換で、隠れ層の間には非線形性が入ります。「ディープラーニング」は、こうした多層ニューラルネットワークを学習する方法全般を指し、行列積だけの別名ではありません。
図の中でノード同士をつなぐ線は重みを表しています。1本1本の線が、重み行列のひとつの要素です。レイヤーが増える = 行列が増える = 学習可能なパラメータが増える、ということになります。
7.5.3 これがパラメータ数の話につながる
「GPT-3 は1750億パラメータ」というとき、そのパラメータの大半は、ここで見たような重み行列の中の数値です。どこかに別途用意された知識ベースに格納されているわけではありません。各レイヤーの W の学習済みの値そのものです。
7.6 活性化関数: 非線形性という材料
7.6.1 なぜ非線形性が必要なのか
線形なレイヤーだけを重ねるとどうなるでしょうか。
y₂ = (x W₁) W₂ = x (W₁ W₂) = x W₃
複数の行列の掛け算は、結局1つの行列の掛け算にまとまってしまいます。何枚レイヤーを積もうと、全体としては1枚のレイヤーと同じことしかできません。これでは複雑なパターンを表現できないのです。
そこで活性化関数をレイヤーの間に挟み、非線形性を持ち込むことで、この「つぶれ」を防ぎます。
7.6.2 ReLU
最もシンプルでよく使われている活性化関数が ReLU (Rectified Linear Unit) です。
ReLU(x) = max(0, x)
正の値はそのまま通し、負の値は 0 にします。
import torch
import torch.nn as nn
x = torch.tensor([-2.0, -1.0, 0.0, 1.0, 2.0])
print(nn.functional.relu(x)) # tensor([0., 0., 0., 1., 2.])
7.6.3 GELU と SwiGLU
最近の LLM では、ゲート付き FFN を含む別の選択肢が使われます。
- GELU (Gaussian Error Linear Unit): GPT-2、BERT などで採用されています。0 付近で ReLU より滑らかです。
- SwiGLU: Llama をはじめ後の多くのモデルで使われるゲート付き方式。1つの射影を、SiLU を通した別の射影でゲートし、3つ目の射影で
d_modelへ戻します。
アーキテクチャを理解するために、これらを暗記する必要はありません。重要なのは、FFN が射影の間に非線形性を入れることです。モデル内のすべての Linear の直後に活性化関数があるわけではありません。
7.7 PyTorch での実装
7.7.1 シンプルなネットワーク
import torch.nn as nn
model = nn.Sequential(
nn.Linear(2, 3), # 入力層: 2次元 → 3次元
nn.ReLU(), # 活性化関数
nn.Linear(3, 1), # 出力層: 3次元 → 1次元
)
空行とコメントを含めても 7 行。これで 1 つのフィードフォワードネットワークが完成します。
行ベクトルの概念式では [in_features, out_features] の行列をよく使いますが、PyTorch の nn.Linear(in_features, out_features).weight は [out_features, in_features] で保存されます。前向き計算は x @ weight.T + bias、bias の形は [out_features] です。
7.7.2 次元の変化
データがネットワークを通っていくときの形は、こうなります。
input (1, 2) @ weight (2, 3) = hidden (1, 3) @ weight (3, 1) = output (1, 1)
行列の掛け算のルールは (a, b) @ (b, c) = (a, c)。内側の次元が一致していなければならず、結果の形は外側の次元になります。
次元の変化を追えるようになることが、Transformer のコードを読むうえでのカギです。
7.8 Transformer ブロック内の FFN
7.8.1 拡張してから縮約するパターン
オリジナル Transformer や GPT-2 系の Block では、Feed Forward Network (FFN) はよく次の形を使います。
[d_model] → [4 × d_model] → [d_model]
ベクトルがいったん 4 倍の幅まで拡張され、非線形な活性化関数を通り、ふたたび d_model まで縮約されます。4 倍は古典的な設定であって、普遍的な規則ではありません。
ffn = nn.Sequential(
nn.Linear(d_model, 4 * d_model), # 拡張
nn.GELU(), # 活性化関数
nn.Linear(4 * d_model, d_model), # 縮約
)
これが GPT-2 系モデルにおける標準的な FFN です。Llama 2 は 3 行列の SwiGLU を使い、d_model = 4096 に対して d_ff = 11008 ですが、「拡張してから縮約する」という大筋は変わりません。
7.8.2 ブロック全体の構造
入力
↓
Norm(LayerNorm または RMSNorm)
↓
Masked Multi-Head Attention
↓
残差接続
↓
Norm(LayerNorm または RMSNorm)
↓
Feed Forward Network (FFN) <- これがニューラルネットワーク層
↓
残差接続
↓
出力
Attention は系列内の位置をまたいで情報を混ぜ合わせ、FFN は各位置の表現を独立に処理します。この2つのサブレイヤーは、相補的な役割を担っています。
- Attention が問うのは「系列内の他のトークンのうち、このトークンにとって関係があるのはどれか?」。
- FFN は、その位置の現在の表現に学習済みの非線形変換を加えます。
7.8.3 なぜトークンごとに独立に処理するのか
FFN は同じ変換を各トークン位置に適用し、位置をまたいだ混合は行いません。混合は Attention 側で起きます。役割をはっきり分けておくことで、アーキテクチャはスケールしやすく、改造しやすくなります。
7.9 パラメータはどこに住んでいるのか
7.9.1 学習可能な重み行列の地図
Transformer の中で、パラメータがどこに住んでいるかをまとめると次のようになります。
| コンポーネント | パラメータ数 |
|---|---|
| 埋め込みテーブル | vocab_size × d_model |
| 従来の2行列 FFN (1 Block あたり) | およそ 2 × d_model × d_ff と、使う場合は bias |
| SwiGLU FFN (1 Block あたり) | およそ 3 × d_model × d_ff |
| full MHA の Q, K, V, O (1 Block あたり) | およそ 4 × d_model²。MQA/GQA は K/V が小さい |
| LayerNorm / RMSNorm 1モジュール | scale と bias を持つ LayerNorm は 2 × d_model、RMSNorm は通常 d_model |
| LM Head (最終射影) | d_model × vocab_size。入力 embedding と共有するかはモデル次第 |
7.9.2 現実的なモデルでのパラメータ数
Llama 2 7B (d_model = 4096、d_ff = 11008、32 Block、vocab_size = 32,000) を、重みだけで概算してみましょう。
| コンポーネント | パラメータ数 |
|---|---|
| 埋め込み | 32,000 × 4,096 ≈ 131M |
| FFN 1レイヤーあたり (SwiGLU、行列3つ) | 3 × 4,096 × 11,008 ≈ 135M |
| Attention 1レイヤーあたり | 4 × 4,096² ≈ 67M |
| RMSNorm 1 Block あたり | 2つの scale ベクトル:2 × 4,096 = 8,192 |
| LM Head | 4,096 × 32,000 ≈ 131M。入力 embedding とは別 |
*Llama 2 は gate・up・down の 3 射影を持つ SwiGLU を使います。これらの Linear には bias がありません。
7.9.3 FFN にまつわる意外な事実
「Attention の方がパラメータが多そう」と思っている方は多いはずです。しかしこのモデルでは、FFN は 1 Block あたり約 135M、MHA は約 67M で、ほぼ2倍です。
これが 32 レイヤー積み重なるのですから、パラメータ予算の大半は FFN が占めることになります。
使いやすい直感として、Attention は位置をまたいで情報をルーティング・混合し、FFN は各位置で非線形変換を行う、と考えられます。FFN を key-value memory として捉え、そこで事実の関連を観察・編集した研究もあります。ただし、これは「知識が FFN だけに住む」証明ではありません。Embedding、Attention、FFN、残差ストリームが一緒にモデルの振る舞いを作ります。
7.10 章のまとめ
7.10.1 重要な概念
| 概念 | 意味 |
|---|---|
| 学習されるレイヤー | パラメータ付き変換。活性化が続くかは役割次第 |
| 隠れ層 | 中間の変換レイヤー |
| 活性化関数 | 行列の掛け算のあとに適用される非線形関数 (ReLU、GELU、SwiGLU) |
| FFN | 各 Transformer ブロック内部にあるニューラルネットワーク部分 |
| 拡張してから縮約 | FFN のパターン: d_model → d_ff → d_model。4倍は古典的設定 |
7.10.2 中心となる式
output = activation(input × W₁ + b₁) × W₂ + b₂
PyTorch だとこうなります。
ffn = nn.Sequential(
nn.Linear(d_model, 4 * d_model),
nn.GELU(),
nn.Linear(4 * d_model, d_model),
)
7.10.3 結局、押さえるべきこと
- 形: FFN は
[seq_len, d_model]を受け取り、[seq_len, d_ff]まで拡張し、[seq_len, d_model]まで縮約します。拡張比はモデルごとに違います。 - 位置ごと: FFN は各トークンを独立に処理し、位置をまたいだ混合はしません。
- パラメータ: 多くの dense decoder Block では、FFN 重みは MHA のおよそ2倍です。FFN 幅や MQA/GQA で比率は変わります。
- 役割: Attention は位置間で情報を混ぜ、FFN は各位置を変換して学習された関連に参加します。
Transformer の FFN は、アフィン変換と非線形性の小さなスタックです。入力と出力はどちらも
d_model、中間だけが広い「トークンごとの学習済み関数」と捉えれば、全体を考えるには十分です。
第2部のまとめ
これで 第2部: 中核コンポーネント が終わりました。
| 章 | コンポーネント | 中心的な役割 |
|---|---|---|
| 第4章 | トークナイゼーション + Embedding | テキスト → トークン ID → ベクトル |
| 第5章 | 位置エンコーディング | 各ベクトルに位置情報を付与する |
| 第6章 | LayerNorm + Softmax | 活性化を安定させ、スコアを確率に変換する |
| 第7章 | Feed Forward Network (FFN) | 各 token の表現を独立に変換する |
これでコンポーネントは出そろいました。第3部では、それらを束ねて Transformer の力の源泉となるメカニズム、つまり Attention に踏み込みます。
章のチェックリスト
本章を読み終えたあと、次のことができるようになっていれば合格です。
-
y = xW + bが何を計算しているか、学習可能なパラメータがどこにあるかを説明できる。 - レイヤーの間に活性化関数が必要な理由を説明できる。
- FFN の「拡張してから縮約する」パターンと、その次元変化を記述できる。
- Transformer ブロック内における Attention の役割と FFN の役割の違いを述べられる。
- 明示したアーキテクチャで FFN と Attention のパラメータ数を比較し、知識が1箇所だけに住むとは断定しない。
次の章でお会いしましょう
これでニューラルネットワーク層についてはひと区切りです。これまでに、トークナイゼーション、Embedding、位置エンコーディング、LayerNorm、Softmax、そして FFN という、すべての構成要素が手に入りました。
第8章では、Attention に踏み込む前に、ほんの少しだけ幾何学に寄り道します。具体的に答えるのは、Attention に初めて触れた人がほぼ全員つまずく、こんな問いです。「行列の掛け算は、幾何学的にいったい何をやっているのか?」。この絵さえ手に入れば、Attention の中心にある内積の意味がすっと腑に落ちるはずです。
それでは、また次の章で。お疲れさまでした。