学習プロセス

学習目標: 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() を呼ぶタイミングは?