评估图像分类器

PyTorch 深度学习进阶

Michal Oleszak

Machine Learning Engineer

测试时的数据增强

训练数据的数据增强:

train_transforms = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.RandomRotation(45),
    transforms.RandomAutocontrast(),
    transforms.ToTensor(),
    transforms.Resize((64, 64)),
])

dataset_train = ImageFolder(
  "clouds_train", 
  transform=train_transforms,
)

测试数据的数据增强:

test_transforms = transforms.Compose([
    #
    # 测试时不做数据增强
    #
    transforms.ToTensor(),
    transforms.Resize((64, 64)),
])

dataset_test = ImageFolder(
  "clouds_test", 
  transform=test_transforms,
)
PyTorch 深度学习进阶

Precision 与 Recall:二分类

二分类中:

  • Precision:预测为正的样本中有多少是对的
  • Recall:所有正样本中有多少被正确预测

一个 2x2 混淆矩阵,四个格子用不同颜色标记;旁边用这些颜色给出 recall 和 precision 的公式。

PyTorch 深度学习进阶

Precision 与 Recall:多分类

多分类中:为每个类别分别计算 precision 和 recall

  • Precision:预测为积云的样本中有多少是对的
  • Recall:所有积云样本中有多少被正确预测

 

积云图片

PyTorch 深度学习进阶

多类指标的平均方式

  • 7 个类别 → 7 个 precision 和 7 个 recall
  • 可逐类分析,或聚合:
    • Micro 平均:全局计算
    • Macro 平均:各类指标的平均
    • 加权平均:按类权重加权的平均
PyTorch 深度学习进阶

多类指标的平均方式

from torchmetrics import Recall

recall_per_class = Recall(task="multiclass", num_classes=7, average=None)
recall_micro = Recall(task="multiclass", num_classes=7, average="micro")
recall_macro = Recall(task="multiclass", num_classes=7, average="macro")
recall_weighted = Recall(task="multiclass", num_classes=7, average="weighted")

各平均方式的使用场景:

  • Micro:类别不均衡
  • Macro:关注小类表现
  • Weighted:大类错误更重要
PyTorch 深度学习进阶

评估循环

from torchmetrics import Precision, Recall

metric_precision = Precision(
  task="multiclass", num_classes=7, average="macro"
)
metric_recall = Recall(
  task="multiclass", num_classes=7, average="macro"
)

net.eval() with torch.no_grad(): for images, labels in dataloader_test:
outputs = net(images) _, preds = torch.max(outputs, 1) metric_precision(preds, labels) metric_recall(preds, labels)
precision = metric_precision.compute() recall = metric_recall.compute()
  • 导入并定义 precision 和 recall 指标
  • 在测试集上无梯度迭代
  • 每个批次:获取输出、取概率最高的类,并与标签一起传给指标函数
  • 计算最终指标
print(f"Precision: {precision}")
print(f"Recall: {recall}")
Precision: 0.7284010648727417
Recall: 0.763038694858551
PyTorch 深度学习进阶

按类别分析性能

metric_recall = Recall(
  task="multiclass", num_classes=7, average=None
)
net.eval()
with torch.no_grad():
    for images, labels in dataloader_test:
        outputs = net(images)
        _, preds = torch.max(outputs, 1)
        metric_recall(preds, labels)
recall = metric_recall.compute()
print(recall)
tensor([0.6364, 1.0000, 0.9091, 0.7917, 
        0.5049, 0.9500, 0.5493],
       dtype=torch.float32)
  • 使用 average=None 计算
  • 得到每个类别各一分数
  • Dataset.class_to_idx 属性将类名映射到索引
dataset_test.class_to_idx
{'cirriform clouds': 0,
 'clear sky': 1,
 'cumulonimbus clouds': 2,
 'cumulus clouds': 3,
 'high cumuliform clouds': 4,
 'stratiform clouds': 5,
 'stratocumulus clouds': 6}
PyTorch 深度学习进阶

按类别分析性能

{
  k: recall[v].item() 
  for k, v 
  in dataset_test.class_to_idx.items()
}
{'cirriform clouds': 0.6363636255264282,
 'clear sky': 1.0,
 'cumulonimbus clouds': 0.9090909361839294,
 'cumulus clouds': 0.7916666865348816,
 'high cumuliform clouds': 0.5048543810844421,
 'stratiform clouds': 0.949999988079071,
 'stratocumulus clouds': 0.5492957830429077}
  • k = 类名,如 cirriform clouds
  • v = 类索引,如 0
  • recall[v] = tensor(0.6364, dtype=torch.float32)
  • recall[v].item() = 0.6364
PyTorch 深度学习进阶

Passons à la pratique !

PyTorch 深度学习进阶

Preparing Video For Download...