
简介以城市交通通行预测为实战场景面向国科大等高校数据挖掘课程大作业完成者与交通预测初学者解决从原始数据到最终预测结果落地难的问题。资源完整呈现了原始路况数据清洗、特征提取到XGBoost建模与结果生成的全流程方案。包体共14个文件核心包括4个ipynb交互式笔记交通数据预处理、建模预测两大部分及checkpoint版本、1个py工具脚本用于数据读取与辅助处理、1个pkl已训练模型可快速加载推断另有6个txt预测结果和2个png可视化图压缩包整体仅2.09MB结构清晰、便于离线复现。目前已有1558人学习下载。通过该资源可掌握竞赛级交通数据的特征工程思路、回归模型调参与结果优化技巧明确预测结果提交格式并能利用模型对象与脚本快速验证有效避开数据清洗与特征构造中的常见踩坑点适合完成课程设计也适合初学者快速上手交通流预测建模项目。1. 交通通行预测大作业的第一关把rar包解压并认清数据交通通行预测是数据挖掘课程里常见的大作业选题国科大这类作业通常以rar压缩包形式下发里面是一份时间序列交通流量数据、一份报告模板以及一段“预测未来交通通行状态”的宽泛要求。拿到包后第一件事不是急着上模型而是解压、确认时间字段的粒度、覆盖范围和缺失情况。解压只是起点压缩包里的数据形态才是决定整个作业工作量的部分。交通数据天然带时间戳作业本质上是在做时间序列回归数据对齐做不干净后面的特征工程和模型评估都会被带偏。这套流程以一份典型rar包为例从解压、清洗、构造特征到模型训练和验证完整走一遍课程作业可以直接照着改第一次接触交通流预测的工程师也能当参考路线。2. 交通通行预测的数据清洗粒度统一、缺失值插补与异常过滤2.1 从rar解压到确认时间戳粒度与覆盖范围rar解压是机械操作但解压之后的文件检查决定了整个数据挖掘大作业的走向。Windows下用图形界面即可Linux或macOS下命令行更顺手# Linux/macOS 下解压 rar 包 unrar x traffic_data.rar # 若已经解压过用 l 参数列出包内文件确认是否有数据字典 unrar l traffic_data.rarunrar x解压到当前目录unrar l只列出包内文件名而不解压适合先确认压缩包里是单个数据文件还是附带说明文档。当环境里没有 unrar 时常见做法是用unar替代装一下对应的包管理器组件就能用。解压完成后先写一小段 pandas 代码看数据轮廓而不是直接用 Excel 打开。课程数据量通常在几万到几十万行Excel 打开会卡而且对列类型和时间格式的判断不如代码直观import pandas as pd df pd.read_csv(traffic_data.csv, parse_dates[time]) df df.set_index(time) print(df.shape) print(df.head()) print(时间范围:, df.index.min(), -, df.index.max()) print(时间戳是否对齐15分钟:, df.index.floor(15min).equals(df.index))parse_dates[time]把时间列直接转成datetime64省去后续手工转换set_index(time)之后所有时间操作都走索引。floor(15min)用于校验原始数据是否已经对齐到整刻钟返回True说明时间轴干净返回False说明后面必须重采样。时间覆盖范围决定了滞后窗口能开多大如果数据只有一周48 阶的滞后特征会把样本首尾掏空这个矛盾要在构造特征前就意识到。2.2 缺失值插补线性插值、周期填充与不引入未来信息交通流数据缺失通常来自检测器故障或网络传输丢包缺失模式分单点和连续段两种处理方式完全不同。缺失模式常用方法注意点单点缺失线性插值相邻值差异大时插值偏平缓连续短段缺失前向填充会产生平台期夜间流量低时影响小连续长段缺失同期均值填充按星期几小时分组保留周期特征选择哪种方案要结合预测目标。交通通行预测关注的是早晚高峰的突变如果缺失段刚好落在高峰时段前向填充会把峰值直接抹平模型在这个时段学到的是错误的平稳形态。周期均值填充用“上周同一天同时段”的均值补进去虽然会平滑掉个别突发拥堵但至少不会把整个高峰填成平路。# 先线性插值处理少量缺失 df[flow] df[flow].interpolate(methodlinear, limit_directionboth) # 长段缺失用周同期均值兜底 period_mean df.groupby([df.index.dayofweek, df.index.hour])[flow].transform(mean) df[flow] df[flow].fillna(period_mean)interpolate的limit_directionboth允许数据开头和结尾也参与插补避免首尾 NaN 堆积。groupby(...).transform(mean)返回与原索引对齐的均值序列直接作为 fillna 的填充值。顺序是先线性插值、后周期均值不能反过来否则单点缺失也会被周期均值平滑掉丢失短期波动信息。2.3 重采样对齐时间轴并过滤异常流量如果 2.1 的时间校验返回False就需要重采样。检测器上报延迟会让部分时间戳落在 07:01、07:02 这类非整点位置统一到 15 分钟或 1 小时粒度后续滞后特征的语义才会干净。# 统一重采样到 15 分钟粒度取均值作为该时段流量 df df.resample(15min).mean() # 剔除完全没有数据的空时段 df df.dropna(subset[flow])resample(15min)把时间轴对齐到整刻钟mean()把同一时段内的多个上报点聚合成一个值。重采样后不要用pad()那等价于把缺失时段全部填成上一时刻的值会制造出大量平台期看起来数据连续了实际上引入的是伪规律。异常流量过滤用中位数绝对偏差MAD比 3 倍标准差更稳妥。交通流量在不同时段方差差异很大凌晨可能只有几十辆晚高峰能到几千全局标准差会把凌晨的正常波动误判成异常。用滚动窗口计算局部中位数和 MAD再过滤局部离群点rolling_median df[flow].rolling(window48, centerTrue).median() mad (df[flow] - rolling_median).abs().rolling(window48, centerTrue).median() df[flow] df[flow].mask((df[flow] - rolling_median).abs() 5 * mad) df[flow] df[flow].fillna(rolling_median)window48在 15 分钟粒度下是 12 小时覆盖半个日周期能贴合交通流的局部变化centerTrue让窗口以当前点为中心避免只依赖过去信息造成偏移。超过 5 倍局部 MAD 的流量被替换为窗口中位数这样不会因为个别异常上报把模型整体拉偏。3. 构造时间特征与滞后特征把交通通行预测变成监督学习3.1 为什么不能直接拿原始流量列跑模型不少大作业的第一版代码是拿“昨天同一时刻”的流量当预测值。这是一个很强的 baseline但它本身不是数据挖掘模型。直接把流量列和时间戳丢给线性回归模型只能学到“当前值约等于上一时刻值”的朴素规律早晚高峰的爬升速度、工作日和周末的形态差异都体现不出来。把时间序列预测改造成监督学习核心是构造“X 是历史信息y 是未来值”的训练样本。对交通通行预测任务X 至少要包含三类信息时间周期位置、近期流量形态、长期流量背景。这三类信息分别对应下面三节的特征构造方式。3.2 时间周期特征小时循环编码加上工作日标记小时列如果直接当数值特征用会有个明显问题模型会认为 23 和 0 在数值上很接近这个没问题但它也会认为 7 和 17 都是“中午附近”的值实际上一个是早高峰一个是晚高峰。离散数值编码无法表达时间的循环属性。import numpy as np df[hour] df.index.hour df[weekday] df.index.weekday df[is_weekend] (df.index.weekday 5).astype(int) df[hour_sin] np.sin(2 * np.pi * df.index.hour / 24) df[hour_cos] np.cos(2 * np.pi * df.index.hour / 24)hour_sin和hour_cos把 24 小时映射到单位圆上23 点和 0 点在三角函数空间里是相邻坐标模型能感知“深夜到凌晨”的连续性。is_weekend是离散标记树模型可以直接用它切分出工作日和周末两套规律。只保留hour数字列不够数字列描述的是“第几小时”循环编码描述的是“时间在周期中的位置”。3.3 滞后特征与滑动窗口窗口长度怎么定滞后特征是把过去若干时间点的流量作为当前预测的输入。窗口长度的选择直接决定特征矩阵的信息量。15 分钟粒度的数据过去 3 小时是 12 个点过去一天是 96 个点窗口太长会塞进无关历史窗口太短看不到日周期。特征列含义15分钟粒度下的构造方式lag_115分钟前流量shift(1)lag_345分钟前流量shift(3)lag_6当前时刻的上一个半小时shift(6)lag_96昨天同一时刻流量shift(96)rolling_mean_3h过去3小时平均流量shift(1).rolling(12).mean()# 短时滞后过去1到6个点 for lag in range(1, 7): df[flag_{lag}] df[flow].shift(lag) # 日周期滞后 df[lag_96] df[flow].shift(96) # 过去3小时均值与标准差先shift去掉当前值 df[rolling_mean_3h] df[flow].shift(1).rolling(12).mean() df[rolling_std_3h] df[flow].shift(1).rolling(12).std()shift(lag)把序列整体下移 lag 个位置第 t 行的lag_3就是 t-3 时刻的真实流量。rolling(12).mean()默认包含当前点必须先用shift(1)把当前值移除否则预测目标 y 的信息被混进特征这是时间序列特征工程最常见的泄漏点。生成完特征后数据开头会有约 96 行 NaN最早样本没有足够历史。直接删掉这些行不要用 0 填充0 填充会让模型学到“流量从 0 开始”的错误先验。3.4 训练集与验证集按时间切分不能用随机打乱数据挖掘通用流程里的train_test_split(X, y, test_size0.2, random_state42)会随机打乱数据放到交通通行预测里就是灾难。随机打乱之后训练集里混入了验证集时刻之后的样本模型等于提前看到了未来验证集分数虚高换个时间段就崩。feature_cols [hour, weekday, is_weekend, hour_sin, hour_cos, lag_1, lag_2, lag_3, lag_4, lag_5, lag_6, lag_96, rolling_mean_3h, rolling_std_3h] valid_size int(len(df) * 0.2) X_train df[feature_cols].iloc[:-valid_size] X_valid df[feature_cols].iloc[-valid_size:] y_train df[flow].iloc[:-valid_size] y_valid df[flow].iloc[-valid_size:]iloc按行位置切分前 80% 训练、后 20% 验证验证集的时间全部晚于训练集。feature_cols固定列顺序LightGBM 预测时依赖同样的列集合。切分结果可以打印一次X_train.index.min()和X_valid.index.min()确认时间顺序作业报告里放这个输出能直接证明没有数据泄漏。注意如果数据量再大一些可以按 7:3 切分或做滚动起源交叉验证但作业周期内按时间切分一次就够重点放在特征构造和参数调整上。4. 用 LightGBM 训练交通通行预测模型参数设定与调优4.1 模型选型树模型在课程作业场景下的优势交通通行预测的模型选项不少传统的有 SARIMA 和 SVR深度方向有 LSTM。课程作业周期内LightGBM 这类梯度提升树是最稳妥的选择。三个理由特征工程阶段构造的是表格结构树模型天然擅长树模型不要求归一化凌晨几百、晚高峰几千的动态范围对树模型没有尺度压力训练快几万条数据几十秒内出结果留出时间迭代特征。SARIMA 作为 baseline 可以放进报告对比但它对缺失值敏感、需要显式处理周期阶数。LSTM 要把数据重排成三维序列调参成本高作业周期内要在验证集上稳定超过调好的 LightGBM 并不容易。如果报告里需要“多模型对比”加入一个只做滞后特征的线性回归就够了对比表格里能体现树模型的优势。4.2 基线模型训练与评估MAE、RMSE 和 MAPE 的取舍import lightgbm as lgb from sklearn.metrics import mean_absolute_error, mean_squared_error model lgb.LGBMRegressor( objectiveregression, learning_rate0.05, n_estimators3000, num_leaves31, min_child_samples20, subsample0.8, subsample_freq1, colsample_bytree0.8, random_state42, n_jobs-1 ) model.fit( X_train, y_train, eval_set[(X_valid, y_valid)], eval_metricmae, callbacks[lgb.early_stopping(100), lgb.log_evaluation(200)] ) y_pred model.predict(X_valid) mae mean_absolute_error(y_valid, y_pred) rmse mean_squared_error(y_valid, y_pred, squaredFalse) print(fMAE: {mae:.2f}, RMSE: {rmse:.2f})learning_rate0.05配合n_estimators3000用小步长、多轮数逼近解比一次性加大树数量更不容易过拟合。num_leaves31控制每棵树的叶子数。subsample0.8和colsample_bytree0.8分别做行采样和特征采样缓解过拟合。early_stopping(100)表示验证集 MAE 连续 100 轮不下降就提前终止log_evaluation(200)每 200 轮打印一次日志。新版本 sklearn 里 RMSE 可以直接用root_mean_squared_error效果与squaredFalse相同。评估指标上 MAE 和 RMSE 够用。MAPE 在交通数据上有坑夜间流量接近零时真实值 50、预测偏差 30MAPE 高达 60%但 30 辆车的绝对误差在夜间场景完全可以接受。MAPE 只能分时段算不能全局算。注意如果作业硬性要求 MAPE先过滤掉truth低于某个阈值的夜间样本再计算并注明过滤规则否则结果会被极小值主导。4.3 三个直接生效的调参方向4.3.1 学习率与迭代轮数配合早停使用固定n_estimators然后反复试learning_rate是常见误区。正确做法是设置一个很大的n_estimators让early_stopping决定实际轮数。学习率从 0.1 降到 0.05 通常能带来 1% 到 3% 的 MAE 改善训练时间翻倍在作业数据量下可接受再降到 0.03 提升有限除非时间充裕否则不必。4.3.2 num_leaves 与 min_child_samples 的取值边界num_leaves是 LightGBM 里最容易过拟合的参数。几万条数据时num_leaves127可以在训练集上接近零误差但验证集反而更差。先 31、再 64 和 15观察验证集 MAE 的 U 型曲线取最低点对应的值。min_child_samples设 20 到 50防止叶子节点只覆盖个别极端时段。这两个参数配合调整不要只动其中一个。4.3.3 特征重要性排序与冗余特征剔除importance_df pd.DataFrame({ feature: feature_cols, importance: model.feature_importances_ }).sort_values(importance, ascendingFalse) print(importance_df)输出里通常lag_1排第一hour_sin、hour_cos、rolling_mean_3h紧随其后。如果lag_5、lag_6重要性很低删掉重新训练看验证集 MAE 有没有反弹。每次只删一两个低重要性特征不要一次删完树模型对冗余特征组合的依赖比线性模型更强。参数作用作业场景建议值learning_rate每轮步长越小越稳0.05n_estimators最大训练轮数配合早停3000num_leaves树复杂度越大越容易过拟合31min_child_samples叶子节点最少样本数20subsample行采样比例0.8colsample_bytree特征采样比例0.8表格里的建议值是基线配置最终以自己验证集上的 MAE 为准不要照搬。5. 用滚动预测验证交通通行预测模型分时段误差与答辩可视化5.1 滚动预测循环里的关键改动前面的验证流程每一步都使用真实滞后特征叫一步预测。实际部署时t 时刻的预测值会被当作 t1 时刻的输入误差逐轮累积。滚动预测通过逐步回填预测值来复现这个过程能看出模型在误差累积下是否仍能跟上早晚高峰的形态。循环里有两个关键点lag_1到lag_6按从大到小的顺序整体平移最后把新预测值填入lag_1lag_96、滑动统计和时间特征在预测时属于已知信息直接从验证集取对应时刻的值。rec X_valid.iloc[0:1].copy() preds_roll [] for i in range(len(X_valid)): pred model.predict(rec[feature_cols])[0] preds_roll.append(pred) for lag in [6, 5, 4, 3, 2]: rec[flag_{lag}] rec[flag_{lag - 1}] rec[lag_1] pred if i 1 len(X_valid): for col in [lag_96, rolling_mean_3h, rolling_std_3h, hour, weekday, is_weekend, hour_sin, hour_cos]: rec[col] X_valid[col].iloc[i 1]滞后更新的顺序必须是 6 到 2 而不是 1 到 6反过来会提前覆盖掉lag_1到lag_5的原值。长滞后特征从验证集按位置取值不参与滚动这样误差只在短时窗口内传播得到的结果反映模型在短期递归预测下的表现。5.2 分时段计算 MAE 找到模型薄弱时段把预测结果对齐到时间索引按小时切出早高峰、晚高峰、平峰和夜间四段分别计算 MAE。早晚高峰 MAE 大是因为流量基数大夜间 MAPE 大是因为基数小这两组现象都是正常的。真正需要关注的是平峰时段的 MAPE 是否突然高于高峰时段如果是说明模型在平稳流量段存在系统性偏差。eval_df pd.DataFrame( {truth: y_valid.iloc[:len(preds_roll)], pred: preds_roll}, indexX_valid.index[:len(preds_roll)] ) eval_df[hour] eval_df.index.hour for name, (s, e) in {早高峰: (7, 10), 晚高峰: (17, 20), 平峰: (10, 17), 夜间: (0, 6)}.items(): sub eval_df[(eval_df[hour] s) (eval_df[hour] e)] print(f{name}: MAE{mean_absolute_error(sub[truth], sub[pred]):.2f})分组评估能直接定位模型的短板。作业报告里把这张分时段误差表放进去比只贴一个全局 MAE 更有说服力也方便答辩时被问到“模型哪里不好”时有话可说。5.3 答辩展示四张图对应四个环节数据挖掘大作业答辩时评委不会从头读完代码。可视化按“数据—特征—模型—验证”四个环节各准备一张。第一张是连续两周的原始流量时间序列曲线让人一眼看到日周期和周末低谷。第二张是滞后特征相关性热力图展示lag_1到lag_6与当刻流量的相关系数佐证特征工程方向没有跑偏。第三张是训练集与验证集的预测-真实散点图点越贴近对角线效果越好。第四张是滚动预测最后一个星期的对比折线图真实流量和预测流量画在同一坐标早晚高峰的跟随效果一目了然。报告里把这四张图按顺序放好对应章节分别给出关键参数表和分时段误差表评委一般会先看这几页再决定要不要追问细节。本文还有配套的精品资源点击获取