Главная » Хабрахабр » Зимой и летом одним цветом? Поиск сезонности в данных

Зимой и летом одним цветом? Поиск сезонности в данных

Всплески интереса к цветам, новогодним подаркам и шинам — вполне ожидаемы. Однажды мы решили посмотреть, какие сезонные интересы есть у пользователей 2ГИС в разных городах. Мы решили ими не ограничиваться и пойти дальше, проверив все сферы деятельности во всех 113 городах присутствия.

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

Зачем вообще нужно измерять сезонность?

Потребности пользователей 2ГИС меняются в течение года: товары народного потребления, сферы услуг, строительство, государственные службы. Знания о сезонностях полезны по нескольким причинам:

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

Виды трафика

Прежде чем рассказывать о том, как мы обрабатываем трафик, стоит уточнить, что мы его делим на несколько видов.

Ему надо уточнить адрес, расписание работы или найти вход. Рекавери — вид трафика, при котором пользователь точно знает компанию, в которую хочет обратиться. В этом случае поиск происходит по названию фирмы, номеру телефона и прочим атрибутам самой компании.

То есть пользователь исследует варианты и предложения рынка, зачастую обзванивая организации или заходя на их сайты. Дискавери-трафик — это когда пользователь формулирует запрос в более общих терминах: «мягкая мебель», «поесть на Ленина», «бани».

Например, ищет ближайшие к дому аптеки или СТО.

Все пользовательские запросы и все последующие за ними действия размечаются по трафику. Гео-трафик возникает в том случае, когда пользователь работает с картой. Так как они, во-первых, соответствуют проявлению пользовательских интересов, во-вторых, ими можно управлять. Для поиска сезонностей в анализ взяли дискавери + гео-трафик. Управлять рекавери-трафиком нельзя.

Про тренды

График 1: Вы видите сезонность?
График 1: Вы видите сезонность?

Мы учитывали, что аудитории WinPhone и ПК-версий непрерывно падают. Перед тем, как приступить к поиску сезонности, нужно учесть изменения объёма трафика на разных типах устройств. Тогда как онлайн, Android, iOS — перманентно растут.

Проверка гипотез о наличии тренда

Критерии определения сезонности разработаны для стационарных рядов. Нужно проверить гипотезу о том, что ряд содержит тренд. Будем рассматривать временной ряд как случайный процесс. Тогда элементы ряда представляют собой реализации некоторой случайной величины.

Тогда основная гипотеза имеет вид:
$H_0: m_i=m, i=1,2,...,N$
против конкурирующей гипотезы о наличии тренда
$inline$H_1: ∣m_−m_i∣ > 0, i=1,2,...,N−1$inline$
где N — это количество элементов в ряде. Можем проверить гипотезу о том, что все выборочные значения принадлежат к одной генеральной совокупности со средним m.

На основе проведённых исследований выбрали критерий инверсий. Для того, чтобы проверить гипотезу, нужно воспользоваться одним из критериев значимости тренда.

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

График 2: Временной ряд (из графика 1) и его тренд
График 2: Временной ряд (из графика 1) и его тренд

Про грабли и открытия

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

  1. Пропуски в данных. В узких сферах деятельности в некоторые даты может не быть данных. Особенно кейс актуален для маленьких городов. Эту особенность нужно учитывать для корректного построения регрессии.
  2. В случае обнаружения точки перегиба — учитывайте её близость к началу или концу ряда. Возможна неправильная интерпретация поведения ряда в краевых условиях. Например, на графике 2 первые 120 точек, казалось бы, указывают на кусочно-линейный рост. Но, на самом деле, это проявила себя сезонность, которую мы увидим позже.
  3. Выбор правильной точки отсчёта. Чтобы получить корректные коэффициенты, нужно использовать ряд, начиная с первой значимой точки, и запоминать координату X этой точки (дату появления данных в ряде). Тренд будет строится в системе координат с 0 в этой точке. Этот кейс актуален для сравнения сфер между собой. Например, в 2ГИС города запускались не одномоментно и, соответственно, начинали отправлять статистику в разное время. То же самое справедливо для появления новых бизнесов, таких как, например, барбершопы.
  4. Пожалуй, самое сложное — это найти компромисс между уровнем детализации и достаточностью объёма данных. Мы остановились на тройке измерений: город, сфера деятельности, платформа пользовательского устройства.

График 3: Ряд без тренда
График 3: Ряд без тренда

Поиск сезонностей

После вычитания из временных рядов соответствующих им трендов можно переходить к задаче поиска сезонностей. Она состоит из двух подзадач:

  1. Обнаружения самого факта наличия сезонности ряда.
  2. Определения высокого и низкого сезонов — именно это имеет практическую ценность.

Обнаружение корреляций

Готовые функции поиска корреляций есть как в R, так и в Python. Мы использовали корреляцию Пирсона. При работе с векторами пользовательских интересов надо иметь в виду следующее:

  • После вычитания тренда из исходного ряда могут получиться отрицательные значения. Это нормально на данном этапе.
  • Для нашей задачи достаточно проверки корреляции временных рядов в 365 дней. Да, влияние високосного года незначительно и мы его в расчёт не берём.
  • Для поиска сезонности необходимо наличие данных как минимум за два полных периода. В наших расчётах использовались данные за четыре периода.

Ищем корреляцию двух векторов: X: [0; N-365], Y: [366; N]. Где N — длина ряда.

График 4: Обнаружение корреляции
График 4: Обнаружение корреляции

Получаем пользу

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

Где единица — это «нормальный» уровень пользовательского интереса к сфере деятельности. В качестве конечного результата была выбрана мультипликативная шкала. Значение отличное от единицы характеризует кратное увеличение или спад интереса.

Для определения уровня 1 использовали медиану помесячного внимания пользователей. В нашем случае [пока] достаточно временного масштаба продолжительностью в месяц. Далее вычисляли кратное отклонение от этой медианы.

График 5: Годовая сезонность
График 5: Годовая сезонность

На этом и всех предыдущих графиках — клики в музеи Санкт-Петербурга. Пора раскрыть тайну, какие данные показывают графики статьи. Как видно из последнего графика, музеи популярны в январские праздники, когда много выходных, и летом.

А что если ...

… взять и скормить алгоритму не интересы пользователей, а, например, продажи?

Алгоритм действий такой же:

  1. Ищем тренды. Аудитория городов растёт, и вместе с ней растёт число рекламодателей. Надо вычитать тренд, связанный с ростом популярности 2ГИС как рекламной площадки, для получения отраслевых всплесков и спадов.
  2. Находим корреляции продаж из года в год, а затем высокий и низкий сезоны.

Понадобилось внести ряд коррективов

Реклама в 2ГИС продаётся помесячно, поэтому за масштаб взяли месяц, но пользовательскую сезонность анализировали с точностью до дня. Для обратной совместимости адаптировали алгоритмы, чтобы они работали с произвольными рядами, где по оси X — порядковый номер точки, а по оси Y некое value (на этом уровне семантика value не имеет значения).

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

В этом случае корреляцию надо считать в 12 точек вместо 365. Так как продажи помесячные, то и точек в рядах у нас существенно меньше.

График 6: Сезонность продаж
График 6: Сезонность продаж

Теперь видно, где мы продаём рекламу позже, чем надо, и отстаём от пользовательского спроса. В качестве завершающего этапа мы решили наложить сезонность продаж на пользовательскую сезонность.

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

График 7: Пересечение пользовательской сезонности и сезонности продаж
График 7: Пересечение пользовательской сезонности и сезонности продаж (зеленый — пользовательская, голубой — продажи, красный — совпадение)

На чём делали

Всё выше описанное реализовано в MS SQL Server 2016. Для поиска линейной регрессии и корреляции используется R, который входит в состав сервера, начиная с версии 2016. И поскольку у нас Data Warehouse и аналитика пользовательской статистики уже на SQL Server, оказалось очень удобным использовать R для математических расчётов.

Пример использования R из TSQL:

INSERT INTO #tmp
EXEC sp_execute_external_script @language = N'R', @script = @R, @input_data_1 = N'SELECT DataId, Number, Value FROM #data ORDER BY 1, 2'

Где:

  • переменная R содержит непосредственно R-код;
  • language = N'R' — указывает на то, что скрипт, переданный в переменной R, содержит код на языке R. В SQL Server 2017 помимо R можно использовать language = N'Python'. Тогда, соответственно, в параметр script необходимо передать код на Python.
  • input_data_1 — содержит SQL-запрос, к результатам которого внутри R-кода можно обращаться как к InputDataSet;
  • Результатом выполнения процедуры будет рекордсет OutputDataSet, сформированный как OutputDataSet < — calcAllTrend(data = InputDataSet);
  • Обязательно указать формат результирующего рекордсета: количество и типы столбцов. В данном случае формат OutputDataSet определяется таблицей #tmp, куда происходит запись результатов. Либо можно воспользоваться WITH RESULT SETS для описания результирующего рекордсета.

В нашем случае оказалось, что существенную часть времени выполнения sp_execute_external_script занимает непосредственно обращение к R Services. Сам R-код отрабатывал быстро.

Поэтому решили передавать в InputDataSet не один ряд (Number, Value), а сразу несколько, сгруппированных по DataId. Напомню, мы хотели посчитать тренды и сезонности для всех городов покрытия 2ГИС и всех сфер деятельности. Тем самым существенно сэкономили на вызове службы R Services. А цикл по DataId организовали внутри R.

Факты из жизни

Вы дочитали статью до конца, это похвально. Чтобы развлечь вас перед итогами, делимся интересными фактами, выявленными в ходе анализа сезонности.

Факт №1

Автомобилисты знают из личного опыта, что сезон поиска шин и шиномонтажа — весна и осень. Но, если быть точным, сезон в разных городах может сильно отличаться. Поэтому при формировании подборок и дашбордов (стартовых экранов в продуктах) важно учитывать сезонность в каждом конкретном городе.

График 8: Сезонности шин в Краснодаре, Новосибирске и Норильске
График 8: Сезонности шин в Краснодаре, Новосибирске и Норильске

Факт №2

Сезонности могут отличаться даже внутри одной сферы деятельности — на разных типах устройств. Например, «новогодние подарки» на большом экране начинают искать в октябре. Тогда как в мобильных версиях поиск стартует на месяц позже и пик приходится ближе к Новому году.

График 9: Поиск новогодних подарков в онлайне и мобильной версии 2ГИС
График 9: Поиск новогодних подарков в онлайне и мобильной версии 2ГИС

Факт №3

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

Спойлер-подсказка

Значит, ни погода, ни регион, ни локальные бизнесы, а что-то глобально общее.
3 месяца = квартал. Сильно разные города России. Обратите внимание на апрель…

График 10
График 10

Ответ

Это фонды социального страхования — квартальная отчётность сдается в ФСС раз в три месяца, а апрельский пик объясняется сменой форм отчетности с 1 января каждого года.

Ещё раз о главном

Собираетесь искать корреляции в данных? Не забудьте эти данные подготовить: обработать пропуски, очистить от трендов и выбросов. Имейте в виду, что подготовка займет бОльшую часть времени.

Очень сильно поможет визуализация на каждом этапе обработки. На этапе работы с рядами максимально абстрагируйтесь от семантики: работайте с value и порядковым номером точки, тогда код будет проще переиспользовать.

S.: задача поиска трендов и сезонностей делалась в рамках другой задачи — прогнозирования изменения пользовательского внимания после приобретения рекламы в 2ГИС. P. Готов рассказать, как мы делали прогноз, если вам будет интересно.


Оставить комментарий

Ваш email нигде не будет показан
Обязательные для заполнения поля помечены *

*

x

Ещё Hi-Tech Интересное!

[Перевод] Как Apple пошла вопреки пяти общепринятым PR-нормам, но сохранила своё доброе имя

Спустя несколько дней после запуска iPhone 4 (самый успешный из когда-либо запускаемых Apple продуктов) – пошли слухи о том, что при определённом способе захвата мобильника (при т.н. В январе 2010 Apple столкнулась с огромным кризисом, который сулил резкое падение репутации. ...

[Из песочницы] Локальный NPM репозиторий за 5 минут со своими пакетами и кэширование

Доброго времени суток! Рано или поздно в организациях возникают проблемы с распространением js модулей между проектами, настало то время когда в нашей компании встал этот вопрос. Копировать и вставлять код это путь на темную сторону, поэтому было принято решение писать ...