本题A榜给出了9月19日到10月18日期间3个收费站共五个方向(其中2号收费站只有0方向)的车辆通过记录作为训练集。预测集中给出了10月19日到10月25日共七天 每天6点到8点,15点到17点的车辆通过记录,需要预测当天8点到10点,17点到19点以20分钟为单位的车流量
B榜训练集又给出了10月19日到10月25日所有的车辆通过记录,预测集是10月25日到10月31日6点到8点,15点到17点的车辆记录,需要预测10月25日到10月31日8点到10点,17点到19点以20分钟为单位的车流
description of the feature:
Traffic Volume through the Tollgates
time | datatime | the time when a vehicle passes the tollgate |
---|---|---|
tollgate_id | string | ID of the tollgate |
direction | string | 0:entry, 1:exit |
vehicle_model | int | this number ranges from 0 to 7, which indicates the capacity of the vehicle(bigger the higher) |
has_etc | string | does the vehicle use ETC (Electronic Toll Collection) device? 0: No, 1: Yes |
vehicle_type | string | vehicle type: 0-passenger vehicle, 1-cargo vehicle |
B榜评分 0.1664,名次38/提交346/总队伍数3582
- 数据中有部分车辆没有“vehicle_type”信息,通过分析数据发现:记录在案的载重量大于等于5的车辆都是货车,载重量为4的车辆以客车居多,载重量3,2的车辆货车居多, 载重量1的车辆客车居多。剩下载重量为0的车辆,不是很理解什么样的车辆载重量会是0,所以单独处理。所以“vehicle_type”为空的记录根据其载重量以及相同载重量的记录中较多的“vehicle_type”去填充空值。具体填充如下:
vehicle_model0 = volume_df[volume_df['vehicle_model'] == 0].fillna("No")
vehicle_model1 = volume_df[volume_df['vehicle_model'] == 1].fillna("passenger")
vehicle_model2 = volume_df[volume_df['vehicle_model'] == 2].fillna("cargo")
vehicle_model3 = volume_df[volume_df['vehicle_model'] == 3].fillna("cargo")
vehicle_model4 = volume_df[volume_df['vehicle_model'] == 4].fillna("passenger")
vehicle_model5 = volume_df[volume_df['vehicle_model'] >= 5].fillna("cargo")
- 每个收费站和方向分开分析,分别有:1号收费站0方向;1号收费站1方向;2号收费站0方向;3号收费站0方向;3号收费站1方向。每块数据按照20分钟切片, 统计20分钟内通过的车流数量。以两个小时(6段)车流量为特征,用最后一个特征向后偏移20 * offset 时段的车流为因变量构建预测集,其中offset = 1,2,3...6。构建过程类似时间窗每次向后平移20分钟。例如: 2017年9月19日为例,时间切片之后车流数据如下:
时间段 | 车流量 |
---|---|
00:00:00~00:20:00 | a |
00:20:00~00:40:00 | b |
00:40:00~01:00:00 | c |
01:00:00~01:20:00 | d |
01:20:00~01:40:00 | e |
01:40:00~02:00:00 | f |
02:00:00~02:20:00 | g |
02:20:00~02:40:00 | h |
构建训练集:
feature1 | feature2 | festure3 | feature4 | feature5 | feature6 | y |
---|---|---|---|---|---|---|
a | b | c | d | e | f | g |
b | c | d | e | f | g | h |
这么做是因为预测集中需要用前两个小时预测后两个小时车流。尝试过不区分收费站和方向的情况,效果没有区分的好。
-
20分钟切片里除了有车流量,还有货车数量,客车数量,客车载重量,货车载重量等特征;2个小时内的数据也包含了一些信息,包括总的车流量,总货车数,总客车数,总货车载重量,总客车载重量,平均货车载重量,平均客车载重量等。用sklearn的GBDT预测, 参数设置为:默认参数基础上增加一些泛化能力,没有针对评分调参
-
因变量的时间特征也能用上,包括因变量所处时间点的月,日,时,分,周几等;注意时间信息有两种处理方式,当作离散标签处理(用one_hot编码),或者当作连续值处理,实验发现后者效果好。在GBDT等树形模型中,两者的区别还是很 明显的,前者在叶子节点时相当于只将某一个值作为划分点(例如是以是三点和不是三点作为叶子节点的划分),后者就能以多个连续值作为划分点(例如以12点为划分点,小于12点和大于等于12点分别是两个叶子节点)。
-
分析车流波形发现10月1日到10月7日之间的车流波形和其他时间区别非常大,所有收费站的所有方向都是如此。不知道用的是不是中国的数据,感觉就是国庆期间啊……所以将训练集中这段时间的数据全部删除
-
参考Kaggle里Stacking Start的帖子,做了三层Stacking模型,第一层用了9个模型(LASSO,Ridge,GBDT,ADABoost,XgBoost,XgBoost2,ExtraTrees,Liner,RandomForest),第二层用了(GBDT,XgBoost,XgBoost2),第三层是将第二层取平均。 为了增加第二层模型之间的不相关程度,第二层的输入不是第一层所有模型的输出,其中(LASSO,Ridge,GBDT,ADABoost,XgBoost,XgBoost2,ExtraTrees,Liner)的输出为第二层GBDT的输入,(LASSO,Ridge,GBDT,ADABoost,XgBoost,XgBoost2,ExtraTrees,Liner,RandomForest) 的输出为第二层XgBoost的输入,(Ridge,GBDT,ADABoost,XgBoost,XgBoost2,ExtraTrees,Liner,RandomForest)输出是第二层XgBoost2的输入。参数设置为:在默认参数的基础上增强了泛化能力,没有针对评分调参
-
观察GBDT对各特征的评分,发现虽然增加时间特征能够提高名次,但是时间特征在模型中的评分非常低,通过对数据的观察发现客流量有非常明显的时间特征。因此建立第二套训练集,特征只有前两个小时每20分钟的车流量,载重量, 以及待预测时段的时间特征(离散时间特征和连续时间特征同时加上)。第二套训练集同样用Stacking模型训练。通过实验发现,不区分收费站和方向的预测结果要比区分的结果好,所以这套训练集不区分收费站和方向
-
两套训练集得到的预测结果根据名次高低线性加和,名次高的结果乘以0.6,名次低的结果乘以0.4
-
学习了去年KDD第三名的分享,发现不能的通过单纯增加Stacking的模型种类提高成绩。因此决定使用相关性低的模型,或者单模型效果好的模型因此去掉了Stacking模型了部分模型,第一套Stacking的一层模型模型中去掉了ADABoost,Liner; 第二套Stacking的第一层模型中去掉所有线性模型;
-
进一步观察数据,发现存在7万条记录没有车辆类型,而且全部都是各收费站0方向,因此去掉之前填空值策略能更加尊重原数据,因此在去掉第一步填充空值的方法,这样就只能减少0方向的部分特征,包括货车数量,客车数量,货车载重量,客车载重量等。使用如下特征替代: 重量0-2的车辆数量,重量3-4的车辆数量,重量5-7的车辆数量。这一步优化的结果没有提升,但毕竟是尊重原数据,所以还是保留了这次优化。
-
B榜数据给出后,立马用B榜数据和之前的预测结果做对比,同时再次观察训练集数据,发现下午17点到19点是一个下降趋势(每个收费站,每个方向的每一天几乎都是这个趋势),反观之前的建模,好像并没有将每天这四个小时车流的特点凸显出来,当时有两种 解决方案:利用重采用,将训练集中6点到8点,15点到17点的数据复制多次;增加训练集中6点到8点,15点到17点数据权重;最后选择使用第一个方案,因为该方案能够通过实验得到较好的重采样次数,而第二个方案在不知道sklearn会对权重高的样本怎样处理的情况下, 没办法控制权重的值。于是利用方案一优化A榜单模型预测结果,而且模型区分上下午。根据实验结果,最后选择在原始训练集基础上,上午数据重采样10份作为上午的训练集,下午数据重采样10份作为下午训练集。
-
B榜两套训练集分别进行上一步的改进,区分上下午,并对特定时段数据做重采样,并根据各自的预测结果设定权值,最终结果 = 结果1 * 0.3 + 结果2 * 0.7
总结:
-
解法只考虑了前2个小时的车流,没有考虑前一天,三天,五天,七天等时段的车流特点。之前没想好要怎解做,比赛最后一天才想到,以第二步训练集最后一维特征的时间点为基准点,获取该时间点前一天,前三天,前五天,前七天的车流量。
-
Stacking模型没有调参,个人决定应该是通过单模型调参,再放到Stacking里训练。我的解法数据划分的太细,导致单模型调参难度同样非常大,所以到最后也没时间调参。
-
借鉴第二名的思路,可以在构建训练集的时候,时间窗口平移幅度变成5分钟,同时将数据集中在预测时段,这样即能够突出训练集中预测时段的特点,同时能够增加数据量
-
借鉴第一名的思路,可以通过设置样本权重为真实值倒数的方式将损失函数等价转换。传统gbdt提供的损失函数只有平方损失函数和绝对值误差损失函数,而题目给出的评估函数是MAPE,特点是损失值会受到样本真实值大小的影响。将样本权重设置为真实值的倒数,综合考虑加权损失的时候就等价于对损失函数进行改造。
-
借鉴第一名的思路,可以更加合理的构建验证集,传统的验证集是从训练集中不交叉的选择10%的数据进行验证,该操作同时进行10次。而由于本题目预测集是有时间段限制的,即严格固定了时间段,因此需要构造和预测集相同时间段,相同时间跨度的验证集才比较合理。具体可以参考第一名的构造验证集思路,有一点复杂,但是方便后续的线下优化工作
-
在单模型的基础上加上一个清洗脏数据的功能,用三层gbdt清洗掉百分之十的数据,再用五层GBDT预测(不知道为什么才0.7876)
-
纯时间特征模型加上数值类型的时间特征(成功从0.2016提高到了0.1730)
-
stacking1使用的训练集做微小调整,在构造训练集过程中不处理nan值,拿到模型里才处理,这样训练集的Volume0~volume5和y之间更有连贯性(0.1788已经被纯时间特征超过了)
-
重新提交2017-05-11日第一个优化点(>0.3)
-
在2017-5-11的基础上减少stacking2模型的数量,纯时间模型去掉ADAboost(0.1775)
-
检查训练集,在2017-05-11的基础上减少stacking1模型的数据,去掉所有ADAboost模型,二层不适用随机模型,尽量减少模型之间的相关度(0.1735)
-
在2017-05-12基础上修改过滤时的评分函数
-
修正时间特征计算代码0.1681
-
stacking的第二层备选模型中去掉随机模型(ET和RF)(0.1739)
- 在2017-05-13项目1的基础上,舍弃数据过滤功能,改成特征选取功能,功能按照单个特征做回归的评分高低降序排序,每次选取一个效果最好的特征加到备选集中,并预测打分,得到最好的特征集(0.1841降了)
-
GBDT3层和5层有没有区别,可以尝试一下,而且注意用评价函数(3层效果好,说明5层有严重的过拟合)
-
加一些特征吧,比如说最大值,最小值(0.1747)
-
发现不论是原始的训练集还是原始的预测集,0方向(entry)的车辆都不记录vehicle_type,而1方向(exit)的方向都记录了该值, 所以不能盲目用众数来填充vehicle_type的空值,在分端口和方向的时候适当剔除掉一些特征
-
3层GBDT(0.1627)
-
存在7万条记录没有车辆类型,而且全部都是各收费站0方向,都没用电子桩(暂时不做处理,因为题目也说载重量是0到7,说明0载重量是存在的)
-
在昨天基础上,删除处理后产生的空值,之前我都是在stacking文件里专门处理训练集和预测集的空值,在volume_predict2文件里 没有这功能。(0.1683)
-
在昨天基础上,增加层数到5层(0.1694)
过拟合了,想想怎么肥四
- 把10月1日到10月7日的数据加回来,增加部分特征,包括20分钟内使用etc的车辆数、总载重量,没使用etc的车辆数、总载重量
-
按照预测集分布筛选,用预测集车流的最大值,最小值,均值,标准差压缩训练集vloume0 ~ volume5的区间,注意用均值加减二倍标准差和 最大值,最小值比较(0.1687)
-
直接用训练集本身的分布特点筛选数据,用训练集的最大值,最小值,均值,标准差压缩区间,均值加二倍标准差为上限, 下限设置常数3(0.1692)
-
0.1672 分端口方向构造不同的特征,10月1日到10月7日数据全部变成null,但是当时忘记删除这些值,将其全部填成0
-
0.1747 在上面的基础上删除所有的空值
-
0.1647 在上面的基础上删除部分特征,包括最大值,最小值,均值等特征
-
0.1658 考虑到大量的0数据能够改变树的分布,将部分较小的数值隔离开,因此想增加10月1日至10月7日数据来平衡数据分布
-
0.1687 用测试集的最大值,最小值,均值,方差清洗数据,均值加减二倍方差
-
0.1692 用训练集的最大值,最小值,均值,方差清洗数据,均值加减二倍方差和最大值,最小值,用最大区间
-
10月1日至10月7日数据全部删除
-
除此之外,其余数据resample得到的空值均填为0
-
用之前的非调参stacking模型+时间特征模型的融合(0.1728, 0.1617)
-
使用另一种stacking方式,二层固定使用两种参数的XGB和一个GBDT,一层使用三种模型集合,集合长度分别为6,7,6(0.1673,0.1602)
-
单模型调整,单独剔除10月1日到10月7日的数据(保证resample之后没有这个东西),在此基础上将所有的空值设置为0(0.1674)
-
单模型调整,删除全部空值(尽量合理删除空值),顺便检查代码
-
把1放到05-22的第二个stacking模型中
-
时间特征模型调参,可以稍微过拟合,目的是降低和主train&test1模型的相关度,0.5x+0.5y的比例分配结果,最后成绩是0.1589