Практическая многоцелевая классификация с использованием Python

Обзор подходов, показателей оценки и лучших практик

Введение

В настоящее время я работаю над разработкой алгоритма машинного обучения, способного идентифицировать различные типы повреждений, обнаруженных в зданиях. Повреждения не все одинаковы, у каждого из них разные причины и риски, поэтому мы выделили около 4 разных типов переломов. Затем алгоритм будет развернут на беспилотнике, который автоматически будет фотографировать здание и сможет сказать, что и какова серьезность повреждений в здании.

Очевидно, что на фотографии, сделанной дроном, могут быть разные типы повреждений, по этой причине дрон, которому предоставлена ​​фотография, должен уметь идентифицировать все различные классы повреждений, присутствующие на фотографии, а не только один. Вот почему я начал изучать так называемую задачу многоцелевой классификации. И я пишу эту статью в надежде, что она будет полезна и вам.

Что такое многоцелевая классификация?

Многоцелевая классификация — это тип задачи машинного обучения, который включает прогнозирование нескольких меток для одного образца. В отличие от традиционной бинарной или мультиклассовой классификации, где каждый образец относится к одному классу, многоцелевая классификация позволяет образцу принадлежать к нескольким классам одновременно. Это может быть полезно в ситуациях, когда один образец может иметь несколько соответствующих ярлыков, например новостная статья, которую можно классифицировать как о политике, спорте и развлечениях одновременно.

Давайте посмотрим на пример, чтобы понять различные типы классификаций.

Существует несколько подходов к решению задач многоцелевой классификации, включая использование бинарных классификаторов, многоклассовых классификаторов и многозадачного обучения. В этой статье мы рассмотрим различные типы многоцелевой классификации и обсудим их плюсы и минусы. Мы также рассмотрим показатели оценки для многоцелевой классификации. Наконец, я предложу некоторые личные взгляды и выводы о преимуществах и ограничениях многоцелевой классификации и передовых методах достижения успеха.

Типы многоцелевой классификации

Существует несколько подходов к многоцелевой классификации, каждый из которых имеет свои преимущества и ограничения.

Бинарные классификаторы

Одним из подходов к многоцелевой классификации является использование нескольких бинарных классификаторов, каждый из которых обучен предсказывать один ярлык. Например, если у нас есть задача многоцелевой классификации с тремя метками (A, B и C), мы можем обучить три отдельных бинарных классификатора: один для предсказания метки A, один для предсказания метки B и один для предсказания метки C, а затем запустить все три модели для классификации экземпляра. Этот подход прост и удобен в реализации, но может оказаться неэффективным, если количество меток велико. Кроме того, на производительность классификаторов может повлиять несбалансированное распределение меток в обучающих данных.

Мультиклассовые классификаторы

Другой подход к многоцелевой классификации заключается в использовании многоклассового классификатора, который предназначен для одновременного прогнозирования нескольких меток. Существует несколько типов мультиклассовых классификаторов, в том числе один против остальных и один против одного.

  • Классификаторы один против остальных (OvR) обучены принимать бинарное решение для каждого ярлыка, рассматривая все остальные ярлыки как отрицательный класс. Например, в случае трех меток (A, B и C) классификатор OvR будет обучен предсказывать метка A против не-A, ярлык B против не-B и ярлык C против не-C. Таким образом, вы окажетесь в случае наличия нескольких бинарных классификаций, как было показано ранее. Этот подход прост и эффективен, но он может страдать от несбалансированного распределения меток и может не учитывать зависимости между метками.
  • Один на один (OvO) классификаторы обучены принимать двоичные решения для каждой пары ярлыков. Например, в случае трех меток (A, B и C) классификатор OvO будет обучен предсказывать A и B, A и C, и B против C. Этот подход требует больше вычислительных ресурсов, чем OvR, но он может обрабатывать несбалансированные распределения меток и фиксировать зависимости между метками.

Многозадачное обучение

Многозадачное обучение — это тип машинного обучения, который включает в себя обучение модели прогнозированию нескольких задач одновременно. В контексте многоцелевой классификации многозадачное обучение состоит в обучении одной модели предсказанию всех меток для выборки.

Если задачи похожи, например, вам нужно классифицировать разные типы дефектов или вам нужно классифицировать наличие автомобиля, велосипеда и грузовика, этот подход более эффективен чем использование нескольких бинарных или мультиклассовых классификаторов, но требуется большой объем размеченных данных и твердое предположение, что задачи связаны.

Давайте программировать!

Давайте посмотрим, как реализовать алгоритм многозадачного обучения в области компьютерного зрения, а также применить методологию трансферного обучения.

Что я хочу сделать, так это взять сеть, которая предварительно обучена распознаванию изображений, например Resnet (конечно, вы можете использовать другие) и модифицировать ее так, чтобы она могла решать несколько задач одновременно. .

Что обычно делается в случаях мультиклассовой классификации, так это использование Resnet и присоединение к нему классификатора, который имеет столько выходных нейронов, сколько классов в наборе данных, и, таким образом, получает класс для каждого экземпляра.

Однако мы хотим распознавать не один класс, а несколько классов одновременно, поэтому мы просто прикрепим несколько классификаторов (линейных слоев) поверх Resent.

Однако в нашем случаекаждый классификатор является бинарным, ему нужно только сообщить нам, присутствует ли автомобиль, велосипед или грузовик.
Чтобы создать бинарный классификатор, мы только нужен один выходной нейрон, чтобы ответить нет/да. Таким образом, сетевая архитектура довольно проста.

В более общем случае, когда вам нужно 3 мультиклассовых классификатора, архитектура должна быть следующей.

Давайте посмотрим, как на самом деле реализовать такую ​​сеть с помощью PyTorch.

class ResnetBasedModel(nn.Module):
    def __init__(self, pretrained, clf_in_features,  labels_nr:int, freeze:bool = True):
        super().__init__()
    
        self.pretrained_model = pretrained
        #model without last layer
        self.model_wo_fc = nn.Sequential(*(list(self.pretrained_model.children())[:-1])) 
        
        if freeze:
            for param in self.model_wo_fc.parameters():
                param.requires_grad = False
        
        self.classifiers = nn.ModuleDict()
                
        for i in range(labels_nr):
            self.classifiers[f'clf_{i}'] = nn.Sequential(
                nn.Dropout(p=0.2),
                nn.Linear(in_features = clf_in_features, out_features = 1)
            )

    def forward(self, x):
        x = self.model_wo_fc(x)
        x = torch.flatten(x, 1)
        
        return {name: classifier(x) for name, classifier in self.classifiers.items()}

Предыдущий код реализует класс Python, который наследует nn.Module, что является классическим способом создания модели на основе нейронной сети.

Модель принимает в качестве входных данных предварительно обученную сеть, такую ​​как Resnet (предварительно обученная), она принимает в качестве входных данных количество выходных нейронов предпоследнего слоя предварительно обученной сети (clf_in_features ), например, в Resnet34 это число равно 512, а в Resnet50–101 — 2048.

Класс также принимает на вход количество выходных двоичных классификаторов (labels_nr) и то, хотим ли мы освободить параметры предварительно обученной сети (заморозить).

Давайте посмотрим подробнее, как работает этот класс.

Следующий цикл используется для освобождения параметров предварительно обученной сети, чтобы мы собирались буксировать только выходные классификаторы, это значительно ускорит наше обучение.

if freeze:
    for param in self.model_wo_fc.parameters():
        param.requires_grad = False

После этого я создаю столько классификаторов, сколько указано в аргументах, сохраняя их в словаре.

for i in range(labels_nr):
      self.classifiers[f'clf_{i}'] = nn.Sequential(
          nn.Dropout(p=0.2),
          nn.Linear(in_features = clf_in_features, out_features = 1)
      )

В конце концов, в прямом методе я передаю каждый ввод x для предварительно обученной сети и для каждого классификатора в словаре и возвращаю вывод каждого элемента (классификатора) в словаре.

def forward(self, x):
        x = self.model_wo_fc(x)
        x = torch.flatten(x, 1)
        
        return {name: classifier(x) for name, classifier in self.classifiers.items()}

Теперь вы можете использовать свою сеть для многоцелевой классификации. Помните, что для создания экземпляра предварительно обученной сети и передачи ее в качестве входных данных в класс вам нужно использовать только модуль PyTorch Torchvision.

from torchvision import models

resnet34 = models.resnet34(weights=models.ResNet34_Weights.DEFAULT)

Чтобы обучить модель, вам нужно будет создать экземпляр функции потерь для каждого классификатора и суммировать эти потери. В результате вы можете обновить всю модель,

def criterion(y, yhat):
    '''y : is a dict with keys 'labels' and 'path'''
    losses = 0
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    for _, key in enumerate(yhat):
        losses += loss_func(yhat[key], y[f'label_{key}'].float().unsqueeze(1).to(device))
return losses

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

Оценка производительности модели многоцелевой классификации может быть сложной задачей, поскольку необходимо учитывать несколько меток и различные способы их комбинирования. Вот некоторые общие показатели оценки для многоцелевой классификации:

Потери Хэмминга. Этот показатель измеряет долю ошибочно предсказанных меток. Он рассчитывается как количество ошибочно классифицированных меток, деленное на общее количество меток.

Это метрика, которую я предпочел использовать для оценки моей модели, и вот реализация потери Хэмминга.

def hamming_error(yhat:list, y:list) -> float:
    loss = sum([yhat_i != y_i for yhat_i, y_i in zip(yhat, y)])
    avg_loss = loss/len(yhat) 

    return avg_loss

В этом фрагменте элементы двух массивов сравниваются попарно и возвращается среднее значение найденных несоответствий. Этот код можно легко обобщить для одновременного сравнения целых пакетов.
Давайте быстро рассмотрим другие показатели, используемые в этой области.

  • Потеря рейтинга. Этот показатель измеряет среднее количество ошибочно ранжированных ярлыков для выборки. Например, если выборка имеет метки A, B и C, а модель предсказывает метки в порядке C, B, A, потеря при ранжировании равна 2 (поскольку B и C ранжированы неправильно).
  • Индекс Жаккара. Этот показатель измеряет совпадение между предсказанными и истинными метками для выборки. Он рассчитывается как размер пересечения, деленный на размер объединения.
  • Оценка F1. Эта метрика представляет собой баланс между точностью и полнотой, где точность – это доля правильных спрогнозированных меток, а полнота – доля спрогнозированных истинных меток. Он рассчитывается как среднее гармоническое точности и полноты. Чтобы использовать оценку F1 для многоцелевой классификации, вам потребуется вычислить точность и полноту для каждой метки отдельно, а затем усреднить оценки по всем меткам, чтобы получить общую оценку F1. Эта метрика более чувствительна к несбалансированному распределению меток по сравнению с предыдущими метриками.
F1 = 2 * (precision * recall) / (precision + recall)
  • Средняя точность. Этот показатель измеряет точность каждого значения полноты для всех выборок в наборе данных. Он рассчитывается как среднее значение точности при первом ложном срабатывании, втором ложном срабатывании и т. д.
Average precision = (1/n) * Σ(precision at each recall value)

Чтобы вычислить среднюю точность для нескольких меток, вы можете просто усреднить среднюю точность для каждой метки. Например, если у вас есть три метки (A, B и C), вы можете рассчитать среднюю точность для каждой метки, используя приведенную выше формулу, а затем усреднить баллы, чтобы получить общую среднюю точность. Это также чувствительно к несбалансированному распределению.

Проблемы оценки многоцелевых моделей классификации

Оценка многоцелевых моделей классификации может быть сложной из-за следующих факторов:

  • Несбалансированное распределение меток: некоторые метки могут быть более распространенными, чем другие, что может повлиять на производительность модели. Например, если метка встречается редко, у модели может не хватить примеров для обучения, что приведет к снижению производительности.
  • Зависимости между метками: некоторые метки могут с большей вероятностью встречаться вместе, чем другие, что может повлиять на производительность модели. Например, если модель обучена прогнозировать метки A и B, но метке A всегда предшествует метка B, у модели могут возникнуть трудности с прогнозированием метки A без прогнозирования метки B.
  • Метрики оценки с несколькими метками. Существует несколько метрик оценки для многоцелевой классификации, каждая из которых имеет свои сильные стороны и ограничения. Выбор правильной метрики может быть затруднен, так как это зависит от конкретных требований задачи и характеристик данных.

Последние мысли

Многоцелевая классификация — это мощный инструмент для решения задач, связанных с прогнозированием нескольких меток для одного образца. Его можно применять к широкому спектру реальных приложений, таких как классификация текста, аннотации изображений и системы рекомендаций.

Существует несколько подходов к многоцелевой классификации, включая бинарные классификаторы, многоклассовые классификаторы и многозадачное обучение. Выбор подхода зависит от конкретных требований задачи и характеристик данных.

Оценка производительности многоцелевой модели классификации может быть затруднена из-за несбалансированного распределения меток, зависимостей между метками и наличия нескольких метрик оценки. Важно выбрать правильную метрику оценки и сравнить производительность модели с базовым уровнем.

Конец

Марчелло Полити

Linkedin, Twitter, CV