История 3-го места на ML Boot Camp III |
||
МЕНЮ Искусственный интеллект Поиск Регистрация на сайте Помощь проекту ТЕМЫ Новости ИИ Искусственный интеллект Разработка ИИГолосовой помощник Городские сумасшедшие ИИ в медицине ИИ проекты Искусственные нейросети Слежка за людьми Угроза ИИ ИИ теория Внедрение ИИКомпьютерные науки Машинное обуч. (Ошибки) Машинное обучение Машинный перевод Реализация ИИ Реализация нейросетей Создание беспилотных авто Трезво про ИИ Философия ИИ Big data Работа разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика
Генетические алгоритмы Капсульные нейросети Основы нейронных сетей Распознавание лиц Распознавание образов Распознавание речи Техническое зрение Чат-боты Авторизация |
2017-04-30 18:56 машинное обучение новости, разработка по, новости нейронных сетей Недавно завершился контест по машинному обучению ML Boot Camp III от Mail.Ru.
Будучи новичком в machine learning мне удалось занять 3-е место. И в этой статье я постараюсь поделиться своим опытом участия. Я давно участвую в различных контестах по спортивному программированию, в том числе и в других чемпионатах от Mail.Ru, откуда собственно и узнал об этом. С машинным обучениям я был знаком только на уровне лабораторных работ. Слышал о таком ресурсе, как kaggle, но ни в чём подобном ранее не участвовал. Поэтому это стало для меня неким вызовом — вспомнить чему учили в универе, и попытаться что-то из этих знаний собрать. На высокие места особо не надеялся, но призы неплохо добавляли мотивации. Незадолго перед стартом уже была известна задача. Это задача бинарной классификации. Выбор языка программирования был не особо велик, я знал, что было принято использовать Python или R. С обоими я на минимальном уровне знаком, но выбрал R. В нём всё что нужно есть «из коробки», не нужно заморачиваться со сборкой или установкой пакетов. Хоть он и странный, в нём кривой GC, он периодически падает, о выборе я не пожалел. Задача Есть данные об участии игроков в онлайн-игре за последние 2 недели в виде 12 числовых признаков. Нужно определить, покинет-ли её игрок хотя-бы на неделю, или останется. А именно, сказать вероятность этого события. ? Ссылка на полное условие задачи.На первый взгляд задача абсолютно классическая. Таких, наверное, море на kaggle, бери готовый код и используй. Даже в тренировке предлагают схожую задачу кредитного скоринга. Как оказалось, не на столько всё просто. Мне пригодилось:
Обзор данных Обучающая и тестовая выборки без пропусков. Размером по 25000 каждая – на так уж и много. На этом исследование данных практически заканчивается. Я почти не делал никаких графиков и прочих визуализаций.Первые попытки Уже заранее определился, что начну с логических алгоритмов классификации – решающие деревья, решающий лес, а также random forest, bagging, boosting над ними. Решающие деревья и random forest не трудно запрограммировать самому. Это делается по лекциям Воронцова, где описан алгоритм ID3.Стало понятно, что с самописными алгоритмами далеко не пойдёшь, хотя эта процедура здорово помогла в их понимании. Нужно использовать что-то готовое. Xgboost Xgboost — библиотека, реализующая градиентный бустинг. Используется многими победителями соревнований kaggle – значит нужно пробовать.Одним из параметров обучения было количество деревьев (nrounds), но сразу не понятно сколько нужно указывать. Есть и альтернатива – разбить выборку на 2 части – обучение и контроль. Если при добавлении очередных деревьев ошибка на контроле начинает ухудшаться, то останавливать обучение. Я воспользовался техникой Bootstrap aggregating. Делим выборку 200 раз случайным образом на обучающую и контрольную (по моим экспериментам, оптимальным оказалось соотношение 0.95/0.05), и запускаем xgboost. Итоговый классификатор – голосование (среднее) всех 200 базовых классификаторов. Это дало мне гораздо лучший результат, нежели самописный Random Forest или AdaBoost. Feature engineering Следующим шагом стала генерация новых признаков. Самое простое что можно было придумать – сгенерировать множество нелинейных комбинаций существующих признаков, затем ненужные убрать, оставив только оптимальный набор.Новыми признаками стали просто попарное умножение и попарное деление каждого с каждым. Вместе с исходными всего получилось 144 признака. В тех же лекциях Воронцов предлагает использовать жадный алгоритм Add-Del, поочередно удаляя и добавляя новый признак. Но по причине неустойчивости модели (на разных random seed с одинаковыми данными оценка качества сильно колеблется), этот подход не дал результата. Я использовал генетический алгоритм. Сгенерируем начальную популяцию – бинарные вектора, означающие какие признаки брать, а какие нет. Новые индивиды появляются путем скрещивания и мутации предыдущих. Тут нужно было позаниматься подбором различных вероятностей, штрафов за количество признаков, и др. За 4-6 поколений и за 12 часов работы обычно всё сходилось к локальному минимуму. Однако этот локальный минимум уже давал неплохие оценки. Xgboost не очень чувствительный к неинформативным признакам (в отличии от нейросети, о которой будет дальше) – одна из причин того, что скрещивание двух хороших наборов признаков даёт тоже хороший набор. В итоге из 144 признаков у меня отобрались 63. LightGBM Позже я перешел на использования библиотеки LightGBM от Microsoft. Она давала почти такие же результаты как Xgboost, но работала в разы быстрее. А также имела дополнительные параметры обучения. Например, полезной оказалась возможность ограничивать не только максимальную глубину дерева (max_depth), но и число листьев (num_leaves). Для меня оптимальными оказались num_leaves = 9 и max_depth = 4.Нейронная сеть После неудачных попыток использовать SVM, KNN, Random Forest, я остановился на нейронной сети. А точнее, на персептроне с одним скрытым слоем, используя пакет nnet.Одним из первых что я сделал – запустил примерно такой код: Это практически пример из мануала. Далее, взял среднее арифметическое с тем что получил от LightGBM, и сделал посылку на сервер. Очень удивился, как это закинуло меня на первое место, где продержался около недели. Обработка частных случаев Как и в обучающей, так и тестовой выборках присутствовали одинаковые вектора, но с разными ответами. Например, присутствовали такие, которые встречались по 1423, 278, 357, 110 раз. Наверное, нет ничего лучше, чем посчитать для них вероятности отдельно, что я и сделал. Обработал только те, которые встречались более 15 раз. Вопрос был только в том, исключать эти повторы из обучения, или нет. Я попробовал оба варианта, и сделал вывод, что исключение делает хоть немного, но хуже.На самом деле сейчас можно было остановиться. Это дало бы финальное первое место с небольшим запасом. Но задним числом все умны. Ансамбль из двух моделей Стоило придумать более удачную агрегирующую функцию, нежели просто среднее арифметическое или среднее геометрическое. Идея следующая:
Нейронная сеть + bootstrap Оставлять то, что получилось с удачным выбором seed было нельзя. Просто повезло, и, казалось, это явный overfit. Далее всё время я потратил на то, чтобы хотя-бы приблизиться к полученному результату. Итак, повезло с удачным выбором seed, т.е. удачно подобрались веса для нейронов. Тогда нужно было много раз запустить обучение, и выбрать лучшее. Но как определить получилось-ли лучше? И я придумал следующее:
Таким образом, я почти приблизился к желаемому результату. Но к сожалению, для победы чуть-чуть не хватило. Нереализованные задумки
Спасибо за внимание. Список литературы:
Код на github Источник: habrahabr.ru Комментарии: |
|