Automated Driving Crashes Part 1

Atcharawan.ks
5 min readDec 14, 2022

--

National Highway Traffic Safety Administration

วิเคราะห์การขัดข้องของรถยนต์ระบบ ADS และ ADAS Part 1

Cr: https://innovationatwork.ieee.org/autonomous-vehicles-for-today-and-for-the-future/

การจัดทำขึ้นในครั้งนี้เป็นส่วนหนึ่งของ 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) =
สมาคมวิศวกรรมยานยนต์นานาชาติหรือ

คำถามที่ต้องการจากข้อมูล

  1. อัตราการเพิ่มขึ้นหรือลดลงของจำนวนอุบัติเหตุรถยนต์อัตโนมัติมีแนวโน้มเป็นอย่างไร
  2. Roadway Surface หรือพื้นผิวของถนน ส่งผลต่อการเกิดอุบัติเหตุมากหรือน้อยกว่า
  3. ช่วงเวลาใดส่งผลต่อการทำงานของรถยนต์อัตโนมัติหรือไม่
  4. สาเหตุที่พบมากที่สุดในอุบัติเหตุแต่ละครั้งของระบบ ADS และ ADAS
  5. รายงานอุบัติเหตุเกิดขึ้นในเมืองไหนมากที่สุด

ซึ่งระหว่างดำเนินการวิเคราะห์นั้นเราก็อาจจะได้คำตอบอื่น ๆ ที่นอกเหนือจากนี้เช่นกัน เดี๋ยวเรามาดูกันว่าข้อมูลที่เรามีนั้นบอกอะไรเราได้บ้าง

มาเริ่มกันเลยดีกว่าค่ะ

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})
pairplot

ลองแสดงข้อมูลการเกิดอุบัติเหตุของแต่ละเดือนในปี 2021 และ ปี 2022 แยกกัน

plt.figure(figsize = (15, 10)) 
sns.set(style = 'whitegrid')

sns.countplot(x=Y_M1['Report Year'], hue = Y_M1['Report Month'])
Report

พบว่าหากอิงจากข้อมูลที่เรามีนั้น ปี 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 สามารถไปติดตามกันได้เลยฮะ

ทั้งนี้หากข้อมูลผิดพลาดประการใดต้องขออภัยไว้ ณ ที่นี้อีกครั้งนะคะ ขอบคุณที่เข้ามาอ่านกันจนจบค่า

--

--