Как стать автором
Поиск
Написать публикацию
Обновить

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

Время на прочтение4 мин
Количество просмотров4.5K

Всем привет!

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

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

Архитектура

В целом, направления делятся на несколько крупных подгрупп, для которых логично использовать разные паттерны в прогнозировании. Так, например, есть курортные направления из Москвы (Сочи, Крым и прочие), по которым спрос хоть и сезонен, но довольно стабилен. Есть курортные направления из регионов, где спрос сильно сезонен хотя бы по той причине, что рейсы выполняются только летом. В целом, поток на курортных направлениях сильно зависит от количества гостиниц - нельзя уместить миллион туристов в Сочи за раз, если койко-мест - всего 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. Добавить в анализ перемещения между городами в том числе трансферными рейсами

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

Теги:
Хабы:
Всего голосов 18: ↑18 и ↓0+18
Комментарии19

Публикации

Ближайшие события