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

#random-forest #metrics #multilabel-classification #imbalanced-data #boosting

Вопрос:

Я работаю над проблемой классификации с очень несбалансированными классами. В моем наборе данных есть 3 класса : класс 0,1 и 2. Класс 0 составляет 11% от обучающего набора, класс 1-13%, а класс 2-75%.

Я использовал классификатор случайных лесов и получил точность 76%. Но я обнаружил, что 93% этой точности приходится на класс 2 (класс большинства). Вот перекрестная таблица, которую я получил.

Результаты, которые я хотел бы получить :

  • меньше ложных срабатываний для классов 0 и 1 ИЛИ/И меньше ложных срабатываний для классов 0 и 1

Что я нашел в Интернете, чтобы решить эту проблему, и что я пробовал :

  • используя class_weight= «сбалансированный» или настроенный class_weight ( 1/11% для класса 0, 1/13% для класса 1, 1/75% для класса 2), но это ничего не меняет (точность и перекрестная стабильность остаются прежними). У вас есть интерпретация/объяснение этого ?
  • поскольку я знаю, что точность не является лучшей метрикой в этом контексте, я использовал другие показатели : precision_macro, precision_weighted, f1_macro и f1_weighted, и я реализовал область под кривой точности и отзыва для каждого класса и использовал среднее значение в качестве показателя.

Вот мой код (приветствуется обратная связь) :

 from sklearn.preprocessing import label_binarize

def pr_auc_score(y_true, y_pred):
    y=label_binarize(y_true, classes=[0, 1, 2])
    return average_precision_score(y[:,:],y_pred[:,:])

pr_auc = make_scorer(pr_auc_score, greater_is_better=True,needs_proba=True)
 

а вот график кривых точности и отзыва.

Увы, для всех этих показателей перекрестная таблица остается прежней… похоже, они не оказывают никакого эффекта

  • Я также настроил параметры алгоритмов повышения ( XGBoost и AdaBoost) (с точностью до метрики), и снова результаты не улучшились.. Я не понимаю, потому что алгоритмы повышения должны обрабатывать несбалансированные данные
  • Наконец, я использовал другую модель (BalancedRandomForestClassifier), и я использовал метрику точности. Результаты хорошие, как мы можем видеть в этой перекрестной таблице. Я рад таким результатам, но я замечаю, что, когда я меняю метрику для этой модели, результаты снова не меняются…

Поэтому мне действительно интересно узнать, почему использование class_weight, изменение метрики или использование алгоритмов повышения не приводят к лучшим результатам…

Комментарии:

1. Вы пробовали Xgboost с использованием массива весов? Я использовал xgboost для несбалансированной классификации двоичных классов, и установка scale_pos_weight улучшила производительность модели. Поскольку у вас многоклассовая классификация, вы не можете использовать scale_pos_weight, если вы не используете один подход против остальных, но вместо этого вы можете использовать массив весов, и это должно решить проблему.

Ответ №1:

Как вы выяснили, вы столкнулись с «парадоксом точности»;

Предположим, у вас есть классификатор, точность которого составляет 98%, это было бы удивительно, не так ли? Это может быть так, но если ваши данные состоят на 98% из класса 0 и на 2% из класса 1, вы получите точность 98%, присвоив все значения классу 0, что действительно является плохим классификатором.

Итак, что же нам делать? Нам нужна мера, инвариантная к распределению ROC — кривых ввода данных.

  • ROC-кривые инвариантны к распределению данных, поэтому являются отличным инструментом для визуализации характеристик классификации для классификатора независимо от того, несбалансирован он или нет. Но они работают только для задачи двух классов (вы можете расширить ее до многоклассовой, создав кривую «один против одного» или «один против одного» ROC-кривой).
  • Оценка F может быть немного более «сложной» в использовании, чем ROC-AUC, так как это компромисс между точностью и отзывом, и вам нужно установить бета-переменную (которая часто является «1», следовательно, оценка F1).

Вы пишете: «меньше ложных срабатываний для классов 0 и 1 или/И меньше ложных срабатываний для классов 0 и 1«. Помните, что все алгоритмы работают либо путем минимизации чего — либо, либо путем максимизации чего-либо-часто мы минимизируем какую-либо функцию потерь. Для случайного леса предположим, что мы хотим минимизировать следующую функцию L:

 L = (w0 w1 w2)/n
 

где wi число классов i , классифицируемых как не класс i , т. е. если w0=13 мы неправильно классифицировали 13 образцов из класса 0, и n общее количество образцов.

Ясно, что когда класс 0 состоит из большей части данных, то простой способ получить небольшой L -это классифицировать большинство образцов как 0 . Теперь мы можем преодолеть это, добавив вместо этого вес к каждому классу, например

 L = (b0*w0 b1*w1 b2*x2)/n
 

в качестве примера скажем b0=1, b1=5, b2=10 . Теперь вы можете видеть, что мы не можем просто присвоить большую часть данных c0 без наказания весами, т. е. мы гораздо более консервативны, назначая образцы классу 0, так как присвоение класса 1 классу 0 дает нам в 5 раз больше потерь, чем раньше! Именно так weight работают (большинство) классификаторов — они назначают штраф/вес каждому классу (часто пропорциональный его соотношению, т. е. если класс 0 состоит из 80%, а класс 1 состоит из 20% данных, то b0=1 и b1=4 ) но вы часто можете указать свой собственный вес; если вы обнаружите, что классификатор все еще генерирует множество ложных отрицаний класса, то увеличьте штраф для этого класса.

К сожалению, «такого понятия, как бесплатный обед, не существует», т. е. это проблема, данные и конкретный выбор использования, какой показатель использовать.

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