Как победить в соревновании на Kaggle. Советы Data Scientist-a
Помимо работы над проектами клиентов, наша data science команда часто принимает участие в различных соревнованиях.
Недавно мы показали хороший результат в Quora Question Pairs Challenge на Kaggle. Это соревнование примечательно большим количеством неожиданных открытий и оживленных дискуссий среди участников. Поэтому я решил детально описать особенности этого соревнования и раскрыть вам рецепт победы.
Автор: Артем Фаразей.
Автор: Артем Фаразей
Помимо работы над проектами клиентов, наша data science команда часто принимает участие в различных соревнованиях.
Недавно мы показали хороший результат в Quora Question Pairs Challenge на Kaggle. Это соревнование примечательно большим количеством неожиданных открытий и оживленных дискуссий среди участников. Поэтому я решил детально описать особенности этого соревнования и раскрыть вам рецепт победы.
Описание и цель соревнованияQuora — социальный сервис для обмена знаниями, где любой может задать интересующий его вопрос. Аудитория Quora очень разнообразна. Люди используют сайт для учебы, работы, и в любой ситуации, когда у них возникают вопросы, на которые они затрудняются найти ответы. Более 100 миллионов человек посещает ресурс каждый месяц, поэтому не удивительно, что многие задают похожие вопросы. Вопросы-дубликаты усложняют процесс поиска ответов и заставляют отвечающих тратить больше сил на то, чтобы охватить все похожие вопросы. Перед участниками соревнования была поставлена задача предсказать, какие из предложенных пар вопросов являются дубликатами.
Участникам предложили тренировочный датасет, который содержал больше 404 тысяч пар вопросов. Если вы присмотритесь к примерам, то сразу поймете, что данная задача очень сложна даже для человека:
Первые три вопроса были предварительно помечены Quora как дубликаты, а пары 4-6 считались не дубликатами. Как видно из примеров, словарное наполнение вопросов-дубликатов может совсем не совпадать, а вопросы, которые не являются дубликатами, могут отличаться всего одним словом. Это одна из главных особенностей датасета, которая делает задачу такой сложной для NLP технологий.
Интересные особенности датасетаПрактически сразу после начала Kaggle соревнования участники начали делиться интересными наблюдениями о датасете. Примеры самых распространенных наблюдений:
Шумная разметка данных
Как признались сами организаторы, «Предварительная разметка необходима для того, чтобы проинформировать участников, но не является на 100% правильной, может содержать ошибки. Мы считаем, что в разметке соблюдено равновесие, но в отдельных случаях возможны исключения». На самом деле, участникам встретилось множестве примеров, где разметка была неправильной, либо двусмысленной. Некоторые сравниваемые вопросы были включены только частично. Вот несколько примеров:
У участников этого соревнования часто случались ситуации, когда на некоторых вопросах их модели предсказывали метки более точные, чем те, которые содержались в оригинальной разметке. Еще необходимо отметить, что ручное исправление явно неверных меток в обучающей выборке не приводило к улучшению качества на тестовой выборке, т. к. в ней видимо тоже много некорректных меток.
Большое количество вопросов про Индию
Несмотря на то что обучающая выборка содержит вопросы, которые затрагивают большое количество различных тем (начиная с вопросов про котиков и собачек, заканчивая вопросами про недавние громкие политические события), сразу бросается в глаза, что значительная часть вопросов касается Индии. Это неприятно тем, что некоторые NLP модели, обученные на таком датасете, могут начать придавать слишком большое значение словам, которые специфичны только для вопросов про Индию, а значит такие модели могут плохо работать на вопросах не связанных с Индией. Нам это не сильно помешало, т. к. в тестовой выборке тоже было довольно много вопросов про Индию.
Зависимость количества дубликатов от времени и различная доля дубликатов в обучающей и тестовой выборках
Эта интересная особенность связана с id вопросов в обучающей выборке. Сами по себе id вопросов — это служебная информация, однако часто в соревнованиях по машинному обучению id неявно содержат полезную информацию. Например, если мы предположим, что более старые вопросы имеют меньший id, а более новые — больший, то мы можем посмотреть на зависимость доли дубликатов от времени.
Как мы видим на графике, со временем доля дубликатов снижается. К сожалению, в отличии от обучающей, тестовая выборка не содержит id вопросов, поэтому мы не можем явно использовать эту информацию (хотя некоторые участники пытались восстановить id и для вопросов из тестовой выборки). Если учесть то, что распространенной практикой является использование в качестве обучающей выборки более старых данных, а для тестовой — более свежих, то это наталкивает на мысль, что доля дубликатов в тестовой выборке, на самом деле, ниже, чем в обучающей. Более того, для самых новых вопросов из обучающей выборки доля дубликатов находится в районе 15-20%, что очень хорошо согласуется с предыдущими оценками доли дубликатов в public leaderboard, согласно которым в тестовой выборке всего 17,5% дубликатов.
Вкупе с тем, что организаторы случайным образом делили тестовую выборку на public и private, мы вполне можем надеяться, что и в private датасете доля дубликатов будет примерно такой же.
Нам очень важно знать, если распределение дубликатов в тестовой выборке существенно отличается, так как используемая в данной задаче метрика качества сильно от неё зависит и очень чувствительна к её изменению. Например, если модель будет сомневаться, к какому классу отнести какой-нибудь пример, то она скорее всего отметит его как не дубликат просто потому, что в выборке, на которой эта модель обучалась, не дубликатов было значительно больше чем дубликатов.
Магические фичиИзначально предполагалось, что участники будут использовать только текстовые данные, однако оказалось, что очень много информации о вопросах хранится в структуре датасета. Для того, чтобы использовать эту информацию удобно представить датасет в виде графа. Это можно сделать разными способами. Например, можно построить граф, в котором каждая запись в датасете будет представлена двумя вершинами, соединенными ребром, при этом каждая вершина соответствует одному вопросу из датасета. Например, если мы представим, что датасет состоит всего из семи записей,
граф будет выглядеть следующим образом:
Теперь мы можем для каждой пары вопросов, которые соответствуют какой-либо записи из датасета, посчитать количество «общих соседей», т. е. вопросов, которые соседствуют в графе с обоими вопросами из данной записи. Например, для первой записи из нашего примера таких вопросов-соседей будет два:
Оказалось, что количество таких «общих соседей» — очень мощная фича. Это можно увидеть на следующем графике, где изображено соотношение дубликатов и не дубликатов в обучающей выборке для записей с определенным числом общих соседей.
Так, например, среди всех записей, для которых значение этой фичи равно нулю, дубликатов около 80%, тогда как среди записей, имеющих одного соседа, дубликатов меньше 40%.
Другая структурная особенность — частота вопроса. Давайте посчитаем для каждой вершины графа количество инцидентных ей ребер (или другими словами, просто посчитаем сколько раз каждый отдельный вопрос встретился в датасете). Тогда каждой записи будет соответствовать частоты двух вопросов, и в качестве фич мы можешь взять минимальную (максимальную) из этих частот, их среднее или модуль разности. Такие фичи тоже получаются довольно мощными и улучшают качество модели (впрочем, это может объясняться корреляцией этих фич с предыдущей).
Во время соревнования эти фичи окрестили «магическими», так как они были очень мощными, для многих было неожиданно, что можно извлечь информацию не только из текста, а также не было понятно, будут ли подобные фичи полезны в реальной жизни (для организаторов соревнования). К тому же, некоторые NLP модели (например TF-IDF) неявно используют частоту вопроса, а значит они могут давать прирост качества только потому, что эксплуатируют особенность датасета.
Наше решение Quora Question Pairs Competition на KaggleDeep learning
Учитывая то, какая перед нами стояла задача, можно справедливо отметить, что перед началом соревнования многие (в том числе и организаторы соревнования) возлагали большие надежды на deep learning. Ведь действительно, DL модели зачастую оказывались намного лучше, чем модели использующие сотни ручных фичей (а именно такая модель использовалась на тот момент в Quora). Именно поэтому мы начали именно с них.
Word vectors (Embeddings)
Под DL моделями в настоящее время подразумеваются глубокие нейронные сети, которые принимают на вход сырые данные (в нашем случае это тексты вопросов) и сами извлекают из них необходимые фичи. Однако есть проблема — нейронные сети (да и вообще компьютеры в целом) предпочитают работать с наборами чисел (векторами) и совершенно не умеют работать с сырыми текстами. (Например слова «dog» и «puppey» имеют довольно похожий смысл, но для компьютера это просто строки, причем не очень похожие строки. Они имеют разную длину, у них встречаются разные буквы, и компьютер просто по этим двум строкам не сможет сказать, что они имеют одинаковый смысл. А для данной задачи нам жизненно необходимо понимать, похожи слова или нет.) Для решения этой проблемы используется подход, который называется word2vec. Его смысл можно описать известной цитатой: «You shall know a word by the company it keeps» — Firth, J. R. 1957. Word2vec преобразует слова в векторы так, что слова, которые встречаются в схожих контекстах, имеют схожие векторы. Используя word2vec мы можем преобразовать сырой текст в набор векторов, которые можно с лёгкостью скормить нейронной сети.
Стоит еще отметить, что word2vec (или другие embeddings) очень тяжело обучать, т. к. для этого требуется корпус текста размером с Википедию. Поэтому почти все участники используют заранее обученные модели.
Капучино и эспрессо почти всегда используются в одном контексте, поэтому не удивительно, что для робота-официанта использующего word2vec это почти одно и то же.
Нейронные сети
Для данной задачи как нельзя лучше подходят сиамские нейронные сети. Они используются, когда нам определить насколько похожи или непохожи два объекта. Их архитектура предполагает два абсолютно одинаковых входа, которые используются для извлечения фич из переданных в них объектов (в нашем случае это текст вопросов). Далее либо на их основе считаются какие-либо метрики сходства (например косинусное расстояния), либо фичи двух объектов объединяются и передаются в полносвязный слой. После нескольких экспериментов мы остановились на архитектуре, которая нарисована на схеме:
Глядя на нее, хочется отметить несколько вещей:
- Помимо двух входов для сравниваемых вопросов, присутствует третий вход для ручных фичей, что не очень характерно для DL моделей. Это сделано из-за «магических фичей», которые хорошо работают на данном датасете.
- В нашем решении мы использовали две нейронный сети: в первом случае для извлечения информации из вопросов использовался LSTM, а во втором — несколько сверточных слоев с последующим Global Max Pooling.
- Архитектура, на которой мы остановились, на самом деле, не очень «глубокая». Чтобы глубокие нейронные сети работали хорошо, нужно очень много данных. К сожалению, наш датасет не такой большой, и довольно шумно размечен. При добавлении новых слоев мы рискуем сильно переобучиться (особенно если мы используем LSTM).
- Есть ещё много идей, с которыми мы бы хотели поэкспериментировать, например:
- LSTM with attention
- Character-Aware Neural Network
- Triplet Neural Network
- Target encoding
После экспериментов с нейронными сетями стало понятно, что только ими нам не обойтись. Помимо того, что датасет не достаточно большой и шумно размеченный, чтобы DL модели показали на нём всю свою силу, есть проблемы и с представлением текста в виде векторов: в датасете часто встречаются вопросы, которые содержат математические формулы, нераспространённые сокращения, опечатки и т. д. Из-за этого теряется часть информации о вопросе, что существенно усложняет задачу нейронным сетям.
Градиентный бустинг
Пришло время для излюбленного инструмента участников data science соревнований — градиентного бустинга, который зарекомендовал себя как мощная и устойчивая к шуму модель.
Для него мы использовали следующие фичи:
- Длина вопросов, количество слов, количество слов без стоп-слов
- Количество заглавных букв, вопросительные знаки, скобки и тд.
- Индикаторы вопросов, такие как «Are», «Can», «How» и тд.
- Различные меры сходства, основанные на word embeddings (Word2Vec, FastText, Glove)
- Word Mover’s Distance
- Различные меры сходства, основанные на n-граммах символов (включая TF-IDF)
- Jaccard, Canberra, Chebyshev similarities
- А также фичи предоставленные Abhishek и Mephistopheies
- PageRank
Во время этого соревнования у нас была возможность протестировать новую библиотеку градиентного бустинга LightGBM. Оказалось, что по точности она не хуже (а даже немного лучше), чем старый добрый XGBoost, и при этом в несколько раз быстрее его. Так что все наши финальные модели (как и модели многих других участников) использовали LightGBM.
Также мы добавили out of fold предсказания нейронных сетей как фичи для бустинга. Осталось только не забыть сбалансировать классы, подобрать параметры модели и аккуратно провалидировать результаты. Такой модели с лихвой хватит чтобы получить серебряную медаль.
Рецепт победыЧто же нужно было сделать, чтобы победить в этом соревновании? Вот краткий «рецепт успеха»:
Чем больше, тем лучше
В то время как мы использовали около 70 ручных фич и 3 модели, победители этого соревнования оперировали 1000+ фичами и объединяли сотни (вплоть до 1000) моделей. В общем, как это часто бывает в соревнованиях на kaggle, чем больше различных моделей объединяешь — тем лучше.
Продвинутые графовые фичи
Как уже ранее упоминалось, рассмотренные нами графовые фичи — далеко не единственный способ использовать особенности предоставленных данных. В погоне за первым местом участники придумали большое количество более сложных графических фич, которые содержат в себе еще больше информации о структуре датасета.
Local rescaling
Ключевая идея здесь в том, что весь датасет можно разделить на несколько более маленьких датасетов, каждый из которых будет иметь различное распределение дубликатов, поэтому балансировать эти датасеты нужно по разному.
Постобработка предсказаний
Ещё один способ улучшить результат, которым пользовались участники — корректировка уже полученных предсказаний модели. Например, для этого можно использовать свойство транзитивности (т.е. если вопрос B — дубликат вопроса A, а вопрос C — дубликат вопроса B, то очевидно, что A и C — тоже дубликаты)
Хотелось бы отдельно обратить внимание на решение Alex, в котором используется всего одна модель — сверточная нейронная сеть (ее архитектура довольно похожа на нашу). Эта модель показывает хорошую точность и при этом, в отличии от всех остальных решений, имеет очень хорошую производительность. Она больше других подходит для применения в реальной жизни и определенно заслуживает внимания.
Соревнования на Kaggle это всегда отличное место, чтобы узнать что-то новое. Тем не менее, лучшее решение на Kaggle не гарантирует лучшее решение проблемы бизнеса. Пример этого соревнования показывает, что нужно быть очень внимательными и рассудительными во время подготовки данных для обучения моделей. Ведь если те особенности датасета, которые мы описали, являются искусственными и не характерны для всей базы Quora, то все решения, которые предоставили участники соревнования, не будут работать в реальной жизни. Это соревнование также показало, что важно сохранять широкий взгляд на проблему, видеть различные способы улучшения модели и оставаться открытыми к новым идеям и подходам. Надеюсь, эта статья была полезна для вас.
Читать на dev.by