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

В чем проблема несбалансированных занятий?

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

Примеры

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

Почему это проблема?

Несбалансированные классы создают проблему по двум основным причинам:

  1. Мы не получаем оптимизированных результатов для класса, который не сбалансирован в реальном времени, так как модель / алгоритм никогда не получает достаточного представления о базовом классе.
  2. Это создает проблему создания проверочной или тестовой выборки, поскольку трудно иметь представление по классам в случае, если количество наблюдений для нескольких классов чрезвычайно мало.

Какие подходы используются для решения этой проблемы?

Предлагается три основных подхода, каждый из которых имеет свои плюсы и минусы:

  1. Недостаточная выборка - случайным образом удалите класс, имеющий достаточное количество наблюдений, чтобы сравнительное соотношение двух классов было значимым в наших данных. Хотя этот подход действительно прост, но существует высокая вероятность того, что данные, которые мы удаляемые могут содержать важную информацию о прогнозирующем классе.
  2. Передискретизация - для несбалансированного класса случайным образом увеличьте количество наблюдений, которые являются просто копиями существующих выборок. Это в идеале дает нам достаточное количество выборок, с которыми можно поиграть. Передискретизация может привести к переобучению обучающих данных
  3. Синтетическая выборка (SMOTE) - метод требует синтетического производства наблюдений несбалансированных классов, которые аналогичны существующим с использованием классификации ближайших соседей. Проблема в том, что делать, когда количество наблюдений чрезвычайно редкий класс. Например, у нас может быть только одно изображение редкого вида, которое мы хотим идентифицировать с помощью алгоритма классификации изображений.

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

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

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

Проблема. Мы выбрали «Задачу по идентификации горбатых китов» на kaggle, которую, как мы ожидали, предстоит решить для несбалансированных классов (так как в идеале количество классифицированных китов будет меньше, чем неклассифицированные, также будет несколько редких видов китов, для которых у нас будет меньше изображений)

От kaggle: «В этом соревновании вам предстоит создать алгоритм для определения видов китов на изображениях. Вы проанализируете базу данных Happy Whale, содержащую более 25 000 изображений, собранных исследовательскими учреждениями и общественными авторами. Внося свой вклад, вы поможете открыть обширные области понимания динамики популяций морских млекопитающих по всему миру ».

Давайте начнем смотреть на данные

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

Приведенная выше таблица показывает, что из 4251 обучающих изображений более 2000 имеют только одно изображение на класс. Существуют также классы с ~ 2–5 изображениями. Теперь это серьезная проблема несбалансированных классов. не могу ожидать, что модель DL будет обучаться, используя только одно изображение для каждого класса (хотя есть алгоритмы, которые могут просто делать это, например, классификация одного кадра, но мы на данный момент игнорируем это). Это также создает проблему, как создать разделение Между обучающей и проверочной выборкой. В идеале вы хотите, чтобы каждый из классов был представлен как в обучающей, так и в проверочной выборке.

Что нам теперь делать?

В частности, мы рассмотрели два варианта:

option1 - Строгое увеличение данных в обучающей выборке (мы могли бы это сделать, но поскольку нам нужно увеличение данных только для определенных классов, это может не решить нашу задачу полностью). Поэтому я выбрал вариант 2, который выглядел достаточно просто попробовать.

option2- Похож на вариант с передискретизацией, о котором я упоминал выше. Я просто скопировал изображения несбалансированных классов обратно в обучающие данные 15 раз, используя различные методы дополнения изображений. Это вдохновлено Джереми Ховардом , который, я полагаю, упомянул об этом в одной из лекций по глубокому обучению части 1 fast.ai course.

Прежде чем мы начнем с варианта-2, давайте рассмотрим несколько изображений из обучающей выборки.

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

Я также заметил, что в данных есть много изображений, которые являются конкретными черно-белыми или только каналами R / B / G.

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

import os
from PIL import Image
from PIL import ImageFilter
filelist = train['Image'].loc[(train['cnt_freq']<10)].tolist()
for count in range(0,2):
  
  for imagefile in filelist:
    os.chdir('/home/paperspace/fastai/courses/dl1/data/humpback/train')
    im=Image.open(imagefile)
    im=im.convert("RGB")
    r,g,b=im.split()
    r=r.convert("RGB")
    g=g.convert("RGB")
    b=b.convert("RGB")
    im_blur=im.filter(ImageFilter.GaussianBlur)
    im_unsharp=im.filter(ImageFilter.UnsharpMask)
    
    os.chdir('/home/paperspace/fastai/courses/dl1/data/humpback/copy')
    r.save(str(count)+'r_'+imagefile)
    g.save(str(count)+'g_'+imagefile)
    b.save(str(count)+'b_'+imagefile)
    im_blur.save(str(count)+'bl_'+imagefile)
    im_unsharp.save(str(count)+'un_'+imagefile)

Вышеупомянутый блок кода выполняет следующие действия с каждым из изображений в несбалансированном классе (которые имеют частоту менее 10):

  1. Сохраните увеличенную копию каждого изображения как R / B и G
  2. Сохраните увеличенную копию каждого изображения, которое размыто.
  3. Сохраните увеличенную копию каждого изображения, которое нечетко

Мы строго использовали подушку (библиотека изображений Python) для этого упражнения, как видно из приведенного выше кода.

Теперь у нас есть по всем несбалансированным классам минимум 10 образцов, и мы приступили к обучению.

Увеличение изображения - мы сохранили это просто. Мы только хотели убедиться, что наша модель может получить подробный вид двуустки кита. Для этого мы включили увеличение в увеличение изображения.

Средство поиска скорости обучения - Мы выбрали скорость обучения 0,01, что было обозначено как lr find.

Мы выполнили несколько итераций с использованием Resnet50 (сначала замороженные и размороженные). Оказалось, что замороженная модель также неплохо подходит для этой постановки задачи, так как есть изображения китовых сосальщиков в imagesenet.

epoch      trn_loss   val_loss   accuracy                     
    0      1.827677   0.492113   0.895976  
    1      0.93804    0.188566   0.964128                      
    2      0.844708   0.175866   0.967555                      
    3      0.571255   0.126632   0.977614                      
    4      0.458565   0.116253   0.979991                      
    5      0.410907   0.113607   0.980544                      
    6      0.42319    0.109893   0.981097

Как это соотносится с тестовыми данными?

Наконец, момент истины в таблице лидеров kaggle. Решение предложило 34 место в этом соревновании со средней средней точностью @ 5 0,41928 :)

Заключение

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