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

Классификация Multilabel отличается от классификации Multiclass. В классификации мультиклассов каждый образец принадлежит только к одному из множества классов. Но в классификации Multilabel один образец может принадлежать более чем одному классу.

Набор данных, который мы используем для этого проекта, представляет собой набор данных Multi-instance Multi-Label Learning, доступный здесь.

Этот пакет состоит из двух частей:

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

Набор данных изображения состоит из 2000 изображений естественной сцены, где каждому изображению назначен набор меток. Количество изображений, принадлежащих более чем к одному классу (например, море + закат), составляет более 22% набора данных, многие комбинированные классы (например, горы + закат + деревья) крайне редки. В среднем каждому изображению соответствует 1,24 метки класса. Всего существует 5 различных меток: пустыня, горы, море , закат, деревья.

«Обработанная» часть этого пакета содержит данные с несколькими экземплярами с несколькими метками (в формате MATLAB), полученные из изображений естественной сцены. Этот файл можно прочитать с помощью scipy.io.loadmat, а затем преобразовать в фрейм данных для простоты использования. Столбец target содержит метки, а поле class_names содержит имена классов.

А теперь давайте попробуем свои силы в этой задаче. В этом посте мы будем использовать Keras. Однако большая часть части, такой как обработка данных и создание генератора данных (загрузчик данных в PyTorch), будет аналогична при использовании PyTorch. Только код для построения модели и обучения будет отличаться. Остальная часть - это простой питон!

Весь код был запущен в Google Colab, поэтому перед запуском на локальном компьютере необходимо изменить несколько путей и команд Linux.

Импорт необходимых библиотек

Загрузка и извлечение данных

Обработка данных

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

После этого шага DataFrame data_df выглядит так

Результат последней строки приведенного выше фрагмента кода

Поскольку очень очевидно, что набор данных в нашей руке сильно несбалансирован, если мы посмотрим на гистограмму, созданную из преобразованных меток.

Гистограмма для каждой отдельной метки

Перед разделением набора данных на набор данных для обучения и проверки

Отдельные метки также несбалансированы.

Разделение данных

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

После разделения набора данных распределение данных в обучающем наборе train_df отображается с графиком гистограммы отдельных меток.

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

Передискретизация

Гистограмма меток Powerset после передискретизации

Гистограмма отдельных меток классов после передискретизации

Как мы можем ясно видеть, что после передискретизации в соответствии с пропорциями меток Powerset отдельные классы все еще остаются несбалансированными. Итак, для обучения модели CNN мы будем использовать Weighted Loss во время процедуры обучения.

Для каждого ярлыка (например, пустыня) мы рассмотрим наличие (1) и отсутствие (0 ) метки как два класса. Встречаемость - это положительные и меньшинство, а Отсутствие считается отрицательным и основным классом.

Расчет весов классов

Для расчета весов классов мы следуем тому же принципу, что и в scikit-learn.

Расчет размеров изображения

Затем нам нужно создать генератор данных.

Генератор данных

Проверка данных

Объявить фиктивный генератор данных

tdg = DataGeneratorKeras(True,True,preprocess_input,16)

Вызовите метод __getitem__(0), чтобы получить 16 изображений и этикеток.

Результат выглядит как

Из приведенного выше изображения мы можем сказать, что изображение, выводимое генератором данных, соответствует нашим требованиям.

Создание генераторов обучающих и проверочных данных

Создание модели

Model: “sequential” _________________________________________________________________ Layer (type)                Output Shape                Param # ================================================================= resnet50 (Model)            (None, 2048)                23587712 _________________________________________________________________ dense (Dense)               (None, 5)                   10245 ================================================================= Total params: 23,597,957 
Trainable params: 23,544,837 
Non-trainable params: 53,120 _________________________________________________________________

Пользовательская функция потерь для несбалансированных классов

Скомпилировать модель

Epoch 1/10 loss: 2.5940 - binary_accuracy: 0.7481 - auc: 0.8399 - val_loss: 2.2787 - val_binary_accuracy: 0.7620 - val_auc: 0.8596 Epoch 2/10 loss: 1.5246 - binary_accuracy: 0.8951 - auc: 0.9629 - val_loss: 1.8206 - val_binary_accuracy: 0.8422 - val_auc: 0.9189 Epoch 3/10 lss: 1.1148 - binary_accuracy: 0.9292 - auc: 0.9814 - val_loss: 1.5445 - val_binary_accuracy: 0.8755 - val_auc: 0.9392 Epoch 4/10 loss: 0.8195 - binary_accuracy: 0.9487 - auc: 0.9893 - val_loss: 1.2648 - val_binary_accuracy: 0.8891 - val_auc: 0.9506 Epoch 5/10 loss: 0.6824 - binary_accuracy: 0.9586 - auc: 0.9928 - val_loss: 1.6201 - val_binary_accuracy: 0.9036 - val_auc: 0.9589 Epoch 6/10 loss: 0.5583 - binary_accuracy: 0.9655 - auc: 0.9952 - val_loss: 1.0191 - val_binary_accuracy: 0.9120 - val_auc: 0.9587 Epoch 7/10 loss: 0.4702 - binary_accuracy: 0.9719 - auc: 0.9961 - val_loss: 1.0357 - val_binary_accuracy: 0.9203 - val_auc: 0.9654 Epoch 8/10 loss: 0.4685 - binary_accuracy: 0.9749 - auc: 0.9967 - val_loss: 0.9998 - val_binary_accuracy: 0.9250 - val_auc: 0.9647 Epoch 9/10 loss: 0.3911 - binary_accuracy: 0.9773 - auc: 0.9974 - val_loss: 0.8011 - val_binary_accuracy: 0.9260 - val_auc: 0.9664 Epoch 10/10 loss: 0.3445 - binary_accuracy: 0.9804 - auc: 0.9976 - val_loss: 1.0636 - val_binary_accuracy: 0.9281 - val_auc: 0.9711

Построение метрик

Сюжеты представлены ниже

Мы видим, что есть небольшое переоснащение, которое можно исправить с помощью соответствующих техник.

Показатели эффективности

Код для получения указанного выше результата можно найти здесь.



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

Кривые ROC, кривые PR и матрицы неточностей.

Ярлыки расположены в следующем порядке: пустыня, горы, море. , закат, деревья.

Визуализация некоторых прогнозов на валидационном наборе

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



Хлопайте, если вам понравился пост или вы думаете, что он окажется полезным для других учеников!