本文へスキップ
BecomeCoder

PyTorchコース · 第3章 ニューラルネットワークをnumpyで作る · レッスン11

小さなNNを訓練する ― 分類を解く

ブラウザで完結

導入

部品がそろいました。仕上げに、直線では分けられないデータを、numpy 製の小さな NN で分類してみます。ここまでの順伝播・逆伝播・勾配降下法が、1つの「学習するプログラム」として動く瞬間です。

説明

題材は有名な XOR 問題(0,0)(1,1)クラス0、(0,1)(1,0)はクラス1。1本の直線ではどう引いても分けられません。隠れ層のある NN なら、非線形な境界を学習して解けます。

flowchart LR
  in["入力 (x1, x2)"] --> hid["隠れ層(4)<br/>sigmoid"]
  hid --> out["出力(1)<br/>sigmoid = クラス1の確率"]
  out --> loss["損失で誤差を測り<br/>逆伝播で全重み更新"]
  loss -. 繰り返す .-> in

やってみよう

下のコードは、隠れ層4つの NN を逆伝播で訓練し、XOR を解きます。実行すると損失が下がり、最後に4つの入力すべてを正しく分類できるようになります。直線では不可能な問題を、自作 NN が解く瞬間を見てください。

import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

# XOR データ
X = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float)
Y = np.array([[0],[1],[1],[0]], dtype=float)

np.random.seed(42)
W1 = np.random.randn(2, 4)      # 入力2 → 隠れ4
b1 = np.zeros(4)
W2 = np.random.randn(4, 1)      # 隠れ4 → 出力1
b2 = np.zeros(1)
lr = 0.5

for epoch in range(5000):
    # 順伝播
    A1 = sigmoid(X @ W1 + b1)
    P  = sigmoid(A1 @ W2 + b2)
    # 逆伝播
    dP = (P - Y) * P * (1 - P)
    dW2 = A1.T @ dP
    db2 = dP.sum(axis=0)
    dA1 = (dP @ W2.T) * A1 * (1 - A1)
    dW1 = X.T @ dA1
    db1 = dA1.sum(axis=0)
    # 更新
    W2 -= lr * dW2; b2 -= lr * db2
    W1 -= lr * dW1; b1 -= lr * db1
    if epoch % 1000 == 0:
        loss = np.mean((P - Y) ** 2)
        print(f"epoch {epoch:4d}:  loss = {loss:.4f}")

pred = sigmoid(sigmoid(X @ W1 + b1) @ W2 + b2)
print("\n最終予測(0に近い=クラス0, 1に近い=クラス1):")
for xi, pi in zip(X, pred):
    print(f"  入力 {xi}{pi[0]:.3f}  → 判定クラス {int(pi[0] > 0.5)}")

演習

隠れ層のニューロン数を 4 から 2 に減らして実行してみましょう。学習が難しくなり、損失の下がりが悪くなる(うまく解けないことがある)のを観察してください。表現力=隠れニューロン数の大切さを体感します。

ヒント1を見る

W1np.random.randn(2, 2)b1np.zeros(2)W2np.random.randn(2, 1) に変えます。

ヒント2を見る

ニューロンが少ないと表現力が足りず、XORのような問題は解けたり解けなかったりします。乱数シードを変えると結果が変わることも確かめてみましょう。

まとめ

  • 隠れ層のある NN は、**直線では分けられない問題(XOR)**も学習で解ける。
  • 順伝播・逆伝播・勾配降下法を組み合わせれば、それが「学習するプログラム」になる。
  • ここまで numpy で自作した一連の処理を、次章から PyTorch が自動化してくれる。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。