1. 程式人生 > >使用神經網路預測航班起飛準點率

使用神經網路預測航班起飛準點率

前些日子,參加了一個解放號的行業大資料創新應用大賽,

一.問題描述

  賽題是根據西安機場上半年的航班起降資訊,建立適當預測模型,預測未來七天的航班準點率,(航班實際起飛時間-航班計劃起飛時間)< 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日的殘缺資料)的原因,可以後續對該模型繼續留待觀察。