交通事故等级预测(附代码)
? ? ? ?博主最近做了高速公路交通事故等級預測的項目,使用的數據集為英國高速公路2019年事故數據集。本來博主是用它來寫論文的,但最近論文方向發生改變,因此將項目分享出來,給大家參考,如果有人做的是事故發生預測,也可以參考一下,具體方法不會差,只是數據標簽變一下。由于水平有限,不足之處請見諒。
一、數據收集與處理
? ? ? ?博主找過很多數據,最終采用的是英國高速公路2019年事故數據,在很多論文里也看到有人使用美國高速公路數據,這里推薦大家在csdn上搜一搜,能夠搜到,也推薦大家一個公眾號“交通邦”,一個東南學長創的,數據比較全,不過英國數據集是2018年的,如果有人需要2019年數據可以和博主聯系,但是由于博主收集辛苦,可能需要點費用,后面也會將數據壓縮包放到csdn里,關注博主后可以找到發布的下載鏈接,數據內容具體如圖:
? ? ? ?上圖可以看出,數據集里面的內容很全,有事故等級、天氣、路面條件、燈光等等。對每個數據還會有專門的標注,大家下載之后就能看出。同時,做事故等級預測需要用到交通流數據,我這里也是根據位置在英國的觀測點地圖上一個個手工定位,花了好幾天時間,也會保存到壓縮包里發送給有需要的同學,具體也可看圖:
? ? ? ?上圖是一處事故發生點的上游數據,做這方面論文研究的都知道,事故預測是需要用到事故上下游數據的,工作量很大。這已經完成了初步論文處理,緊接著就是對數據進行繁瑣的清楚異常值、篩選變量等等操作,統稱為數據清洗。這里的程序雖然簡單,但是內容繁雜,就不將代碼粘貼上來了。
二、參數排序
? ? ? ?我們將數據清洗完成之后,就需要面臨一個問題,選擇哪些參數來建立預測模型。從之前的數據圖中也可以看到,可選數據太多,這不是一個好現象,會造成算法的崩潰。因此,我在這里選擇用隨機森林對各數據的重要度進行排序,代碼如下所示:
import numpy as np import pandas as pdtestset=pd.read_csv("C:\\Users\\15217\\Desktop\\病例組.csv") #print(testset.head(5))#可以試運行,查看運行結果"""進行數據集導入""" dataset=testset #將不需要進行排序的路面條件提取出來 dataset.target=testset['Road_Surface_Conditions'] dataset.target.head(287) #將不需要進行排序的列刪除 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','上游線圈平均交通量','上游線圈平均速度','上游線圈平均時間占有率','下游線圈平均交通量(輛/30s)','下游線圈平均速度(km/h)','下游線圈平均時間占有率','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', '上下游交通量差的絕對值', '上下游平均速度差的絕對值', '上下游平均時間占有率差的絕對值']]# 用0來代替缺失值 dataset.data = dataset.data.replace(np.nan, 0) #print(np.isnan(dataset.data).any())"""處理初始的數據集得到的data、target和feature_names""" print(dataset.data.shape) X=dataset.data print(X.shape) Y=dataset.target names=dataset.feature_names #利用sklearn這個包中的隨機森林對特征進行排序 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個特征值 # -*- 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'] #顯示中文標簽 plt.rcParams['axes.unicode_minus'] = False plt.yticks(fontsize=5) plt.barh(range(len(per_list)), per_list,tick_label = name_list)#名字太長,放不進去 plt.show()代碼運行后,會產生一個重要度排序圖:
?
? ? ? ?這里需要選擇事故發生前可獲得的影響因素為:路面條件、天氣狀況、光照條件、上下游交通量差的絕對值、上下游平均速度差的絕對值、上下游時間占有率差的絕對值。?
三、建立模型
? ? ? ?參數選擇完成之后,就需要建立相應的預測模型,由于事故等級一般分為輕度、嚴重、致命三種類型,選擇機器學習中的SVM建立模型。同時,在建立模型之后,選擇網格搜索優化參數來對g和C進行調參,得到預測精度最高的模型。相關代碼如下:
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是數據類型是‘list',轉化為數組類型好處理 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)"""劃分數據與標簽""" y,x=np.split(data,indices_or_sections=(1,),axis=1) #x為數據,y為標簽,axis是分割的方向,1表示橫向,0表示縱向,默認為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相當于隨機數種子的作用 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,#作用是通過隨機數來隨機取得一定量得樣本作為訓練樣本和測試樣本train_size=0.7,test_size=0.3)"""網格搜索優化參數""" 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"""訓練svm分類器"""classifier=svm.SVC(C=C,kernel='rbf',gamma=G,decision_function_shape='ovr') # ovr:一對多策略classifier.fit(train_data,train_label.ravel()) #ravel函數在降維時默認是行序優先"""計算分類準確率"""#print("訓練集:",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) # 訓練集的預測標簽tes_label = classifier.predict(test_data) # 測試集的預測標簽print("訓練集:",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)模型建立完成之后,需要一個混淆矩陣來顯示預測結果,而不是單純寫個精度。
"""輸出混淆矩陣""" 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) # 輸出混淆矩陣輸出的結果如下:
? ? ? ?可以看到預測精度還是不理想,初步推測誤差來源于數據樣本中不同事故等級與其它數據關聯不明顯,程序難以識別,這也是我下一個優化方向,但因為換研究方向了,也就沒法繼續學術探討了,如果有人感興趣,可以繼續做。
?看在博主這么真誠分享的份上,給個點贊關注吧!
?
目錄
一、數據收集與處理
二、參數排序
三、建立模型
?
總結
以上是生活随笔為你收集整理的交通事故等级预测(附代码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 精益生产浪费有哪些?如何减少消除精益生产
- 下一篇: 动态控制表格表头显隐,让表格变得更加智能