Прогнозирование авиапассажиропотока между городами РФ
- суббота, 28 января 2023 г. в 00:42:56
Всем привет!
Это моя первая статья на Хабре, поэтому буду рад комментариям, советам, предложениям и любой реакции.
Я работаю в авиакомпании, занимаюсь анализом продаж, что сильно связано в том числе с планированием и прогнозированием. В условиях, когда российский рынок авиаперевозок сужается, авиакомпании стремятся оптимизировать свою маршрутную сеть, а если и развиваться - то только на направлениях с высоким пассажиропотоком. Дефицит самолетов в условиях санкций делает ошибки непростительными, поэтому своей целью я ставил разработку модели прогнозирования трафика между городами РФ.
В целом, направления делятся на несколько крупных подгрупп, для которых логично использовать разные паттерны в прогнозировании. Так, например, есть курортные направления из Москвы (Сочи, Крым и прочие), по которым спрос хоть и сезонен, но довольно стабилен. Есть курортные направления из регионов, где спрос сильно сезон - банально по той причине, что рейсы выполняются только летом. В целом, поток на курортных направлений сильно зависит от количества гостиниц - нельзя уместить миллион туристов в Сочи за раз, если койко-мест - всего 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%;
Решение задачи кластеризации позволило осуществить качественное разделение рейсов по подгруппам, что может быть использовано в авиакомпаниях для упрощения анализа и группировки данных.
Рекомендации для себя на будущее я оставил следующие:
Добавить фактор емкостей конкурентов для повышения точности модели
Включить фактор сезонных мероприятий или перевахтовок для крупных городов
Добавить в анализ перемещения между городами в том числе трансферными рейсами
Спасибо за уделенное внимание. Буду рад обратной связи.