摘要
本文记录一个可以直接运行的共享单车需求预测与调度建议项目。项目不再停留在随机生成样例,而是使用 UCI Bike Sharing Dataset 中 Capital Bikeshare 2011-2012 年的真实小时级hour.csv数据完成训练、评估和预测;站点库存部分使用项目内置的运营场景表,用来补齐 UCI 数据集中缺失的站点容量、当前车辆数和区域类型,从而形成“全城需求预测 + 站点补调建议”的业务闭环。
本次完整运行python run_demo.py,模型训练、未来 168 小时预测、站点需求拆分、调度建议、跨站转运计划、Streamlit 看板和结果图片均已重新生成。最终最佳模型为 RandomForest,测试集 RMSE 为 55.880,R2 为 0.935;未来 24 小时预测租车量为 2239,系统识别出 1 个需要补车站点、10 个可调出车辆站点,并生成 1 条跨站转运计划。
关键词:共享单车需求预测、UCI Bike Sharing Dataset、RandomForest、时间序列特征工程、车辆调度、Streamlit、Python 项目实战
一、项目场景与真实数据来源
共享单车运营不是单纯预测“明天会有多少订单”,更关键的是提前知道哪些时段需求会抬升、哪些站点可能缺车、哪些站点车辆相对富余。早高峰的地铁口、晚高峰的写字楼、周末的景区和商圈,都会形成不同的小时需求模式。把需求预测结果接入站点库存表,就能从数据分析进一步落到运营调度建议。
下图是 Wikimedia Commons 上的 Capital Bikeshare 真实站点照片,能够对应本文使用的 Capital Bikeshare 数据场景。
本项目使用的真实数据为 UCI Bike Sharing Dataset 的hour.csv,数据来自美国华盛顿特区 Capital Bikeshare 系统,覆盖 2011-01-01 到 2012-12-31,共 17,379 条小时级记录。字段包含日期、小时、季节、工作日、天气、温度、湿度、风速、临时用户租车数、注册用户租车数和总租车数cnt。运行时,项目将cnt作为预测目标。
站点库存数据需要说明清楚:UCI 官方数据只提供全城小时聚合需求,并不包含具体站点容量和当前车辆数。因此资源包里保留了一份可运行的站点库存场景表station_inventory_sample.csv,用于演示调度建议模块如何把全城预测结果拆分到站点。真实落地时,可以把这张表替换为运营平台中的站点容量、当前车辆数、经纬度和区域类型。
二、真实运行结果与页面截图
项目运行入口为run_demo.py。本次使用如下命令重新生成全部结果:
python run_demo.py运行完成后,核心结果如下:
| 指标 | 本次真实运行结果 |
|---|---|
| UCI 原始小时记录数 | 17,379 |
| 构造滞后特征后的监督样本数 | 17,211 |
| 训练集样本数 | 13,768 |
| 测试集样本数 | 3,443 |
| 特征数量 | 38 |
| 最佳模型 | RandomForest |
| MAE | 32.617 |
| RMSE | 55.880 |
| WMAPE | 0.132 |
| R2 | 0.935 |
| 未来预测小时数 | 168 |
| 未来 24 小时预测租车量 | 2,239 |
| 需要补车站点数 | 1 |
| 可调出车辆站点数 | 10 |
| 跨站转运车辆数 | 2 |
下面这张图是启动真实 Streamlit 页面后截取的运行界面,不是手工拼接的示意图。页面中可以看到最佳模型、误差指标和未来需求曲线。
从截图可以看到,系统在真实 UCI 数据上选择了 RandomForest 作为最佳模型。Web 页面支持上传同结构 CSV,也可以通过侧边栏调整预测未来小时数和调度建议窗口,适合课程设计、项目答辩和资源包演示。
三、系统流程与核心实现
系统整体按照“真实小时数据 -> 时间序列特征 -> 多模型训练 -> 未来预测 -> 站点调度 -> 看板与报告”的方式组织。下面的系统流程图根据当前项目实际模块重新绘制,图中包含 UCIhour.csv、站点库存、特征工程、模型对比、168 小时预测、站点调度、转运计划、Streamlit 看板和报告输出。
项目代码没有把所有逻辑堆在一个脚本里,而是拆成相对清晰的模块:
src/generate_sample_data.py 数据生成兜底与站点库存场景表 src/feature_engineering.py 日历、周期、滞后、滑动窗口特征 src/model_training.py Ridge、RandomForest、GradientBoosting 训练与评估 src/predictor.py 未来需求递归预测、站点拆分、调度建议 src/visualization.py 模型对比、预测曲线、调度图和页面预览 src/report.py 生成模型报告和调度报告 run_demo.py 命令行全流程入口 app.py Streamlit 交互式页面特征工程是这个项目的核心。共享单车需求有很明显的小时周期、星期周期、季节变化和历史惯性,所以项目构建了三类关键特征。
第一类是日历和运营特征,包括月份、小时、是否工作日、是否早晚高峰、是否夜间等。第二类是周期编码,例如hour_sin、hour_cos,用正弦和余弦表达 0 点与 23 点相邻的周期关系。第三类是滞后和滑动窗口特征,包括lag_1、lag_24、lag_168,以及 6、24、72、168 小时滚动均值和标准差。
项目按时间顺序划分训练集和测试集,而不是随机切分。这样做更符合真实预测场景:模型只能用过去数据预测未来,不能提前看到未来样本。所有滚动特征也基于shift(1)之后的历史需求计算,避免把当前目标值泄漏到特征中。
四、模型效果与调度建议解读
本次真实数据训练中,三类模型的指标如下:
| 模型 | MAE | RMSE | WMAPE | R2 |
|---|---|---|---|---|
| Ridge | 54.025 | 78.928 | 0.218 | 0.871 |
| RandomForest | 32.617 | 55.880 | 0.132 | 0.935 |
| GradientBoosting | 40.379 | 61.691 | 0.163 | 0.921 |
模型对比图如下。RandomForest 在 MAE、RMSE 和 WMAPE 上都优于另外两个模型,因此被保存为最佳模型。
测试集真实值与预测值曲线如下。可以看到模型能较好跟住小时级需求的周期波动,尤其是通勤和日内峰谷变化。个别尖峰仍有误差,这是共享单车真实数据中很常见的问题,通常需要继续接入天气突变、节假日活动、城市事件、地铁客流等外部变量。
训练完成后,系统会递归预测未来 168 小时需求。由于模型使用了滞后特征,预测未来时不能一次性把所有未来样本直接喂给模型,而是先预测第 1 个未来小时,再把这个预测值加入历史序列,继续构造第 2 个小时的滞后特征。这样得到的结果更接近上线后的滚动预测方式。
调度建议部分把全城预测需求按照站点基础占比、区域类型和小时模式拆分到站点,再结合当前车辆数、容量、安全库存和预留空桩计算目标车辆数。当前运行中,Tech Park 被识别为需要补车,Railway North 等站点车辆相对富余,系统生成了从 Railway North 向 Tech Park 转运 2 辆车的计划。
站点需求热力图用于观察未来 24 小时内不同站点的需求强弱。相比只输出一张 CSV,热力图更适合让运营人员快速判断哪个站点在什么时段更紧张。
五、运行方式、资源包内容与二次开发
下载资源包后,建议先创建 Python 环境并安装依赖:
pipinstall-rrequirements.txt命令行运行:
python run_demo.pyWeb 页面运行:
streamlit run app.py资源包中已经包含 UCIhour.csv的本地副本,默认运行路径为:
data/hourly_bike_sharing_sample.csv同时保留原始下载文件:
data/raw/uci_bike_sharing_dataset/hour.csv data/raw/uci_bike_sharing_dataset/day.csv data/raw/uci_bike_sharing_dataset/Readme.txt项目输出主要包括:
models/best_bike_demand_model.joblib outputs/predictions/test_predictions.csv outputs/predictions/future_demand_forecast.csv outputs/predictions/station_demand_forecast.csv outputs/reports/model_metrics.json outputs/reports/dispatch_recommendations.csv outputs/reports/transfer_plan.csv images/results/*.png如果要做二次开发,可以从三个方向扩展。第一,替换为真实运营订单表和实时天气数据,把cnt从全城小时需求扩展为区域或站点级需求。第二,把当前规则式调度升级为优化问题,加入车辆容量、司机班次、站点距离、道路时间和调度成本。第三,把 Streamlit 页面升级为 FastAPI + Vue/React 或后台管理模板,并加入地图展示、定时任务和数据库持久化。
参考资料
UCI Machine Learning Repository - Bike Sharing Dataset
https://archive.ics.uci.edu/dataset/275/bike+sharing+datasetFanaee-T, Hadi, and Gama, Joao. Event labeling combining ensemble detectors and background knowledge. Progress in Artificial Intelligence, 2013.
https://doi.org/10.1007/s13748-013-0040-3Scikit-learn RandomForestRegressor 文档
https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestRegressor.htmlStreamlit 文档
https://docs.streamlit.io/Wikimedia Commons - Capital Bikeshare Key West Ave Rockville MD
https://commons.wikimedia.org/wiki/File:Capital_Bikeshare_Key_West_Ave_Rockville_MD_20210414_183503552.jpg
图片来源说明:Capital Bikeshare 站点照片作者为 G. Edward Johnson,许可协议为 CC BY 4.0;系统流程图根据本项目实际流程绘制。