Добрый день.
В этой статье я хотел бы кратко рассказать о решении, которое принесло мне первое место в конкурсе по машинному обучению ML Boot Camp III от mail.ru. Разрешите представиться, меня зовут Карачун Михаил, я также победитель предыдущего конкурса mail.ru. Мое прошлое решение описано Здесь и иногда я буду ссылаться на это.
Условия
Участникам конкурса было предложено на основе выборки данных спрогнозировать вероятность того, что игрок, игравший в онлайн-игру, покинет ее.Выборка содержала некоторые данные об активности игроков за две недели; логлосс , подробное описание задачи на сайт конкурса .
Введение
Каждое соревнование по машинному обучению имеет свою специфику, которая зависит от выборки данных, предлагаемой участникам.Это может быть огромная таблица необработанных бревен, которые нужно очистить и преобразовать в знаки.
Это может быть целая база данных с различными таблицами, из которых тоже нужно генерировать признаки.
В нашем случае данных было очень мало (25 тысяч строк и 12 столбцов), пропусков и ошибок не было.
На основании этого были сделаны следующие предположения:
- Генерировать и сортировать гипотезы эффективнее, чем их придумывать, поскольку объем данных очень мал.
- Скорее всего, в образце нет одной очень крутой скрытой зависимости, которая в итоге всё решит (killer Feature).
- Скорее всего, борьба будет за n-ное место после запятой и топ-10 будет очень плотной.
Так и произошло.
Небольшое лирическое отступление.
Большинство решений, выигравших конкурсы по машинному обучению, не подходят для реальных систем.
Возьмем знаменитый случай с Netflix: они заплатили 1 миллион долларов за решение, которое не смог реализовать .
Поэтому финальные модели на таких соревнованиях напоминают мне некий роман.
Вторая часть его имени «Современный Прометей» — тот, кто принес людям огонь и знания.
Первая часть, конечно, Франкенштейн.
Базовое решение
В качестве базового решения я использовал xgboost, который после оптимизации параметров через Hyperopt сразу выдал результат в таблице лидеров 0,3825. Затем я перешел к разработке функций.Например, было замечено, что распределения многих признаков напоминают логарифмические, поэтому я добавил их логарифмы (точнее, log(x+1)) в базовые столбцы.
Далее я сгенерировал различные функции из всех возможных комбинаций двух столбцов и проверил, как они повлияли на результат. В рамках этой задачи мне казалось бессмысленным придумывать какие-то «интерпретируемые» фичи, потому что гораздо быстрее было бы просто перебрать их, благо объем данных позволяет. Хороший результат, например, получен при разнице различных характеристик, что позволило на одном и том же xgboost получить 0,3819.
Вы можете прочитать об оптимизации параметров и выборе столбца в моя предыдущая статья .
Первые неприятности
При проверке решений в самом начале чемпионата выяснилось, что изменение рейтинга в таблице лидеров довольно плохо соответствует изменению локального рейтинга.При генерации новых столбцов логлосс на локальной перекрестной проверке стабильно уменьшался, а на лидерборде рос, и никакие изменения параметров локального разделения выборки для проверки не помогали.
Наблюдая за общим чатом соревнований, можно было заметить, что с этой проблемой столкнулись многие участники, независимо от среднего и дисперсии локальных оценок.
Это был еще один знак в пользу создания ансамбля моделей.
Еще деревья.
Используя тот же набор столбцов (их на тот момент у меня было 70), я создал еще два ансамбля деревьев градиентов, но из других библиотек — sklearn и легкий ГБМ .
Обучение проходило следующим образом - сначала я настраивал каждую модель индивидуально на лучший результат, затем брал среднее, сохранял результаты всех моделей и настраивал каждую по очереди, но не на свой лучший результат, а на лучший результат в ансамбль из трех моделей.
Это дало примерно 0,3817 в таблице лидеров.
Регрессия
Несмотря на то, что даже разные реализации одних и тех же алгоритмов дают лучшие результаты при усреднении в ансамбле, гораздо эффективнее объединять разные алгоритмы вместе.Так к общему ансамблю добавилась логистическая регрессия.
Модель строилась так же, как и предыдущие — генерируем все возможные признаки, рекурсивно выбираем и оставляем лучшие.
Здесь я был разочарован.
Локальная регрессия показала лучшие результаты, чем xgboost! В таблице лидеров результат был гораздо хуже: 0,383. Я довольно долго с этим боролся, выбрасывал признаки, распределение которых на обучающей и тестовой выборках различалось, пробовал различные методы нормализации, пробовал делить признаки на интервалы — ничего не помогало.
Но даже при таком результате добавление регрессии в ансамбль оказалось полезным — результат примерно 0,3816.
Нейронные сети
Раз уж линейная регрессия показала хорошие результаты, то стоит попробовать нейронные сети.Я потратил на них много времени, так как применение стандартных алгоритмов гипероптимизации к структуре нейронной сети дает очень слабый результат. В результате была найдена хорошая конфигурация, которая дала в лидерборде примерно столько же, сколько и регрессия.
Для реализации использовалась библиотека керас , саму структуру я здесь приводить не буду, вы можете найти ее в конечном файле, я просто приведу небольшой пример кода, который мне очень помог.
Перекрестная проверка показала, что результат модели сильно зависит от количества эпох обучения.
Можно снизить скорость обучения – но это ухудшит результат; Распад поставить не удалось - результат тоже ухудшился.
Тогда я просто решил изменить скорость обучения один раз в середине тренировки.
Результат после добавления в ансамбль составляет примерно 0,3815.from keras.callbacks import Callback as keras_clb class LearningRateClb(keras_clb): def on_epoch_end(self, epoch, logs={}): if epoch ==300: self.model.optimizer.lr.set_value(0.01)
Больше моделей богу моделей
Все вышеперечисленные модели были построены примерно на одних и тех же столбцах — сгенерированных на основе базовых признаков и их логарифмов.Я также пытался создать объекты на основе базовых столбцов и их квадратных корней.
Это тоже помогло — были добавлены ещё два ансамбля градиентных деревьев.
Этот набор стал финальным: регрессия, нейронная сеть и пять ансамблей градиентных деревьев.
Результат примерно 0,3813.
Анализ образца
Важным дополнением к ансамблю стало небольшое изменение общего результата модели перед отправкой.Обнаружено, что в обучающей выборке присутствуют большие группы строк с абсолютно одинаковыми характеристиками.
А поскольку логлосс побуждает нас оптимизировать вероятность, было бы логично заменить результаты модели на этих группах средним значением, рассчитанным на обучающей выборке.
Это было сделано для групп размером более 50 элементов.
Результат примерно 0,3809.
Идеи, от которых я отказался
Укладка.При таком большом количестве моделей кажется, что мы могли бы придумать лучшую функцию для их усреднения, чем простое среднее арифметическое.
Вы могли бы, например, поместить их результаты в другую модель.
Я отказался от этой идеи, поскольку локальные результаты не сильно совпадали с лидербордом, и даже самый простой тип стекирования — средневзвешенный — не работал.
Изменение результатов вручную.
В обучающей выборке были подгруппы, результаты которых были строго 1 или строго 0, например, все игроки, игравшие 14 дней.
Здесь, конечно, стоило вспомнить, как сильно наказывает logloss за такие значения; в случае использования может быть потеряно более ста мест. Также до последнего момента среди моделей присутствовал и случайный лес, но в итоге, исходя из публичной оценки, я его исключил, хотя, как выяснилось позже, модель с ним показала лучший результат на частный счет. В заключение очень хочу поблагодарить организаторов! Здесь Здесь Вы можете увидеть исходный код решения.
Теги: #Машинное обучение #наука о данных #конкурсы #python #учебный лагерь по электронной почте #Машинное обучение
-
Hdr-Фотография Может Быть Уместна
19 Oct, 24 -
Хороший Сайт – Это Сервис И Простота
19 Oct, 24 -
Портативная Призма
19 Oct, 24