評估影像分類器

Intermediate Deep Learning with 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([
    #
    # NO DATA AUGMENTATION AT TEST TIME
    #
    transforms.ToTensor(),
    transforms.Resize((64, 64)),
])

dataset_test = ImageFolder(
  "clouds_test", 
  transform=test_transforms,
)
Intermediate Deep Learning with PyTorch

Precision 與 Recall:二元分類

在二元分類中:

  • Precision(精確率):預測為正類且正確的比例
  • Recall(召回率):所有正類中被正確預測的比例

一個 2×2 的混淆矩陣,四個格子以不同顏色標示;旁邊以這些顏色代碼表示精確率與召回率公式。

Intermediate Deep Learning with PyTorch

Precision 與 Recall:多類別分類

在多類別分類中:為每個類別分別計算 precision 與 recall

  • Precision:預測為 cumulus 的樣本中,正確的比例
  • Recall:所有 cumulus 樣本中,被正確預測的比例

 

積雲(cumulus)照片

Intermediate Deep Learning with PyTorch

多類別評分的平均方式

  • 有 7 個類別,就有 7 個 precision 與 7 個 recall 分數
  • 你可以逐類分析,或彙整成:
    • Micro 平均:全域計算
    • Macro 平均:各類別分數的算術平均
    • 加權平均:各類別分數的加權平均
Intermediate Deep Learning with 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:較重視大類別的錯誤
Intermediate Deep Learning with 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
Intermediate Deep Learning with 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}
Intermediate Deep Learning with 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
Intermediate Deep Learning with PyTorch

一起來練習吧!

Intermediate Deep Learning with PyTorch

Preparing Video For Download...