一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何用Python和循環(huán)神經網絡預測嚴重交通擁堵?

電子工程師 ? 來源:lq ? 2018-12-16 10:47 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本文為你介紹,如何從 Waze 交通事件開放數據中,利用序列模型找到規(guī)律,進行分類預測。以便相關部門可以未雨綢繆,提前有效干預可能發(fā)生的嚴重擁堵。

尋找

之前在《文科生如何理解循環(huán)神經網絡(RNN)?》一文中,我為你講解過循環(huán)神經網絡的含義。《如何用 Python 和循環(huán)神經網絡做中文文本分類?》一文,我又為你介紹了如何用循環(huán)神經網絡對文本做分類。

我不希望給你一種錯誤的簡單關聯,即“循環(huán)神經網絡只能用來處理文本數據”。

事實上,只要是序列數據,你都可以考慮一下循環(huán)神經網絡。

我一直打算找個其他序列數據的樣例,給你展示循環(huán)神經網絡的更多應用場景。

但是這個數據不太好選擇。

目前一個熱門的應用場景,就是金融產品的價格預測。

每時每秒,金融產品的價格都在變動。把它匯集起來,是個典型的序列數據。

但是我一直不看好這種應用。因為金融產品的定價,應該是面向未來的?;跉v史價格信息尋找波動規(guī)律,并對未來價格進行預測,實際上如同看著后視鏡開車一般危險。

但是,還有很多人依然樂此不疲地嘗試。很多時候,他們也能嘗到成功的甜頭。

這是為什么?

原因在于,金融市場的參與者,并非理性的機器,而是由人組成的群體。從行為金融學的角度來看,進化給人類思考與行為帶來了一些“快捷方式”,你可以利用它們從中漁利。

陸蓉教授的《行為金融學》欄目,對此有詳細介紹。

例如,人們追漲殺跌,認為歷史會重演;

例如,吸引大眾關注到事件,總會帶來買入;

例如,人們會傾向于投資于自己熟悉的標的;

例如,人們會購買下跌的已持倉標的,來攤薄成本。

……

如果沒有大風浪,這種對市場參與者行為規(guī)律的洞察,確實可以幫你賺錢。你可以從價格的歷史波動中,挖掘出這些規(guī)律的影響。但是這對沒有模型可用的人來說,不公平。教你建模,就如同教你考試作弊。

如果遇到黑天鵝事件,其影響大概率會超過市場參與者行為偏誤帶來的歷史價格波動規(guī)律。那么你,可能會因為應用模型,而遭遇虧損。你大約不會認為這是自己的錯誤,而直接把我當做騙子,朝我扔雞蛋。

理性權衡后,我決定不用金融產品價格趨勢分析,作為循環(huán)神經網絡的應用樣例。

其他開放的序列數據,當然也有很多。例如共享單車租用數據、氣溫變化數據等。

不過這些應用,一來別人都寫過了,不新鮮。二來,氣溫變化,你看天氣預報就好了。共享單車租用數量……你真的關心這里的規(guī)律嗎?

正在我猶豫的時候,一次偶然的機會,我接觸到了一個新的序列數據樣例——交通事件數據。我覺得,把它作為應用案例分享給你,可能更合適一些。

比賽

拿到這個數據,是因為我參與了一次編程馬拉松(hackathon)比賽。

比賽在 Frisco 的 UNT Inspire Park 舉辦。從早上8點開始,一直到晚上9點多才結束。中間可以自由吃免費提供的點心和水果,也可以到院子里曬曬太陽放放風。大家還可以自由交流和組隊。

主辦方為參賽者提供了若干種開放數據,也提了一些問題供大家參考解答。當然,實際參賽的時候,你也可以自己擬定新的題目。

這其中,就包括了 Waze 數據。

我在中國開車,平時用的都是高德導航,對于 Waze 這款 App 不大熟悉。

簡而言之,這個 Waze 應用除了提供一般的導航功能之外,還有一個類似于眾包的功能——讓司機們自由提交路況信息。

這樣一來,Waze 就利用群體智慧形成了一個眼觀六路耳聽八方的巨大網絡,隨時依據用戶提供的情況,匯總成實時交通參考。并且匯報給用戶,以便于大家調整自己的行車路線。

我覺得最有用的特點是,在堵車的時候,你可以了解到前面究竟發(fā)生了什么。其他導航也有實時交通狀況提示,但是你對前面的情況一無所知。道路半幅施工?交通事故?

信息的對稱,可以在很大程度上,讓司機避免焦慮。

Waze 從幾年前開始,就和政府部門合作,進行數據開放共享。這樣一來,政府可以通過 Waze 的數據了解交通實時狀況,對于問題進行快速的響應處理;與此同時, Waze 用戶也因為可以獲取整合其他相關類型的政府開放數據(例如道路規(guī)劃等),更加有效合理安排出行。

這次比賽,主辦方提供的數據,是 DFW (達拉斯-沃斯堡都會區(qū))區(qū)域,11月1日到29日的 Waze 交通事件(Incidents)開放數據,這是政府開放數據的一部分。這些數據基本都是來自于 Waze 用戶的提交。

原始的數據,接近 300 MB。每一條事件信息,都包含了提交的經緯度,以及時間。因此在探索性數據分析階段,我做了幾個可視化圖形。

這是我當天跟新認識的編程高手 Jesse 學的 QGIS 分析結果。

看看圖上的點,每一個都對應一次事件匯報。這叫一個密密麻麻啊。

因為 QGIS 初學,用得不熟,我還是用 Python 進行了分類繪圖。

這只是前 3000 條數據中部分類型的可視化。其中紅色代表交通擁堵,黃色代表事故發(fā)生,藍色代表有車停在了路肩上。

可以看到,紅色的數據量最大。這說明交通擁堵是個大問題。

我把全部的數據都拿了出來,提煉出包含的事件類型,包括以下這些類:

我看到,其中單是交通阻塞,也是分為若干級別的。其中最嚴重的,分別是“大型交通擁堵”(large traffic jam)和“超大型交通擁堵”(huge traffic jam)。

于是,我把所有這兩種嚴重交通擁堵事件,合并成一個集合;其他剩余事件,作為另一個集合。

對于每一個嚴重擁堵事件,我追溯30分鐘,把之前同一條道路上,發(fā)生的事件,按照順序存成一個列表。這樣的列表,有987個;但是,其中有一些,是驟然發(fā)生的,30分鐘的區(qū)間里面,沒有任何其他事件作為先兆。這樣的空列表,我進行了清除。剩下了861個有效序列。

同樣,從剩余事件集合中,我們隨機找到了861個非空有效序列。這些序列,后續(xù)緊隨事件,都不是嚴重擁堵。

我們對嚴重擁堵之前30分鐘的事件序列,標記為1;對于非嚴重擁堵之前30分鐘的事件序列,標記為0。

于是,我們就把問題轉換成了,能否利用事件序列,進行分類,預測后續(xù)是否會發(fā)生嚴重擁堵。

靠著這個模型,我們團隊(UNT IIA lab代表隊,其實不過就是我和春迎倆人,團隊昵稱 watch-dumpling )在這次比賽中,獲得第一名。

這是 HackNTX 官網的報道(http://t.cn/EUbS9m5) 。

UNT 網站也正式發(fā)布了這則新聞(http://t.cn/EUbS127),于是我周圍盡人皆知。我才剛拿到手的獎金,立即就因為請客被掃蕩一空了。

奪冠純屬是個意外,幸運占得比重很大。但是我覺得我們做的這個模型,還是有些應用價值的。

下面,我就以這組 Waze 交通事件數據,詳細給你講解一下,如何用 Python, Keras 和循環(huán)神經網絡,來實現這個序列數據分類模型。

環(huán)境

要運行深度學習,你需要有 GPU 或者 TPU 的支持,否則會累壞你的筆記本電腦的。Google Colab 是個不錯的實驗平臺,可以讓你免費使用 TPU 來進行深度學習訓練。你可以閱讀《如何免費云端運行Python深度學習框架?》一文,查詢更為詳細的介紹。

這里,請你使用 Chrome 瀏覽器,點擊這個鏈接,安裝一個插件 Colaboratory 。

把它添加到 Google Chrome 之后,你會在瀏覽器的擴展工具欄里面,看見下圖中間的圖標:

然后,請到本范例的github repo 主頁面。

打開其中的demo.ipynb文件。

點擊 Colaboratory 擴展圖標。Google Chrome 會自動幫你開啟 Google Colab,并且裝載這個 ipynb 文件。

點擊上圖中紅色標出的“復制到云端硬盤”按鈕。Google 會為你新建一個屬于你自己的副本。

點擊菜單欄里面的“代碼執(zhí)行程序”,選擇“更改運行時類型”。

在出現的對話框中,確認選項如下圖所示。

點擊“保存”即可。

下面,你就可以依次執(zhí)行每一個代碼段落了。

注意第一次執(zhí)行的時候,可能會有警告提示。

出現上面這個警告的時候,點擊“仍然運行”就可以繼續(xù)了。

如果再次出現警告提示,反勾選“在運行前充值所有代碼執(zhí)行程序”選項,再次點擊“仍然運行”即可。

環(huán)境準備好了,下面我們來一步步運行代碼。

代碼

首先,我們讀入 Pandas 軟件包,以便進行結構化數據的處理。

importpandasaspd

這次還要讀入的一個軟件包,是 Python 中間進行數據存取的利器,叫做 pickle 。

importpickle

它可以把 Python 數據,甚至是許多組數據,一起存儲到指定文件。然后讀出的時候,可以完全恢復原先數據的格式。這一點上,它比用 csv 進行數據存儲和交換的效果更好,效率也更高。

下面我們從本文配套的 github 項目中,把數據傳遞過來。

!gitclonehttps://github.com/wshuyi/demo_traffic_jam_prediction.git

數據的下載,很快就可以完成。

Cloninginto'demo_traffic_jam_prediction'...remote:Enumeratingobjects:6,done.[Kremote:Countingobjects:100%(6/6),done.[Kremote:Compressingobjects:100%(4/4),done.[Kremote:Total6(delta0),reused3(delta0),pack-reused0[KUnpackingobjects:100%(6/6),done.

我們告訴 Jupyter Notebook ,數據文件夾的位置。

frompathlibimportPathdata_dir=Path('demo_traffic_jam_prediction')

打開數據文件,利用 pickle 把兩組數據分別取出。

withopen(data_dir/'data.pickle','rb')asf:[event_dict,df]=pickle.load(f)

先看其中的事件詞典event_dict:

event_dict

以下就是全部的事件類型。

{1:'roadclosedduetoconstruction',2:'trafficjam',3:'stoppedcarontheshoulder',4:'roadclosed',5:'other',6:'objectonroadway',7:'majorevent',8:'pothole',9:'trafficheavierthannormal',10:'roadconstruction',11:'fog',12:'accident',13:'slowdown',14:'stoppedcar',15:'smalltrafficjam',16:'stoppedtraffic',17:'heavytraffic',18:'minoraccident',19:'mediumtrafficjam',20:'malfunctioningtrafficlight',21:'missingsignontheshoulder',22:'animalontheshoulder',23:'animalstruck',24:'largetrafficjam',25:'hazardontheshoulder',26:'hazardonroad',27:'iceonroadway',28:'weatherhazard',29:'flooding',30:'roadclosedduetohazard',31:'hail',32:'hugetrafficjam'}

同樣,我們來看看存儲事件序列的數據框。

先看前10個:

df.head(10)

注意,每一行,都包含了標記。

再看結尾部分:

df.tail(10)

讀取無誤。

下面我們來看看,最長的一個序列,編號是多少。

這里,我們利用的是 Pandas 的一個函數,叫做idxmax(),它可以幫助我們,把最大值對應的索引編號,傳遞回來。

max_len_event_id=df.events.apply(len).idxmax()max_len_event_id

結果為:

105

我們來看看,這個編號對應的事件序列,是什么樣子的:

max_len_event=df.iloc[max_len_event_id]max_len_event.events

下面是長長的反饋結果:

['stoppedcarontheshoulder','heavytraffic','heavytraffic','heavytraffic','slowdown','stoppedtraffic','heavytraffic','heavytraffic','heavytraffic','heavytraffic','trafficheavierthannormal','stoppedcarontheshoulder','trafficjam','heavytraffic','stoppedtraffic','stoppedtraffic','stoppedtraffic','heavytraffic','trafficjam','stoppedcarontheshoulder','stoppedtraffic','stoppedtraffic','stoppedtraffic','heavytraffic','trafficheavierthannormal','trafficheavierthannormal','trafficheavierthannormal','trafficheavierthannormal','heavytraffic','stoppedtraffic','trafficheavierthannormal','pothole','stoppedcarontheshoulder','trafficjam','slowdown','stoppedtraffic','heavytraffic','trafficheavierthannormal','trafficjam','trafficjam','stoppedcarontheshoulder','majorevent','trafficjam','trafficjam','stoppedtraffic','heavytraffic','trafficheavierthannormal','stoppedcarontheshoulder','slowdown','heavytraffic','heavytraffic','stoppedcarontheshoulder','trafficjam','slowdown','slowdown','heavytraffic','stoppedcarontheshoulder','heavytraffic','minoraccident','stoppedcarontheshoulder','heavytraffic','stoppedcarontheshoulder','heavytraffic','stoppedtraffic','heavytraffic','trafficheavierthannormal','heavytraffic','stoppedcarontheshoulder','trafficheavierthannormal','stoppedtraffic','heavytraffic','heavytraffic','heavytraffic','stoppedcarontheshoulder','slowdown','stoppedtraffic','heavytraffic','stoppedcarontheshoulder','trafficheavierthannormal','heavytraffic','minoraccident','majorevent','stoppedcarontheshoulder','stoppedcarontheshoulder']

讀一遍,你就會發(fā)現,在超級擁堵發(fā)生之前,確實還是有一些先兆的。當然,這是由人來閱讀后,獲得的觀感。我們下面需要做的,是讓機器自動把握這些列表的特征,并且做出區(qū)別分類。

我們看看,這個最長列表的長度。

maxlen=len(max_len_event.events)maxlen

結果為:

84

這里的前導事件,還真是不少啊。

下面我們要做的,是把事件轉換成數字編號,這樣后面更容易處理。

我們使用以下的一個小技巧,把原先的事件詞典倒置,即變“序號:事件名稱”,為“事件名稱:序號”。這樣,以事件名稱查詢起來,效率會高很多。

reversed_dict={}fork,vinevent_dict.items():reversed_dict[v]=k

我們看看倒置的結果詞典:

reversed_dict

這是反饋結果:

{'accident':12,'animalontheshoulder':22,'animalstruck':23,'flooding':29,'fog':11,'hail':31,'hazardonroad':26,'hazardontheshoulder':25,'heavytraffic':17,'hugetrafficjam':32,'iceonroadway':27,'largetrafficjam':24,'majorevent':7,'malfunctioningtrafficlight':20,'mediumtrafficjam':19,'minoraccident':18,'missingsignontheshoulder':21,'objectonroadway':6,'other':5,'pothole':8,'roadclosed':4,'roadclosedduetoconstruction':1,'roadclosedduetohazard':30,'roadconstruction':10,'slowdown':13,'smalltrafficjam':15,'stoppedcar':14,'stoppedcarontheshoulder':3,'stoppedtraffic':16,'trafficheavierthannormal':9,'trafficjam':2,'weatherhazard':28}

成功了。

下面我們編寫一個函數,輸入一個事件列表,返回對應的事件編號列表。

defmap_event_list_to_idxs(event_list):list_idxs=[]foreventin(event_list):idx=reversed_dict[event]list_idxs.append(idx)returnlist_idxs

然后,我們在剛才是找到的最長列表上,實驗一下:

map_event_list_to_idxs(max_len_event.events)

結果是這樣的:

[3,17,17,17,13,16,17,17,17,17,9,3,2,17,16,16,16,17,2,3,16,16,16,17,9,9,9,9,17,16,9,8,3,2,13,16,17,9,2,2,3,7,2,2,16,17,9,3,13,17,17,3,2,13,13,17,3,17,18,3,17,3,17,16,17,9,17,3,9,16,17,17,17,3,13,16,17,3,9,17,18,7,3,3]

看來功能實現上,沒問題。

讀入 numpy 和 Keras 的一些工具。

importnumpyasnpfromkeras.utilsimportto_categoricalfromkeras.preprocessing.sequenceimportpad_sequences

系統(tǒng)自動提示我們,Keras 使用了 Tensorflow 作為后端框架。

UsingTensorFlowbackend.

我們需要弄清楚,一共有多少種事件類型。

len(event_dict)

結果是:

32

因此,我們需要對32種不同的事件類型,進行轉換和處理。

我們把整個數據集里面的事件類型,都變成事件編號。

df.events.apply(map_event_list_to_idxs)

結果如下:

0[9,17,18,14,13,17,3,13,16,3,17,17,...1[2,10,3]2[2]3[2]4[2,2,2,2,2,2,2,9]5[3,2,17]6[3,2,17]7[2,15,2,17,2,2,13,17,2]8[17,2,2,16,17,2]9[17,2,2,16,17,2]10[17,16,17,2,17,3,17,17,16,17,16,18,...11[17]12[17]13[24,24]14[24,2,24,24,2]15[24,2,24,24,2]16[2,10,2,2,2,18,16,16,7,2,16,2,2,9...17[2,10,2,2,2,18,16,16,7,2,16,2,2,9...18[24,24,24,16,2,16]19[24,24,24,16,2,16]20[2,2]21[2,16,2]22[2,16,2]23[2,2]24[2,2]25[24,24]26[2,2]27[2,2,2,17]28[2,19,2]29[24]...831[9,9,9,2,9,9,17,2,9,17]832[3,3,3]833[2,9,2,17,17,2]834[3,3,17,3,13,3,3,23,9,3,3,25,3,3]835[3,17,9,14,9,17,14,9,2,9,3,2,2,17]836[2]837[17,2,16,3,9,17,17,17,13,17,9,17]838[13,17,17,3,3,16,17,16,17,16,3,9,1...839[2]840[3]841[2]842[17,17,17,3,17,23,16,17,17,3,2,13,...843[3,3]844[2]845[2,17,2,2,2,2,2,17,2,2]846[7,17,3,18,17]847[3,3,3]848[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,...849[2,2]850[2,2,2,2,2,2,2,2,2,2,2,13,3,2]851[2,2,2]852[16,2,16]853[3,16,5,3,17,3,16,9,3,2,17]854[16]855[3,3,3,3,3,3,3,3,2,13,3,6,3,6,3,...856[17,17,17,2,3,2,2,2,2,2]857[2,2]858[2,2,9,17,2,2]859[17,3,2,2,2,2,2,2]860[17,3,3,17,3,17,2,3,18,14,3,3,16,...Name:events,Length:1722,dtype:object

現在,作為人類,我們確實是看不清楚,列表里面的事件都是什么了。好在計算機對于數字,更加喜聞樂見。

我們把該列表,起名為 sequences ,并且顯示前5項內容。

sequences=df.events.apply(map_event_list_to_idxs).tolist()sequences[:5]

下面是結果:

[[9,17,18,14,13,17,3,13,16,3,17,17,16,3,16,17,9,17,2,17,2,7,16,17,17,17,17,13,5,17,9,9,16,16,3],[2,10,3],[2],[2],[2,2,2,2,2,2,2,9]]

注意,第一行,明顯比后幾行都要長。

對于輸入序列,我們希望它的長度都是一樣的。因此,下面我們就用最長的序列長度作為標準,用 0 來填充其他短序列。

data=pad_sequences(sequences,maxlen=maxlen)data

這是結果:

array([[0,0,0,...,16,16,3],[0,0,0,...,2,10,3],[0,0,0,...,0,0,2],...,[0,0,0,...,17,2,2],[0,0,0,...,2,2,2],[0,0,0,...,3,3,2]],dtype=int32)

注意,所有的0,都補充到了序列的最前端。序列都一樣長了。

下面,我們把全部的分類標記,存儲到 labels 變量里面。

labels=np.array(df.label)

后面,我們有好幾個函數,需要用到隨機變量。

為了咱們運行結果的一致性。我這里指定隨機種子數值。你第一次嘗試運行的時候,不要動它。但是后面自己動手操作的時候,可以任意修改它。

np.random.seed(12)

好了,下面我們“洗牌”。打亂數據的順序,但是注意序列和對應標記之間,要保持一致性。

indices=np.arange(data.shape[0])np.random.shuffle(indices)data=data[indices]labels=labels[indices]

然后,我們取 80% 的數據,作為訓練;另外 20% 的數據,作為驗證。

training_samples=int(len(indices)*.8)validation_samples=len(indices)-training_samples

我們正式劃分訓練集和驗證集。

X_train=data[:training_samples]y_train=labels[:training_samples]X_valid=data[training_samples:training_samples+validation_samples]y_valid=labels[training_samples:training_samples+validation_samples]

看看訓練集的內容。

X_train

結果為:

array([[0,0,0,...,15,15,3],[0,0,0,...,0,2,2],[0,0,0,...,0,0,16],...,[0,0,0,...,2,15,16],[0,0,0,...,2,2,2],[0,0,0,...,0,0,2]],dtype=int32)

注意由于我們補充了“0”,作為填充,因此原先的32種事件類型的基礎上,又加了一種。

這就是我們新的事件類型數量:

num_events=len(event_dict)+1

我們使用嵌入層,把事件標號,轉換成一系列數字組成的向量。這樣,可以避免模型把事件序號,當成數值型數據來處理。

這里,我們指定每一個標號,轉換成 20 個數字組成的向量。

embedding_dim=20

利用事件類型數量,和事件向量長度,我們隨機構造初始的嵌入矩陣。

embedding_matrix=np.random.rand(num_events,embedding_dim)

下面我們搭建一個循環(huán)神經網絡模型。其中的 LSTM 層,包含了32位輸出數字。

fromkeras.modelsimportSequentialfromkeras.layersimportEmbedding,Flatten,Dense,LSTMunits=32model=Sequential()model.add(Embedding(num_events,embedding_dim))model.add(LSTM(units))model.add(Dense(1,activation='sigmoid'))

這里,我假設你已經看過了《如何用 Python 和循環(huán)神經網絡做中文文本分類?》一文,所以就不對細節(jié)進行講述了。如果你沒有看過,或者已經遺忘,可以點擊這個鏈接復習一下。

如果你對 Keras 的使用方法還不熟悉,我再次向你推薦 Fran?ois Chollet 的《Deep Learning with Python》。

下面,是處理其中的嵌入層參數。我們直接把剛才隨機生成的嵌入矩陣挪進來。而且,不讓模型在訓練中對嵌入層參數進行修改。

model.layers[0].set_weights([embedding_matrix])model.layers[0].trainable=False

下面,我們開始訓練。并且把模型運行結果保存起來。

model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['acc'])history=model.fit(X_train,y_train,epochs=50,batch_size=32,validation_data=(X_valid,y_valid))model.save("mymodel_embedding_untrainable.h5")

可以看到,因為有 TPU 的強力支持,程序在歡快地運行中。

訓練過程結束之后,我們利用 matplotlib 繪圖功能,看一下訓練中,準確率和損失值的變化。

importmatplotlib.pyplotaspltacc=history.history['acc']val_acc=history.history['val_acc']loss=history.history['loss']val_loss=history.history['val_loss']epochs=range(1,len(acc)+1)plt.plot(epochs,acc,'bo',label='Trainingacc')plt.plot(epochs,val_acc,'b',label='Validationacc')plt.title('Trainingandvalidationaccuracy')plt.legend()plt.figure()plt.plot(epochs,loss,'bo',label='Trainingloss')plt.plot(epochs,val_loss,'b',label='Validationloss')plt.title('Trainingandvalidationloss')plt.legend()plt.show()

這是準確率變化曲線。

可以看到,效果還是不錯的。因為我們數據中,不同標記各占一半。因此如果構建一個 dummy model 作為標準線的話,對所有的輸入都猜測0或者1,準確率應該只有50%。

這里的準確率,已經達到了65%-75%之間,證明我們的模型是有意義的。只不過,抖動比較厲害,穩(wěn)定性差。

這是損失值變化曲線。

這個圖看起來,就不是很美妙了。因為雖然訓練集上面的損失值一路下降,但是驗證集上,這個效果并不是很明顯,一直劇烈波動。

看到結果,不是最重要的。關鍵是我們得分析出目前遇到問題,原因是什么。

注意我們前面使用了嵌入矩陣。它隨機生成,卻又沒有真正進行訓練調整,這可能是個問題。

因此,我們這里再次構建和跑一下模型。唯一改動的地方,在于讓嵌入矩陣的參數也可以隨著訓練進行自動調整。

fromkeras.modelsimportSequentialfromkeras.layersimportEmbedding,Flatten,Dense,LSTMunits=32model=Sequential()model.add(Embedding(num_events,embedding_dim))model.add(LSTM(units))model.add(Dense(1,activation='sigmoid'))

注意這里的差別,就是trainable設置為真值。

model.layers[0].set_weights([embedding_matrix])model.layers[0].trainable=True

構建模型,再次運行。

model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['acc'])history=model.fit(X_train,y_train,epochs=50,batch_size=32,validation_data=(X_valid,y_valid))model.save("mymodel_embedding_trainable.h5")

繪圖看看。

importmatplotlib.pyplotaspltacc=history.history['acc']val_acc=history.history['val_acc']loss=history.history['loss']val_loss=history.history['val_loss']epochs=range(1,len(acc)+1)plt.plot(epochs,acc,'bo',label='Trainingacc')plt.plot(epochs,val_acc,'b',label='Validationacc')plt.title('Trainingandvalidationaccuracy')plt.legend()plt.figure()plt.plot(epochs,loss,'bo',label='Trainingloss')plt.plot(epochs,val_loss,'b',label='Validationloss')plt.title('Trainingandvalidationloss')plt.legend()plt.show()

這次的準確率曲線,看起來好多了。驗證集波動沒有這么劇烈,模型穩(wěn)定性好了許多。而且,準確率的取值,也獲得了提升。后半程穩(wěn)定在了75%以上。這樣的模型,就有應用價值了。

但是我們看看損失值曲線,可能就不這么樂觀了。

注意從半程之后,訓練集和驗證集的損失值變化,就發(fā)生了分叉。

這是典型的過擬合(over-fitting)。

發(fā)生過擬合,主要原因就是相對于復雜的模型,訓練數據不夠用。

這時候,要么增加訓練數據,要么降低模型復雜度。

立即增加數據,不太現實。因為我們手中,目前只有那29天里積攢的數據。但是降低模型復雜度,是可以利用 Dropout 來嘗試完成的。

Dropout 的實現機理,是在訓練的時候,每次隨機把一定比例的模型中神經元對應權重參數,設置為0,讓它不起作用。這樣,模型的復雜度,就會降低。

下面,我們輕微修改一下,在 LSTM 層上,加入dropout=0.2, recurrent_dropout=0.2這兩個參數。

fromkeras.modelsimportSequentialfromkeras.layersimportEmbedding,Flatten,Dense,LSTMunits=32model=Sequential()model.add(Embedding(num_events,embedding_dim))model.add(LSTM(units,dropout=0.2,recurrent_dropout=0.2))model.add(Dense(1,activation='sigmoid'))

依然保持嵌入層可以被訓練。

model.layers[0].set_weights([embedding_matrix])model.layers[0].trainable=True

再次運行。

model.compile(optimizer='rmsprop',loss='binary_crossentropy',metrics=['acc'])history=model.fit(X_train,y_train,epochs=50,batch_size=32,validation_data=(X_valid,y_valid))model.save("mymodel_embedding_trainable_with_dropout.h5")

繪制圖形的函數跟之前兩次完全一致。

importmatplotlib.pyplotaspltacc=history.history['acc']val_acc=history.history['val_acc']loss=history.history['loss']val_loss=history.history['val_loss']epochs=range(1,len(acc)+1)plt.plot(epochs,acc,'bo',label='Trainingacc')plt.plot(epochs,val_acc,'b',label='Validationacc')plt.title('Trainingandvalidationaccuracy')plt.legend()plt.figure()plt.plot(epochs,loss,'bo',label='Trainingloss')plt.plot(epochs,val_loss,'b',label='Validationloss')plt.title('Trainingandvalidationloss')plt.legend()plt.show()

這次的準確率曲線,看起來達到的數值,跟沒有加入 Dropout 的差不多。

然而,我們可以感受到訓練集和驗證集達到的準確率更加貼近。曲線更加平滑。

下面我們看看損失值曲線的變化。

這個曲線上,過擬合的去除效果就更為明顯了??梢钥吹接柧毤万炞C集兩條曲線的波動基本保持了一致。這樣我們更可以確信,模型預測能力是穩(wěn)定的,對外界新的輸入信息,適應性更好。

如果把咱們的模型放在交通管理部門那里,可以期望它根據 Waze 獲得的新序列數據,能以大約 75% 的準確率,預測嚴重交通擁堵的發(fā)生。這樣,交管部門就可以未雨綢繆,提前做出干預了。

用序列模型,欺負金融市場的散戶,屬于零和博弈。然而這種在交通管理上的應用,大概更能造福社會,體現科技的價值吧。

小結

通過本文的學習和實際上手操作,希望你已了解了以下知識點:

不只是文本,其他序列數據,也可以利用循環(huán)神經網絡來進行分類預測。

對定類數據(categorical data)進行嵌入表示,如果用隨機數初始,那么在建模過程中把嵌入層一起訓練,效果會更好。

數據量不夠的情況下,深度學習很可能會發(fā)生過擬合。使用 Dropout ,可以降低過擬合的影響,讓模型具有更好的穩(wěn)定性和可擴展性。

希望這篇文章,可以幫助你了解循環(huán)神經網絡的更多應用場景。在實際的工作和學習中,靈活運用它來處理序列數據的分類等任務。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯系本站處理。 舉報投訴
  • 神經網絡
    +關注

    關注

    42

    文章

    4814

    瀏覽量

    103648
  • 數據
    +關注

    關注

    8

    文章

    7256

    瀏覽量

    91894
  • python
    +關注

    關注

    56

    文章

    4827

    瀏覽量

    86773

原文標題:如何用Python和循環(huán)神經網絡預測嚴重交通擁堵?

文章出處:【微信號:rgznai100,微信公眾號:rgznai100】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    有提供編寫神經網絡預測程序服務的嗎?

    有提供編寫神經網絡預測程序服務的嗎?
    發(fā)表于 12-10 13:50

    用matlab編程進行BP神經網絡預測時如何確定最合適的,BP模型

    請問用matlab編程進行BP神經網絡預測時,訓練結果很多都是合適的,但如何確定最合適的?且如何用最合適的BP模型進行外推預測?
    發(fā)表于 02-08 14:19

    關于BP神經網絡預測模型的確定!!

    請問用matlab編程進行BP神經網絡預測時,訓練結果很多都是合適的,但如何確定最合適的?且如何用最合適的BP模型進行外推預測?
    發(fā)表于 02-08 14:23

    如何構建神經網絡?

    原文鏈接:http://tecdat.cn/?p=5725 神經網絡是一種基于現有數據創(chuàng)建預測的計算系統(tǒng)。如何構建神經網絡?神經網絡包括:輸入層:根據現有數據獲取輸入的層隱藏層:使用反
    發(fā)表于 07-12 08:02

    GABP神經網絡交通預測中的應用研究

    交通流的預測是智能交通系統(tǒng)的重要技術之一,傳統(tǒng)的神經網絡預測方法存在對初始網絡權值設置敏感、易陷
    發(fā)表于 02-23 14:20 ?22次下載

    改進人工蜂群算法優(yōu)化RBF神經網絡的短時交通預測模型

    為了提高徑向基函數RBF神經網絡預測模型對短時交通流的預測準確性,提出了一種基于改進人工蜂群算法優(yōu)化RBF神經網絡的短時
    發(fā)表于 12-01 16:31 ?2次下載
    改進人工蜂群算法優(yōu)化RBF<b class='flag-5'>神經網絡</b>的短時<b class='flag-5'>交通</b>流<b class='flag-5'>預測</b>模型

    結合小波變換的LSTM循環(huán)神經網絡的稅收預測

    分析歷史稅收數據之間的隱藏關系,利用數學模型來預測未來的稅收收入是稅收預測的研究重點。在此,提出了一種結合小波變換的長短期記憶(LSTM循環(huán)神經網絡的稅收
    發(fā)表于 04-28 11:26 ?10次下載
    結合小波變換的LSTM<b class='flag-5'>循環(huán)</b><b class='flag-5'>神經網絡</b>的稅收<b class='flag-5'>預測</b>

    卷積神經網絡python代碼

    的卷積操作,將不同層次的特征進行提取,從而通過反向傳播算法不斷優(yōu)化網絡權重,最終實現分類和預測等任務。 在本文中,我們將介紹如何使用Python實現卷積神經網絡,并詳細說明每一個步驟及
    的頭像 發(fā)表于 08-21 16:41 ?1317次閱讀

    如何使用神經網絡進行建模和預測

    神經網絡是一種強大的機器學習技術,可以用于建模和預測變量之間的關系。 神經網絡的基本概念 神經網絡是一種受人腦啟發(fā)的計算模型,由大量的節(jié)點(神經
    的頭像 發(fā)表于 07-03 10:23 ?1374次閱讀

    循環(huán)神經網絡和卷積神經網絡的區(qū)別

    循環(huán)神經網絡(Recurrent Neural Network,RNN)和卷積神經網絡(Convolutional Neural Network,CNN)是深度學習領域中兩種非常重要的神經網絡
    的頭像 發(fā)表于 07-04 14:24 ?2119次閱讀

    循環(huán)神經網絡的基本概念

    循環(huán)神經網絡(Recurrent Neural Network,簡稱RNN)是一種具有循環(huán)結構的神經網絡,其核心思想是將前一個時間步的輸出作為下一個時間步的輸入,從而實現對序列數據的建
    的頭像 發(fā)表于 07-04 14:31 ?1320次閱讀

    循環(huán)神經網絡算法原理及特點

    循環(huán)神經網絡(Recurrent Neural Network,簡稱RNN)是一種具有記憶功能的神經網絡,能夠處理序列數據。與傳統(tǒng)的前饋神經網絡(Feedforward Neural
    的頭像 發(fā)表于 07-04 14:49 ?1374次閱讀

    遞歸神經網絡循環(huán)神經網絡

    遞歸神經網絡(Recurrent Neural Network,簡稱RNN)和循環(huán)神經網絡(Recurrent Neural Network,簡稱RNN)實際上是同一個概念,只是不同的翻譯方式
    的頭像 發(fā)表于 07-04 14:54 ?1547次閱讀

    rnn是遞歸神經網絡還是循環(huán)神經網絡

    RNN(Recurrent Neural Network)是循環(huán)神經網絡,而非遞歸神經網絡循環(huán)神經網絡是一種具有時間序列特性的
    的頭像 發(fā)表于 07-05 09:52 ?1043次閱讀

    python做bp神經網絡預測數據

    介紹如何使用Python實現BP神經網絡進行數據預測。 1. 神經網絡基礎 1.1 神經元模型 神經
    的頭像 發(fā)表于 07-11 10:54 ?1878次閱讀