論文一覧に戻る 📚 用語集トップ 🗺 概念マップ
📚 用語解説(ジャストインタイム型データサイエンス教育)
ニューラルネットワーク基礎
Neural Networks (Fundamentals)
脳の神経細胞をモデルにした学習機械 — 深層学習の出発点
教師あり学習回帰・分類両用勾配ベース計算機集約

📍 あなたが今見ているもの

本ページは、 ニューラルネットワーク (NN) の基礎概念を統合的に解説します。 パーセプトロンから始まり、 多層パーセプトロン (MLP)活性化関数誤差逆伝播最適化器まで一気通貫で扱います。

近年の深層学習・LLM はすべてここから派生しています。 まずは「線形変換と非線形活性化を交互に重ねる」という基本構造を、 数式と Python で押さえます。

🔖 🔖 キーワード索引(チップから該当箇所へジャンプ)

論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:

パーセプトロン ニューロン MLP 順伝播 活性化関数 Sigmoid tanh ReLU Softmax 損失関数 誤差逆伝播 連鎖律 勾配降下法 SGD モーメンタム Adam 重み初期化 勾配消失

💡 30秒で分かる結論

📚 章構成

内容
1. パーセプトロンNN の最小単位
2. 多層化(MLP)隠れ層を持つ NN
3. 活性化関数非線形性の源
4. 損失関数予測の良し悪しの尺度
5. 誤差逆伝播勾配の計算
6. 最適化器SGD・Adam 等
7. 初期化と正規化学習の安定化
8. 学習ループPyTorch 実装例

🧠 1. パーセプトロン

1.1 1個のニューロン

入力 $\mathbf{x} = (x_1, \dots, x_p)^\top$、 重み $\mathbf{w}$、 バイアス $b$、 活性化 $\phi$ に対し:

$$z = \mathbf{w}^\top \mathbf{x} + b, \qquad a = \phi(z)$$

記号読み:$z$ は「ゼット」プリアクティベーション(活性化前の値)、 $a$ は「エー」アクティベーション(活性化後)。 $\phi$ は「ファイ」活性化関数。

1.2 単純パーセプトロン(1957 Rosenblatt)

$\phi$ がステップ関数のとき。 線形分離可能なデータのみ完璧分類。 XOR が解けない(線形分離不能)ことが指摘され、 第一次 AI 冬の時代を招いた。

1.3 実値計算

$\mathbf{x}=(1,2)$、 $\mathbf{w}=(0.5,-0.3)$、 $b=0.1$、 $\phi=$ ReLU のとき:

🏗 2. 多層パーセプトロン(MLP)

1953 年代後半に提案、 1986 年の Rumelhart の誤差逆伝播で実用化。 隠れ層を持つことで XOR も解ける。

2.1 順伝播の定式化

$L$ 層 MLP において、 各層 $\ell$ で:

$$\mathbf{z}^{(\ell)} = \mathbf{W}^{(\ell)} \mathbf{a}^{(\ell-1)} + \mathbf{b}^{(\ell)}, \qquad \mathbf{a}^{(\ell)} = \phi^{(\ell)}(\mathbf{z}^{(\ell)})$$

記号読み:$\mathbf{W}^{(\ell)}$ は「ダブリュー上付きエル」、 第 $\ell$ 層の重み行列。 入力 $\mathbf{a}^{(0)} = \mathbf{x}$、 出力 $\hat{y} = \mathbf{a}^{(L)}$。

2.2 表現能力

万能近似定理(Cybenko 1989、 Hornik 1991):1層の隠れ層を持つ MLP は十分な幅があれば任意の連続関数を任意の精度で近似できる。 ただし幅は指数的に大きくなりうるため、 実用では深くする。

⚡ 3. 活性化関数

NN に非線形性を入れる装置。 線形ばかりだと層を重ねても線形のまま。

3.1 Sigmoid

$$\sigma(z) = \frac{1}{1+e^{-z}}, \quad \sigma'(z) = \sigma(z)(1-\sigma(z))$$

3.2 tanh

$$\tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}}$$

出力 (-1, 1)。 ゼロ中心で sigmoid より好まれる場合あり。

3.3 ReLU(現代の標準)

$$\mathrm{ReLU}(z) = \max(0, z)$$

3.4 Leaky ReLU / GELU / Swish

3.5 Softmax(出力層用)

$$\mathrm{softmax}(z)_k = \frac{e^{z_k}}{\sum_{j=1}^{K} e^{z_j}}$$

多クラス分類の出力層で、 ロジット $z_k$ を確率に変換。

📏 4. 損失関数

タスク 損失関数 出力層
回帰MSE / MAE / Huber恒等関数
二値分類バイナリ交差エントロピーSigmoid
多クラス分類交差エントロピーSoftmax
多ラベルBCE × クラス数クラス別Sigmoid

$$L_{\text{CE}} = -\sum_{k=1}^{K} y_k \log \hat{p}_k$$

🔁 5. 誤差逆伝播 (Backpropagation)

順伝播で予測 → 損失計算 → 勾配を出力側から入力側に向かって計算する。

5.1 連鎖律

$$\frac{\partial L}{\partial W^{(\ell)}} = \frac{\partial L}{\partial \mathbf{a}^{(L)}} \cdot \frac{\partial \mathbf{a}^{(L)}}{\partial \mathbf{z}^{(L)}} \cdots \frac{\partial \mathbf{a}^{(\ell)}}{\partial \mathbf{z}^{(\ell)}} \cdot \frac{\partial \mathbf{z}^{(\ell)}}{\partial W^{(\ell)}}$$

各層の局所勾配を計算し、 連鎖律で合成する。 計算複雑度は順伝播と同じ $O(\text{パラメータ数})$。

5.2 PyTorch では自動微分で完了

🎯 このコードでやること:SSDSE-B-2026(2023 年・47 都道府県)の人口・出生率・小売額から県民所得 D1101 を MLP で回帰し、 5-fold 交差検証で R² を算出します。 sklearn の Pipeline で標準化→学習を一括化。
📥 入力例(SSDSE-B-2026 サンプル) # 2023 年フィルタ後、 X=3 特徴量、 y=県民所得 A1101=人口(千人) A4101=出生率 F2401=小売額 D1101=県民所得 東京都: [14010, 7.4, 18.5e6] → 5.5e6(万円) 北海道: [ 5092, 5.5, 6.2e6] → 2.9e6
📤 実行例(期待出力) R² (5-fold): 0.842 ± 0.061 # 標準化・early_stopping で過学習を抑制した結果
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
from sklearn.neural_network import MLPRegressor
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.model_selection import cross_val_score

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['年度']==2023]
X = df[['A1101', 'A4101', 'F2401']].values
y = df['D1101'].values

pipe = Pipeline([
    ('scale', StandardScaler()),
    ('mlp', MLPRegressor(hidden_layer_sizes=(16, 8), activation='relu',
                          solver='adam', learning_rate_init=0.001,
                          max_iter=2000, early_stopping=True, random_state=42))
])
scores = cross_val_score(pipe, X, y, cv=5, scoring='r2')
print(f'R² (5-fold): {scores.mean():.3f} ± {scores.std():.3f}')
💬 読み方:R² ≈ 0.84 は人口・出生率・小売額の 3 特徴で県民所得の分散の 84% を説明している意味。 ± は fold 間の標準偏差で、 小さいほど安定。

② PyTorch — フルコントロールの実装

🎯 このコードでやること:3→16→8→1 の MLP を PyTorch で構築し、 Dropout・gradient clipping・Early Stopping を組み合わせて学習。 SSDSE-B-2026 を train_loader 経由でミニバッチ学習する標準パターン。
📥 入力例(SSDSE-B-2026 サンプル) # 標準化済み Tensor (X_tr, y_tr) を TensorDataset → DataLoader へ X_tr.shape = torch.Size([37, 3]) # 47 都道府県の 80% y_tr.shape = torch.Size([37, 1]) X_val.shape = torch.Size([10, 3]) # 残り 20%
📤 実行例(期待出力) Epoch 10: val_loss = 0.45 Epoch 35: val_loss = 0.18 Early stopping at epoch 58
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset

## 再現性のための seed 固定
torch.manual_seed(42)

class MLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(3, 16),
            nn.ReLU(),
            nn.Dropout(0.2),
            nn.Linear(16, 8),
            nn.ReLU(),
            nn.Linear(8, 1)
        )
    def forward(self, x):
        return self.net(x)

model = MLP()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3, weight_decay=1e-4)
criterion = nn.MSELoss()

## 学習ループ + Early Stopping
best_val_loss = float('inf')
patience = 20
counter = 0
for epoch in range(200):
    model.train()
    for xb, yb in train_loader:
        pred = model(xb)
        loss = criterion(pred, yb)
        optimizer.zero_grad()
        loss.backward()
        torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm=1.0)  ## 勾配クリッピング
        optimizer.step()
    ## Early Stopping 判定
    model.eval()
    with torch.no_grad():
        val_loss = criterion(model(X_val), y_val).item()
    if val_loss 0
    else:
        counter += 1
        if counter >= patience:
            print(f'Early stopping at epoch {epoch}')
            break
💬 読み方:clip_grad_norm_ は勾配爆発を抑え、 Early Stopping は patience=20 で val_loss が改善しなくなったら学習を止める。 過学習防止の 3 種の神器 (Dropout + clip + ES) が揃った教科書的実装。

③ Keras / TensorFlow — 宣言的 API

🎯 このコードでやること:同じ MLP を Keras の Sequential API で宣言的に記述。 BatchNorm・He 初期化・LR スケジューラ・Early Stopping をコールバックで一括設定し、 fit→history→可視化までを 1 行で実現します。
📥 入力例(SSDSE-B-2026 サンプル) # 標準化済み numpy 配列 X_tr.shape = (47, 3) # 都道府県 × 3 特徴量 y_tr.shape = (47,) # validation_split=0.2 で内部分割
📤 実行例(期待出力) Epoch 1/200 loss: 1.234 val_loss: 1.156 Epoch 50/200 loss: 0.213 val_loss: 0.187 Epoch 78: ReduceLROnPlateau → lr 1e-3 → 5e-4 Restoring best weights from epoch 71.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from tensorflow import keras
from tensorflow.keras import layers, callbacks

model = keras.Sequential([
    layers.Input(shape=(3,)),
    layers.BatchNormalization(),
    layers.Dense(16, activation='relu', kernel_initializer='he_normal'),
    layers.Dropout(0.2),
    layers.Dense(8, activation='relu', kernel_initializer='he_normal'),
    layers.Dense(1)
])
model.compile(optimizer=keras.optimizers.Adam(1e-3),
              loss='mse', metrics=['mae'])

es = callbacks.EarlyStopping(monitor='val_loss', patience=20, restore_best_weights=True)
lr_sched = callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10)

history = model.fit(X_tr, y_tr, validation_split=0.2,
                    epochs=200, batch_size=8, callbacks=[es, lr_sched], verbose=0)

## 学習曲線のプロット
import matplotlib.pyplot as plt
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='val')
plt.xlabel('Epoch'); plt.ylabel('MSE Loss'); plt.legend()
💬 読み方:train と val の loss 曲線が乖離していけば過学習。 ReduceLROnPlateau は val 改善停止時に lr を半減し、 EarlyStopping は patience 経過後に学習を打ち切る。 history で学習進捗を後から再確認可能。

🎨 直感で掴む — ニューラルネットは「複合関数の積み木」

SSDSE-B-2026 から「総人口・出生率・高齢化率・大学進学率」の 4 指標を入力に、 「合計特殊出生率」を当てるタスクを考えます。 線形回帰は「重みの 1 回掛け算 + 足し算」一段ですが、 ニューラルネットは「重み付け → 非線形変換 → また重み付け → 非線形変換 → 最後に出力」と何段も積み木を重ねます。 各層の非線形(ReLU や tanh)が「曲がり」を作り、 直線では表現できない複雑な都道府県パターン(例: 進学率が高すぎる都市部では出生率は逆に下がる、 などの非単調関係)を捉えられるようになります。

📐 数式 — 多層パーセプトロンの順伝播

$$ h^{(l)} = \sigma\!\left( W^{(l)} h^{(l-1)} + b^{(l)} \right), \quad l = 1, 2, \ldots, L $$

$$ \hat{y} = W^{(L+1)} h^{(L)} + b^{(L+1)} $$

ここで $h^{(0)} = x$(入力ベクトル: 標準化された 47 都道府県指標)、 $\sigma$ は活性化関数(ReLU など)、 $W^{(l)}, b^{(l)}$ が層 $l$ の学習パラメータ。 損失 $\mathcal{L} = \frac{1}{n}\sum_i (y_i - \hat{y}_i)^2$ を勾配降下で最小化します。

🔬 数式を言葉で読み解く

記号意味SSDSE-B-2026 での具体例
$x$入力ベクトル標準化済みの 47 都道府県指標 (A1101 人口, A4101 出生率, F2401 小売額…)
$W^{(l)}$層 $l$ の重み行列学習で更新する パラメータ。 1 層目は (16, 3) 形状
$\sigma$活性化関数ReLU、 tanh、 sigmoid、 GELU など。 非線形性の源泉
$\hat{y}$予測値D1101 県民所得(回帰)または合計特殊出生率の予測
$\mathcal{L}$損失関数MSE = $\frac{1}{47}\sum(y_i-\hat{y}_i)^2$

🧮 実値で計算してみる(SSDSE-B-2026)

3 都道府県だけ取り出して、 標準化済み入力 $x$ から 1 層目の中間出力 $h^{(1)}$ までを手計算してみます(重み $W^{(1)}$ は学習後の代表値を仮定)。

都道府県$x_1$ 人口$x_2$ 出生率$x_3$ 小売額$z = W \cdot x + b$$h = \text{ReLU}(z)$
東京都+2.84+0.41+2.62+1.87+1.87
北海道+0.62-0.59+0.31+0.18+0.18
沖縄県-0.66+1.92-0.74-0.420.00

ReLU で 負値は 0 にクリップ されるため、 沖縄県は 1 層目で「死んだニューロン」状態。 並列の別ニューロンが沖縄パターンを拾うように冗長設計するのがポイント。

🐍 Python 実装 — 手計算と一致確認

🎯 このコードでやること:上の手計算(東京都・北海道・沖縄県の 1 層目通過)を numpy で再現し、 ReLU の挙動を確認します。
📥 入力例(SSDSE-B-2026) X = np.array([[2.84, 0.41, 2.62], # 東京都 [0.62,-0.59, 0.31], # 北海道 [-0.66,1.92,-0.74]]) # 沖縄県 W = np.array([[0.4, 0.2, 0.3]]) b = np.array([-0.1])
📤 実行例 z = [[1.87], [0.18], [-0.42]] h = [[1.87], [0.18], [0.00]] # ReLU で沖縄県は 0
import numpy as np
X = np.array([[2.84, 0.41, 2.62],
              [0.62,-0.59, 0.31],
              [-0.66, 1.92,-0.74]])
W = np.array([[0.4, 0.2, 0.3]])
b = np.array([-0.1])
z = X @ W.T + b
h = np.maximum(0, z)   # ReLU
print(z.round(2)); print(h.round(2))
💬 読み方:手計算の表と numpy 出力が一致。 学習を多層化することで、 沖縄県のような外れ値型パターンも別のニューロンで拾えるようになる。

🌐 関連手法・派生