Получение рекомендаций — это то, что мы все знаем из таких крупных компаний, как Netflix и Amazon. Людям, которым нравится этот продукт, также нравятся эти продукты. Авиабилеты могут быть особым продуктом, поскольку на один и тот же рейс в другой месяц, день недели, аэропорт вылета или незадолго до или задолго до вылета спрос может быть совершенно разным. Тот же самый продукт может быть даже в 10 раз дешевле, если он куплен задолго до даты вылета. Также часто бывает, что клиенты покупают обратные рейсы, и в этот момент вы фактически покупаете два рейса в пакете, что вместе должно быть для вас выгодной сделкой. Это делает его интересным для рекомендательных систем.

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

Соревнование

Предоставление рекомендаций может показаться простым, но проблема в том, что возможны миллионы комбинаций возврата, и у нас есть около 100–200 мс, чтобы предоставить вам лучшие рекомендации на веб-сайте. Поэтому крайне важно разумно сузить варианты, которые могут быть актуальны для вас, и составить топ-3, которые мы хотели бы вам показать.

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

Наслаждайтесь магазином функций

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

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

Feast, сокращение от Feature Store, — это центральное место для хранения функций, готовых к использованию в любой модели. Центральный репозиторий с определениями, который выводит ETL функций из проекта и способствует повторному использованию в проектах. Существует центральное место, где определяются объекты, определения объектов, представления объектов и сервисы объектов. Кроме того, существует автономное хранилище (например, база данных SQL), где хранятся все исторические функции, и онлайн-хранилище (например, кэш Redis), где хранятся последние значения функций.

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

Во время обучения мы спросим у нашего офлайн-магазина, какие значения функций были в отметке времени x для клиента y, чтобы убедиться, что нет утечки данных. Во время вывода, когда вызывается наш рекомендательный API, мы быстро спрашиваем наш интернет-магазин, каковы последние значения функций для клиента, который в настоящее время сделал запрос на посещение домашней страницы или страницы поиска рейсов на нашем веб-сайте.

Таким образом, за миллисекунды мы получаем всю информацию, необходимую для запуска процесса рекомендации.

Генерация кандидатов и предсказание

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

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

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

Используя Databricks и модель PySpark, мы теперь предсказываем, какие рейсы вряд ли будут забронированы кем-либо в ближайшие 24 часа. Многие комбинации рейсов туда и обратно просто не имеют значения, продолжительность пребывания, например. 24 дня, отправление во вторник и возвращение в пятницу, исторически говоря, просто не то, что клиенты склонны бронировать. Самые дорогие билеты, у которых есть более дешевые альтернативы, также иногда отфильтровываются. Как правило, метод повышения градиента применяется для получения склонностей для каждой комбинации доходности. Мы сортируем их и отфильтровываем x%, что составляет большую часть всех рейсов. Мы теряем здесь некоторую точность модели, но лишь небольшую часть, в то время как улучшенная задержка того стоит.

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

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

Если у нас есть информация о ваших предыдущих бронированиях, мы могли бы, например, выбрать только рейсы, вылетающие из вашего любимого аэропорта вылета, выпадающие на праздничный период, в ваши любимые дни вылета или те, которые будут летать в те же пункты назначения, в которые вы летали.
Если у нас нет информации о вас, мы все равно можем уменьшить количество вариантов, но сделать это с учетом последних тенденций; люди, как правило, бронируют авиабилеты на 3, 4 или 7 дней, есть определенные направления, которые более популярны в определенные месяцы и т. д. Мы, конечно, также можем попробовать и порекомендовать лучшие предложения на нашем веб-сайте. Цель — остаться с набором из 500–1000 обратных рейсов. Это гарантирует, что наша модель может делать прогнозы для этих кандидатов за разумное время.

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

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

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

Моделирование подъема

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

Есть клиенты, которые приходят на сайт и точно знают, чего хотят. Это прекрасно, им не нужны рекомендации (конечно). Тогда есть люди, которые не обратятся несмотря ни на что (безнадежное дело). Две другие группы более важны. Может быть небольшая группа, которая может быть раздражена лечением или начать сомневаться из-за рекомендаций и не покупать билеты, в то время как в противном случае (спящие собаки). Будем надеяться, что таких не много. И затем группа, которую мы пытаемся сделать как можно больше, убедительные, которые будут конвертироваться благодаря нашим рекомендациям и не конвертировались бы иначе.

Если вы думаете о таких группах, может оказаться, что кандидаты с наивысшими показателями склонности к клиенту могут не сделать их убедительными, скорее вы будете «правильными» в определенных вещах, но не получите никаких дополнительных конверсий. . Они бы сами нашли те варианты, где мы рекомендуем просто взять следующий день по тому же маршруту, или, может быть, остаться на день больше или меньше. Когда мы немного спустимся в этом рейтинге, мы можем найти более интересных кандидатов. Это кандидаты, которых клиенты могли не найти сами, например. другой аэропорт вылета, тот же рейс через неделю или комбинация. Рекомендация их может означать, что вы чаще ошибаетесь, но, эй, они все равно бронировали, так что нет проблем, но вы можете привлечь больше клиентов, как это сделают некоторые, которые, возможно, не бронировали без рекомендаций, сейчас. Это то, что в итоге повысит конверсию.

Вместо того, чтобы предсказывать показатель склонности, вы можете напрямую применить моделирование подъема. Либо используя две модели, одну модель, но делая 2 прогноза, один с функцией обработки, установленной на 1, и другой, установленный на 0, и проверяя разницу в склонности, или применяя одну модель, которая напрямую предсказывает подъем, как это делают поднятые деревья.
Какой бы метод вы ни выбрали, вам потребуются исторические данные как для случаев без лечения, так и для случаев лечения, которых у нас пока нет. Таким образом, наш первый подход, прежде чем мы перейдем к моделированию подъема, заключается в применении сигмовидной функции к 100 верхним баллам склонности ранжированных кандидатов и выборке на основе этого распределения. Это гарантирует, что мы часто будем рекомендовать хорошие рекомендации, но получим много вариаций и исследований в нашем наборе данных, которые мы позже сможем использовать для подбора модели подъема.

A/B-тестирование и контекстные бандиты

Теперь, когда наше приложение машинного обучения работает от начала до конца, пришло время его протестировать. Первый вопрос: помогают ли рекомендации в целом покупателю найти то, что он ищет, повышая тем самым конверсию? Мы хотим убедиться, что влияние на клиентов положительное, и исключить, что рекомендации являются только отвлечением.

Мы начали с A/B/C-теста, в котором A является исходным. Вообще никаких рекомендаций. B — простая рекомендательная система, функционирующая как базовое сравнение. И C – наш новый интеллектуальный рекомендатель рейсов.
Для B мы решили рекомендовать наиболее часто бронируемые рейсы за последние 2 недели.

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

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

Недостатком текущей настройки является то, что она обучается на исторических данных и, таким образом, опирается на относительно длительные исторические тренды. Если мы добавим в нашу сеть новые направления, что происходит довольно часто, или если обстоятельства в реальном мире (например, Covid) резко изменят потребительский спрос в быстром темпе, наша модель будет медленно адаптироваться из-за настройки автономного обучения на исторических данных. . Контекстная бандитская установка применяет онлайн-обучение, в котором она будет балансировать между исследованием и эксплуатацией. Конкретно, используя ранжирование показателей склонности, он будет пробовать рекомендации, которые могут не занимать первое место, но для которых склонность менее определенна. Таким образом, даются новые рекомендации, которые не рекомендуются при контролируемой настройке обучения. Эта стратегия исследования соберет данные и даст модели лучшее понимание того, что работает, а что нет. Она может попробовать порекомендовать новые направления или быстрее адаптироваться к изменениям на рынке. Он также будет пробовать рейсы, которые клиент вряд ли найдет, что даст нам возможность улучшить подъем.
Несмотря на то, что первоначальное исследование обходится дорого, эти методы, как правило, превосходят традиционную настройку в долгосрочной перспективе, поскольку они постоянно уравновешивают исследование и эксплуатацию для оптимизации производительности. Так что это определенно следующий шаг для нас.

Производительность

Возвращаясь к результатам испытаний, которые мы видели до сих пор, мы довольны тем, чего достигли. Оба рекомендателя показывают повышенный уровень бронирования по сравнению с тем, чтобы не показывать рекомендации. Версия B, базовая модель, показывает небольшое увеличение, а версия C, наша модель, показывает значительное увеличение конверсии. CTR нашей интеллектуальной модели также в 10 раз выше по сравнению с базовой рекомендательной системой.

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

С точки зрения технических характеристик наше приложение также держится хорошо. В среднем мы можем предоставить рекомендации в течение 100–120 мс при большой нагрузке от трафика сайта. Запрос через Интернет занимает некоторое время, вызов Feast занимает всего 3–5 мс, применение бизнес-правил на самом деле занимает больше всего времени, а модель LightGBM работает очень быстро (хотя ей приходится делать до 1000 прогнозов на запрос). ). Это означает, что есть возможность улучшить сложность модели за счет добавления функций, а также настройки ее гиперпараметров.

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