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

Часть I. Советы и рекомендации по стекированию + код с нуля

В Части II я представляю полностью автоматизированную структуру стекирования, которая инкапсулирует все необходимое для создания окончательного многоуровневого ансамбля стекирования с помощью нескольких однострочников

Где именно можно использовать стек в проекте машинного обучения?

Давайте разобьем машинное обучение на основные этапы:

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

3. Выбрать/обучить/проверить/настроить результирующую модель…

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

«Слепая» разработка функций может улучшить или не улучшить значение метрики

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

Укладка

Проще говоря:

  1. У нас есть данные поезда X, y и тестовые данные test. Допустим, X и test имеют по 100 функций каждый.
  2. Перед подгонкой окончательной модели (meta_modelпо соглашению) мы обучаем промежуточные модели (base_models по соглашению) и используем их прогнозы в качестве дополнительных функций для обогащения наборов данных X и test.
  3. Эти новые функции (скажем, 10 новых признаков), которые были созданы для набора данных X, можно затем использовать для обучения meta_model прогнозированию y_hat на соответствующих 10 новых функциях, созданных для набора test.

Звучит просто, верно?

Действительно - концепция ясна

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

Существует несколько различных подходов, и их выбор зависит от экспериментов и тщательной проверки. Мы рассмотрим их все

Шаги укладки

В этом руководстве мы будем считать, что все данныеtrainиtestпредварительно обработаны, исключают NaN и готовы к обучению любой модели

Каждый шаг будет сопровождаться примером фрагмента кода

1. Определите модели для создания составных функций

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

Как добиться разнообразия моделей

  • Наименьший (корневой) уровень разнообразия достигается за счет использования разных типов моделей: линейные модели / древовидные модели / повышающие ансамбли / нейронные сети / алгоритмы кластеризации
  • В пределах типов моделей выберите разные алгоритмы (линейная регрессия против SVM в линейных моделях)
  • В рамках одного и того же алгоритма выберите разные настройки (max_depth является хорошим отличием для древовидных моделей / разное количество слоев и конфигурация хорошо подходят для добавления в ансамбль более одной нейронной сети)
  • На самом высоком уровне разнообразие моделей может быть достигнуто с помощью различных seed
  • Еще один вариант — использовать разные выборки данных (по строкам/столбцам), которые дадут разные результаты для двух идентичных моделей.

Выбор алгоритмов

Линейные модели: линейная регрессия, гребень, пассивно-агрессивные алгоритмы и практически любая модель, представленная sklearn.linear_models. Подобные алгоритмы можно отличить по настройкам регуляризации l1, l2, C

Модели на основе дерева: Desicion Tree, Random Forrest. Разнообразить на max_depth, num_leaves

Ускоренные алгоритмы: GradientBoostingClassifier/Regressor, XGBoost, lightgbm, Catboost. Разнообразить на max_depth, num_leaves, subsample, colsample_bytree

Алгоритмы кластеризации: KNN, K-Means, DBSCAN, Gaussian Mixture Model. Диверсифицировать на n_neighbors

Нейронные сети: TensorFlow, PyTorch (оба как бэкенд в обертке Keras). Разнообразие по количеству слоев, количеству нейронов в слое, различным функциям активации и оптимизаторам

Если время и вычислительная мощность доступны, вы также можете настроить несколько других важных параметров для каждого из алгоритмов, используя небольшой GridSearch

Количество моделей

Модели с большим, чем с меньшим количеством стеков, как правило, лучше, но после определенного момента производительность снижается, а сложность увеличивается.

Даже два четко определенных сложенных объекта могут увеличить производительность meta_model, но лучшим выбором будет 10–15 моделей для первого слоя.

А пока давайте определим один слой

2. Обучение/прогнозирование сложенных подвигов

Обучение созданию сложенных наборов навыков

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

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

Таким образом, для каждой модели в ансамбле разделите данные на 4 складки, чтобы тренировочные складки не перекрывались со сгибами для прогнозирования сложенного подвига. Таким образом, будет 4 итерации fit/predict; каждый из предсказанных массивов хранится в индексах нового умения для соответствующей тестовой складки. Не забудьте использовать StratifiedKFoldSplit для задач классификации!

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

Создание набора тестовых наборов способностей

Здесь у нас есть два варианта:

  • для конкретной модели после создания сложенных подвигов в поезде с использованием тактики kfoldобучить эту модель еще раз, но на этот раз на всем наборе поездов, чтобы затем предсказать сложенные подвиги на основе функций тестового набора
  • или используйте каждую из этих 4 моделей, обученных в 4 раза, чтобы создать 4 независимых прогноза. Вот почему в нашем фрагменте выше функция create_stacked_feat() возвращает 4 подобранные модели вместе с их прогнозами. В этом случае окончательный прогноз набора тестов должен быть усреднен путем получения mean из 4 прогнозов (регрессия и бинарная классификация) или наиболее распространенного прогноза mode для мультиклассовых задач.

Между ними нет правильного выбора, но, как правило, второй вариант более устойчив к переоснащению.

Вот как вы можете сгенерировать сложенные подвиги для данного слоя в наборе поездов.

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

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

Стратегия проверки

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

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

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

Необработанные данные о соревнованиях не совсем предварительно обработаны, поэтому мы будем использовать verstack, чтобы быстро сделать их пригодными для машинного обучения. В частности, мы будем вводить пропущенные значения в каждом столбце с помощью XGBoost и кодировать все категориальные столбцы с помощью MeanTargetEncoding.

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

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

И отправьте файл отправки в Kaggle.

Теперь давайте используем весь код, который мы определили выше, чтобы обогатить наши обучающие и тестовые данные сложенными подвигами.

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

Сначала мы будем обучать ту же модель, которую использовали для измерения базовой линии, но на этот раз мы будем использовать только 5 новых stacked_feats в качестве входных данных для обучения/прогнозирования. Наша базовая оценка составила 0,14199 с базовой моделью LGBMRegressor.

Оценка проверки снижена

Теперь давайте обучим простую линейную модель на stacked_feats. Мы будем использовать sklearn.linear_model.Ridge

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

Это интересно. Таким образом, простая линейная модель, обученная на 79 исходных функциях, набрала 0,33731, что очень плохо, но при обучении на 5 stacked_feats ее ошибка уменьшилась вдвое и почти соответствует мощной модели LGBMRegressor. Это наглядно демонстрирует силу стекирования

Теперь нам все еще нужно как-то побить наш базовый результат. Давайте используем все исходные черты вместе с stacked_feats для обучения/прогнозирования с нашей моделью LGBMRegressor, которую мы использовали в качестве основы.

Вот оно. Ошибка уменьшилась на 5% с 0,14199 до 0,13574.

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

Многослойная укладка

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

Если вводится второй слой, он должен содержать меньшее количество моделей, чем предыдущий слой. Хорошим эталоном является объединение 10–15 моделей в layer_1, 2–3 моделей в layer_2, а затем meta_model, обученных на последнем сложенном слое прогнозов двух моделей.

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

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

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

Мета-функции

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

Последний эксперимент

На этот раз мы развернем verstack.LGBMTuner для оптимизации гиперпараметров модели lightgbm наиболее эффективным способом и сравним их с нашими результатами.

  • Сначала мы будем использовать только оригинальные функции
  • Тогда мы будем использовать только stacked_feats
  • И, наконец, мы будем использовать как оригинальные функции, так и наши stacked_feats.

Теперь мы можем видеть, что с обширной LGBMRegressor настройкой сложенных функций (оценки 0,15498 и 0,13697) нам не удалось превзойти наш лучший результат с той же, но неоптимизированной моделью. Это указывает на то, что очень сложная модель будет соответствовать stacked_feats, поскольку они изначально являются очень мощными предикторами.

Но если посмотреть на лучший результат 0,13493, который был получен только для исходных функций, мы видим, что мы фактически превзошли все наши предыдущие результаты. Означает ли это недооценку концепции стекирования? Точно нет. Если стек base_models тщательно отобран, оптимизирован и соответствующий meta_model обучен — результаты превзойдут любую настройку алгоритма, а это совсем другая история.

В Части II читайте о полностью автоматизированном инструменте укладки, который включает в себя все необходимое для создания идеального многослойного ансамбля укладки.