Дисбаланс классов

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

В задаче классификации данные называются несбалансированными (Imbalanced Data), если в обучающей выборке доли объектов разных классов существенно различаются, также говорят, что «классы не сбалансированы». Есть понятие несбалансированности и для задач регрессии, но там оно граничит с наличием аномалий в данных, поэтому здесь мы будем рассматривать только задачи классификации и для простоты – бинарной классификации. На рис. 1 (слева) схематически показан дисбаланс: розовым цветом – объекты «большого» класса 0 и синим – объекты «малого» класса 1. Не надо путать дисбаланс с разреженностью, на рис. 1 (справа) показаны данные в виде матрицы (например «user-item»), лишь для небольшого числа элементов матрицы известна метка, поэтому говорят о разреженности данных, но пропорции классов примерно равны.

Рис. 1. Несбалансированная задача классификации (слева) и разреженная сбалансированная задача (справа).

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

Что делать при дисбалансе?

Такой вопрос часто задают на собеседованиях, есть блог-заметки и ютуб-ролики на эту тему, почти все они дают ложное представление о дисбалансе. Обычно рекомендуют давать такой ответ – надо сделать перебалансировку данных: недо- или пере- сэмплирование (определим дальше), иногда вспоминают аббревиатуру SMOTE. Сейчас поговорим о том, что подобный ответ не учитывает теорию и практику классификации.

Во-первых, при ответе на вопрос надо обязательно уточнить природу задачи: в чём причина дисбаланса, сколько классов, насколько серьёзный дисбаланс, какими данными и мета-данными мы располагаем. Например, очень часто к дисбалансу приводит наличие дубликатов, первое напрашивающееся действие – устранить дубликаты. Также часто дисбаланс возникает в задаче с очень большим числом классов и некоторые классы малы по естественным причинам, например это генотипы представителей малых народов. Удивительно, но в этом случае бывает не так важно, относит ли алгоритм какие-то объекты к малым классам. Если позитивных (класса 1) объектов в обучении крайне мало, например 1-3 на 1 миллион объектов (а такие задачи бывают, например, когда позитивный класс – катастрофы или большие экономические кризисы), то задачу логично решать как детектирование аномалий (здесь мы не будем подробно описывать пайплайн решения). Дисбаланс может меняться со временем, например пропорции классов могут сильно отличаться в обучении и контроле – это отдельная ситуация и здесь логично «выравнивать» пропорции классов в обучении и контроле (чтобы обучение было похоже на контроль). Дисбаланс может быть из-за недостатка размеченных данных (например, порция данных с объектами класса 1 не была полностью размечена), тут есть варианты использования, например, синтетических данных. Наконец, всего перечисленного может не быть, у нас обычная бинарная задача классификации, пропорции классов не меняются со временем и процент объектов класса 1 – от 2% до 10%. Такую ситуацию и рассмотрим дальше (она соответствует, например, задаче банковского скоринга в стабильной экономической обстановке).

Во-вторых, надо уточнить функцию ошибки (функционал качества). Почему это важно? Если используется LogLoss, то каких-то «танцев с перебалансировкой» делать не только не нужно, но и недопустимо, поскольку это делает решение (алгоритм) неоткалиброванным. Если используется ROC AUC, то перебалансировка и многие другие рецепты не влияют на значение функционала (будет изменение в третьем знаке после запятой). Если используется F1-мера, то тут уже интереснее – подобные функции ниже и рассмотрим.

Но прежде чем говорить о настройке на F1-меру (и другие похожие на неё функционалы), давайте осознаем, а что означает эта настройка. Допустим у нас две корзины, в каждой 10 шаров, в первой – 1 чёрный, во второй тоже 1 чёрный, все остальные шары белые, см. рис. 2. Сейчас мы вытащим шар из корзины (это будет случайная корзина, они равновероятны, но мы будем знать из какой корзины берётся шар), надо угадать его цвет. Рассмотрим прогноз «шар белый», его точность (accuracy)

0.5 x 0.9 + 0.5 x 0.9 = 0.9,

его F1-мера равна нулю. Рассмотрим прогноз «шар из перовой корзины белый, а из второй – чёрный», его точность (accuracy)

0.5 x 0.9 + 0.5 x 0.1 = 0.5,

его F1-мера равна 1/(1/0.1 + 1/0.5)) = 0.08(3). Мы увеличили F1-меру, но что означает это увеличение? Стал ли наш прогноз более адекватным и вообще, научились ли мы угадывать цвет? Очевидно, нет! Кстати, противоположный прогноз «шар из первой корзины чёрный, а из второй – белый» обладает такими же показателями качества. Дальше мы не будем расписывать, что из этого следует, наиболее сообразительные догадаются сами;) Но самое главное – F1-мера может расти не из-за того, что прогноз становится «адекватнее», а как раз из-за того, что он становится нетривиальным (как и многие другие показатели качества).

Рис. 2. Модельная задача с корзинами.

В-третьих, нужно уточнить контекст вопроса. Есть выражение «проблема дисбаланса», но на самом деле, никакой проблемы дисбаланса нет! Дисбаланс – это естественное свойство данных. Когда говорят, что в этом случае использование точности неправильно, т.к. формально высокая точность получается у константного решения (см. пример с шарами), то это проблема выбора функционала качества при дисбалансе, а не самого дисбаланса. Когда говорят, что при настройке моделей они превращаются в константные, то это проблема настройки, выбора loss-функции и порога бинаризации. Если ошибки первого и второго рода имеют разную цену (обычно ошибочная классификация объектов малого класса стоит дороже), то это надо напрямую учитывать при обучении алгоритмов (с помощью весов классов, об этом ниже). Также возможно в вопросе про дисбаланс имеется в виду изменение пайплайна решения задачи, например использование стратифицированного контроля (его обязательно надо использовать, хотя в большинстве современных библиотек машинного обучения он включён по умолчанию).

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

Перебалансировка данных / изменение выборки

На рис. 3 показана идея перебалансировки: мы делаем классы сбалансированными, для этого заменяем большой класс подвыборкой по мощности равной малому классу – это называется недосэмлированием (Undersampling the majority class) или «увеличиваем в размерах малый класс» – это называется пересемплированием (Oversampling the minority class). Простейшая стратегия недосэмплирования – взять случайную подвыборку, простейшая стратегия пересэмплирования – продублировать объекты малого класса. О более «умных» поговорим дальше. У пересэмплирования качество, как правило выше, т.к. мы используем все данные, однако недосэмплирование позволяет учить модель на маленькой выборке (можно кстати, строить ансамбль над алгоритмами, обученными на разных недосэмплированиях).

Рис. 3. Undersampling (слева) и Oversampling (справа).

Nearmiss1/2, Tomek links, Edited nearest neighbors (ENN)

Основная идея «умного недосэмплирования» – брать из большого класса только объекты важные для решения рассматриваемой задачи. Стратегия метода NearMiss-1 – из большего класса выбираем объекты, у которых среднее расстояний до N ближайших малого класса наименьшее, т.е. из граничной зоны (первая картинка рис. 4.1). Стратегия метода NearMiss-2 – из большего класса выбираем объекты, у которых среднее расстояний до N дальних малого класса наименьшее (вторая картинка рис. 4.1). Стратегия метода Tomek links – удалить объекты большого класса, образующие связи Томека (объекты двух разных классов образуют связь Томека, если нет объекта, который ближе к одному из них при этом являясь объектом другого класса, см. рис. 4.1). Стратегия ENN – сделать скользящий контроль, например по 10 фолдам, удалить объекты большого класса, на которых ближайший сосед ошибается. В последних двух методах не гарантируется выравнивание классов по мощности. Заметим, что последний метод может быть использован вместе с какой-то моделью алгоритмов (и «отвязан» от конкретной метрики), а предыдущие методы ориентировались на метрику. Есть и другие стратегии недосэмплирования, но общая идея должна быть понятна.

Рис. 4.1. Слева-направо: ближайшие соседи из малого класса, дальние соседи из малого класса, связи Томека.

Ни рис. 4.2 показано применение различных стратегий недосэмлирования от случайной до ENN, в подписи они названы по именам соответствующих функций из библиотеки imblearn. Исходные данные изображены на первой картинке рис. 5.2.

Рис. 4.2. Иллюстрация стратегий недосэмплирования (слева направо): RandomUnderSampler, NearMiss(version=1), NearMiss(version=2), TomekLinks(), EditedNearestNeighbours().

SMOTE = Synthetic Minority Oversampling Techniques, ADASYN = Adaptive Synthetic

Идея метода SMOTE: увеличить малый класс за счёт представителей выпуклых комбинаций пар (см. рис. 5.1). Подобная идея реализуется в современных методах аугментации, например в MixUp. В методе SMOTE для точки малого класса выбирается один из k ближайших соседей и на отрезке между ними случайно выбирается новый объект. Почему-то нигде в описаниях не указывается, но в качестве k ближайших соседей рассматриваются только объекты малого класса. Есть разные модификации метода, например такие, в которых все точки делятся на группы, в зависимости от процента «чужих» в окрестности (от этого зависит вероятность порождения нового объекта).

Рис. 5.1. Идея метода SMOTE.

Метод ADASYN аналогичен SMOTE, но число объектов, которые генерируются с помощью объекта малого класса, пропорционально числу чужаков (объектов большого класса) в его окрестности.

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

Рис. 5.2. Иллюстрация методов пересэмплирования, слева-направо: RandomOverSampler, SMOTE, ADASYN.

Взвешивание объектов

Большинство методов реализованных в sklearn имеет параметр «веса объектов» или «веса классов», обычно берут веса объектов большого класса 0 равным 1, а веса объектов малого класса 1 – m0 / m1 , где m0, m1 – число объектов в классах 0 и 1 соответственно. Обычно при настройке алгоритма классификации минимизируют эмпирический риск

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

Нетрудно видеть, что весовые схемы обобщают идею сэмплирования, но являются более удобной, простой и гибкой техникой. Чтобы не задумываться о значении весов можно в sklearn выбрать class_weight=’balanced’.

Отметим также, что есть функции, которые не зависят от пропорции классов. Например, если функция устроена не в виде суммы ошибок на объектах, а в виде суммы ошибок на парах объектов разных классов как ROC AUC.

Решающее правило: выбор порога

Обычно модель получает некоторые оценки принадлежности к классам, а сама классификация – это результат бинаризации (по умолчанию порог = 0.5). Но порог можно подбирать, мы рассмотрим простую стратегию: при скользящем контроле по 10 фолдам получим оценки принадлежности классу 1 на обучении (функция cross_val_predict в sklearn), потом для заданного функционала качества подберём оптимальный порог бинаризации (при котором значение функционала максимально). Этот же порог будем потом использовать на тесте.

Технику выбора порога можно использовать совместно с перевзвешиванием выборки и балансировкой данных. На рис. 6 (слева) показано, как значения качества зависят от выбора порога, на рис. 6 (справа) аналогичные графики приведены после перевзвешивания, видно что «графики растягиваются» и оптимальные пороги смещаются вправо, но при этом оптимальные значения порогов отличны от 0.5.

Рис. 6. Показатели качества от значения порога бинаризации до перевзвешивания выборки (слева) и после (справа).

Что использовать на практике

Давайте проведём несколько простых экспериментов, они довольно наглядно пояснят, что и как работает в разных ситуациях на практике. Решаемые задачи (реальные или модельные) не так важны, поэтому мы взяли их из стандартных генераторов sklearn-а. Но вот геометрия данных и используемые модели будут важны. Рассмотрим задачу «два полумесяца» с сильным дисбалансом и разной степенью зашумлённости данных, см. рис. 7.

Рис. 7. Решаемая задача «два полумесяца» с разной степенью шума.

Сначала решим задачу с помощью логистической регрессии (хотя здесь нет линейной зависимости, решение должно получиться неплохим), а также с помощью градиентного бустинга (воспользуемся библиотекой LightGBM). Гиперпараметры в обоих методах не будем настраивать и возьмём значения рекомендованные «по умолчанию». В таблицах ниже каждая строка соответствует своему показателю качества, первые пять (точность, сбалансированная точность, каппа Коэна, F1-мера и коэффициент Мэттьюса) зависят от бинаризации (именно они наиболее интересны), остальные (logloss, площади под ROC и PR кривыми) – не зависят. Первый столбец (None) – алгоритм с параметрами по умолчанию, второй (Weights) – использование взвешивания классов, третий (Th-d) – подбор порога на 10-fold-контроле, четвёртый (Th-d + W) – совмещение взвешивания и подбора порога, следующие три столбца – разные техники пересэмплирования, последние пять столбцов – разные техники недосэмплирования.

Табл. Задача 1 + логистическая регрессия
Табл. Задача 2 + логистическая регрессия
Табл. Задача 1 + градиентный бустинг
Табл. Задача 2 + градиентый бустинг

Какие выводы можно сделать?

Подбор порога (без совмещения с любой другой техникой) – идеальная стратегия для «нешумных данных». На самом деле, только это и надо использовать, когда геометрия данных относительно проста, модель хорошо описывает данные (и особенно, если хорошо откалибрована). Обратим внимание, что качество признакового пространства (шум и геометрия) в классическом ML зависит исключительно от Вас, поэтому, если Вы умеете решать задачи, то кроме подбора порога Вам ничего не нужно. Бустинг, который идеально справился с задачей, показывает хорошее качество по умолчанию или с использованием весовой схемы (т.е. достаточно оптимизировать гиперпараметры). Вообще, полезно запомнить – хорошие признаки и правильно подобранная модель это самое главное в ML, всё остальное от лукавого (и не важно есть дисбаланс или нет его).

Неужели описанные схемы сэмплирования особо не нужны? На самом деле, для любой схемы можно найти применение (надо только взять «не очень подходящую» модель и/или увеличить шум). В табл. ниже показано качество метода случайный лес, видим, что SMOTE здесь явно предпочтителен (хотя сами показатели значительно просели).

Табл. Задача 2 + случайный лес

Какие ещё методы существуют?

В DL есть свои методы учёта дисбаланса. Перебалансировка выборки здесь чаще производится на уровне батчей (например, так делали при формировании батчей для обучения R-CNN), причём её можно совместить с аугментацией (про MixUp мы уже вспоминали). Также есть специфические задачи, в которых дисбаланс связан ещё и с эффективностью вычислений, см. например Negative Sampling. Кроме того, есть специальные функции ошибок для обучения нейросетей при дисбалансе, например focal loss (она же используется для калибровки сетей). Ниже дадим ссылку на очень хороший обзор.

Ссылки

Содержание поста сильно коррелирует с аналогичной лекцией автора в программе OzonMasters (на которую недавно стартовал новый набор).

  • Ноутбук с кодом экспериментов (на примере логистической регресии)
  • Библиотека, в которой реализовано большинство описанных методов
  • Статья про SMOTE
  • Статья про ADASYN
  • Неплохой обзор стратегий сэмплирования
  • Обзор по методам обучения глубоких сетей на несбалансированных данных

Дисбаланс классов: 24 комментария

  1. А на Kaggle в решениях победителей хоть когда-нибудь использовали для решения табличных задач техники типа SMOTE?

    Я просто сколько мониторил — ни разу не видел :/

    Ну и на практике сколько пробовал эти техники, не видел заметного прироста метрик после их использования. Спасибо за развернутую статью, я теперь понял как получить прирост метрик =)

  2. Добрый день, Александр Геннадьевич.

    У меня следующий вопрос — нельзя ли сказать, что вообще в задаче дисбаланса сложность возникает в первую очередь не из-за дисбаланса, а из-за наличия перекрытия данных разных классов в признаковом пространстве? Если перекрытия классов не будет, то можно ожидать, что методы, основанные на построение границ вокруг классов будут способны отделить классы один от другого, а в противном случае (при наличии перекрытия классов) и возникает проблема дисбаланса и соответственно нужно подбирать пороги

    • Если перекрытия не будет, то совсем всё хорошо. Есть даже статья, где подобный результат как-то теоретически обоснован. Но, на самом деле, перекрытие не так страшно. Можете провести эксперимент: взять две гауссианки — логистическая регрессия всё равно будет нормально работать, даже при перекрытии, при условии ,что в данных не будет лишних шумовых признаков и объектов малого класса будет «достаточно много».

  3. Добрый день, Александр Геннадьевич.

    Я на одной задаче тоже сравнивал различный стратегии сэмплирования при наличии большого числа категориальных признаков. Cтратегии SMOTE и его различные модификации работали очень плохо. По своей идее, мне кажется, они больше подходят для непрерывных числовых признаков. В моём случае лучшим методом оказался wRACOG https://www.researchgate.net/publication/270741861

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

  4. Была следующая публикация, которая рекомендуют для нейронных сетей oversampling of minority class: https://arxiv.org/pdf/1710.05381.pdf (A systematic study of the class imbalance problem
    in convolutional neural networks)

    Это же раньше рекомендовал Jeremy Howard (https://medium.com/@hiromi_suenaga/deep-learning-2-part-1-lesson-2-eeae2edd2be4):
    Question: How do we deal with unbalanced dataset? [01:38:46] This dataset is not totally balanced (between 60 and 100) but it is not unbalanced enough that Jeremy would give it a second thought. A recent paper says the best way to deal with very unbalanced dataset is to make copies of the rare cases.

    В последней версии курса он немного изменил рекомендацию (https://github.com/hiromis/notes/blob/master/Lesson2.md):

    Question: What do you do if you have unbalanced classes such as 200 grizzly and 50 teddy? [1:10:00]

    Nothing. Try it. It works. A lot of people ask this question about how do I deal with unbalanced data. I’ve done lots of analysis with unbalanced data over the last couple of years and I just can’t make it not work. It always works. There’s actually a paper that said if you want to get it slightly better then the best thing to do is to take that uncommon class and just make a few copies of it. That’s called «oversampling» but I haven’t found a situation in practice where I needed to do that. I’ve found it always just works fine, for me.

  5. Александр, спасибо большое! Отличная статья!

    Интересно было бы услышать Ваше мнение по следующему вопросу. Если у нас в реальном процессе наблюдается дисбаланс например 98% и 2% но при этом есть возможность собрать выборку для обучения 50% на 50%, ввиду наличия большого количества прецедентов. С одной стороны, кажется что это поможет нашей модели точнее подбирать решающие правила и это правильный подход, но с другой стороны не нарушает ли это репрезентативность?
    Очень интересно ваше мнение на этот счет.

    Спасибо!

    • Здравствуйте! Не совсем понятно, как у Вас получится 50/50? За счёт того, что Вы будете игнорировать какие-то примеры большого класса? Тогда это недосэмплирование….

      • Александр, спасибо за ответ!

        Да, все верно. То есть из дисбаланса 98% на 2%, я оставлю 2% на 2%. Но меня смущает следующий момент.

        Так как объем данных достаточно большой, более сотни миллионов прецедентов. И для обучения хочется собрать небольшую выборку ~ 3-4 млн. Вот здесь встает вопрос, как собирать. Если собирать рандомно,+- получим 98% на 2% , а вот если добавить ограничение на классы , то можно собрать 50% на 50%. Но в таком случае, кажется что потеряется консистентность данных, и при скоринге новых прецедентов, прогнозы будут смещены. Интересно послушать Ваше мнение на этот счет.

        Спасибо!

      • Моё мнение: лучше проверить эти стратегии семплирования, на контроле по фондам, например. Выделяете стратифицировано фолд, на остальной части выборки делаете семплирование, потом смотрите качество на фолде. И так k раз (по числу фолдов). Так Вы для каждой стратегии семплирования проверите, как она работает…

  6. Александр, здравствуйте! Большое спасибо за статью.

    Подскажите, пожалуйста, что еще стоит посмотреть/почитать по особенностям работы с дисбалансом классов в multilabel задачах?

    Начал пока со статьи Addressing imbalance in multilabel classification: Measures and random resampling algorithms (2015)

    Нажмите для доступа к 1790_2015-Neuro-Charte-MultiLabel_Imbalanced.pdf

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

      • Да, опечатался. На самом деле вообще случайно комментарий раньше времени отправил и спешно его ниже дописывал. Геометрическое тоже там осталось 😦

  8. Поверить не могу, что задаю такой примитивный вопрос, но я реально не понимаю, как здесь считается F1-мера. По классическому определению это должно быть среднее геометрическое между precision и recall, но я не понимаю, что здесь явлется предсказываемым событием. Сказано просто: предсказываем цвет, но как в этом случае определяются false positive и true negative, например?

    • Ну смотрите, класс 1 = чёрный, класс 0 = белый. При прогнозе «шар из перовой корзины белый, а из второй – чёрный», получаем, что истинные ответы
      y = [1 0 … 0 1 0 .. 0]
      а ответ алгоритма предсказания
      a = [0 0 … 0 1 1 … 1]

      • Ага, то есть, предсказываем не абстрактно цвет, а конкретно чёрный. Это было не очевидно, честно говоря, ведь если взять в качестве предсказываемого события белый цвет, то F1-мера будет совсем другой. Дополнительно сбила с толку тут же рассчитываемая accuracy, и даже показалось, что accuracy=0.5 почему-то попала в расчёт F1-меры (там тоже было никак не обозначенное значение 0.5). В общем, спасибо, теперь разобрался.

      • Только после этого комментария, по-моему, понял смысл модельной задачи (фраза «Рассмотрим прогноз «шар из перовой корзины белый, а из второй – чёрный»» наводила на мысль, что результат вытягивания двух шаров нужно рассматривать как один эксперимент [sample], что сбивало с толку). Но F1, кажется, должна быть в 2 раза больше: 2/(1/0.1 + 1/0.5)), а не 1/(1/0.1 + 1/0.5)) .

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

        Спасибо за интересную статью.

Добавить комментарий для alexanderdyakonov Отменить ответ

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google photo

Для комментария используется ваша учётная запись Google. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s