# 天池智慧交通预测挑战赛解决方案
本博客分享新人第一次参加天池比赛的实况记录,比较完整地给出了数据预处理,缺失值补全,特征分析过程以及训练和交叉验证的注意事项,适合数据挖掘新人找到解题思路,全程没有调参,没有模型融合,只凭一手简单的特征和xgboost,最后止步41/1716,基本上可以作为时间序列预测类的比赛的baseline.完整代码在[Github](https://github.com/PENGZhaoqing/TimeSeriesPrediction)
(ps. 不是我不调参,不融合模型,是以现在的特征即使做了这些,提高也不会很大,所以还是特征的问题,可能太简单了)
* preprocess.py: 数据预处理(类型转换,缺失值处理,特征提取)
* xgbosst.py: 训练模型和交叉验证
# 1. 数据和题目说明
这个比赛的目标是提供一些路段流量的历史信息, 以此来预测未来一段时间的交通流量, 提供的数据一共有3个表: link_info, link_tops 和travel_time. 分别如下所示:
```
link_infos = pd.read_csv('../raw/gy_contest_link_info.txt', delimiter=';', dtype={'link_ID': object})
print link_infos.head(5)
link_ID length width link_class
0 4377906289869500514 57 3 1
1 4377906284594800514 247 9 1
2 4377906289425800514 194 3 1
3 4377906284525800514 839 3 1
4 4377906284422600514 55 12 1
```
link_info表里共存着每条路的id, 长度, 宽度和类型,共有132条路
```
link_tops = pd.read_csv('../raw/gy_contest_link_top.txt', delimiter=';', dtype={'link_ID': object})
print link_tops.head(5)
link_ID in_links out_links
0 4377906289869500514 4377906285525800514 4377906281969500514
1 4377906284594800514 4377906284514600514 4377906285594800514
2 4377906289425800514 NaN 4377906284653600514
3 4377906284525800514 4377906281234600514 4377906280334600514
4 4377906284422600514 3377906289434510514#4377906287959500514 4377906283422600514
```
link_top里储存每一条路的上下游关系, in_links里放着这条路的上游路id, 中间用`#`分割, 而out_links里则给出了这条路的下游路id; 下游路可以理解为出路, 上游路为入路
```
df = pd.read_csv('../raw/quaterfinal_gy_cmp_training_traveltime.txt', delimiter=';', dtype={'link_ID': object})
print df.head(5)
link_ID date time_interval travel_time
0 4377906283422600514 2017-05-06 [2017-05-06 11:04:00,2017-05-06 11:06:00) 3.00
1 3377906289434510514 2017-05-06 [2017-05-06 10:42:00,2017-05-06 10:44:00) 1.00
2 3377906285934510514 2017-05-06 [2017-05-06 11:56:00,2017-05-06 11:58:00) 35.20
3 3377906285934510514 2017-05-06 [2017-05-06 17:46:00,2017-05-06 17:48:00) 26.20
4 3377906287934510514 2017-05-06 [2017-05-06 10:52:00,2017-05-06 10:54:00) 10.40
```
travel_time表里存着这132条路从2017.4-2017.6以及2016.7每天车通过路的平均旅行时间, 统计的时间间隔为2分钟; 除了2016.4到6月每天的信息, 还有2017.7月每天6:00-8:00, 13:00-15:00, 16:00-18:00的记录, 然后我们需要预测的就是7月每天在早高峰, 午平峰, 晚高峰三个时间段(8:00-9:00, 15:00-16:00, 18:00-19:00)每条路上的车平均旅行时间
# 2. 题目分析和思路
这是一个关于时间序列预测的问题, 并不是普通的回归问题, 而是自回归, 一般的回归问题比如最简单的线性回归模型:`Y=a*X1+b*X2`, 我们讨论的是因变量Y关于两个自变量X1和X2的关系, 目的是找出最优的a和b来使预测值`y=a*X1+b*X2`逼近真实值Y. 而自回归模型不一样, 在自回归中, 自变量X1和X2都为Y本身, 也就是说`Y(t)=a*Y(t-1)+ b*Y(t-2)`,其中`Y(t-1)`为Y在t-1时刻的值, 而 `Y(t-2)`为Y在t-2时刻的值, 换句话说, 现在的Y值由过去的Y值决定, 因此自变量和因变量都为自身, 这种回归叫自回归.
根据题目给出的信息, 除了路本身的信息外, 训练数据基本上只有旅行时间, 而我们要预测的也是未来的平均旅行时间, 而且根据我们的常识, 现在的路况跟过去一段时间的路况是很有关系的, 因此该问题应该是一个自回归问题, 用过去几个时刻的交通状况去预测未来时刻的交通状况
传统的自回归模型有自回归模型(AR)、移动平均模型(MA)、自回归移动平均模型(ARMA)以及差分自回归移动平均模型(ARIMA), 这些自回归模型都有着严格理论基础,讲究时间的平稳性, 需要对时间序列进行分析才能判断是否能使用此类模型. 这些模型对质量良好的时间序列有比较高的精度, 但此比赛中有大量的缺失值, 因此我们并没有采用此类模型. 我们的思路其实很简单: 就是构建`Y(t)=a*Y(t-1)+ b*Y(t-2)+..`, 但并不是用的线性模型, 用的是基于树的非线性模型, 比如随机森林和梯度提升树.
# 3. 数据分析
## 3.1 特征变换
先对原始数据进行一些分析, 首先了解一下平均旅行时间的分布:
```
fig, axes = plt.subplots(nrows=2, ncols=1)
df['travel_time'].hist(bins=100, ax=axes[0])
df['travel_time'] = np.log1p(df['travel_time'])
df['travel_time'].hist(bins=100, ax=axes[1])
plt.show()
```
![这里写图片描述](http://img.blog.csdn.net/20170911182135429?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHBwODMwMDg4NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
我们发现这个平均旅行时间变量travel_time是一个长尾分布, 也就是大数值的特别少, 而大部分数据都集中在很小的区域, 如上面的图, 因此做一个log的特征变换, 一般对数变换为ln(x+1), 避免x=0而出现负无穷大, 可以看出经过对数变换后, 数据的分布非常均匀, 类似正态分布, 比较适合模型来处理
## 3.2 数据平滑
即使做了log变换后, 还是有部分travel_time值过于大, 为了消除一些离群点的影响, 我们对travel_time做一个百分位的裁剪clip, 我们把上下阈值设为95百分位和5百分位, 即将所有大于上阈值的travel_time归为95百分位数, 而小于小阈值的travel_time设为05百分位数:
```
def quantile_clip(group):
group.plot()
group[group < group.quantile(.05)] = group.quantile(.05)
group[group > group.quantile(.95)] = group.quantile(.95)
group.plot()
plt.show()
return group
df['travel_time'] = df.groupby(['link_ID', 'date'])['travel_time'].transform(quantile_clip)
```
这个clip百分位过滤是对于每一条路每天的travel_time来说的,因此使用groupby方法并传入link_ID和date, 因此得到的group变量里储存着某条路某天的所有travel_time, 对此进行百分位的clip, 如下图:
![这里写图片描述](http://img.blog.csdn.net/20170911185001367?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHBwODMwMDg4NQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
这是Link_ID为4377906283422600514的路在2017-05-06的travel_time时间序列图, 我们clip掉了蓝色的部分, 留下为橙色部分所示
## 3.3 缺失值补全
### 3.3.1 为什么要补全缺失值? 不补全可不可以?
如果我们的思路是通过前几个时刻的travel_time来预测下一个时刻的travel_time, 那么这个缺失值一定要补齐, 因为我们总不能让前几个时刻的travel_time出现空值吧, 而且这种情况下要预测的travel_time也有可能是空值. 如果是其他思路, 比如你的feature中没有出现前几个时刻的travel_time, 而是以minute_of_hour, hour_of_day, day_of_week, day_of_month, month_of_year来标识目前要预测的travel_time的话, 不补全至少模型还是可以跑通的, 至于效果�
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
天池智慧交通预测挑战赛解决方案 本博客分享新人第一次参加天池比赛的实况记录,比较完整地给出了数据预处理,缺失值补全,特征分析过程以及训练和交叉验证的注意事项,适合数据挖掘新人找到解题思路,全程没有调参,没有模型融合,只凭一手简单的特征和xgboost,最后止步41/1716,基本上可以作为时间序列预测类的比赛的baseline.完整代码在 (ps. 不是我不调参,不融合模型,是以现在的特征即使做了这些,提高也不会很大,所以还是特征的问题,可能太简单了) preprocess.py: 数据预处理(类型转换,缺失值处理,特征提取) xgbosst.py: 训练模型和交叉验证 1. 数据和题目说明 这个比赛的目标是提供一些路段流量的历史信息, 以此来预测未来一段时间的交通流量, 提供的数据一共有3个表: link_info, link_tops 和travel_time. 分别如下所示: lin
资源详情
资源评论
资源推荐
收起资源包目录
timeseriesprediction-master.zip (5个子文件)
TimeSeriesPrediction-master
related_lagging.py 4KB
ultis.py 5KB
README.md 44KB
preprocess.py 19KB
xgbosst.py 8KB
共 5 条
- 1
dongyuwu
- 粉丝: 39
- 资源: 4559
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0