Настройка, обучение и оценка моделей с помощью Scikit-learn

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

Материалы и методы: Используя Scikit-learn, мы генерируем набор данных, аналогичный Madelon, для задачи классификации. Основные компоненты нашего рабочего процесса можно резюмировать следующим образом: (1) Создан набор для обучения и тестирования. (2) Затем функции масштабируются с помощью нормализации Z-балла. (3) Применяется алгоритм выбора признаков, чтобы уменьшить количество признаков. (4) Алгоритм машинного обучения обучается и оценивается. Прогностическая сила 18 обученных классификаторов будет оцениваться с использованием площади под рабочей кривой приемника (AUC).

Аппаратное обеспечение: мы обучаем и оцениваем наши модели на рабочей станции, оснащенной Inter (R) Core (TM) i7–8700 с 12 процессорами с тактовой частотой 3,70 ГГц и NVIDIA GeForce RTX 2080.

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

Набор данных

Мы сгенерируем синтетический набор данных, подобный Мадлону, с помощью Scikit-learn для задачи классификации. Набор данных Мадлон - это искусственный набор данных, который содержит 32 кластера, размещенных в вершинах пятимерного гиперкуба со сторонами длиной 1. Кластеры случайным образом помечаются как 1 или -1 (2 класса).

Набор данных, который мы сгенерируем, будет содержать 30 функций, из которых 5 будут информативными, 15 - избыточными (но информативными), 5 из них будут повторяться, а последние 5 будут бесполезны, так как они будут заполнены случайными шум. Столбцы набора данных будут упорядочены следующим образом:

  1. Информационные функции - столбцы 1–5. Эти функции - единственное, что вам действительно нужно для построения вашей модели. Следовательно, пятимерный гиперкуб.
  2. Избыточные функции - столбцы 6–20: эти функции создаются путем линейного комбинирования информативных функций с разными случайными весами. Вы можете думать об этом как о специально разработанных функциях.
  3. Повторяющиеся элементы - столбцы 21–25. Эти элементы выбираются случайным образом из информативных или повторяющихся функций.
  4. Бесполезные функции - столбцы 26–30: эти функции заполнены случайным шумом.

Начнем с импорта библиотек.

Теперь мы можем сгенерировать наш набор данных.

Путем случайной выборки без замены мы создаем наши обучающие и тестовые наборы.

Классификаторы

Мы обучим и настроим 18 классификаторов и оценим их работу, используя площадь под кривой работы приемника (AUC). Обсуждение технических особенностей каждого классификатора выходит за рамки данной статьи; тем не менее, для заинтересованного читателя вы можете перейти по ссылкам в списке, показанном ниже. Каждому классификатору дается метка, обозначаемая строкой, заключенной в круглые скобки.

  1. Анализ линейной дискриминации (LDA)
  2. Квадратичный дискриминантный анализ (QDA)
  3. Классификатор Adaboost (AdaBoost)
  4. Классификатор упаковки (Bagging)
  5. Классификатор дополнительных деревьев (Ансамбль дополнительных деревьев)
  6. Классификатор повышения градиента (Gradient Boosting)
  7. Классификатор Случайный лес (Случайный лес)
  8. Гребной классификатор (Гребень)
  9. Классификатор SGD (SGD)
  10. Классификатор Бернулли Н.Б. (БНБ)
  11. Классификатор Гауссова НБ (ГНБ)
  12. Классификатор ближайших соседей (KNN)
  13. Классификатор MLP (MLP)
  14. Линейный SVC (LSVC)
  15. Nu SVC (NuSVC)
  16. СВК (SVC)
  17. Классификатор дерева решений (DTC)
  18. Дополнительный классификатор деревьев (ETC)

Классификатор гиперпараметров

Здесь мы создадим словарь, пары ключ-значение которого состоят из

  • ключ: строка, обозначающая классификатор.
  • значение: словарь гиперпараметров для соответствующего классификатора.

Ни в коем случае используемые здесь гиперпараметры не представляют оптимальную сетку гиперпараметров для каждого классификатора. Вы можете изменить сетку гиперпараметров по своему усмотрению.

Методы выбора функций

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

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

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

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

1. Метод фильтрации: выбор характеристик на основе корреляции

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

На этом этапе алгоритма выбора признаков мы сначала вычисляем абсолютное значение матрицы коэффициентов, используя все функции, см. рисунок 1. Затем мы определяем группу признаков, у которых коэффициент корреляции превышает 0,95. Из каждой группы коррелированных функций мы выберем одну из них и отбросим остальные. Вы можете изменить этот порог, который я произвольно установил.

Это должно удалить 6 функций из набора данных, а это немного, а именно, функции 13 и функции 21–25. Однако в реальных наборах данных, с которыми я работал, этот шаг сократил количество функций до 50%. Просто обратите внимание, что если у вас есть тысячи функций, это может быть дорогостоящим с точки зрения вычислений.

2. Метод оболочки: рекурсивное исключение признаков с перекрестной проверкой.

После удаления сильно коррелированных функций мы еще больше уменьшим количество функций, применив алгоритм исключения рекурсивных функций. Объект рекурсивного исключения функций Scikit-learn с перекрестной проверкой (RFECV) позволяет использовать только оценщики / классификаторы с атрибутами feature_importances_ или coef_. По опыту я заметил, что RFECV часто переоценивает количество действительно необходимых вам функций.

2.a. Настройка базового оценщика

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

Как только базовая оценка определена, мы настроим ее гиперпараметры. Причины для этого заключаются в том, чтобы уменьшить риск переобучения и максимизировать производительность оценщика. Для этого мы создадим объект Scikit-learn Pipeline, который будет использоваться с объектом Scikit-learn GridSearchCV.

GridSearchCV выполнит исчерпывающий поиск по сетке гиперпараметров и сообщит о гиперпараметрах, которые максимизируют эффективность перекрестно проверенного классификатора. Вот хорошая статья на Medium с более подробным объяснением. Мы установим количество складок на 5.

Ниже приведены шаги в нашем конвейере.

Шаг 1. Масштабирование функций. Обычно масштабирование функций выполняется перед их использованием в алгоритме. Это сделано для того, чтобы все функции в вашем наборе данных имели одинаковый масштаб. Следовательно, объекты с большими значениями не будут преобладать над объектами с меньшими значениями. Вы можете обратиться к этой статье для более подробного объяснения. Мы будем использовать образцы в обучающем наборе для масштабирования данных (обучение и тест) с помощью нормализации Z-показателя. Все функции сосредоточены вокруг нуля и имеют стандартное отклонение 1.

Шаг 2 - Классификатор. Определение объекта классификатора для использования в конвейере.

Время обработки для настройки классификатора случайного леса заняло 4,8 минуты.

2.b. Рекурсивный выбор функций с помощью настроенного оценщика

После того, как мы настроили наш базовый оценщик, мы создадим еще один конвейер, аналогичный первому, но у него будет настроенный классификатор на втором этапе. Теперь возникает техническая сторона вопроса. Поскольку объект конвейера Scikit-learn не имеет атрибутов feature_importances_ или coef_, нам придется создать собственный объект конвейера, если мы хотим использовать его с RFECV. Здесь Джон Рэми показывает нам, как это делать. Спасибо, Джон!

Наконец, мы можем использовать RFECV с нашим новым конвейером. Уф! Иди возьми пива, дружище.

Теперь давайте визуализируем результаты. Построение графиков на питоне - это безумие, но неважно.

Какая красивая фигура! На рисунке 2 мы можем увидеть эффективность классификатора в зависимости от ряда характеристик. Как видите, пиковая производительность составляет около 10 функций с AUC около 0,89; однако, если вы проверите длину списка selected_features, вы заметите, что RFECV определил, что вам нужно более 18 функций для достижения максимальной производительности.

Проблема в том, что мы начали с 30 функций, зная, что только 5 из них действительно необходимы, и что после нашего алгоритма выбора функций мы получили более 18 репрезентативных функций. Чтобы решить эту проблему, взгляните на рисунок 2, визуально определите, сколько функций вы хотите использовать (например, 10), и используйте Scikit-learn RFE object с параметром then_features_to_select, установленным на 10 Обратите внимание, что после 7 функций прирост производительности по мере добавления функций минимален. Вы можете использовать это в качестве порогового значения, но я хотел бы добавить небольшую избыточность, поскольку я не знаю оптимального количества функций для других 17 классификаторов. Из документации Scikit-learn RFE:

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

Теперь вам может быть интересно, почему мы не использовали RFE вместо RFECV. Что ж, в реальных сценариях жизни вы не будете знать заранее, сколько функций вам действительно понадобится. Используя RFECV, мы можем получить оптимальное подмножество функций; однако, по моему опыту, он часто переоценивает. Тем не менее, из RFECV мы получаем кривую производительности, по которой мы можем принять обоснованное решение о том, сколько функций нам нужно. Недостатком использования RFE является отсутствие перекрестной проверки результатов.

Важность функции

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

Сначала мы обучим настроенный классификатор случайного леса выбранным функциям. Затем мы воспользуемся атрибутом feature_importances_ и создадим с ним гистограмму. Обратите внимание, что следующий код будет работать только в том случае, если классификатор, выбранный вами в качестве основы, содержит feature_importances_ атрибут.

Среди наиболее важных функций - функции 6 и 19, которые относятся к классу избыточных функций. Может показаться нелогичным, что избыточные функции кажутся более важными, чем информативные функции (функции 1–5). С другой стороны, на соревнованиях Kaggle часто можно увидеть, что инженерное искусство может дать вам толчок. Важно отметить, что значения функций, назначаемые случайным по своей природе классификатором машинного обучения, не являются надежными. Например, если бы вы перезапустили RFE, вы могли бы получить несколько другие результаты, поскольку мы не исправляли сид в случайном лесу. Вот почему вам необходимо провести перекрестную проверку результатов, если вы планируете сделать какой-то вывод из важности ваших функций. Вот отличная статья, в которой рассказывается о случайности машинного обучения. Кроме того, не доверяйте важности функции, если ваш классификатор не настроен. Вот замечательная статья о том, как более надежно определить важность функции.

Итерационная настройка и оценка классификатора

Теперь, когда мы определили подмножество репрезентативных функций, мы собираемся настроить и обучить 18 моделей, чтобы исследовать самые эффективные из них. Для этого мы переберем классификаторы, определенные в Скрипт 4, и будем использовать Скрипт 7, чтобы настроить их с помощью гиперпараметров, определенных в Скрипт 5 . Мы внесем незначительные изменения в Скрипт 7 и добавим несколько дополнительных строк кода, чтобы оценить производительность настроенного классификатора на тестовом наборе и сохранить результаты.

Сценарий 13 выполнялся на моей рабочей станции примерно за 30 минут. По моим оценкам, в двухъядерном ЦП это займет около 3 часов. Все результаты будут сохранены в объекте словаря с именем results . Доступ к содержимому словаря results можно получить с помощью classifier_label (см. Раздел Классификаторы). Для каждого классификатора мы храним следующие объекты:

  • Классификатор: объект конвейера с обученным классификатором. Вы можете использовать это, чтобы делать прогнозы на новых образцах.
  • Лучшие параметры: словарь, содержащий параметры, которые показали наибольшую эффективность в обучающем наборе.
  • AUC обучения: перекрестно подтвержденная AUC, полученная в обучающем наборе.
  • Test AUC: AUC, полученная в тестовом наборе.

Визуализируем результаты:

Из рисунка 4 мы можем визуально определить, что классификаторы SVC, NuSVC, Gradient Boosting и AdaBoost показали наивысшую производительность в тестовом наборе. Просмотрите содержимое объекта фрейма данных pandas auc_scores, чтобы увидеть числовые результаты.

Заключительные замечания

Если вы дошли до конца этой статьи, поздравляю! На самом деле мы просмотрели много материала. Я надеюсь, что это вам поможет. Вы можете найти весь код для этой статьи в моем репозитории GitHub. Добро пожаловать на форк. Если вы хотите его использовать, просто измените Скрипт 2 и убедитесь в следующем:

  • Загрузите свои данные и закодируйте все категориальные переменные.
  • Позаботьтесь о любых пропущенных значениях или выбросах.
  • Сбалансируйте свой набор данных (при необходимости).
  • Сохраните матрицу функций X в объекте DataFrame pandas. Сделайте то же самое для целей в y.

Если ваш набор данных содержит около 1000 образцов и 30 функций, для выполнения всего процесса потребуется около 30–45 минут - при условии, что у вас аналогичное оборудование, чем у меня.

Теперь несколько советов, чтобы определить, что делать дальше, чтобы улучшить производительность этих классификаторов.

Проще всего было бы выбрать пять наиболее эффективных классификаторов и запустить поиск по сетке с разными параметрами. Когда вы почувствуете, где должны быть лучшие параметры, вы можете выполнить более точный поиск по сетке в этой точке в пространстве параметров. После дальнейшей настройки этих классификаторов выберите три лучших из пяти и используйте их в VotingClassifier в Scikit-learn. Это, скорее всего, приведет к более высокой производительности, но увеличит сложность вашего моделирования. Вы также можете рассмотреть возможность укладки - чтобы узнать о ней подробнее, нажмите здесь.

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

Найдите меня в LinkedIn. До скорого!