可視化

学習目標: 学習過程とモデルの振る舞いを可視化する方法を学ぶ

学習曲線の可視化

import matplotlib.pyplot as plt

# 学習履歴を記録
history = {'train_loss': [], 'val_loss': [], 'train_acc': [], 'val_acc': []}

for epoch in range(epochs):
    train_loss, train_acc = train(...)
    val_loss, val_acc = validate(...)
    history['train_loss'].append(train_loss)
    history['val_loss'].append(val_loss)
    history['train_acc'].append(train_acc)
    history['val_acc'].append(val_acc)

# 可視化
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))

ax1.plot(history['train_loss'], label='Train')
ax1.plot(history['val_loss'], label='Val')
ax1.set_title('Loss')
ax1.legend()

ax2.plot(history['train_acc'], label='Train')
ax2.plot(history['val_acc'], label='Val')
ax2.set_title('Accuracy')
ax2.legend()

plt.show()

混同行列

from sklearn.metrics import confusion_matrix
import seaborn as sns

# 予測を収集
all_preds, all_labels = [], []
model.eval()
with torch.no_grad():
    for data, labels in test_loader:
        outputs = model(data)
        preds = outputs.argmax(dim=1)
        all_preds.extend(preds.cpu().numpy())
        all_labels.extend(labels.cpu().numpy())

# 混同行列を作成
cm = confusion_matrix(all_labels, all_preds)

# 可視化
plt.figure(figsize=(10, 8))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

特徴マップの可視化(CNN)

def visualize_feature_maps(model, image, layer_idx=0):
    # フックで中間層の出力を取得
    activations = []
    def hook(module, input, output):
        activations.append(output)

    # 最初の畳み込み層にフックを登録
    handle = list(model.features.children())[layer_idx].register_forward_hook(hook)

    # 順伝播
    model.eval()
    with torch.no_grad():
        model(image.unsqueeze(0))

    handle.remove()

    # 特徴マップを可視化
    act = activations[0].squeeze()
    fig, axes = plt.subplots(4, 8, figsize=(16, 8))
    for i, ax in enumerate(axes.flat):
        if i < act.shape[0]:
            ax.imshow(act[i].cpu(), cmap='viridis')
        ax.axis('off')
    plt.show()

TensorBoard

from torch.utils.tensorboard import SummaryWriter

writer = SummaryWriter('runs/experiment_1')

for epoch in range(epochs):
    train_loss = train(...)
    val_loss = validate(...)

    writer.add_scalar('Loss/train', train_loss, epoch)
    writer.add_scalar('Loss/val', val_loss, epoch)

writer.close()

# 実行: tensorboard --logdir=runs

理解度チェック

Q. 訓練損失は下がるが検証損失が上がる場合、何が起きている?