历时两个月的比赛终于结束了,最终以第32名的成绩告终,在此和大家分享下解决问题的思路。
从初赛到复赛,有走过弯路,也有突然灵光一现的时刻。一路走来,对数据各种把玩,分析了各种可能的情况,尽可能得挖掘数据中潜在的信息来构建更为准确的模型。
本文无法涵盖所有的分析历程,但是会涉及解决问题的主要思路以及部分代码,详细的代码见Github页面
竞赛详细信息参见比赛官方网站
1. 问题描述
机场拥有巨大的旅客吞吐量,与巨大的人员流动相对应的则是巨大的服务压力。安防、安检、突发事件应急、值机、行李追踪等机场服务都希望能够预测未来的旅客吞吐量,并据此提前调配人力物力,更好的为旅客服务。本次大赛以广州白云机场真实的客流数据为基础,每天数万离港旅客在机场留下百万级的数据记录。希望参赛队伍通过数据算法来构建客流量预测模型。
2. 数据概览
提供的数据:
Table |
---|
连接WIFI AP (Access Point)的人数表 airport_gz_wifi_ap |
安检旅客过关人数表 airport_gz_security_check |
旅客进入-离开机场的行程表 airport_gz_departure |
航班排班表airport_gz_flights [比赛一段时间后才提供] |
机场登机口区域表 airport_gz_gates [比赛一段时间后才提供] |
机场WIFI接入点坐标表 airport_gz_wifi_coor [复赛提供的] |
例如airport_gz_wifi_ap 表数据概览:
wifi_ap_tag | passenger_count | time_stamp |
---|---|---|
E1-1A-1 | 15 | 2016-09-10-18-55-04 |
E1-1A-2 | 15 | 2016-09-10-18-55-04 |
E1-1A-3 | 38 | 2016-09-10-18-55-04 |
E1-1A-4 | 19 | 2016-09-10-18-55-04 |
提交表格案例:
passenger_count | wifi_ap_tag | slice10min |
---|---|---|
1.1 | E1-1A-1 | 2016-09-14-15-0 |
2.2 | E1-1A-1 | 2016-09-14-15-1 |
3.3 | E1-1A-1 | 2016-09-14-15-2 |
4.4 | E1-1A-1 | 2016-09-14-15-3 |
5.5 | E1-1A-1 | 2016-09-14-15-4 |
3. 初赛
3.1初赛数据描述
初赛提供了2016-10-09至2016-09-25的数据
3.2初赛问题描述
选手需要预测未来三小时(9月25日15:00:00到18:00)的时间窗口里,机场内每个WIFI AP点每10分钟内的平均设备连接数量
3.3初赛解决方案
简要概括:均值加趋势
数据预处理:
提供的表格中时间数据都是精确到秒,而所提交的结果要求是每10分钟的平均情况,所以我们首先需要将数据按照每十分钟的间隔汇总起来(详细代码见Github)
此处提供两种方案:
以airport_gz_wifi_ap表为例截取time_stamp的部分字符串,然后按照截取的time_stamp和wifi_ap_tag进行aggregate
t = t0[:15] # 例如将t0 = 2016-09-10-18-55-04截取为t = 2016-09-10-18-5
将数据按照时间排序,然后抽出每十分钟的数据进行处理后整合,这个方式可能会比较麻烦,但是这个方式有他的优势,我们只需调整一个参数,便能让数据按照任意的时间间隔进行统计,便于以后复用函数
此处附加Python处理时间格式的一些函数
我们可以直接使用pandas中的参数解析时间数据
# Normal
df =pd.read_csv(path, parse_dates=['column name'])
# Special
dateparse = lambdax: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df =pd.read_csv(path, parse_dates=['column name'], date_parser=dateparse)
当然也可以自己写函数处理
import pandas as pd
def ReturnTimeElement(Date):
return [int(t) for t in Date.split('-')]
def TransToTime(TimeElement):
return pd.datetime(*(TimeElement))
def GetTime(Date):
TimeElement = ReturnTimeElement(Date)
Time = TransToTime(TimeElement)
return Time
T = '2016-10-19-9-47-00'
>>> GetTime(T)
datetime.datetime(2016, 10, 19, 9, 47)
处理后可以得到如下数据,命名为WIFITAPTag_Mean_All
PassengerCountMean | Time | WIFIAPTag |
---|---|---|
16.2 | 2016/9/10 19:00 | E1-1A-1 |
19.7 | 2016/9/10 19:10 | E1-1A-1 |
19.7 | 2016/9/10 19:20 | E1-1A-1 |
20.5 | 2016/9/10 19:30 | E1-1A-1 |
20.5 | 2016/9/10 19:40 | E1-1A-1 |
24.8 | 2016/9/10 19:50 | E1-1A-1 |
问题分析:
对于这个预测问题有以下关键两点:
- 机场每天的排班表基本稳定,用户在机场内的行走模式也基本稳定
- 时间序列具有一定程度的连续性,下午三点至六点的情况会一定程度延续此前几小时的情况
基于以上两点想法,就得到了两个基本模型:均值模型
和时间序列模型
比赛初期只提供了前三个表格,所以开始就注重分析了这几个表格,例如从WIFIAPTag中可以提取出大概的位置信息和楼层信息,分组统计不同区域的WIFIAP是否有接近的模式,同时也可从安检和出发表格中寻找一定的关联等等。
但是经过分析发现,airport_gz_security_check及airport_gz_departure的数据虽然和airport_gz_wifi_ap的数据有一定的关联,但是其本身存在较大的随机因素,用随机预测随机存在太大的变数,不如只使用airport_gz_wifi_ap中的数据进行更稳定的预测(当然肯定也有队伍能很好得从airport_gz_security_check及airport_gz_departure中提出很很棒的特征)。后期提供的几个表格由于数据质量问题,经分析后发现贡献不是特别大,故也没有进一步利用。
因而之后要说的均值模型
和时间序列模型
都基于WIFITAPTag_Mean_All表格的数据,并且是以WIFIAP为对象, 每一个分开预测。
数据探索:
接下来让我们对数据有一个大概的了解
def GetTimeSeries(WIFIAPTag):
'''
Get WIFIAPTag 's Time Series
'''
Tag_Data = WIFITAPTag_Mean_All[WIFITAPTag_Mean_All.WIFIAPTag == WIFIAPTag]
MinTime = min(Tag_Data.Time)
MaxTime = max(Tag_Data.Time)
DataTimeRange = pd.date_range(start = MinTime , end = MaxTime , freq = '10Min')
ts_0 = pd.Series([0]*len(DataTimeRange),index=DataTimeRange)
ts =pd.Series(Tag_Data.PassengerCountMean.values , index = Tag_Data.Time)
TS = ts_0+ts
TS = TS.fillna(0)
return TS
以上函数能提取出特定WIFIAP的时间序列数据,及每10分钟的平均连接数
ts = GetTimeSeries('E1-1A-1<E1-1-01>')
ts
Out[7]:
2016