Прогнозирование авиапассажиропотока между городами РФ

от автора

Всем привет!

Это моя первая статья на Хабре, поэтому буду рад комментариям, советам, предложениям и любой реакции.

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

Архитектура

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

Соответственно, в качестве факторов, влияющих на пассажиропоток, я выбрал следующие:

  • Тип направления: курортное, вахтовое, деловое (между крупными деловыми центрами)

  • Средняя температура в городах и обеспеченность коллективными средствами размещения (для выделения курортных направлений)

  • Расстояние между городами

  • Сезонность

  • Средняя зарплата в городах, население городов, коэффициент мобильности населения и ВРП региона (для выделения вахтовых направлений)

  • Годовой пассажиропоток между городами

Глобально, алгоритм должен выглядеть следующим образом:

Концептуальная схема прогностической модели
Концептуальная схема прогностической модели

Кластеризация

Определим вводные данные для кластеризации:

Признак

Описание

RSC

Круговой сегмент

Var

Месячный к-т вариации

Dist

Расстояние

Temp*

Среднегодовая температура

Population*

Население

Total*

Годовой пассажиропоток чз город

Mobility*

Коэффициент мобильности населения

GRP*

ВРП региона

GRP_per_capita*

ВРП на душу населения в регионе

ZP*

Средняя заработная плата в регионе

* — парные факторы для города вылета и города прилета

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

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

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

from geopy.geocoders import Nominatim from geopy.distance import geodesic as GD from math import radians, cos, sin, asin, sqrt   app = Nominatim(user_agent='myencoder', timeout=5)  cities_for_dist = tdf['Город'].unique() dist = pd.DataFrame(columns=['Dist'], index=cities_for_dist)  def get_dist(city1='Москва', city2='Санкт-Петербург'):          loc1 = app.geocode(city1).raw     loc2 = app.geocode(city2).raw     lat1 = float(loc1['lat'])     lon1 = float(loc1['lon'])     lat2 = float(loc2['lat'])     lon2 = float(loc2['lon'])     dest = distance_1(lat1, lat2, lon1, lon2)     return dest  def distance_1(La1, La2, Lo1, Lo2):             Lo1 = radians(Lo1)      Lo2 = radians(Lo2)      La1 = radians(La1)      La2 = radians(La2)              # Формула Гаверсинуса     D_Lo = Lo2 - Lo1      D_La = La2 - La1      P = sin(D_La / 2)**2 + cos(La1) * cos(La2) * sin(D_Lo / 2)**2         Q = 2 * asin(sqrt(P))            # Радиус земли для расчета расстояния     R_km = 6371              # Итоговый результат     return(Q * R_km)

Алгоритм выполнялся довольно долго — для 400 направлений ушло около 20 минут. Поэтому я сразу сохранил его в csv и в следующих итерациях читал csv-файл с расстояниями. Удивительно, что не возникло проблем с распознаванием таких специфических городов, как Игарка, Талакан и Купол.

Я планировал сформировать около 5-10 кластеров, чтобы выборки в каждом кластере были адекватного (не слишком маленького) размера.

Вводные данные выглядят следующим образом:

Вводные данные для кластеризации
Вводные данные для кластеризации

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

Видим, что лучшее число кластеров — 7 штук, при гиперпараметре в n_init равном 2. Хотя коэффициент Силуэта невысокий, этого достаточно, чтобы получить приемлемые результаты. А результаты кластеризации оказались очень интересными.

Кластерная разбивка
Кластерная разбивка

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

Регрессия

Теперь попробуем построить три модели регрессии: RandomForest, GradientBoosting, CatBoost.

В качестве вводных берем следующие факторы:

Признак

Описание

Total

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

Var

Месячный к-т вариации

Dist

Расстояние

Temp*

Среднегодовая температура

Population*

Население

Total1*

Годовой пассажиропоток чз город

Mobility*

Коэффициент мобильности населения

GRP*

ВРП региона

GRP_per_capita*

ВРП на душу населения в регионе

ZP*

Средняя заработная плата в регионе

Вводные для регрессии выглядят так:

После отбора гиперпараметров, вышли следующие результаты:

Модель/

Метрика

RandomForest Regressor

GradientBoosting Regressor

CatBoost Regressor

R2

0,56

0,45

0,75

MAPE

29,3%

30,0%

53,6%

Видим, что для всех трех моделей и R2, и MAPE оказались не очень качественными, но для дальнейших исследований я оставлю RandomForest и GradientBoosting.

Вывод

Удалось с умеренной точностью прогнозировать пассажиропоток на московских рейсах с ошибкой менее 30%;

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

Рекомендации для себя на будущее я оставил следующие:

  1. Добавить фактор емкостей конкурентов для повышения точности модели

  2. Включить фактор сезонных мероприятий или перевахтовок для крупных городов

  3. Добавить в анализ перемещения между городами в том числе трансферными рейсами

Спасибо за уделенное внимание. Буду рад обратной связи.


ссылка на оригинал статьи https://habr.com/ru/post/713160/


Комментарии

Добавить комментарий

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