学習プロセス
学習目標: PyTorchでの学習ループの実装方法を理解する
学習ループの基本構造
import torch
import torch.nn as nn
import torch.optim as optim
# 1. モデル、損失関数、最適化アルゴリズムの準備
model = MyModel()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# 2. 学習ループ
for epoch in range(num_epochs):
model.train() # 訓練モードに設定
for batch_idx, (data, target) in enumerate(train_loader):
# 勾配をリセット
optimizer.zero_grad()
# 順伝播
output = model(data)
# 損失計算
loss = criterion(output, target)
# 逆伝播
loss.backward()
# パラメータ更新
optimizer.step()
print(f"Epoch {epoch+1}, Loss: {loss.item():.4f}")
損失関数
分類タスク
nn.CrossEntropyLoss()- 多クラス分類nn.BCELoss()- 二値分類(Sigmoid出力後)nn.BCEWithLogitsLoss()- 二値分類(Sigmoid込み)nn.NLLLoss()- 負の対数尤度
回帰タスク
nn.MSELoss()- 平均二乗誤差nn.L1Loss()- 平均絶対誤差nn.SmoothL1Loss()- Huber損失
最適化アルゴリズム
# SGD(確率的勾配降下法)
optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9)
# Adam(推奨)
optimizer = optim.Adam(model.parameters(), lr=0.001)
# AdamW(重み減衰付きAdam)
optimizer = optim.AdamW(model.parameters(), lr=0.001, weight_decay=0.01)
# 学習率スケジューラ
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)
検証ループ
def validate(model, val_loader, criterion, device):
model.eval() # 評価モードに設定
val_loss = 0
correct = 0
with torch.no_grad(): # 勾配計算を無効化
for data, target in val_loader:
data, target = data.to(device), target.to(device)
output = model(data)
val_loss += criterion(output, target).item()
pred = output.argmax(dim=1)
correct += (pred == target).sum().item()
val_loss /= len(val_loader)
accuracy = correct / len(val_loader.dataset)
return val_loss, accuracy
完全な学習コード
def train_model(model, train_loader, val_loader, epochs=10):
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
for epoch in range(epochs):
# 訓練フェーズ
model.train()
train_loss = 0
for data, target in train_loader:
data, target = data.to(device), target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
train_loss += loss.item()
# 検証フェーズ
val_loss, val_acc = validate(model, val_loader, criterion, device)
print(f"Epoch {epoch+1}/{epochs}")
print(f" Train Loss: {train_loss/len(train_loader):.4f}")
print(f" Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}")
理解度チェック
Q. 学習ループで optimizer.zero_grad() を呼ぶタイミングは?