
ディープラーニング入門:データから関数を学ぶ仕組み
ニューロン、層、損失、勾配、逆伝播。小さなネットワークにXORを学ばせながら、ディープラーニングが「学ぶ」仕組みを短く整理する。
ディープラーニングは、層を重ねた関数の重みを、予測、損失、勾配、更新の繰り返しで、データに合わせていく方法です。LLMも、この仕組みの上にあります。
ディープラーニングとは
ディープラーニングは、入力から出力を作る関数を、データから学ぶ方法です。画像なら「写っているもの」、文章なら「次の単語」を出す関数を、人がルールを書く代わりに、例をたくさん見せて作ります。関数は、単純な計算(ニューロン)を、層にして何段も重ねた形をしています。この「深く重ねる」ことが、名前の由来です。
1つのニューロンがすること
ニューロンは、入力にそれぞれの重みを掛けて足し、バイアスを加えて、活性化関数に通すだけです。
- 重みとバイアスが、学習で決まる数(パラメータ)
- 活性化関数(ReLU、tanh、sigmoidなど)は、計算に「曲がり」を入れる。これがないと、何層重ねても、直線的な関数にしかならない
- 層を重ねると、前の層の出力を材料に、より複雑な特徴を組み立てられる
LLMのパラメータが「数十億」と言われるのは、この重みとバイアスの数のことです。
学習の流れ
学習は、次の4つの繰り返しです。
- 予測:今の重みで、入力から出力を計算する(順伝播)
- 損失:予測と正解のずれを、1つの数にする
- 勾配:損失を減らすには、各重みをどちらへ、どれだけ動かせばよいかを計算する。出力側から入力側へ、順に計算するので誤差逆伝播法と呼ぶ
- 更新:勾配の逆向きに、重みを少しだけ動かす(勾配降下法)。動かす幅が学習率
小さな例:XORを学ぶ
XORは、2つの入力が違うときだけ1になる関数です。直線1本では分けられないので、隠れ層が要ります。NumPyだけで、上の4つの手順をそのまま書きました(筆者が実行した結果を載せています)。
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の中身で扱います。