- PVSM.RU - https://www.pvsm.ru -
У большинства крупных поисковиков и сервисов есть механизм похожих поисковых запросов, когда пользователю предлагаются варианты, тематически близкие к тому, что он искал. Так делают в google, yandex, bing, amazon, несколько дней назад это появилось и у нас на hh.ru!

В этой статье я расскажу о том, как мы добывали похожие поисковые запросы из логов сайта hh.ru.
Для начала несколько слов о том, что такое “похожие запросы” (related searches) и зачем они нужны.
Мы давно думали об этой фиче, но окончательный толчок дала прекрасная статья от LinkedIn про их реализацию похожих запросов — metaphor [5]. В ней описаны три метода извлечения таких запросов из поисковой активности пользователей, которые мы и реализовали.
Самый простой и очевидный из алгоритмов извлечения связанных запросов — это overlap или поиск пересекающихся запросов.

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

где overlap — количество общих токенов в запросах q1 и q2,
Q(t) — количество запросов с токенов t,
N — число уникальных запросов.
Следующий способ — коллаборативная фильтрация (CF). Он часто используется в рекомендательных системах и хорошо подходит для рекомендации похожих запросов. За сложным названием стоит простое предположение, что в течение одной сессии пользователь делает связанные запросы. Причём для поиска работы длинной сессией можно пренебречь, потому что предпочтения пользователя меняются медленно. Трудно представить, что соискатель, который сегодня делает запрос “персональный водитель”, завтра будет искать вакансии “java разработчика”. Но такое допущение не верно для работодателей, они могут искать кандидатов на очень разные вакансии даже в течение одного часа.

Итак, при коллаборативной фильтрации мы для каждого пользователя находим все сделанные им запросы за некий период и формируем из них пары. Чтобы выбрать самые частотные пары используем вариацию формулы tf-idf.

где tf — число пар запросов q1 и q2,
df — количество пар, содержащих запрос q2,
N — число уникальных запросов,
c = 0.1, это значение пока захардкодили, но его можно подобрать из поведения пользователей.
df не дает самым распространенным запросам вроде “менеджер” и “бухгалтер” появляться в рекомендациях слишком часто.
Третий алгоритм QRQ (query-result-query) похож на CF, но пары запросов мы строим не по пользователю, а по вакансии.

Т.е. похожими считаем запросы, по которым переходят на одну и ту же вакансию. Найдя все пары запросов, нам остается выбрать из них самые подходящие. Для этого нам нужно найти самые популярные пары, не забыв понизить вес у частотных запросов и вакансий. LinkedIn в своей статье предлагает следующие формулы, и они дают интересные результаты даже для редких запросов: например, для “теория вероятностей” связанные запросы — “алгоритмическая торговля” и “фьючерс”.



Несмотря на то что формулы выглядят сложно, за ними стоят простые вещи. V — это вклад вакансии в общий ранк: отношение числа просмотров вакансии по запросу q к общему числу просмотров этой вакансии. Аналогично, Q — вклад запроса: отношение числа просмотров вакансии по запросу q к количеству просмотров других вакансий по этому запросу.
Нужно заметить, что последние два метода не симметричны, т.е.
Мы реализовали описанные выше алгоритмы с помощью hadoop и hive. Hadoop — это система для распределенного хранения “больших данных”, управления кластером и выполнения распределённых вычислений. Каждую ночь мы загружаем туда access логи сайта за прошедший день, при этом трансформируем их в удобную структуру для анализа.

Также мы используем Apache Hive, надстройку над Hadoop, позволяющую формулировать запросы к данным в виде HiveQL (SQL-like язык заросов). HiveQL не соответствует стандартам SQL, но позволяет делать join и subselect, содержит много функций для работы со строками, датами, числами и массивами. Умеет делать Group By и поддерживает разные агрегатные функции и window-функции. Позволяет писать свои map, reduce и transform функции на любом языке программирования. Например, для того чтобы получить самые популярные поисковые запросы за день, нужно выполнить такой HiveQL:
SELECT lower(query_all_values['text']), count(*) c
FROM access_raw
WHERE
year=2014 AND month=7 AND day=16
AND path='/search/vacancy' AND query_all_values['text'] IS NOT NULL
GROUP BY lower(query_all_values['text'])
ORDER BY c DESC LiMIT 10;
Перед тем как начинать “добычу” похожих запросов, их нужно почистить от мусора и нормализовать. Мы сделали следующее:
После такой модификации запрос “тендерный отдел начальник” превратился в “#0d26431546 начальник отдел”. Показывать пользователям такое нельзя, поэтому подобный код меняем на самую популярную форму запроса “начальник тендерного отдела”.
Затем приступаем к реализации описанных выше алгоритмов, которая заключается в применении нескольких последовательных трансформаций исходных логов. Все трансформации написаны на HiveQL, что, возможно, не очень оптимально с точки зрения производительности, зато просто, наглядно и занимает несколько строк кода. На рисунке показаны преобразования данных для коллаборативной фильтрации. QRQ реализуется аналогично.

Чтобы не рекомендовать “мусорные” запросы, мы каждый запрос прогнали через поиск вакансий на hh.ru и выкинули все, для которых находится менее 5 результатов.
Последний этап задачи — это объединение результатов трех алгоритмов. Мы рассматривали два варианта: показывать пользователям по три топ-запроса из каждого метода или попытаться просуммировать веса. Мы выбрали второй способ, нормализовав перед суммированием веса:

И все вроде получилось неплохо, но для некоторых запросов вылезли странные результаты: “начинающий специалист” -> “начальник карьера”. Во-первых, тут нас подвел стемминг, который “карьер” и “карьеру” приводит к одной форме. А во-вторых, оказалось, что у трех найденных весов разное распределение и просто так суммировать их нельзя.

Пришлось привести их к одному масштабу. Для этого отсортировали каждый вес по возрастанию, пронумеровали и полученный порядковый номер поделили на общее количество пар запросов для определенного алгоритма. Это число и стало новым весом, проблема с “начальником карьера” исчезла.
Для нахождения похожих поисковых запросов мы использовали логи hh.ru за 4 месяца, а это — 270 миллионов поисков и 1.2 миллиарда просмотров вакансий. Всего пользователями было сделано около 1.5 миллионов уникальных текстовых запроса, после чистки и нормализации мы оставили чуть более 70 тысяч.
Уже за первый день работы этой фичи исправлением запросов воспользовалось около 50 тысяч человек. Самые популярные исправления:
водитель -> персональный водитель
администратор -> администратор салона красоты
водитель -> водитель с личным автомобилем
бухгалтер -> бухгалтер на первичную документацию
бухгалтер -> заместитель главного бухгалтера
Исправления популярных запросов в it-сфере:
| системный администратор | помощник системного администратора, helpdesk, системный администратор windows |
| программист | программист с++, удаленный программист, программист c# |
| технический директор | директор по эксплуатации, заместитель технического директора, технический руководитель |
| тестировщик | специалист по тестированию, тестировщик игр, тестировщик удаленно |
| junior | java junior, junior c++, junior qa |
Интересно было посмотреть, в каких профессиональных областях эта фича наиболее востребована:

Видно, что больше половины студентов, которые искали вакансии, пробовали другие запросы. Менее всего функция популярна в IT и Консультировании.
Что еще хотелось бы сделать:
Metaphor: A System for Related Search Recommendations [5]
Apache Hadoop [6]
Apache Hive [7]
Автор: martyshev
Источник [8]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/data-mining/66179
Ссылки в тексте:
[1] менеджер в Москве: http://hh.ru/search/vacancy?area=1&text=%D0%BC%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80+%D0%B2+%D0%BC%D0%BE%D1%81%D0%BA%D0%B2%D0%B5
[2] менеджер по продажам строительных материалов: http://hh.ru/search/vacancy?area=1&text=%D0%9C%D0%B5%D0%BD%D0%B5%D0%B4%D0%B6%D0%B5%D1%80+%D0%BF%D0%BE+%D0%BF%D1%80%D0%BE%D0%B4%D0%B0%D0%B6%D0%B0%D0%BC+%D1%81%D1%82%D1%80%D0%BE%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D1%85+%D0%BC%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%B0%D0%BB%D0%BE%D0%B2
[3] стажер бухгалтер по расчету заработной платы: http://hh.ru/search/vacancy?text=%D1%81%D1%82%D0%B0%D0%B6%D0%B5%D1%80+%D0%B1%D1%83%D1%85%D0%B3%D0%B0%D0%BB%D1%82%D0%B5%D1%80+%D0%BF%D0%BE+%D1%80%D0%B0%D1%81%D1%87%D0%B5%D1%82%D1%83+%D0%B7%D0%B0%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BD%D0%BE%D0%B9+%D0%BF%D0%BB%D0%B0%D1%82%D1%8B
[4] бухгалтер стажер: http://hh.ru/search/vacancy?clusters=true&text=%D0%B1%D1%83%D1%85%D0%B3%D0%B0%D0%BB%D1%82%D0%B5%D1%80+%D1%81%D1%82%D0%B0%D0%B6%D0%B5%D1%80
[5] metaphor: http://mitultiwari.net/docs/papers/related_search_cikm2012.pdf
[6] Apache Hadoop: http://hadoop.apache.org
[7] Apache Hive: https://hive.apache.org/
[8] Источник: http://habrahabr.ru/post/231393/
Нажмите здесь для печати.