酒店预订取消预测与收益管理分析
基于酒店预订需求数据集构建订单取消风险预测项目,结合多模型比较、风险分层和 Streamlit 页面,为收益管理、库存保护和客户提醒策略提供支持。

本项目基于 `hotel-booking-demand` 数据集,面向酒店订单管理场景构建取消风险预测系统。目标是在订单确认后的运营阶段,尽早识别更可能取消的预订,以便提前做库存保护、客户提醒、押金策略或候补替补安排,从而降低空置风险并优化收益管理。
1. 课题介绍
酒店行业面临的一个典型问题是订单取消。提前预订并不一定最终入住,尤其在旺季、长提前期和特定渠道条件下,取消率可能明显上升。如果酒店无法在订单存续期间识别高风险预订,就容易在需求管理、价格控制和库存保护上失去主动权。本项目围绕“预订时点可见信息”构建预测系统,避免使用最终状态字段,确保建模口径更符合真实业务使用场景。
2. 研究目标
- 建立酒店预订取消预测模型
- 处理订单最终状态带来的标签泄漏风险
- 输出关键影响因素并解释不同酒店和提前期的取消差异
- 按风险概率输出高、中、低三档订单分层
- 搭建可演示的 Streamlit 页面用于分析和单订单评估
3. 数据集介绍
项目使用 `datasets/hotel-booking-demand/data/hotel_bookings.csv` 数据文件。该数据集共包含 119,390 条订单记录和 32 个字段,目标变量为 `is_canceled`。数据覆盖 `City Hotel` 与 `Resort Hotel` 两类酒店,并包含预订提前期、入住日期、住店夜数、人数结构、客源渠道、押金类型、历史预订行为和房价等字段,适合做订单取消预测与经营分析。
4. 使用的技术介绍
- `Python`:项目开发语言
- `Pandas`、`NumPy`:数据清洗、特征工程和结果导出
- `scikit-learn`:预处理管道、模型训练、预测和评估
- `Matplotlib`、`Seaborn`:生成模型图和业务图表
- `Streamlit`、`Plotly`:构建交互式分析页面
- `joblib`:保存最佳模型
5. 使用的模型介绍
项目使用 `LogisticRegression`、`DecisionTree` 和 `RandomForest` 三种模型进行对比。逻辑回归作为稳定基线,决策树用于增强可解释性,随机森林负责捕捉更复杂的非线性关系。项目最终选择 `RandomForest` 作为部署模型,其 `ROC-AUC` 达到 `0.9349`,在三种候选模型中表现最佳。
6. 数据分析与特征工程
建模前,项目先显式删除 `reservation_status` 与 `reservation_status_date` 两个字段,因为它们与订单最终是否取消高度相关,直接使用会造成明显标签泄漏。随后构造了 `total_nights`、`total_guests`、`has_agent`、`has_company`、`previous_history`、`adr_per_night`、`special_request_intensity` 等衍生特征,使模型能够更好地刻画订单规模、价格约束和客户历史行为。
下面这段代码展示了项目如何先做泄漏控制,再补充关键衍生特征:
working_df = add_features(df)
working_df = working_df.drop(
columns=["reservation_status", "reservation_status_date"],
errors="ignore",
)
frame["total_nights"] = frame["stays_in_weekend_nights"] + frame["stays_in_week_nights"]
frame["total_guests"] = frame["adults"] + frame["children"].fillna(0) + frame["babies"]
frame["has_agent"] = frame["agent"].notna().astype(int)
frame["has_company"] = frame["company"].notna().astype(int)下图展示了订单取消标签分布,可用于说明样本中已取消与未取消订单的数量关系。

7. 模型结果与影响因素
模型训练采用统一预处理管道,确保数值插补、标准化、类别编码和分类器训练在同一工作流中完成。核心训练逻辑如下:
pipeline = Pipeline(
steps=[
("preprocessor", clone(preprocessor)),
("model", estimator),
]
)
pipeline.fit(X_train, y_train)
pred = pipeline.predict(X_test)
prob = pipeline.predict_proba(X_test)[:, 1]真实运行后的模型指标如下:
| 模型 | Accuracy | Precision | Recall | F1 | ROC-AUC | Avg Precision |
|---|---|---|---|---|---|---|
| RandomForest | 0.8590 | 0.8355 | 0.7712 | 0.8020 | 0.9349 | 0.9075 |
| DecisionTree | 0.8232 | 0.7597 | 0.7644 | 0.7621 | 0.9082 | 0.8471 |
| LogisticRegression | 0.8118 | 0.7302 | 0.7801 | 0.7543 | 0.8970 | 0.8559 |
下图展示了模型对比、最佳模型 ROC 曲线、混淆矩阵和特征重要性。




从最佳模型的重要性结果看,`deposit_type_Non Refund`、`deposit_type_No Deposit`、`country_PRT`、`lead_time`、`special_request_intensity`、`total_of_special_requests` 和 `previous_cancellations` 等变量最关键。这说明押金政策、客源结构、提前预订时长以及客户的历史行为,是解释订单取消风险的核心维度。
8. 业务分析内容
项目围绕酒店类型和预订提前期做了两组直接可解释的业务图表。不同酒店类型的取消率可以帮助管理者识别城市酒店与度假酒店在订单稳定性上的差异;提前期与取消率关系则能反映越早预订是否越容易发生取消。基于模型输出的取消概率,项目还会将订单划分为 `High`、`Medium`、`Low` 三档风险层,并分别匹配人工确认、提醒干预和标准处理策略。
页面和推理逻辑会把取消概率直接映射成风险等级,核心代码如下:
if probability > thresholds["medium_upper"]:
segment = "High"
elif probability > thresholds["low_upper"]:
segment = "Medium"
else:
segment = "Low"真实风险分层结果如下:
| 风险分层 | 样本数 | 平均提前期 | 平均房价 | 真实取消率 |
|---|---|---|---|---|
| High | 23,878 | 184.24 | 101.77 | 0.9581 |
| Medium | 41,786 | 95.61 | 113.76 | 0.4663 |
| Low | 53,726 | 74.89 | 92.58 | 0.0347 |
这说明模型已经能有效区分订单稳定性,高风险订单几乎全部集中在取消样本中,适合作为人工确认、押金策略和超售保护的重点处理对象。


9. 系统实现内容
项目目录包含:
- `train_hotel_cancellation.py`:训练、评估、图表生成和产物导出
- `dashboard.py`:Streamlit 交互式页面
- `outputs/`:模型结果、风险分层和图表
- `artifacts/`:最佳模型与元数据
页面分为“取消洞察”“风险分层”“单订单评估”“核心代码”四个模块,既能展示整体分析结论,也能输入单笔订单信息做实时预测。
10. 项目亮点
- 主动规避最终状态字段带来的标签泄漏问题
- 样本量大,结果更适合做经营分析和答辩展示
- 同时输出模型比较、订单风险分层和页面交互
- 页面中集成核心代码片段,适合课堂展示或项目讲解
11. 不足与改进方向
- 当前以传统机器学习为主,后续可以加入 LightGBM、CatBoost 等更强模型
- 目前没有纳入节假日、天气和区域供需等外部特征
- 风险分层阈值仍以分位数为主,后续可结合真实取消成本优化
12. 总结
本项目完成了从数据清洗、泄漏控制、特征工程、分类建模、业务图表到交互式页面展示的完整链路,适合用于酒店取消风险预警、收益管理分析和课程设计展示。最终项目在不使用最终状态字段的前提下,仍取得了 `0.9349` 的 `ROC-AUC`,并输出了高、中、低三档清晰的风险分层,具备较强的业务落地解释力。