交通事故等级预测(附代码)
? ? ? ?博主最近做了高速公路交通事故等級(jí)預(yù)測的項(xiàng)目,使用的數(shù)據(jù)集為英國高速公路2019年事故數(shù)據(jù)集。本來博主是用它來寫論文的,但最近論文方向發(fā)生改變,因此將項(xiàng)目分享出來,給大家參考,如果有人做的是事故發(fā)生預(yù)測,也可以參考一下,具體方法不會(huì)差,只是數(shù)據(jù)標(biāo)簽變一下。由于水平有限,不足之處請(qǐng)見諒。
一、數(shù)據(jù)收集與處理
? ? ? ?博主找過很多數(shù)據(jù),最終采用的是英國高速公路2019年事故數(shù)據(jù),在很多論文里也看到有人使用美國高速公路數(shù)據(jù),這里推薦大家在csdn上搜一搜,能夠搜到,也推薦大家一個(gè)公眾號(hào)“交通邦”,一個(gè)東南學(xué)長創(chuàng)的,數(shù)據(jù)比較全,不過英國數(shù)據(jù)集是2018年的,如果有人需要2019年數(shù)據(jù)可以和博主聯(lián)系,但是由于博主收集辛苦,可能需要點(diǎn)費(fèi)用,后面也會(huì)將數(shù)據(jù)壓縮包放到csdn里,關(guān)注博主后可以找到發(fā)布的下載鏈接,數(shù)據(jù)內(nèi)容具體如圖:
? ? ? ?上圖可以看出,數(shù)據(jù)集里面的內(nèi)容很全,有事故等級(jí)、天氣、路面條件、燈光等等。對(duì)每個(gè)數(shù)據(jù)還會(huì)有專門的標(biāo)注,大家下載之后就能看出。同時(shí),做事故等級(jí)預(yù)測需要用到交通流數(shù)據(jù),我這里也是根據(jù)位置在英國的觀測點(diǎn)地圖上一個(gè)個(gè)手工定位,花了好幾天時(shí)間,也會(huì)保存到壓縮包里發(fā)送給有需要的同學(xué),具體也可看圖:
? ? ? ?上圖是一處事故發(fā)生點(diǎn)的上游數(shù)據(jù),做這方面論文研究的都知道,事故預(yù)測是需要用到事故上下游數(shù)據(jù)的,工作量很大。這已經(jīng)完成了初步論文處理,緊接著就是對(duì)數(shù)據(jù)進(jìn)行繁瑣的清楚異常值、篩選變量等等操作,統(tǒng)稱為數(shù)據(jù)清洗。這里的程序雖然簡單,但是內(nèi)容繁雜,就不將代碼粘貼上來了。
二、參數(shù)排序
? ? ? ?我們將數(shù)據(jù)清洗完成之后,就需要面臨一個(gè)問題,選擇哪些參數(shù)來建立預(yù)測模型。從之前的數(shù)據(jù)圖中也可以看到,可選數(shù)據(jù)太多,這不是一個(gè)好現(xiàn)象,會(huì)造成算法的崩潰。因此,我在這里選擇用隨機(jī)森林對(duì)各數(shù)據(jù)的重要度進(jìn)行排序,代碼如下所示:
import numpy as np import pandas as pdtestset=pd.read_csv("C:\\Users\\15217\\Desktop\\病例組.csv") #print(testset.head(5))#可以試運(yùn)行,查看運(yùn)行結(jié)果"""進(jìn)行數(shù)據(jù)集導(dǎo)入""" dataset=testset #將不需要進(jìn)行排序的路面條件提取出來 dataset.target=testset['Road_Surface_Conditions'] dataset.target.head(287) #將不需要進(jìn)行排序的列刪除 del_key = ['Location_Easting_OSGR','Location_Northing_OSGR','Longitude','Latitude','Accident_Severity','Number_of_Vehicles','Number_of_Casualties','Date','Time','1st_Road_Class','1st_Road_Number','Speed_limit','2nd_Road_Class','2nd_Road_Number','Urban_or_Rural_Area','Vehicle_Reference','Casualty_Reference','Casualty_Class','Casualty_Severity','Car_Passenger','Bus_or_Coach_Passenger','Casualty_Type','上游線圈平均交通量','上游線圈平均速度','上游線圈平均時(shí)間占有率','下游線圈平均交通量(輛/30s)','下游線圈平均速度(km/h)','下游線圈平均時(shí)間占有率','Location_Northing_OSGR.1'] for key in del_key:testset.drop(columns=[key],inplace=True)#剩余需要排序的特征 dataset.feature_names=testset.columns dataset.data=testset[['Road_Type', 'Junction_Detail', 'Junction_Control', 'Light_Conditions','Weather_Conditions', 'Road_Surface_Conditions','Special_Conditions_at_Site', 'Sex_of_Casualty', 'Age_of_Casualty','Age_Band_of_Casualty', 'Vehicle_Reference.1', 'Vehicle_Type','Towing_and_Articulation', 'Vehicle_Manoeuvre','Vehicle_Location-Restricted_Lane', 'Junction_Location','Skidding_and_Overturning', 'Was_Vehicle_Left_Hand_Drive?','Journey_Purpose_of_Driver', 'Sex_of_Driver', 'Age_of_Driver','Age_Band_of_Driver', 'Engine_Capacity_(CC)', 'Age_of_Vehicle','Unnamed: 47', '上下游交通量差的絕對(duì)值', '上下游平均速度差的絕對(duì)值', '上下游平均時(shí)間占有率差的絕對(duì)值']]# 用0來代替缺失值 dataset.data = dataset.data.replace(np.nan, 0) #print(np.isnan(dataset.data).any())"""處理初始的數(shù)據(jù)集得到的data、target和feature_names""" print(dataset.data.shape) X=dataset.data print(X.shape) Y=dataset.target names=dataset.feature_names #利用sklearn這個(gè)包中的隨機(jī)森林對(duì)特征進(jìn)行排序 from sklearn.ensemble import RandomForestClassifier rf=RandomForestClassifier() rf.fit(X,Y) print("Features sorted by their score:") print(sorted(zip(map(lambda x:round(x,4),rf.feature_importances_),names)))"""繪制比重圖""" per_data = sorted(zip(map(lambda x:round(x,4),rf.feature_importances_),names)) #print(per_data[0][0],per_data[27][0])#總共28個(gè)特征值 # -*- coding: utf-8 -*- import matplotlib.pyplot as plt name_list = []#特征值名稱 per_list = []#可用來存放百分比 for i in range(1,28):name_list.append(per_data[i][1])#從1開始,是為了去掉無用的Unnamed,下同 for j in range(1,28):per_list.append(per_data[j][0]) plt.rcParams['font.sans-serif'] = ['SimHei'] #顯示中文標(biāo)簽 plt.rcParams['axes.unicode_minus'] = False plt.yticks(fontsize=5) plt.barh(range(len(per_list)), per_list,tick_label = name_list)#名字太長,放不進(jìn)去 plt.show()代碼運(yùn)行后,會(huì)產(chǎn)生一個(gè)重要度排序圖:
?
? ? ? ?這里需要選擇事故發(fā)生前可獲得的影響因素為:路面條件、天氣狀況、光照條件、上下游交通量差的絕對(duì)值、上下游平均速度差的絕對(duì)值、上下游時(shí)間占有率差的絕對(duì)值。?
三、建立模型
? ? ? ?參數(shù)選擇完成之后,就需要建立相應(yīng)的預(yù)測模型,由于事故等級(jí)一般分為輕度、嚴(yán)重、致命三種類型,選擇機(jī)器學(xué)習(xí)中的SVM建立模型。同時(shí),在建立模型之后,選擇網(wǎng)格搜索優(yōu)化參數(shù)來對(duì)g和C進(jìn)行調(diào)參,得到預(yù)測精度最高的模型。相關(guān)代碼如下:
from sklearn import svm from sklearn.svm import SVC import sklearn import matplotlib.pyplot as plt import matplotlib import numpy as np from numpy import loadtxt import pandas as pd import csv from sklearn import preprocessing from sklearn.model_selection import cross_val_score from mpl_toolkits.mplot3d import Axes3D from sklearn.model_selection import GridSearchCV """讀取樣本""" #define converts(字典) def Iris_label(s):it={b'\\ufeff2':2 }return it[s]#data=np.array(rows)#rows是數(shù)據(jù)類型是‘list',轉(zhuǎn)化為數(shù)組類型好處理 path = 'C:\\Users\\15217\\Desktop\\SVM樣本.csv' data=np.loadtxt(path, dtype=float, delimiter=',',encoding='utf-8-sig') #print("out0=",type(data),data.shape) #print("out1=",data)"""劃分?jǐn)?shù)據(jù)與標(biāo)簽""" y,x=np.split(data,indices_or_sections=(1,),axis=1) #x為數(shù)據(jù),y為標(biāo)簽,axis是分割的方向,1表示橫向,0表示縱向,默認(rèn)為0 x=x[:,0:6]#為便于后邊畫圖顯示(二維顯示),只選取前兩維度。若不用畫圖,可選取前六列x[:,0:6]"""使用SMOTE算法""" y_1 = y[:,0] from collections import Counter print(Counter(y_1)) # 使用imlbearn庫中上采樣方法中的SMOTE接口 from imblearn.over_sampling import SMOTE # 定義SMOTE模型,random_state相當(dāng)于隨機(jī)數(shù)種子的作用 smo = SMOTE(random_state=50) X = x.astype('float64') X_smo, y_smo = smo.fit_resample(X, y_1) print(Counter(y_smo)) print(X_smo) print(type(X_smo))train_data,test_data,train_label,test_label =sklearn.model_selection.train_test_split(X_smo,y_smo,random_state=1,#作用是通過隨機(jī)數(shù)來隨機(jī)取得一定量得樣本作為訓(xùn)練樣本和測試樣本train_size=0.7,test_size=0.3)"""網(wǎng)格搜索優(yōu)化參數(shù)""" results = [] for i in (-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5):C = 2 ** ifor j in (-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5):G = 2 ** j"""訓(xùn)練svm分類器"""classifier=svm.SVC(C=C,kernel='rbf',gamma=G,decision_function_shape='ovr') # ovr:一對(duì)多策略classifier.fit(train_data,train_label.ravel()) #ravel函數(shù)在降維時(shí)默認(rèn)是行序優(yōu)先"""計(jì)算分類準(zhǔn)確率"""#print("訓(xùn)練集:",classifier.score(train_data,train_label))#print("測試集:",classifier.score(test_data,test_label))results.append(classifier.score(test_data,test_label))if classifier.score(test_data,test_label) == 0.8308457711442786:tra_label = classifier.predict(train_data) # 訓(xùn)練集的預(yù)測標(biāo)簽tes_label = classifier.predict(test_data) # 測試集的預(yù)測標(biāo)簽print("訓(xùn)練集:",classifier.score(train_data,train_label))print("測試集:", classifier.score(test_data, test_label))print("C=",C)print("G=", G) results_new = list(set(results)) results1=sorted(results_new,reverse=True) for i in results1:print(i)模型建立完成之后,需要一個(gè)混淆矩陣來顯示預(yù)測結(jié)果,而不是單純寫個(gè)精度。
"""輸出混淆矩陣""" from sklearn.metrics import confusion_matrix def my_confusion_matrix(y_true, y_pred):labels = list(set(y_true))conf_mat = confusion_matrix(list(y_true), list(y_pred), labels = labels)print ("confusion_matrix(left labels: y_true, up labels: y_pred):")print ("labels"," ",end='')for i in range(len(labels)):print (labels[i]," ",end='')print('\n')for i in range(len(conf_mat)):print (i+1," ",end='')for j in range(len(conf_mat[i])):print (conf_mat[i][j]," ",end='')print('\n')y_test = list(map(float,test_label)) y_pred = list(map(float,classifier.predict(test_data))) print(y_test) print(y_pred) my_confusion_matrix(y_test, y_pred) # 輸出混淆矩陣輸出的結(jié)果如下:
? ? ? ?可以看到預(yù)測精度還是不理想,初步推測誤差來源于數(shù)據(jù)樣本中不同事故等級(jí)與其它數(shù)據(jù)關(guān)聯(lián)不明顯,程序難以識(shí)別,這也是我下一個(gè)優(yōu)化方向,但因?yàn)閾Q研究方向了,也就沒法繼續(xù)學(xué)術(shù)探討了,如果有人感興趣,可以繼續(xù)做。
?看在博主這么真誠分享的份上,給個(gè)點(diǎn)贊關(guān)注吧!
?
目錄
一、數(shù)據(jù)收集與處理
二、參數(shù)排序
三、建立模型
?
總結(jié)
以上是生活随笔為你收集整理的交通事故等级预测(附代码)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 精益生产浪费有哪些?如何减少消除精益生产
- 下一篇: 动态控制表格表头显隐,让表格变得更加智能