Мультиклассовая классификация несбалансированных данных с использованием алгоритма случайного леса в Spark

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

Давайте составим список некоторых преимуществ Random Forest:

  • Случайный лес можно использовать как для задач классификации, так и для задач регрессии.
  • Random Forest — это прозрачная методология машинного обучения, с помощью которой мы можем видеть и интерпретировать то, что происходит внутри алгоритма. Не просто используйте его как приложение черного ящика.
  • Случайный лес хорошо работает как с категориальными, так и с числовыми (непрерывными) функциями. Вам не нужно классифицировать (разделять) числовые функции, прежде чем использовать их. Он поддерживает эти типы функций одновременно.
  • Поскольку случайный лес — это алгоритм, основанный на правилах, вам также не нужно нормализовать числовые признаки, как это делается для алгоритмов машинного обучения с линейным разделителем. В Spark параметр ’maxBins’ задает количество интервалов при дискретизации непрерывных функций. Допустим, у вас есть непрерывный признак, который находится в диапазоне от 0 до 300. Если вы установите параметр maxBins 3, то он разделит этот признак на 0‹‹100, 100‹‹200 и 200‹‹300.

  • Давайте углубимся в вопрос: почему они назвали его «Случайный лес»? На самом деле слова «случайный» и «лес» имеют значения. Есть две причины для слова «случайный». Во-первых, для каждого отдельного дерева решений в лесу обучающие данные каждого дерева решений создаются путем случайной подвыборки всех данных. В Spark они назвали эту переменную subsamplingRate. Второй причиной случайности являются критерии разделения узлов. Для каждого разделения узла в качестве кандидатов на разделение выбирается случайное подмножество признаков, и после вычисления энтропии для каждого признака-кандидата выбирается лучший признак для разделения этого узла. Для большинства алгоритмов случайного леса частота подвыборки по умолчанию равна квадратному корню из общего числа признаков. Например, если у вас есть 100 объектов для обучения модели случайного леса, каждый раз алгоритм будет выбирать 10 случайно выбранных объектов для разделения узла на подузлы. В Spark эта переменная называется featureSubsetStrategy. С помощью этих двух подходов случайности Random Forest действительно устойчив к проблеме переобучения.
  • Чтобы справиться с проблемой переобучения, Random Forest имеет некоторые другие параметры, такие как minInstancesPerNode и maxDepth в реализации Spark. При настройке параметров модели следует попробовать разные значения этих двух параметров с помощью поиска по сетке. Для этой цели в Spark реализован класс ParamGridBuilder.

  • Давайте немного поговорим о том, почему он называется «Лес». Из-за методологии упаковки; вместо обучения одного единственного дерева решений обучается набор деревьев, и их большинство голосов используется в качестве окончательного результата. Поскольку это серия деревьев решений, в названии этого алгоритма есть слово «лес». Было доказано, что в большинстве случаев пакет деревьев дает лучшие результаты по сравнению с одним деревом решений. В Spark количество деревьев в алгоритме случайного леса задается параметром numTrees.
  • Случайный лес также устойчив к выбросам. Поскольку алгоритм использует большинство голосов набора деревьев решений, отрицательный эффект выбросов обрабатывается.
  • RF хорош для распараллеливания.
  • Выбор признаков не является обязательной задачей для RF-алгоритма. Если в вашем наборе функций есть плохие/отклоняющиеся функции, эти функции будут автоматически исключены из-за методологии разделения узлов на основе энтропии. В Spark параметр featureImportances модели RF даст вам список весов важности всех функций. Тем не менее, я должен сказать, что выбор функций всегда стоит пытаться уменьшить сложность модели, даже если вы используете случайный лес.
  • Random Forest может обрабатывать несбалансированные данные. Существует множество различных стратегий, которые можно применить для решения проблемы несбалансированных данных. Собственно, это основная тема, о которой я хотел бы поговорить на протяжении всей этой статьи. В Spark для этой цели есть переменная под названием thresholds. Предположим, что мы используем RF для обучающих данных с распределением меток класса: %90 отрицательных, %10 положительных. Затем, если мы установим пороговую переменную (t) [0,9,0,1], прогнозируется класс с наибольшим значением p/t, где p — исходная вероятность этого класса, а t — порог класса. Однако я считаю, что это не оптимальный способ решения ситуации с несбалансированными данными. Я собираюсь перечислить некоторые другие способы решения этой проблемы позже в этой статье.

Моя главная цель написать эту статью — объяснить, как подойти к проблеме несбалансированных данных с несколькими классами, используя RF. Проблема несбалансированных данных для меня немного более интересна; поэтому я отложу это на потом, а сейчас сосредоточусь на проблеме мультиклассов. Как я уже говорил, RF по своей природе имеет возможность проводить многоклассовую классификацию. Однако в документе, который я недавно прочитал, говорится, что вместо обучения одной модели RF для задачи классификации нескольких классов создается одна модель RF для каждого класса с использованием стратегии One-vs-Rest (One-vs-All) и затем выбор метки класса с максимальной оценкой вероятности дает лучшие результаты. [1] Я лично попробовал этот подход для своего самого последнего проекта и увеличил точность классификации и F-Score. Предположим, вы собираетесь решить задачу классификации нескольких классов с 10 метками классов. Затем, если вы решите использовать этот подход для своей проблемы, вы создадите разные модели для каждого класса и в итоге получите 10 моделей. Если вы хотите оценить и узнать, к какому классу принадлежит новый экземпляр, вы предоставите этот экземпляр в качестве входных данных для всех моделей и выберете класс с наивысшим баллом. В Spark есть класс OneVsRest с параметром classifier. Когда вы устанавливаете свою модель RF для этого параметра классификатора с помощью метода 'setClassifier', вы завершаете применение методологии One-s-Rest с классификатором RF. Однако, если мы хотим использовать класс Spark OneVsRest как есть, остается нерешенная проблема несбалансированных данных, которая вызывает некоторые серьезные проблемы. Мы собираемся поговорить об этом в следующем параграфе. Главный урок здесь состоит в том, чтобы помнить об этом подходе One-vs_Rest, когда вы сталкиваетесь с проблемой классификации нескольких классов и решаете решить эту проблему с помощью RF.

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

Здесь можно перечислить несколько решений:

а. Недостаточная или избыточная выборка:

Это очень интуитивный способ решения этой проблемы. Если вы решите подать заявку в рамках выборки, выберите несколько экземпляров из каждого класса с одинаковым количеством классов меньшинства. Однако у использования метода недостаточной выборки есть недостаток, заключающийся в потере большинства обучающих экземпляров при выполнении выборки. Вероятно, мы не хотим уменьшать наши большие данные. В Spark класс DataFrame имеет метод под названием "sample" с параметром "fraction", который представляет собой отношение/процент выборки.

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

б. Дайте веса экземплярам:

Если вы придадите больший вес экземплярам класса меньшинства и меньший вес экземплярам класса большинства, тогда у нас будет возможность использовать целые данные без выборки. Например, предположим, что у вас есть 3 класса с весами экземпляров (1,3,10). Если новый/тестовый экземпляр попадает в листовой узел, в котором 10 экземпляров класса-А, 4 экземпляра класса-В и 2 экземпляра класса-С, то этому экземпляру присваивается метка С. Это потому, что ВЕС (10)*NUMc(2) больше, чем WEIGHTa(1)*NUMa(10) и WEIGHTb(3)*NUMb(4).

Алгоритм Random Forest в Spark еще не поддерживает эту функцию, но в R вы можете найти эту функцию в пакете RandomForest с параметром classwt. На данный момент Spark поддерживает только «пороги» классов, о которых я упоминал ранее в этой статье, и опять же, это не лучший способ по сравнению с логикой весов классов. Если Spark когда-нибудь начнет поддерживать функцию весов классов, я бы использовал это, чтобы решить любую проблему с несбалансированными данными.

Из-за недостатков текущей версии RF в Spark ML то, что я собираюсь предложить вам для решения проблемы несбалансированных данных в многоклассовой классификации, немного отличается от этих двух подходов выше. Поскольку я предпочитаю использовать стратегию «один против остальных», я применил выборку при создании обучающих данных для каждой модели класса. Предположим, что у нас есть обучающие данные с распределением по классам: % 5 класса A, % 15 класса B и % 80 класса C. Затем при обучении модели для класса A используйте все метки класса A (% 5) и случайным образом выберите одинаковые объем данных от остальных данных (%95). При обучении модели для класса B используйте все данные класса B (%15) и случайным образом выберите такое же количество данных из остальных (%85). Для модели класса C, поскольку она составляет 80% данных, а остальное составляет 20%, случайным образом выбираются образцы из класса C (%80) с таким же количеством экземпляров всех других классов. (В этом случае случайным образом выберите %25 экземпляров класса C — он будет иметь равный размер %20 от всех обучающих данных)

Есть еще один вопрос о Random Forest, которым я хотел бы поделиться с вами и любезно спросить ваше мнение о нем. Это другая реализация RF, и я считаю, что стоит написать об этом исследовательскую работу. Как я уже упоминал ранее в этой статье, алгоритм Random Forest случайным образом выбирает некоторые функции в качестве кандидатов на разделение и использует лучшую функцию для разделения узла на две части. Однако в некоторых случаях нам необходимо настроить этот поток для собственных нужд. Например, предположим, что веб-сайт электронной коммерции хотел бы разработать модель, которая прогнозирует оценки интереса пользователей к каждой категории на веб-сайте. Они знают, что пол пользователя является одним из наиболее важных факторов для расчета этих показателей интереса. Помимо пола, вероятно, в их наборе признаков есть еще десятки различных факторов. Есть два пути: Добавить пол в качестве одной из функций или Создать отдельную модель для каждой гендерной группы. Эти два способа дают совершенно разные результаты. Это связано с тем, что когда мы добавляем пол в наш набор функций, мы не можем быть уверены, что используем признак пола в разделении первого узла (корня). Кто-то может сказать, что если пол является оптимальным признаком для разделения этого первого узла, RF будет продолжать использовать гендерный признак по своей природе [3]. Однако расчет на основе энтропии выполняется только для каждого отдельного узла. Возможно, пол — не лучшая функция для разделения первого узла, но для остальных разделений узла разделение корневого узла по полу может привести к оптимальным конечным узлам.

Конечно, мы можем разделить наши обучающие данные на две части по полу, а затем создать разные модели, используя каждую часть данных. Вопрос в том, что когда мы также решаем использовать фактор «возраст» так же, как пол (‹30 & ›=30 и т. д.), количество отдельных моделей, которые мы должны создать, становится намного больше, и это усложняет нашу систему. . Поэтому, если мы сможем реализовать новую версию алгоритма Random Forest, которой мы сможем назначать определенные функции для разбиения первого/корневого узла, мы сможем решить эту проблему самым простым способом. Вместо обучения модели для каждой части данных (пол и возрастные группы) у нас будет единая модель RF, и это наверняка упростит всю систему. В комплексном исследовании алгоритма Random Forest можно сравнить результаты модели между традиционной RF со всеми признаками (включая пол и возраст) и новой версией RF, в которой мы можем указать внешние признаки для разделения первого узла.

Если вам интересны темы, которые мы рассмотрели в статье, оставьте отзыв и напишите свои комментарии по этому поводу.

Ссылки:

[1] https://www.elen.ucl.ac.be/Proceedings/esann/esannpdf/es2015-5.pdf

[2] http://statistics.berkeley.edu/sites/default/files/tech-reports/666.pdf

[3] http://stackoverflow.com/questions/37044187/force-split-random-forest