Оценка классификаторов изображений

Глубокое обучение на 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,
)
Глубокое обучение на PyTorch: средний уровень

Точность и полнота: бинарная классификация

В бинарной классификации:

  • Точность (Precision): доля верных положительных предсказаний
  • Полнота (Recall): доля правильно предсказанных положительных примеров

Матрица ошибок 2×2, каждая из четырёх ячеек выделена своим цветом; рядом — формулы полноты и точности, выраженные через цветовые обозначения.

Глубокое обучение на PyTorch: средний уровень

Точность и полнота: многоклассовая классификация

В многоклассовой классификации: точность и полнота вычисляются для каждого класса отдельно

  • Точность (Precision): доля верных предсказаний класса «cumulus»
  • Полнота (Recall): доля правильно предсказанных примеров класса «cumulus»

 

Фотография облака кучевого типа

Глубокое обучение на PyTorch: средний уровень

Усреднение метрик многоклассовой классификации

  • При 7 классах получаем 7 значений точности и 7 значений полноты
  • Их можно анализировать по классам или агрегировать:
    • Микро-усреднение: глобальный расчёт
    • Макро-усреднение: среднее значений по классам
    • Взвешенное усреднение: взвешенное среднее значений по классам
Глубокое обучение на 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")

Когда применять каждый из вариантов:

  • Микро: несбалансированные наборы данных
  • Макро: когда важна точность на малых классах
  • Взвешенный: когда ошибки на крупных классах важнее
Глубокое обучение на 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()
  • Импортируем и определяем метрики точности и полноты
  • Итерируемся по тестовым примерам без вычисления градиентов
  • Для каждого батча получаем выходы модели, выбираем наиболее вероятный класс и передаём его в функции метрик вместе с метками
  • Вычисляем метрики
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
  • Это даёт одно значение на каждый класс
  • Атрибут .class_to_idx объекта Dataset сопоставляет имена классов с индексами
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: средний уровень

Давайте потренируемся!

Глубокое обучение на PyTorch: средний уровень

Preparing Video For Download...