第9章
学習と推論の違いを見比べたい
似たコードに見えても、重みが動くかどうかで中身はかなり違います。
今日は何をしたい?
推論は「答えを出すだけ」、学習は「答えを出してから直すまで」です。この違いを、同じモデルを使った短いコードで見比べて、自分の言葉で説明できるようにします。
| 推論 | 学習 | |
|---|---|---|
| forward(答えを出す) | する | する |
| loss(ずれを測る) | しない | する |
| backward(勾配を計算) | しない | する |
| step(重みを更新) | しない | する |
| 重みが変わるか | 変わらない | 変わる |
確認コード
import torch
import torch.nn as nn
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = nn.Linear(1, 1).to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.1)
x = torch.tensor([[1.0]], device=device)
y_true = torch.tensor([[2.0]], device=device)
# 変化を追うため、学習前の重みの値をコピーして保存しておきます
before = model.weight.detach().clone()
# --- 推論(forward だけ) ---
model.eval()
with torch.no_grad():
answer = model(x)
# --- 学習(forward → loss → backward → step) ---
model.train()
# (model(x) - y_true).pow(2).mean() は第8章の nn.MSELoss() と同じ計算を手書きしています
loss = (model(x) - y_true).pow(2).mean()
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 学習後の重みをコピーして、変化を確認します
after = model.weight.detach().clone()
print("inference output:", answer.item())
print("weight changed:", not torch.equal(before, after))このコードでは、前半が推論、後半が学習です。最後の weight changed が True なら、「学習側では重みが動いた」と読めます。
inference output: 0.3127
weight changed: True
weight changed: True が見えれば、「学習側では重みが動いた」と確認できます。推論 vs 学習の違いはこの 1 行に出ます。
実行コマンド
ファイルを chapter09.py という名前で保存したら、ターミナルで次のコマンドを実行します。
python chapter09.pyどこがROCm?
推論は forward だけ、学習は forward に加えて backward(勾配の計算)と step(重みの更新)も入ります。ROCm の見方では、学習のほうが GPU にやらせる仕事がずっと多くなります。特に backward の勾配計算は大量の行列演算を含むため、GPU の並列処理が効きやすい場面です。
ここで出てきたPython
- before / after を比べて変化を確認
- not torch.equal(...) — 真偽を反転して読む
eval() だけでは不十分な理由(クリックで開く)
model.eval() だけでは「絶対に学習しない」わけではありません。学習しない流れは no_grad() とセットで見ると分かりやすいです。推論で答えを出しても、重みは変わりません。
よくあるつまずき
- model.eval() だけでは「絶対に学習しない」わけではありません。学習しない流れは no_grad() とセットで見ると分かりやすいです。
- 推論で答えを出しても、重みは変わりません。
- 学習の後半だけを見ていると、何が増えたのかが見えにくいので、前半との対比が大切です。
1分演習
optimizer.step() を一度コメントアウトして、weight changed がどう変わるかを見てみましょう。