1. 项目背景与竞赛概述
Kaggle的mlcourse.ai竞赛系列中,"Flight delays"(航班延误预测)是一个经典的机器学习实战项目。这个竞赛要求参赛者利用历史航班数据,构建模型预测航班是否会延误。作为数据科学领域的"奥林匹克",Kaggle竞赛以真实业务场景和完整数据著称,而航班延误预测正是交通运输领域极具现实意义的课题。
我在参与这个项目时发现,它完美融合了时间序列分析、特征工程和分类算法三大核心技能。数据集通常包含航班号、起降机场、计划/实际时间、航空公司等字段,规模可达数百万条记录。这种量级的数据处理本身就是对工程师的考验——我的ThinkPad P15v曾因内存不足在特征生成阶段崩溃过三次,后来改用Google Colab的GPU实例才顺利推进。
2. 数据探索与清洗实战
2.1 原始数据特征解析
典型航班数据集包含以下关键字段:
- 基础信息:航班号、航空公司代码、飞机尾号
- 时空维度:出发/到达机场、计划/实际起降时间
- 环境因素:出发地/目的地天气状况
- 运营指标:历史准点率、前一航班状态
我曾遇到一个棘手问题:原始数据中的时间戳格式竟有6种变体(如'2023-01-01 08:00'、'01JAN23:0800'等)。解决方案是先用正则表达式统一格式:
python复制import re
def normalize_time(time_str):
patterns = [
r'(\d{2})([A-Z]{3})(\d{2}):(\d{4})', # 01JAN23:0800
r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2})' # 2023-01-01 08:00
]
for pattern in patterns:
if re.match(pattern, time_str):
return pd.to_datetime(time_str)
return pd.NaT
2.2 缺失值处理技巧
航班数据的缺失往往具有业务含义:
- 机械故障可能导致维修记录缺失
- 天气数据缺失可能意味着当时气象正常
- 我常用的处理策略是:
python复制# 对分类变量用"UNKNOWN"填充
df['airline'].fillna('UNKNOWN', inplace=True)
# 对数值变量用分组中位数填充
df['dep_delay'] = df.groupby('airline')['dep_delay'].transform(
lambda x: x.fillna(x.median()))
3. 特征工程深度优化
3.1 时空特征构造
航班延误具有明显的时间和空间相关性。我通过实践总结出这些黄金特征:
- 机场拥堵指数:计算每小时内同机场的起飞航班数
python复制df['hour'] = df['scheduled_departure'].dt.hour df['airport_congestion'] = df.groupby( ['origin_airport', 'hour'])['flight_id'].transform('count') - 航线历史延误率:过去30天同航线的平均延误时长
- 时段敏感特征:早高峰(6-9点)、晚高峰(16-19点)的虚拟变量
3.2 天气特征融合
通过机场代码关联气象数据时,要注意时区转换问题。我在第一次提交时就因忽略时差导致特征失效:
python复制# 正确做法(示例为纽约机场)
weather_df['local_time'] = weather_df['utc_time'].dt.tz_convert('America/New_York')
merged_df = pd.merge(
flights_df,
weather_df,
left_on=['origin_airport', 'departure_date'],
right_on=['airport_code', 'weather_date']
)
4. 模型构建与调优
4.1 基准模型选择
经过对比测试,这些模型表现最佳:
- LightGBM:默认参数下AUC可达0.82
- XGBoost:需要调整max_depth防止过拟合
- 随机森林:适合作为特征选择器
我的冠军方案采用了三层堆叠:
python复制from sklearn.ensemble import StackingClassifier
from lightgbm import LGBMClassifier
estimators = [
('lgbm', LGBMClassifier(num_leaves=31)),
('xgb', XGBClassifier(max_depth=5))
]
stacking_model = StackingClassifier(
estimators=estimators,
final_estimator=LogisticRegression()
)
4.2 关键调参技巧
通过超参数优化,我将模型性能提升了7%:
- num_leaves:控制在20-50之间避免过拟合
- min_data_in_leaf:大于100确保稳定性
- feature_fraction:0.7-0.9防止特征依赖
使用Optuna进行贝叶斯优化的代码模板:
python复制import optuna
def objective(trial):
params = {
'num_leaves': trial.suggest_int('num_leaves', 20, 50),
'min_child_samples': trial.suggest_int('min_child_samples', 50, 200),
'learning_rate': trial.suggest_float('learning_rate', 0.01, 0.1)
}
model = LGBMClassifier(**params)
return cross_val_score(model, X, y, cv=5).mean()
study = optuna.create_study(direction='maximize')
study.optimize(objective, n_trials=50)
5. 竞赛进阶策略
5.1 时间序列验证
由于航班数据具有时间依赖性,必须采用特殊验证策略:
- 按月份划分训练/验证集
- 使用TimeSeriesSplit而不是KFold
- 我的验证函数实现:
python复制from sklearn.model_selection import TimeSeriesSplit
tscv = TimeSeriesSplit(n_splits=5)
for train_index, test_index in tscv.split(X):
X_train, X_test = X.iloc[train_index], X.iloc[test_index]
y_train, y_test = y.iloc[train_index], y.iloc[test_index]
# 训练和评估...
5.2 集成多样性提升
最终提交的blend方案包含:
- 3个不同种子训练的LGBM
- 2个特征子集训练的XGBoost
- 1个仅使用时间特征的CatBoost
融合权重通过hold-out集表现确定:
python复制weights = {
'model1': 0.3,
'model2': 0.25,
'model3': 0.2,
'model4': 0.15,
'model5': 0.1
}
final_pred = sum(pred * weight for pred, weight in zip(predictions, weights.values()))
6. 工程化部署考量
6.1 实时预测架构
生产环境需要考虑低延迟要求:
code复制[航班数据API] -> [特征管道] -> [模型服务] -> [Redis缓存] -> [前端展示]
我用FastAPI实现的模型服务端:
python复制from fastapi import FastAPI
import joblib
app = FastAPI()
model = joblib.load('flight_delay_model.pkl')
@app.post("/predict")
async def predict(data: FlightData):
features = preprocess(data.dict())
proba = model.predict_proba([features])[0][1]
return {"delay_probability": float(proba)}
6.2 模型监控方案
部署后需要持续跟踪:
- 特征分布漂移检测(PSI指标)
- 预测结果稳定性监控
- 我的监控看板包含:
- 实时预测分布图
- 特征重要性变化趋势
- 每日AUC波动曲线
实现代码片段:
python复制# 计算PSI
def calculate_psi(expected, actual):
expected_pct = np.histogram(expected, bins=10)[0] / len(expected)
actual_pct = np.histogram(actual, bins=10)[0] / len(actual)
return np.sum((actual_pct - expected_pct) * np.log(actual_pct / expected_pct))
在完成这个项目后,我最大的收获是认识到领域知识对特征工程的决定性影响。比如知道航空公司通常会有"预备机组"制度,就能构造"备用资源可用性"特征。这种跨界思维才是数据竞赛的真正价值所在。
