Automated Driving Crashes Part 1
National Highway Traffic Safety Administration
วิเคราะห์การขัดข้องของรถยนต์ระบบ ADS และ ADAS Part 1
การจัดทำขึ้นในครั้งนี้เป็นส่วนหนึ่งของ Final Project รายวิชา DS511 Data Science ปีการศึกษา 2565
หากมีข้อมูลผิดพลาดประการใดต้องขออภัยไว้ ณ ที่นี้ด้วยนะคะ ซึ่งทุกท่านสามารถแนะนำความรู้เพิ่มเติมหรือแนะนำแนวทางที่เหมาะสมเลยค่ะ
สำหรับ Part 2 จะเกี่ยวกับแบบจำลองความเสี่ยงการเกิดอุบัติเหตุของ Automated Driving หรือยานยนต์ขับเคลื่อนอัตโนมัติ สามารถติดตามอ่านได้ที่ แบบจำลองความเสียจากอุบัติเหตุของ Automated Driving หรือยานยนต์ขับเคลื่อนอัตโนมัติ
ก่อนอื่นเราจะขอเกริ่นเกี่ยวกับข้อมูลที่เราจะนำมาวิเคราะห์ก่อน
National Highway Traffic Safety Administration (NHTSA) ได้มีมาตราการ กำหนดให้ผู้ผลิตและผู้ประกอบการการขายยานพาหนะ ต้องรายงานการเกิดอุบัติชนที่เกี่ยวข้องกับกับความช่วยเหลือผู้ขับขี่ขั้นสูงหรือ “ระบบการขับขี่อัตโนมัติ” โดยคำสั่งนี้จะช่วยให้ NHTSA สามารถแจ้งเตือนการขัดข้องของรถยนต์ระบบ ADS และ ADAS แก่ผู้ใช้งานได้อย่างทันท่วงทีและโปร่งใส ซึ่งหาก NHTSA พบข้อบกพร่องด้านความปลอดภัย จะดำเนินการเพื่อให้แน่ใจว่ามีการนำยานพาหนะที่ไม่ปลอดภัยออกจากถนนสาธารณะหรือแก้ไขตามความเหมาะสมต่อไป ทั้งนี้ข้อกำหนดความสามารถของระบบ ADS และ ADAS ระดับ 2 ได้ถูกแยกหมวดหมู่ (CLASSIFICATION) อย่างเป็นทางการโดย SAE International ระบบดังกล่าวจะมีทั้งหมด 5 ระดับ สามารถอ่านรายละเอียดเพิ่มเติมได้จาก https://motortrivia.com/2017/01/autonomous-car-sae-classification/ เนื่องจากเขียนไว้ละเอียดมาก
แต่ทั้งนี้ ในบทความนี้เราจะขอเล่าถึง ความแตกต่างของ ADS กับ ADAS เท่านั้น โดย ADS เป็นรถยนต์ไร้คนขับ ใช้ระบบปฏิบัติการในการขับเคลื่อน แต่ ADAS เป็นระบบจะทำงานผสานร่วมกันระหว่างอุปกรณ์ทางเทคโนโลยีและผู้ขับขี่ช่วยให้คนขับรถสามารถขับรถได้อย่างปลอดภัยมากขึ้นกว่าการขับไร้คนขับแบบทั่วไป
อธิบายเพิ่มเติม
National Highway Traffic Safety Administration (NHTSA) =
สํานักงานความปลอดภัยการจราจรบนทางหลวงแห่งชาติ
SAE International (Society of Automotive Engineers) =
สมาคมวิศวกรรมยานยนต์นานาชาติหรือ
คำถามที่ต้องการจากข้อมูล
- อัตราการเพิ่มขึ้นหรือลดลงของจำนวนอุบัติเหตุรถยนต์อัตโนมัติมีแนวโน้มเป็นอย่างไร
- Roadway Surface หรือพื้นผิวของถนน ส่งผลต่อการเกิดอุบัติเหตุมากหรือน้อยกว่า
- ช่วงเวลาใดส่งผลต่อการทำงานของรถยนต์อัตโนมัติหรือไม่
- สาเหตุที่พบมากที่สุดในอุบัติเหตุแต่ละครั้งของระบบ ADS และ ADAS
- รายงานอุบัติเหตุเกิดขึ้นในเมืองไหนมากที่สุด
ซึ่งระหว่างดำเนินการวิเคราะห์นั้นเราก็อาจจะได้คำตอบอื่น ๆ ที่นอกเหนือจากนี้เช่นกัน เดี๋ยวเรามาดูกันว่าข้อมูลที่เรามีนั้นบอกอะไรเราได้บ้าง
มาเริ่มกันเลยดีกว่าค่ะ
Data Preparing
ขั้นแรกคือ Data Preparing โดย Dataset ที่เรานำมาเขียนบทความนั้นมาจาก https://www.kaggle.com/datasets/michaelbryantds/automated-driving-crashes เราจะเห็นว่า เราจะต้องอ่านข้อมูลที่ถูกเก็บอยู่ในรูปแบบของ .csv
นอกจากนี้ สามารถดูคำจำกัดความของแต่ละ columns ใน Dataset ได้ที่
SGO-2021–01_Data_Element_Definitions.pdf (nhtsa.gov)
สำหรับโค้ดที่ละเอียดมากยิ่งขึ้นอยู่ใน Colab
Reports_ADAS = pd.read_csv('SGO-2021-01_Incident_Reports_ADAS.csv')
#แสดงทุก Columns เพื่อดูข้อมูลที่จะสามารถนำมาวิเคราะห์ข้อมูลที่พอจะสามารถเป็นประโยชน์ได้
pd.set_option('display.max_columns', None)
Reports_ADS = pd.read_csv('SGO-2021-01_Incident_Reports_ADS.csv')
pd.set_option('display.max_columns', None)
Incident_Reports_ADAS มีทั้งหมด 1167 คอลัมน์ 122 แถว (Row)
Incident_Reports_ADS มีทั้งหมด 436 คอลัมน์ 122 แถว (Row)
เราจะรวมทั้งสองตารางเข้าด้วยกัน เพื่อให้ง่ายต่อการดึงข้อมูลมาวิเคราะห์ โดยการวิเคราะห์ในครั้งนี้เราจะไม่วิเคราะ์แยก แต่ผู้เขียนจะขอถือว่าทั้งหมดนี้คือรถขับเคลื่อนอัตโนมัติโดยยังไม่แยกประเภท หากมีโอกาศเราจะมาเปรียบเทียบประเภทอีกครั้ง เผื่อว่าจะเป็นประโยชน์ในการตัดสินใจ
รวมทั้งสองตารางเข้าด้วยกัน
Reports_concat = pd.concat([Reports_ADAS,Reports_ADS], axis=0)
Reports_concat.head(3)
เราจะเห็นว่ามีค่า NaN เราจะทำการสำรวจข้อมูลเบื้องต้น และทำการ cleaning missing data
สำรวจ missing data ด้วยการใช้ msno.matrix
เนื่องจากข้อมูลที่ยังไม่ได้ใช้ ณ ตอนนี้ยังเยอะอยู่ เราจะขอดึงข้อมูลที่สำคัญออกมา
จากรูปนี้ด้านบน ดูเหมือนว่าจะไม่มีค่า Null แล้ว แต่…
ใน dataset ของเรามีค่า unknow อยู่เยอะมาก ๆ อย่างเช่นในยกตัวอย่าง Group ข้อมูลในคอลัมน์ Lighting พบ Unknown 731 ค่า
ดังนั้น เราจะทำการลบข้อมูล Unknow เหล่านี้ ในคอลัมน์ที่เราจะนำมาวิเคราะห์
เช็ค value ที่อยู่ในคอมลัมน์ ว่ามีค่าอะไรบ้างที่ไม่เกิดประโยชน์ต่อการวิเคราะห์
check1 = AD_Submission.groupby(['Lighting'])['Lighting'].count()
check1
ลบค่า Unknow แต่ท้ังนี้เราก็ได้ลบค่า Unknow ในคอลัมน์อื่น ๆ ด้วยเช่นกัน สามารถดูโค้ดเพิ่มเติมได้ที่ Colab นี้ได้เลยค่ะ
AD_dfinal = AD_Submission[AD_Submission['Lighting'].str.contains('Unknown')==False]
ตอนนี้เราเหลือข้อมูลเท่านี้ ซึ่งจะนำไปวิเคราะห์และทำ Model ต่อไป
ต่อมาก็จะเป็นขั้นตอนจัดการพวกวันที่และเวลาให้อยู่ในรูปแบบที่เหมาะสมและเช็ค dtype และ
อย่างแรกเราจะทำการรวมคอลัมน์วันที่และเวลาที่รายงานอุบัติเหตุก่อน เนื่องจากตอนนี้ทั้งสองคอลัมน์แยกกัน และอยู่ในรูปแบบ Object
โดยเมื่อเรารวมกันแล้ว ทั้งสองจะมาอยู่ด้วยกันและกลายเป็นรูปแบบ datetime
ใช้โค้ดนี้เลยยย เรา reset_index ด้วยเพราะว่าจะได้ดูง่าย ๆ และเผื่อนำไปวิเคราะห์
datetime_t = pd.to_datetime(AD_dff['Incident Date'] + ' ' + AD_dff['Incident Time (24:00)']).reset_index(drop=True)
#เปลี่ยนชื่อให้คอลัมน์สักหน่อย
datetime.rename(columns = {0:'Incident Date/Time'}, inplace = True)
datetime
Output:
0 2022-07-01 02:59:00
1 2022-09-01 17:57:00
2 2022-09-01 06:52:00
3 2022-09-01 09:48:00
4 2022-09-01 13:46:00
...
1162 2021-07-01 04:09:00
1163 2021-06-01 01:28:00
1164 2021-07-01 00:35:00
1165 2021-07-01 08:17:00
1166 2021-07-01 00:00:00
Length: 1167, dtype: datetime64[ns]
ตอนนี้ข้อมูลออกมาเป็น Length เราจะเปลี่ยนไปเป็นรูปแบบ frame เพื่อนำไป Concatenate กับตารางใหญ่
datetime = datetime_t.to_frame()
#เปลี่ยนชื่อให้คอลัมน์สักหน่อย
datetime.rename(columns = {0:'Incident Date/Time'}, inplace = True)
Concatenate
#concat หรือรวมเข้ากับตารางใหญ่
AD_df = pd.concat([datetime, AD_dff], axis=1)
AD_df.head(2)
Change Dtype
เปลี่ยน Dtype จาก Float เป็น int เพื่อให้สามารถอ่านข้อมูลตอนเรานำไป plot graph ได้ง่าย
Y_M = AD_df[['Report Month', 'Report Year']]
Y_M['Report Year'] = Y_M['Report Year'].fillna(0).astype(int)
Y_M['Report Month'] = Y_M['Report Month'].fillna(0).astype(int)
print(Y_M.dtypes)
Output:
Report Month int64
Report Year int64
DATA EXPLORATION
สำรวจอัตราการเกิดอุบัติเหตุของรถขับเคลื่อนอัตโนมัติ ในแต่ละเดือน ตลอด 2 ปี (2021–2022 โดยสิ้นสุดเดือน ตุลาคม 2022)
พล็อต countplot ของรายงานแต่ละเดือน โดยใช้ข้อมูลของทั้งสองปี
plt.figure(figsize = (8,8))
sns.countplot(x=Y_M1['Report Month'])
พบว่าส่วนมากอุบัติเหตุจะเกิดขึ้นช่วงปลายปี และเดือนพฤศจิกายนเกิดขึ้นเยอะที่สุด
sns.pairplot(Y_M1, diag_kind='kde', plot_kws={'alpha': 0.2})
ลองแสดงข้อมูลการเกิดอุบัติเหตุของแต่ละเดือนในปี 2021 และ ปี 2022 แยกกัน
plt.figure(figsize = (15, 10))
sns.set(style = 'whitegrid')
sns.countplot(x=Y_M1['Report Year'], hue = Y_M1['Report Month'])
พบว่าหากอิงจากข้อมูลที่เรามีนั้น ปี 2021 เดือนพฤศจิกายน มีอัตราการเกิดมากที่สุด
แล้วพวกแสงสว่าวละส่งผลต่อการเกิดอุตบัติเหตุมากไหมนะ?
ลองพล็อคกราฟออกมาดูเพื่อให้ง่ายต่อการวิเคราะห์
plt.figure(figsize = (15,9))
sns.countplot(x=AD_dfinal['Lighting'])
จากข้อมูลรายงานที่เรามีพบว่า Daylight มีรายงานอุบัติเหตุมากที่สุด อาจจะด้วยเป็นช่วงเวลาที่ใช้งานเยอะ และความเร็วด้วย
รายงานอุบัติเหตุเกิดขึ้นในเมืองไหนมากที่สุด?
grouped = Reports_concat.groupby('City')["City"].count()
df_grouped = grouped.to_frame('count')
df_grouped.sort_values(by = ['count'], inplace=True, ascending=False)
df_grouped
San Francisco มี 268 รายงาน ที่เกิดอุบัติเหตุมากที่สุด เราจะลองพล็อต street network ของเมืองออกมาคร่าว ๆ โดยใช้โค้ดด้านล่างนี้
โดยเราจะใช้ OSMnx เหมาะสำหรับนำมาวิเคราะห์ข้อมูลโครงข่ายแผนที่ โดยอาศัยข้อมูลจาก Openstreetmap แต่ในที่นี้เราอยากดู street network เฉยแหละ ฮ่า ๆ
pip install osmnx
#ห้ามลืมนะไม่งั้น error แน่
import osmnx as ox
# street network in San Francisco
M = ox.graph_from_place('San Francisco', network_type='drive_service')
#‘drive_service’ – get drivable public streets, including service roads
fig, ax = ox.plot_graph(M, node_size=1, node_color='r', edge_color='w', edge_linewidth=0.2)
ก่อนเกิดอุบัติเหตุเกิดอะไรขึ้น?
plt.figure(figsize = (15,8))
plt.xticks(rotation=45)
sns.countplot(x=AD_dfinal2['CP Pre-Crash Movement'])
พบว่าส่วนมากก่อนเกิดเห็นนั้นไปผิดทาง อย่างไรดีผู้เขียนคิดว่า แสดงว่าปัจจุบันการป้อนแผนที่ไปยังรถขับขี่อัตโนมัติยังไม่เพียงพอเท่าที่ควรหรือไม่ เพราะจำนวนการเกิดเหตุจากปัจจัยส่วนนี้เยอะมาก หากเทียบกับปัจจัยอื่น ๆ
Movement ของรถเป็นอย่างไรก่อนเกิดเหตุ
plt.figure(figsize = (8,8))
plt.xticks(rotation=45)
sns.countplot(x=AD_dfinal['SV Pre-Crash Movement'])
Proceeding Straight เยอะสุดเลย 284 แต่ที่รองลงมาคือ Lane / Road Departure 49 ซึ่งต่างกับลำดับแรกมาก ๆ
รถที่ติดตั้ง Air Bags มีความเสียหายไหม และต่างแบบไม่ติดตั้งมากหรือไม่?
sns.countplot(x=AD_dfinal['Property Damage?'], hue=AD_dfinal['CP Any Air Bags Deployed?'])
พบว่ารถที่ติดตั้งและรถที่ไม่ติดตั้งมีค่าต่างกันประมาณ 1 เท่า แต่ทั้งนี้อาจจะไม่สามารถนำมาเป็นตัวตัดสินได้อย่างสอดคล้องเลยสะทีเดียว เพราะมีค่า Unknow มีเยอะอีกและ ข้อมูลรายงานการ Air bag มันส่งผลต่อข้อความเป็นส่วนตัวหรือนี่!!
สุดท้ายนี้ เราจะดูว่าไมล์สะสมกับความเสียหายเป็นอย่างไรสอดคล้องกันหรือไม่
plt.rcParams['figure.figsize'] = (20, 20)
sns.relplot(x="Property Damage?", y="Mileage", data=AD_dfinal, kind='scatter');
พบว่ามีความน่าสนใจอยู่อย่างหนึ่ง เพราะมีรถที่ไม่ได้รับความเสียหาย ทั้งที่มีไมล์สะสมสูงเท่า ๆ กับรถที่ได้รับความเสียหายเลย บ่งบอกถึงคุณภาพหรือไม่นะ เราจะกรองออกมาดูว่าเป็นรถรุ่นอะไร โมเดลปีไหน
Mileage = Reports_concat[['Property Damage?','Mileage','Model Year','Model', 'Make']]
Mileage
ได้ dataframe ออกมาแล้วต่อมาเราจะลบค่า ในวิธีที่ง่านสำหรับเราที่สุด
dell = Mileage[Mileage['Property Damage?'].str.contains('Unknown')==False]
dell1 = dell[dell['Property Damage?'].str.contains('Yes')==False]
Ascending หรือเรียงลำดับจากมากไปน้อย โดยเรียงด้วยคอลัมน์ Mileage
dell1.sort_values(by = ['Mileage'], inplace=True, ascending=False)
dell1
และรูปด้านบนนี้คือข้อมูลของรถที่ไม่ได้รับความเสียหายเทียบกับไมล์สะสม ซึ่ง Lucid Model Dream 2022 เป็นรุ่นที่ไมล์สะสมสูงแต่ก็ไม่ได้รับความเสียหาย ซึ่งไมล์สะสมก็อาจจะไม่สามารถบอกได้เลยสะทีเดียวว่าส่งผลต่ออุบัติเหตุในครั้งนั้นหรือไม่ เพราะว่าเขาอาจจะขับช้าก็ได้ แต่เราเพียงลองแยกออกมาให้ดูเท่านั้น เพราะไมล์สะสมมันก็บ่งบอกถึงพฤติกรรมการใช้งานได้ระดับนึงเช่นใช้บ่อย สภาพของรถก็เสื่อมโทรมไปตามการใช้งาน
สรุป:
โดยการวิเคราะห์ในครั้งนี้เป็นการนำข้อมูลที่มาตอบคำถามของเรา ซึ่งเราได้เน้นไปทาง visualization ออกมาและเปรียบเทียบความแตกต่าง ซึ่งพวกเราก็มีพาร์ทสองที่ชื่อว่า Automated Driving Crashes Model Part 2 สามารถไปติดตามกันได้เลยฮะ
ทั้งนี้หากข้อมูลผิดพลาดประการใดต้องขออภัยไว้ ณ ที่นี้อีกครั้งนะคะ ขอบคุณที่เข้ามาอ่านกันจนจบค่า