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

«Как построить модель для прогнозирования задержки рейсов?» — вопрос из категории Временные ряды, который задают на 26% собеседований Data Scientist / ML Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Прогнозирование задержки рейсов — классическая задача временных рядов, часто решаемая методами машинного обучения. Подход зависит от формулировки: бинарная классификация (задержка > N минут), мультиклассовая (степень задержки) или регрессия (точное время задержки).

1. Этапы решения задачи:

A. Сбор и объединение данных:

  • История рейсов: вылет/прилет по расписанию и фактически, авиакомпания, номер рейса, тип ВС.
  • Контекстуальные данные: погода в аэропортах вылета/прилета (видимость, ветер, осадки), праздники, загруженность аэропорта (количество рейсов в слот).
  • Данные о сети: задержки предыдущих рейсов того же самолета ("заражение" задержкой).

B. Feature Engineering (создание признаков): Это самый важный этап. Примеры признаков:

import pandas as pd

# Из временных меток
df['scheduled_departure_hour'] = df['scheduled_departure'].dt.hour
df['scheduled_departure_dow'] = df['scheduled_departure'].dt.dayofweek  # День недели
df['is_weekend'] = df['scheduled_departure_dow'].isin([5,6]).astype(int)
df['season'] = df['scheduled_departure'].dt.month % 12 // 3 + 1

# Лаговые признаки (временные ряды)
df['avg_delay_origin_3h'] = df.groupby('origin_airport')['departure_delay'].rolling('3h', on='scheduled_departure').mean().values

# Агрегированные признаки
df['airline_avg_delay_last_month'] = df.groupby('airline')['departure_delay'].transform(lambda x: x.rolling('30D', on='scheduled_departure').mean())

# Целевая переменная для бинарной классификации
df['is_delayed'] = (df['departure_delay'] > 15).astype(int)  # Задержка > 15 минут

C. Выбор модели и обучение:

  • Для бинарной/мультиклассовой классификации: GradientBoostingClassifier (XGBoost, LightGBM, CatBoost) или RandomForestClassifier. Они хорошо работают с табличными данными и нелинейными зависимостями.

    from sklearn.ensemble import GradientBoostingClassifier
    from sklearn.model_selection import train_test_split
    
    X = df.drop(columns=['is_delayed', 'actual_departure'])
    y = df['is_delayed']
    X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, shuffle=False) # Для временных рядов shuffle=False!
    
    model = GradientBoostingClassifier(n_estimators=200, random_state=42)
    model.fit(X_train, y_train)
  • Для регрессии (прогноз минут): GradientBoostingRegressor.
  • Чистые временные ряды: Можно испытать Prophet или ARIMA-подобные модели, но они хуже учитывают множество внешних признаков.

D. Валидация и метрики:

  • Валидация: Используйте TimeSeriesSplit из sklearn, чтобы не допустить утечки будущего в прошлое при кросс-валидации.
  • Метрики:
    • Классификация: ROC-AUC (основная), Precision (важно минимизировать ложные "не будет задержки"), Recall (важно поймать все реальные задержки).
    • Регрессия: MAE (Mean Absolute Error), RMSE (Root Mean Square Error).

2. Ключевые сложности:

  • Несбалансированность классов: Задержек обычно меньше, чем своевременных рейсов. Нужны техники вроде балансировки весов классов (class_weight='balanced') или SMOTE.
  • "Заражение" задержкой: Задержка одного рейса влияет на последующие рейсы того же самолета. Это нужно явно моделировать через лаговые признаки.
  • Оперативность прогноза: Модель должна давать прогноз за достаточное время до вылета, чтобы можно было принять меры.