← 記事一覧へ
AI生成画像

ディープラーニング入門:データから関数を学ぶ仕組み

ニューロン、層、損失、勾配、逆伝播。小さなネットワークにXORを学ばせながら、ディープラーニングが「学ぶ」仕組みを短く整理する。

AI作成 · 約7分 · Pythonが読めれば十分
ディープラーニングニューラルネットワーク入門
この記事で扱うこと

ディープラーニングは、層を重ねた関数の重みを、予測、損失、勾配、更新の繰り返しで、データに合わせていく方法です。LLMも、この仕組みの上にあります。

ディープラーニングとは

ディープラーニングは、入力から出力を作る関数を、データから学ぶ方法です。画像なら「写っているもの」、文章なら「次の単語」を出す関数を、人がルールを書く代わりに、例をたくさん見せて作ります。関数は、単純な計算(ニューロン)を、層にして何段も重ねた形をしています。この「深く重ねる」ことが、名前の由来です。

ニューラルネットワークの形入力隠れ層隠れ層出力1つのニューロン:出力 = 活性化(重み × 入力の合計 + バイアス)
図1 丸がニューロン、線が重み。層を重ねるほど「深い」ネットワークになる。学習で決まるのは、線の重みと、各ニューロンのバイアス。

1つのニューロンがすること

ニューロンは、入力にそれぞれの重みを掛けて足し、バイアスを加えて、活性化関数に通すだけです。

  • 重みとバイアスが、学習で決まる数(パラメータ)
  • 活性化関数(ReLU、tanh、sigmoidなど)は、計算に「曲がり」を入れる。これがないと、何層重ねても、直線的な関数にしかならない
  • 層を重ねると、前の層の出力を材料に、より複雑な特徴を組み立てられる

LLMのパラメータが「数十億」と言われるのは、この重みとバイアスの数のことです。

学習の流れ

学習は、次の4つの繰り返しです。

学習の繰り返し予測順伝播で出力を出す損失正解とのずれを数に勾配逆伝播で向きを計算更新学習率の幅だけ動かす繰り返す
図2 予測、損失、勾配、更新を、損失が十分に下がるまで繰り返す。1周ごとに、重みが少しずつ、正解に合う向きへ動く。
  1. 予測:今の重みで、入力から出力を計算する(順伝播)
  2. 損失:予測と正解のずれを、1つの数にする
  3. 勾配:損失を減らすには、各重みをどちらへ、どれだけ動かせばよいかを計算する。出力側から入力側へ、順に計算するので誤差逆伝播法と呼ぶ
  4. 更新:勾配の逆向きに、重みを少しだけ動かす(勾配降下法)。動かす幅が学習率

小さな例:XORを学ぶ

XORは、2つの入力が違うときだけ1になる関数です。直線1本では分けられないので、隠れ層が要ります。NumPyだけで、上の4つの手順をそのまま書きました(筆者が実行した結果を載せています)。

xor.py
import numpy as np

# データ: XOR(2つの入力が違うときだけ1)。直線1本では分けられない
X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtype=float)
y = np.array([[0], [1], [1], [0]], dtype=float)

# モデル: 入力2 → 隠れ層8(tanh) → 出力1(sigmoid)
rng = np.random.default_rng(0)
W1, b1 = rng.normal(0, 1, (2, 8)), np.zeros(8)
W2, b2 = rng.normal(0, 1, (8, 1)), np.zeros(1)
sigmoid = lambda z: 1 / (1 + np.exp(-z))

lr = 0.5  # 学習率: 1回にどれだけ重みを動かすか
for epoch in range(2001):
    # 1. 予測(順伝播)
    h = np.tanh(X @ W1 + b1)
    p = sigmoid(h @ W2 + b2)
    # 2. 損失: 正解とのずれ(交差エントロピー)
    loss = -np.mean(y * np.log(p) + (1 - y) * np.log(1 - p))
    # 3. 勾配(逆伝播): 損失を減らすには、各重みをどちらへ動かすか
    dz2 = (p - y) / len(X)
    dW2, db2 = h.T @ dz2, dz2.sum(0)
    dz1 = (dz2 @ W2.T) * (1 - h ** 2)
    dW1, db1 = X.T @ dz1, dz1.sum(0)
    # 4. 更新: 勾配の逆向きに、少しだけ動かす
    W1 -= lr * dW1; b1 -= lr * db1
    W2 -= lr * dW2; b2 -= lr * db2
    if epoch % 500 == 0:
        print(f"epoch {epoch:4d}  loss {loss:.4f}")

print("予測:", p.round(3).ravel(), "→", (p > 0.5).astype(int).ravel())
実行結果
epoch    0  loss 0.7414
epoch  500  loss 0.0068
epoch 1000  loss 0.0029
epoch 1500  loss 0.0018
epoch 2000  loss 0.0013
予測: [0.001 0.998 0.999 0.002] → [0 1 1 0]

損失が下がり、4つの入力すべてで正しく答えています。なお、隠れ層を4つにすると、乱数の種によっては、途中の谷(局所解)にはまって解けないことがありました(筆者の試行では20通り中1通り)。層を少し広げると、安定しました。

実際には、PyTorchなどのライブラリが、勾配の計算(自動微分)とGPUでの計算を引き受けます。書くのは、モデルの形と、損失と、学習の繰り返しです。

よく出る言葉

言葉意味
エポック学習データを、ひととおり使った回数
バッチ1回の更新に使う、データのかたまり
学習率1回の更新で、重みを動かす幅。大きすぎると発散し、小さすぎると進まない
検証データ学習に使わない、確認用のデータ
過学習学習データにだけ合いすぎて、新しいデータで外れる状態
推論学習済みの重みで、予測だけをすること

過学習を防ぐ

  • データを分ける:学習用と検証用に分け、検証の成績で判断する
  • 早めに止める:検証の損失が下がらなくなったら、学習を止める
  • データを増やす、モデルを小さくする:データに対して、モデルが大きすぎないかを見る

LLMとのつながり

LLMも、同じ仕組みです。ただし、層の作り方にTransformerを使い、膨大な文章で「次のトークンの予測」を学習しています。続きは、LLMはどう動くかと、Transformerの中身で扱います。

公式リファレンス

Dive into Deep Learning ↗
PAIBOT / DEVELOPMENT JOURNAL記事一覧に戻る →

知りたいことを探す

タイトル・タグ・本文から検索 esc で閉じる