Press "Enter" to skip to content

使用神经网络预测航班起飞准点率

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

一.问题描述
赛题是根据西安机场上半年的航班起降信息,建立适当预测模型,预测未来七天的航班准点率,(航班实际起飞时间-航班计划起飞时间)< 15 分钟即为准点。
 
二.问题分析
为解决这个问题,首先需要对比赛数据进行深入了解。赛会提供的数据是一个csv文件,由15万条航班起降数据组成。每条记录包含如下九种属性:[航班号,出发地,到达地,机型,计划起飞时间,计划到达时间,实际起飞时间,实际到达时间,进出港类型]。
下面是几条数据示例:
HV2380,XIY,KUL,A330,2018/1/1 0:30,2018/1/1 5:40,2018/1/1 0:39,2018/1/1 5:59,出港
IU6364,XIY,DMK,B737,2018/1/1 1:35,2018/1/1 5:30,2018/1/1 1:40,2018/1/1 5:17,出港
IU5438,XIY,HKT,B737,2018/1/1 1:35,2018/1/1 6:35,2018/1/1 3:18,2018/1/1 7:51,出港
其中,可以用于预测的特征只有 航班号、机型、出发地、到达地、计划起飞时间这5种特征,仅使用这些特征来建立预测模型的话是不够充分的。
2.1 特征补充——爬取天气数据
为此,我们额外收集了西安机场半年以来的天气数据,根据日常经验可知,天气对于航班起降的影响是巨大的。在给定的数据文件中,仅有2018年1月1日到2018年6月30日的数据,因此,我们在网上爬取了这些日期的天气情况。经过浏览网页,决定使用”逍遥天气”网站的数据,对每天天气新闻进行爬取(如:http://www.xaoyo.com/news/xian/20180629.html)。

 

图1.天气网站示例

   我们使用selenium+phantomJS的框架来对网站的标题进行爬取,发现每天的新闻的URL格式相对固定,仅后方的日期略有差别;此外,每天的新闻标题都存储在<div class=’hed_tit’>中的<h1>标签下,可以使用BeautifulSoup将其解析出来。

1 title = BeautifulSoup(driver.page_source,'html.parser').find('div',class_='hed_tit').find('h1').text

获取了标题字符串之后,我们对其进行解析切分,使用python自带的split()函数,将三种属性:天气、气温、风力 解析出来。经过粗略分析,感觉气温属性对航班的准点率影响不大,便仅留下天气与风力属性,保存在weather.csv文件中。
这里爬虫的具体实现我就不再进行细致讲解,对爬虫没有太多基础的同学可以看我之前的博文(基于selenium+phantomJS的动态网站全站爬取)。
2.2非线性特征数据处理
现在,我们有了航班号、机型、出发地、到达地、计划起飞时间、天气、风力这7种属性。
第一个问题是,神经往往要求我们的输入在[0~1]之间,但航班号、机型、出发地、到达地、天气这5个属性并不是线性的,我们无法使用算数计算的方式将其归一化。为了解决这个问题,直觉上想到One-Hot Vector编码。即将该特征编码成一条N*1的向量,该特征所处的位置赋值为1,向量中的其他位置赋值为0。One-Hot Vector 在网上已有丰富的资料可供查阅,这里我们就简单举例说明一下。
假设现在一共有“HV2380”,“IW5079”,“SY6658”,“WJ5723”,“VQ9535”共5种航班,那么对于数据文件中的第一条数据:
HV2380,XIY,KUL,A330,2018/1/1 0:30,2018/1/1 5:40,2018/1/1 0:39,2018/1/1 5:59,出港
可以将航班号这个特征编码为 [1, 0, 0, 0, 0]。 对于另一条数据:
WJ5723,XIY,TGO,B737,2018/1/1 13:50,2018/1/1 16:30,2018/1/1 13:58,2018/1/1 16:04,出港
可以将航班号这个特征编码为 [0, 0, 0, 1, 0]。
为了准确的对所有航班号属性进行One-Hot编码,我们遍历所有数据条目,统计出一共有1266中不同的航班。也就是说,对于这一种特征来说,就会产生一个1266*1的One-Hot向量,这会导致在神经网络训练的时候产生一个相当大的稀疏矩阵。
 
三.基于数据统计的多步预测模型建立
3.1数据统计及特征提取
上文讲到直接对航班进行One-Hot编码,会产生一个较大的稀疏向量,进而在搭建网络的过程中会出现一个相当大的稀疏矩阵。直观上我会怀疑模型能否可以正确的对其进行训练,达到理想的效果。
因为稀疏矩阵的存在,看起来对每一条航班信息进行准点率预测的模型不是那么好实现。等等,我们再重新审一下题~~赛题的要求是: 预测未来七天的航班准点率!
即,我们不是预测每个航班的起降准点率,而是预测每日所有航班的准点率:(准点航班数量/当日航班总数)*100%。也就是说,对于给定数据文件中的数据,我们没有必要对每一条航班信息建模训练,我们完全可以统计出每一天的航班起降情况,并以天为单位来进行建模预测。
因此,我们着手开始进行数据统计的工作。首先,就是以天为单位,统计每天的航班起降总数与准点航班数目。为达到这个目的,我先初始化了两个长度为181的全0向量(赛题数据一共包含有181天),分别表示第n天的航班总数与准点航班数目。之后开始对数据文档中的15万条数据进行一次遍历,对于每条数据,计算其所属的日期,与其是否准点,分别在对应向量的位置中+=1。

1 count_list = list(np.zeros(day_num))  # 计算每天有多少班次飞机的list
2 accurate_num_list = list(np.zeros(day_num))  # 每天准点的飞机数量list
3 for i in range(len(fin))[1:]:      # 首行是标注,非数据
4         plan_fly_time = time.mktime(time.strptime(fin[4][i],'%Y/%m/%d%H:%M'))
5         day_index = int((plan_fly_time-begin_stamp)/(3600*24))
6         count_list[day_index] += 1
7         actual_fly_time = time.mktime(time.strptime(fin[6][i],'%Y/%m/%d %H:%M'))
8         if actual_fly_time-plan_fly_time < 15*60:
9             accurate_num_list[day_index] += 1

在进行统计的过程中,还会遇见一些有问题的数据,例如说有部分数据的机型一项为NULL,有一部分数据的起飞、降落时间为NULL:

图3.1 值为NA的脏数据示例

图3.2 值为#NA的脏数据示例

在数据处理的过程中,我们选择对这些数据条目进行删除。整体删除量较小(总共删除<20条数据),对建模不会产生任何影响。
在统计完每日航班数目与每日准点率之后,画出其图像,来对其关系进行直观的对比:

图3.3 每日起降航班数目与准点率关系统计图
根据图像,我们可以得出,航班准点率整体趋于一个稳定序列,即没有明显上升、下降趋势的序列,平均准点率大概在60%左右;此外,可以略微的看出每日起降数量与准点率呈反比(如第45~75日),这也与我们的直觉相契合,即航运压力大的时候飞机准点率不高。我们对前两个准点率低谷进行分析,发现在1月3日和1月24日有降雪,降雪不但对当天的航班准点率有影响,还会继续影响后续几天的航班,尤其是降雪过后第二日,航班准点率会比降雪当天还要低。
   
图3.4 降雪会明显影响后续几日航班准点率
此外,继续观察天气数据与航班准点率统计图,可以发现气温对航班准点率几乎没有影响(数据从冬天到夏天,准点率没有明显上升、下降趋势)。因此,在对气象特征进行提取的时候,我们仅仅对天气和风力进行建模。
对于天气建模,我们使用One-Hot编码的方式,将天气分为3类,第一类是{阴,晴,多云},第二类是{小雨,中雨,大雨,暴雨},第三类是{雨夹雪,小雪,中雪,大雪,暴雪}。最终生成一个形状为3*1的向量。如某日天气为“中雨”,特征向量为[0,1,0],某日天气为“多云”,其特征向量为[1,0,0]。而对于风力,我们将其风力的级别提取出来,根据其级别0~12级将其归一化到[0,1]之间。此时,我们就可以将统计数据抽象提取出6个特征,即航班数,,阴晴,雨,雪,风力。
注:   /*  接下来对剩下来的航班号、机型、出发地、降落地进行筛选,考虑到航班号确定时,其机型,出发地,将落地也将是确定的,在构造模型时,我们仅仅保留航班号这一个特征。最终,我们的预测模型拥有。 */
3.2多步预测模型建立

  Nguyen Hoang An曾对神经网络进行多步预测的策略进行过总结[1], 包括直接预测策略、迭代策略,MIMO策略,DirREC策略以及DirMO策略。其中,直接预测策略、DirREC策略和DirMO策略都需要建立多个预测模型,训练开销比较大。而MIMO策略的预测效果并不好,因此我们使用迭代策略来进行多步预测。国内也有学者对传统Airline Passenger数据进行多步预测[2],取得了不错的效果。迭代策略就是训练出一个预测模型,预测出下一个时间节点的数据,之后将预测输出作为输入,对第二个时间节点进行预测,如此迭代反复,获得多步预测结果。

  在上一节的处理中,我们最终留下了航班数,准点率,阴晴,雨,雪,风力6个特征用于预测。其中,模型并不能预测天气情况,仅仅能对航班数、准点率两个特征进行预测,在这次建模中,假设我们可以获得第二天准确的天气情况。每次将预测得到的航班数和准点率与已知的天气数据进行拼接,迭代的预测后续的航班数和准点率,预测得到未来7天的航班起降准点率

  预测模型搭建如下:

1 model = Sequential()
2 model.add(LSTM(128, input_shape=(self.window_len,6),return_sequences=False))  # TODO: input_shape=(timesteps ,data_dim)
3 model.add(Dropout(0.2))
4 model.add(Dense(2))
5 model.add(Activation('sigmoid'))
6 model.compile(loss='binary_crossentropy',optimizer='rmsprop',metrics=['accuracy'])

这里使用keras的序贯模型来构造训练模型。考虑到天气会对准点率有持续的影响,这里使用LSTM循环神经网络来进行预测,时间窗口(self.window_len)设置为6,输入特征数目也是6(即input_shape中的第二个参数)。尤其注意最后一层一定要使用Dense(2),使我们的输出模型可以输出两个结果,第一个结果是第二天航班数的预测效果,第二个结果是第二天准点率的预测结果。
本次数据共有181天,排除掉最后7天的数据(最后七天的仅仅包含入港的数据、没有出港的数据),再减去时间窗口6,得到168个样本。其中划出10个样本作为测试集,158个样本作为训练集。使用这158个样本进行训练,训练2000个epoch,获得模型并保存。
使用这个模型来对10个测试样本进行预测,每次仅预测第二天的航班数和准点率:

图3.5 航班数目预测结果(单点预测)

图3.6 航班准点率预测结果(单点预测)

  使用倒数第7天的样本输出作为初始样本,使用迭代策略来对未来7天的航班数目和准点率进行预测(假设已有未来7天准确的天气预报):

图3.7 航班数目预测结果(连续预测7天)

图3.8 准点率预测结果(连续预测7天)
通过上图可以看出,不论是对航班数目还是准点率,模型都可以对其趋势进行较好的把握,7天准点率预测结果的均方根误差约为5.3%。
当然,在模型训练的时候,我们还可以对其窗口大小、训练次数、批处理大小、dropout比例等进行调整。时间充裕的情况下可以反复调整模型,获得更好的预测效果。
 
Reference:

[1] NH An, DT Anh. Comparison of Strategies for Multi-step-Ahead Prediction of Time Series Using Neural Network[C]. 2015 International Conference on Advanced Computing and Applications (ACOMP), Ho Chi Minh City, 2015, pp. 142-149.

[2] Liu YP, Hou D, Bao JP, et al. Multi-step Ahead Time Series Forecasting for Different Data Patterns Based on LSTM Recurrent Neural Network[C]. 2017 14th Web Information Systems and Applications Conference (WISA), Liuzhou, Guangxi Province, China, 2017, pp. 305-310.

 
后记:此次也有尝试已知未来7日每天航班计划(即已知每日航班数)来仅对航班准点率这一个属性进行预测。但预测效果不如上述模型理想。也许是因为数据较少(仅181天的数据,包括最后7日的残缺数据)的原因,可以后续对该模型继续留待观察。

Be First to Comment

发表评论

电子邮件地址不会被公开。 必填项已用*标注