AI: ニューラルネットワーク

最終更新:2026-08-26

「深層学習」は謎めいて複雑に聞こえるかもしれませんが、その基本単位である「ニューロン」とは、単なる重み付き和に非線形変換を加えたものです。パーセプトロンから始めて、この章では多層ネットワーク、活性化関数、順伝播、誤差逆伝播を段階的に案内し、純粋な Python で MLP をゼロから実装して XOR 問題を解く方法を示します。

1. 学べること



2. ストーリー:10 行のコードの裏にある「脳」

(1) 痛みの種:深層学習ってそもそも何?

Bob は「深層学習」が顔認識も言語翻訳も文章生成もできると聞きましたが、ニューラルネットワークが何なのかまるで分かりませんでした。Wikipedia で調べてみましたが、偏微分と連鎖律だらけの画面にげんなりしてすぐにページを閉じました。「『ニューロン』が実際に何をしているのか、一番簡単な言葉で説明してくれないか?」

(2) Alice の 10 行のコード

Alice は微笑みながら Python を開き、10 行でパーセプトロンを書きました。2 つの数値を入力として受け取り、0 か 1 を出力します。

PYTHON
# 単一パーセプトロン:AND ゲート
def perceptron(x1, x2, w1=1, w2=1, b=-1.5):
    return 1 if w1 * x1 + w2 * x2 + b > 0 else 0

for x1, x2 in [(0,0),(0,1),(1,0),(1,1)]:
    print(f"AND({x1},{x2}) = {perceptron(x1, x2)}")
💻 出力:

TEXT 📖 参照専用
AND(0,0) = 0
AND(0,1) = 0
AND(1,0) = 0
AND(1,1) = 1

Bob は気づきました。「これって単なる重み付き投票じゃないか?両方の入力が 1 で、重み付き和が閾値を超えれば出力が 1 になる。つまりニューラルネットワークって、こうした単純な決定ユニットをつなげたものなんだ!」

(3) メリット:単純なユニットから強力なネットワークへ

Alice はうなずきました。「その通り。単一のパーセプトロンは線形分類しかできませんが、数十~数百のパーセプトロンを多層ネットワークに積み上げれば、極めて複雑な関数にもフィットできます。そこから深層学習が始まるのです。」



3. パーセプトロン――最も単純なニューラルネットワーク

(1) パーセプトロンの数学的定義

1958 年に心理学者 Rosenblatt が提案したパーセプトロンは、最初期の人工ニューロンモデルの一つです。複数の入力 $x_1, x_2, \ldots, x_n$ を受け取り、それぞれに重み $w_i$ とバイアス $b$ を加え、最後にステップ関数を通して 0 か 1 を出力します。

$$y = \text{step}\left(\sum_{i=1}^{n} w_i x_i + b\right)$$

特に、$\text{step}(z) = 1$ if $z > 0$、それ以外は $0$ です。

直感: ランニングに行くかどうか決めていると想像してください。気温、空気の質、時間があるか、気分――各要素に「重み」があり、合計が「サボり閾値」を超えれば出かけます。

(2) パーセプトロンの幾何学的意味

パーセプトロンは二次元空間に直線 $w_1 x_1 + w_2 x_2 + b = 0$ を引き、直線の一方の側で 1、もう一方で 0 を出力します。AND や OR のような線形分離可能な問題は完璧に解けますが、XOR 問題は解けません――XOR では 2 つのクラスの点を一本の直線で分離できないからです。

▶ サンプル: パーセプトロンの AND ゲートを純粋な Python で実装する(難易度:⭐)

PYTHON
# 学習付きパーセプトロン AND ゲート
def step(z):
    return 1 if z > 0 else 0

def train_perceptron(X, y, lr=0.1, epochs=10):
    n_features = len(X[0])
    weights = [0.0] * n_features
    bias = 0.0
    for epoch in range(epochs):
        total_error = 0
        for xi, yi in zip(X, y):
            z = sum(w * x for w, x in zip(weights, xi)) + bias
            pred = step(z)
            error = yi - pred
            total_error += abs(error)
            for j in range(n_features):
                weights[j] += lr * error * xi[j]
            bias += lr * error
        if total_error == 0:
            break
    return weights, bias

X = [[0,0],[0,1],[1,0],[1,1]]
y_and = [0, 0, 0, 1]
w, b = train_perceptron(X, y_and)
print(f"重み: {w}, バイアス: {b}")
for xi in X:
    print(f"AND{xi} = {step(sum(ww*xx for ww,xx in zip(w,xi)) + b)}")
💻 出力:

TEXT 📖 参照専用
重み: [0.2, 0.1], バイアス: -0.2
AND[0, 0] = 0
AND[0, 1] = 0
AND[1, 0] = 0
AND[1, 1] = 1
💡 ヒント: パーセプトロンの学習規則は極めて単純です。予測が正しければ重みは変わらず、誤っていれば重みを誤差の方向に調整します。これが「失敗から学ぶ」という最も基本的な形です。



4. 多層パーセプトロン(MLP)のアーキテクチャ

(1) なぜ複数層が必要か?

単層パーセプトロンは直線しか引けず、XOR 問題を解けません。しかし 2 つのパーセプトロンの出力を第 3 のパーセプトロンに入力すれば、2 本の直線を組み合わせて非線形の境界を作れるようになります。これが多層パーセプトロン(MLP)の核心アイデアです。

(2) MLP の三層構造

機能
入力層 生の特徴を受け取る 2 ノード(x₁, x₂)
隠れ層 中間特徴を抽出 4 ノード(学習された特徴)
出力層 最終予測を出力 1 ノード(0 か 1)

各層のすべてのノードは前の層のすべてのノードと接続されており(全結合)、その結合の強さを 重み が表します。

(3) ニューラルネットワークの順伝播プロセス

100%
graph LR
    X1["x₁"] --> H1["h₁ (sigmoid)"]
    X1 --> H2["h₂ (sigmoid)"]
    X2["x₂"] --> H1
    X2 --> H2
    H1 --> Y["y (出力)"]
    H2 --> Y
    style X1 fill:#e1f5fe
    style X2 fill:#e1f5fe
    style H1 fill:#fff9c4
    style H2 fill:#fff9c4
    style Y fill:#c8e6c9

直感: 入力層は目、隠れ層は脳の処理領域、出力層は答えを口にするようなものです。各層は「重み付き和 + 非線形変換」を行います。

(4) 比較:パーセプトロン vs MLP vs 深層ニューラルネットワーク

比較軸 パーセプトロン MLP 深層ニューラルネットワーク
層数 1 層(隠れ層なし) 2–3 層 ≥ 4 層(複数の隠れ層を含む)
能力 線形分類 非線形分類/回帰 複雑な特徴の自動抽出
学習 パーセプトロン規則 誤差逆伝播 誤差逆伝播 + 最適化技法
典型応用 単純な論理ゲート 小規模分類/回帰 画像認識、NLP、生成
パラメータ数 数十 数百~数千 数万~数十億
代表モデル Rosenblatt パーセプトロン 2 層 MLP CNN、Transformer


5. 活性化関数――ネットワークに非線形性を加える

(1) なぜ活性化関数が必要か?

活性化関数がないと、層をいくら重ねても本質的には線形変換です。複数の線形変換の合成は線形のままだからです。活性化関数は 非線形性 を導入し、ネットワークが複雑な曲線や境界にフィットできるようにします。

比喩: 線形変換は「伸縮と回転」のようなもの。何度伸縮や回転を繰り返しても、結果は直線や平面のまま。活性化関数は「折りたたみ」のようなもので、紙を一度折れば空間が変わります。

(2) 一般的な活性化関数の比較

関数 出力範囲 長所 短所
Sigmoid $\sigma(z)=\frac{1}{1+e^{-z}}$ (0, 1) 出力を確率として扱える 勾配消失、ゼロ中心でない
Tanh $\tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}$ (-1, 1) ゼロ中心 勾配が消失する
ReLU $\max(0, z)$ [0, +∞) 計算が速く、勾配消失を緩和 ニューロン死(負の領域で勾配が 0)
Leaky ReLU $\max(0.01z, z)$ (-∞, +∞) ニューロン死に対処 ハイパーパラメータ調整が必要

▶ サンプル: 異なる活性化関数の出力値を比較する(難易度:⭐)

PYTHON
# 活性化関数を比較
import numpy as np

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

def tanh(z):
    return np.tanh(z)

def relu(z):
    return np.maximum(0, z)

def leaky_relu(z, alpha=0.01):
    return np.where(z > 0, z, alpha * z)

z_values = np.array([-5, -2, -1, 0, 1, 2, 5])
print(f"{'z':>5} | {'Sigmoid':>8} | {'Tanh':>8} | {'ReLU':>8} | {'LeakyReLU':>10}")
print("-" * 55)
for z in z_values:
    s = sigmoid(z)
    t = tanh(z)
    r = float(relu(np.array([z]))[0])
    lr = float(leaky_relu(np.array([z]))[0])
    print(f"{z:5.1f} | {s:8.4f} | {t:8.4f} | {r:8.4f} | {lr:10.4f}")
💻 出力:

TEXT 📖 参照専用
    z |  Sigmoid |     Tanh |     ReLU |  LeakyReLU
-------------------------------------------------------
 -5.0 |   0.0067 |  -0.9999 |   0.0000 |    -0.0500
 -2.0 |   0.1192 |  -0.9640 |   0.0000 |    -0.0200
 -1.0 |   0.2689 |  -0.7616 |   0.0000 |    -0.0100
  0.0 |   0.5000 |   0.0000 |   0.0000 |     0.0000
  1.0 |   0.7311 |   0.7616 |   1.0000 |     1.0000
  2.0 |   0.8808 |   0.9640 |   2.0000 |     2.0000
  5.0 |   0.9933 |   0.9999 |   5.0000 |     5.0000
💡 ヒント: Sigmoid と Tanh は |z| が大きいとき勾配が 0 に近づきます(勾配消失)が、ReLU は正の区間で勾配が常に 1 です。そのため深層ニューラルネットワークでは一般的に ReLU が推奨されます。



6. 順伝播と誤差逆伝播

(1) 順伝播:入力から出力へ

順伝播は、データが入力層から各層を通って出力層に至るプロセスです。

  1. 隠れ層入力を計算:$z^{(1)} = W^{(1)} \cdot x + b^{(1)}$
  2. 活性化関数を適用:$h = \sigma(z^{(1)})$
  3. 出力層入力を計算:$z^{(2)} = W^{(2)} \cdot h + b^{(2)}$
  4. 予測を出力:$\hat{y} = \sigma(z^{(2)})$

(2) 損失関数:予測と真値のずれを測る

平均二乗誤差(MSE)は損失関数として一般的に使われます。

損失とは、実測値と予測値の差の二乗です。

損失が小さいほど予測は正確です。学習の目標は、損失を最小化する重みを見つけることです。

(3) 誤差逆伝播:誤差から重み更新へ

誤差逆伝播の核心アイデア:「出力層の誤差から出発し、各重みが誤差にどう『寄与』したかをネットワークを層ごとに後ろ向きに伝播させて計算し、それに応じて重みを調整する」ことです。

直感的な比喩:工場で製品に不具合があったとします。

数学的にはこれが 連鎖律 です:$\frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w}$

(4) 誤差逆伝播の重要概念一覧

概念 意味 直感
勾配 損失の重みに関する偏微分 重みをどちらの方向にどれだけ調整すべきか
学習率 1 反復あたりのステップ幅 大きすぎ → 最適点を飛び越す;小さすぎ → 学習が遅い
連鎖律 勾配を層ごとに伝播 出力から入力へ「誰の責任か」を層ごとに追跡
重み更新 $w \leftarrow w - \eta \cdot \frac{\partial L}{\partial w}$ 勾配の逆方向へ一歩進む
勾配消失 勾配が層ごとに減少し 0 に近づく 最初の数層はほとんど学習しない
勾配爆発 勾配が層ごとに増幅 重み更新が激しく、モデルが不安定に

(5) 損失曲面の直感

山の上に立って、谷底(最小損失)に到達するのが目標だと想像してください。一歩ごとに最も急な斜面を下ります。それが 勾配降下法 です。学習率は歩幅を決めます。



7. sklearn で MLP を手軽に試す

▶ サンプル: sklearn の MLPClassifier で分類する(難易度:⭐)

PYTHON
# XOR 問題での MLPClassifier
from sklearn.neural_network import MLPClassifier
import numpy as np

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

mlp = MLPClassifier(hidden_layer_sizes=(4,), activation='relu',
                    max_iter=2000, random_state=42)
mlp.fit(X, y)

print("XOR 予測:")
for xi in X:
    print(f"  {xi} -> {mlp.predict([xi])[0]}")
print(f"精度: {mlp.score(X, y):.2f}")
💻 出力:

TEXT 📖 参照専用
XOR 予測:
  [0 0] -> 0
  [0 1] -> 1
  [1 0] -> 1
  [1 1] -> 0
精度: 1.00
💡 ヒント: sklearn の MLPClassifier は順伝播、誤差逆伝播、重みの初期化を含めすべての詳細を自動処理します。原理を理解してしまえば、ライブラリを使うのが最も効率的なアプローチです。

▶ サンプル: 決定境界の変化を可視化する(難易度:⭐⭐)

PYTHON
# XOR での MLP 決定境界を可視化
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPClassifier

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

fig, axes = plt.subplots(1, 3, figsize=(15, 4))
hidden_configs = [(2,), (4,), (8,)]

for ax, config in zip(axes, hidden_configs):
    mlp = MLPClassifier(hidden_layer_sizes=config, activation='relu',
                        max_iter=3000, random_state=42)
    mlp.fit(X, y)

    xx, yy = np.meshgrid(np.linspace(-0.5, 1.5, 100),
                         np.linspace(-0.5, 1.5, 100))
    Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)

    ax.contourf(xx, yy, Z, alpha=0.3, cmap='coolwarm')
    ax.scatter(X[:,0], X[:,1], c=y, cmap='coolwarm', edgecolors='k', s=100)
    ax.set_title(f"隠れ層: {config}, 精度: {mlp.score(X,y):.2f}")
    ax.set_xlabel("x1")
    ax.set_ylabel("x2")

plt.tight_layout()
plt.savefig("mlp_decision_boundary.png", dpi=100)
plt.show()

出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)

💡 ヒント: 隠れ層のノードが多いほど決定境界は柔軟になりますが、過学習しやすくもなります。2 ノードでは XOR を学習するのに不十分なこともあり、8 ノードなら十分すぎるほどです。

▶ サンプル: 隠れ層のノード数が性能に与える影響(難易度:⭐⭐)

PYTHON
# 隠れ層サイズが学習損失に与える影響
import numpy as np
from sklearn.neural_network import MLPClassifier
import matplotlib.pyplot as plt

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

fig, ax = plt.subplots(figsize=(8, 5))
for n_hidden in [2, 4, 8, 16]:
    mlp = MLPClassifier(hidden_layer_sizes=(n_hidden,), activation='relu',
                        max_iter=3000, random_state=42, solver='lbfgs')
    mlp.fit(X, y)
    ax.plot(range(len(mlp.loss_curve_)), mlp.loss_curve_,
            label=f"Hidden={n_hidden}")

ax.set_xlabel("反復回数")
ax.set_ylabel("損失")
ax.set_title("学習損失 vs 隠れ層サイズ")
ax.legend()
ax.set_yscale('log')
plt.savefig("hidden_size_loss.png", dpi=100)
plt.show()

出力: (例を実行して実際の出力を確認するか、上のコードコメントの期待出力の注釈を参照してください。)

💡 ヒント: 隠れノードが多いモデルは一般に速く収束し損失も低くなりますが、パラメータが多く小規模データセットでは過学習する可能性があります。



8. 深層学習 = 多層ニューラルネットワーク

(1) 伝統的 ML と深層学習の比較

比較軸 伝統的機械学習 深層学習
特徴エンジニアリング 特徴の手動設計と選択が必要 データから特徴を自動学習
データ量要件 少量のデータで十分 一般に大量のデータが必要
計算資源 CPU のみ 一般に GPU が必要
モデル解釈性 高い(決定木、線形モデル) 低い(ブラックボックス)
性能上限 特徴の質に依存 データとモデルサイズに応じてスケール
代表アルゴリズム SVM、ランダムフォレスト、XGBoost CNN、RNN、Transformer
適用シナリオ 構造化データ、小標本 画像・テキスト・音声などの非構造化データ

(2) 「深い」とはどういう意味か?

「深さ」とは 隠れ層の数 を指します。一般的に以下のように合意されています。

層が多いほど、ネットワークが抽出できる特徴はより抽象的になります。第 1 層はエッジを、第 2 層はテクスチャを、第 3 層は部品を学習するかもしれません。ネットワークを進むほど特徴はますます「意味的」になります。

(3) 深ければ良いとは限らない

より深いネットワークが必ずしも高性能とは限りません。層が多すぎると以下を招きます。

モデルの深さはタスクの複雑さとデータ量に基づいて選ぶべきです。高層ビルを建てるようなものです。高ければ良いとは限らず、基礎と予算を考慮しなければなりません。



9. 総合実践:MLP 分類器をゼロから実装する

▶ サンプル: ゼロから MLP を実装して XOR 問題を解く(難易度:⭐⭐⭐)

以下では、純粋な Python(フレームワークなし)で完全な MLP を実装します。順伝播、誤差逆伝播、学習ループを含み、XOR 問題を解くのが目標です。

PYTHON
# ゼロから MLP:純粋な Python + NumPy で XOR を解く
import numpy as np

# --- 活性化関数とその導関数 ---
def sigmoid(z):
    return 1 / (1 + np.exp(-np.clip(z, -500, 500)))

def sigmoid_deriv(a):
    return a * (1 - a)

# --- MLP クラス ---
class MLP:
    def __init__(self, layer_sizes):
        # layer_sizes 例: [2, 4, 1] => 入力2、隠れ4、出力1
        self.weights = []
        self.biases = []
        for i in range(len(layer_sizes) - 1):
            w = np.random.randn(layer_sizes[i], layer_sizes[i+1]) * 0.5
            b = np.zeros((1, layer_sizes[i+1]))
            self.weights.append(w)
            self.biases.append(b)

    def forward(self, X):
        self.activations = [X]
        for i in range(len(self.weights)):
            z = self.activations[-1] @ self.weights[i] + self.biases[i]
            a = sigmoid(z)
            self.activations.append(a)
        return self.activations[-1]

    def backward(self, y, lr=0.5):
        m = y.shape[0]
        deltas = [None] * len(self.weights)

        # 出力層のデルタ
        output = self.activations[-1]
        deltas[-1] = (output - y) * sigmoid_deriv(output)

        # 隠れ層のデルタ(逆伝播)
        for i in range(len(self.weights) - 2, -1, -1):
            deltas[i] = (deltas[i+1] @ self.weights[i+1].T) * sigmoid_deriv(self.activations[i+1])

        # 重みとバイアスを更新
        for i in range(len(self.weights)):
            self.weights[i] -= lr * (self.activations[i].T @ deltas[i]) / m
            self.biases[i] -= lr * np.mean(deltas[i], axis=0, keepdims=True)

    def train(self, X, y, epochs=5000, lr=0.5):
        self.losses = []
        for epoch in range(epochs):
            pred = self.forward(X)
            loss = np.mean((y - pred) ** 2) / 2
            self.losses.append(loss)
            self.backward(y, lr)
            if epoch % 1000 == 0:
                print(f"Epoch {epoch:4d} | 損失: {loss:.6f}")

    def predict(self, X):
        return (self.forward(X) > 0.5).astype(int)

# --- XOR で学習 ---
np.random.seed(42)
X = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float)
y = np.array([[0],[1],[1],[0]], dtype=float)

mlp = MLP([2, 4, 1])
mlp.train(X, y, epochs=5000, lr=1.0)

print("\n最終予測:")
preds = mlp.predict(X)
for i in range(4):
    print(f"  XOR{X[i].astype(int).tolist()} = {preds[i,0]} (目標: {y[i,0].astype(int)})")
💻 出力:

TEXT 📖 参照専用
Epoch    0 | 損失: 0.132415
Epoch 1000 | 損失: 0.004726
Epoch 2000 | 損失: 0.002517
Epoch 3000 | 損失: 0.001751
Epoch 4000 | 損失: 0.001330

最終予測:
  XOR[0, 0] = 0 (目標: 0)
  XOR[0, 1] = 1 (目標: 1)
  XOR[1, 0] = 1 (目標: 1)
  XOR[1, 1] = 0 (目標: 0)
💡 ヒント: XOR は古典的な非線形問題です。単層パーセプトロンでは解けませんが、2→4→1 の MLP なら数千回の反復で完璧に解けます。これが多層ネットワークと非線形活性化関数の組み合わせの力を示しています。


❓ よくある質問

Q 深層学習の「深い」とはどういう意味か?
A 「深い」とは隠れ層の数を指します。伝統的な MLP は隠れ層が 1–2 層だけですが、深いネットワークは一般に 4 層以上――時には数百層にもなります。「深い」ことはより高いレベルの特徴抽象化を意味し、各層が前の層に基づいてより高次の特徴を抽出します。
Q なぜ活性化関数が必要か?
A 活性化関数がないと、複数の線形変換の合成は依然として線形になります。層をいくら積み上げても単層の線形変換と等価です。活性化関数は非線形性を導入し、ネットワークが複雑な曲線や決定境界にフィットできるようにします。活性化関数がなければ、深層学習は不可能です。
Q 誤差逆伝播が難しすぎる場合は?
A 誤差逆伝播を手書きする必要はありません。現代のフレームワーク(PyTorch、TensorFlow)は自動微分(Autograd)で勾配を自動計算します。理解すべき重要概念は 3 つだけです。① 出力層の誤差から出発して層ごとに後ろ向きに伝播する;② 各層の「責任」は連鎖律で計算する;③ 重みは勾配の逆方向に更新する。実際にコードを書くとき、微分はフレームワークがすべてやってくれます。
Q ニューラルネットワークには層とノードが何個必要か?
A 万能の公式はありません。実践的には:① 小さなネットワーク(隠れ層 1–2、層あたり 32–128 ノード)から始める;② 学習誤差と検証誤差を監視して層を増やすか判断する;③ データセットが小さいときは過学習を防ぐためノードを少なくする;④ データが大きくタスクが複雑なときだけより深く広いネットワークを検討する。ハイパーパラメータ探索(グリッドサーチ、ランダムサーチ)が一般的なアプローチです。
Q 深層学習は常に伝統的機械学習より優れているか?
A 必ずしもそうとは限りません。深層学習は画像・テキスト・音声などの非構造化データで明確な優位性がありますが、伝統的 ML が優れるのは以下の場面です。① 小規模データセット(< 1,000 サンプル);② 明確に定義された特徴(構造化表データ);③ 解釈性が求められる;④ 計算資源が限られている。モデルの選択は「深さ」を盲目的に追うのではなく、タスク・データ・制約に依存すべきです。

📖 まとめ

重要概念: ニューロン = 重み付き和 + 非線形変換。ニューラルネットワーク = 多くのニューロンを積み上げたもの。深層学習 = 層の多いニューラルネットワーク。10 行のパーセプトロンから GPT まで、本質的にはすべて同じパラダイムに従っています。


📝 練習問題

  1. 基本(⭐): OR ゲートのパーセプトロンを実装しなさい。OR ゲートの真理値表は:(0,0) → 0、(0,1) → 1、(1,0) → 1、(1,1) → 1 です。この章のパーセプトロン学習コードのラベルを変更してモデルを学習し、結果を検証しなさい。
PYTHON
# スターターコード:OR ゲートのパーセプトロン
X = [[0,0],[0,1],[1,0],[1,1]]
y_or = [0, 1, 1, 1]
# TODO: 学習してテストする
  1. 応用(⭐⭐): sklearn の MLPClassifier で Iris データセットを分類し、パラメータを調整して異なる構成の精度を記録しなさい。
PYTHON
# スターターコード:Iris での MLP
from sklearn.datasets import load_iris
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.3, random_state=42)

# TODO: 異なる hidden_layer_sizes、activation、learning_rate を試す
# 各構成の精度を記録する

少なくとも 3 つの異なる hidden_layer_sizes 構成((10,)、(50,50)、(100,) など)と 2 つの活性化関数を試し、どの構成が最良かメモしなさい。

  1. 挑戦(⭐⭐⭐): この章の純粋 Python MLP 実装に基づき、手書き MLP の損失曲線を描きなさい。
PYTHON
# セクション 9 で MLP を学習後、損失曲線を描く
import matplotlib.pyplot as plt

# mlp.losses は学習中にすでに記録されている
plt.figure(figsize=(8, 5))
plt.plot(range(len(mlp.losses)), mlp.losses, linewidth=1)
plt.xlabel("Epoch")
plt.ylabel("損失 (MSE)")
plt.title("MLP 学習損失曲線 (XOR)")
plt.yscale('log')
plt.grid(True, alpha=0.3)
plt.savefig("mlp_loss_curve.png", dpi=100)
plt.show()

発展課題:① 異なる学習率(0.1、0.5、1.0、2.0)の損失曲線を同じグラフで比較する;② 異なる隠れ層サイズ(2、4、8)で収束速度への影響を観察する;③ 学習率が高すぎると損失が振動したり発散したりするか観察する。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%