維基百科上有一個詞條:各國交通事故死亡率列表,數字非常觸目驚心。很大部分都是因爲分心駕駛導致的車禍事故。如果能使用人工智能技術幫助檢測司機的分心狀況,一旦發現司機出現分心的苗頭,就立即提醒,車禍就可以避免了。幸運的是,有這麼一些年輕人,利用深度學習開發並開源了司機分心駕駛檢測的項目。真可謂功德無量。我們再一次見證了:科技改變人生,開源改變世界!
本文和項目是 Amey Athaley、Apoorva Jasti、Sadhana Koneni、Satya Naren Pachigolla、Jayant Raisinghani 在 Joydeep Ghosh 教授的指導下共同貢獻的,請訪問 GitHub 倉庫 以獲取我們的實現代碼。
引言
開車是一項複雜的活兒,需要司機保持全神貫注。分心駕駛是指駕駛時注意力指向與正常駕駛不相關的活動,從而導致駕駛操作能力下降的一種現象。一些研究已經確定了注意力分散的三種主要類型:視覺干擾(司機的視線不在道路上)、手控分心(司機的手離開方向盤)和認知分心(司機的注意力不在開車任務上)。
美國國家公路交通安全管理局(The National Highway Traffic Safety Administration,NHTSA)報告稱,2018 年有 36750 人死於車禍,其中 12% 是由於分心駕駛造成的。發短信是最讓人分心的事情。收發短信會讓你的視線離開道路長達 5 秒鐘。以每小時 88.51 公里的時速行駛來計算,這 5 秒鐘就相當於閉着眼睛行駛了整個足球場那麼長。
現在,在美國有許多州都立法禁止開車時發短信、打電話和其他分心的事情。我們相信,計算機視覺技術可以加強政府的這些努力,以防止因分心駕駛造成的事故。我們的算法能夠自動檢測司機的分心跡象並向他們發出警報。爲了防止因分心駕駛造成事故,我們設想將這類產品嵌入到汽車中。
數據
我們採用了 StateFarm 數據集,其中包含了安裝在汽車中的行車記錄儀拍攝的視頻快照。訓練集中大約有 $22400$ 個標記樣本,這些樣本在各類之間分佈均勻,另外還有 $79700$ 個未標記的測試樣本。圖像分爲 10 類:
評估指標
在繼續構建模型之前,重要的是選擇正確指標來評估其性能。正確率(Accuracy)是我們想到的第一個指標。但是,正確率並不是分類問題的最佳指標。正確率只考慮預測的正確性,即預測的標籤是否與真實的標籤相同。但是,我們將司機的行爲歸類爲分心的置信度(Confidence)對於評估模型的性能非常重要。值得慶幸的是,我們有一個指標可以捕捉到這一點:對數損失(Log Loss)。
對數損失(Logarithmic loss,與交叉熵有關)衡量分類模型的性能,其中預測輸入是介於 0 和 1 之間的概率值。我們的機器學習模型的目標就是最小化這個值。一個理想的模型的對數損失應爲 0,並且隨着預測概率與實際標籤的偏離而增加。因此,當實際觀測標籤爲 1 時,預測概率爲 0.3 將會導致較高的對數損失。
數據泄露
在瞭解了需要實現的目標之後,我們從頭開始構建卷積神經網絡(Convolutional Neural Network,CNN)模型。我們添加了常見的可疑因素:卷積批量歸一化、最大池化和密集層。結果表明,在 3 個輪數內,驗證集的正確度爲 99.6%,損失率爲 0.014。
輪數:3 | 損失 | 正確率 |
---|---|---|
訓練 | 0.0034 | 99.9% |
驗證 | 0.014 | 99.6% |
表:初始模型結果
嗯,我們考慮了一下,就意外地構建了世界上最好的卷積神經網絡架構。因此,我們使用這個模型來預測未標記測試集的類。
關鍵時刻
我們更深入地研究了可能出問題的地方,發現我們的訓練數據中,有多張同一個人在同一個類的圖像,只不過是角度、高度或寬度略有變化而已。這就導致了數據泄露問題,因爲相似的圖像也在驗證中,也就是說,模型接受的訓練與它試圖預測的信息基本相同。
數據泄露的解決方案
爲了解決數據泄露的問題,我們根據人員 ID 來分割圖像,而不是使用隨機的 80-20 分割。
現在,當我們將模型與修改後的訓練集和驗證集進行擬合時,我們看到了更加真實的結果。我們實現了 1.76 的損失和 38.5 的正確率。
輪數:15 | 損失 | 正確率 |
---|---|---|
訓練 | 2.08 | 23.8% |
驗證 | 1.76 | 38.5% |
圖:應對數據泄露後的模型擬合。
爲了進一步提高結果,我們探索使用經過反覆測試的深度神經網絡架構。
譯註:epoch 譯爲輪數,1 個 epoch 等於使用訓練集中的全部樣本訓練一次。舉個例子,訓練集有 10000 個樣本,batchsize=10,訓練完整個樣本集需要:1000 次 iteration,1 次 epoch。
遷移學習
遷移學習是一種將爲相關任務開發的模型重用爲第二個任務上的模型起點的方法。我們可以重用針對標準計算機視覺基準數據集開發的預訓練模型的權重,如 ImageNet 圖像識別挑戰。一般來說,帶有 softmax 激活函數的最後一層被替換,以適應我們數據集中類的數量。在大多數情況下,還會添加額外的層來針對特定任務定製解決方案。
考慮到開發用於圖像分類的神經網絡模型需要耗費大量的算力和時間資源,因此,這是一種流行的深度學習方法。此外,這些模型通常在數百萬張圖像上進行訓練,這一點很有用,特別是當你的訓練集很小的時候。這些模型架構中的大多數都是公認的贏家:VGG16、RESNET50、Xception 和 Mobilenet 模型,我們利用這些模型在 ImageNet 挑戰中取得了非凡的成績。
圖像增強
datagen = ImageDataGenerator(
height_shift_range=0.5,
width_shift_range = 0.5,
zoom_range = 0.5,
rotation_range=30
)
#datagen.fit(X_train)
data_generator = datagen.flow(X_train, y_train, batch_size = 64)
圖像增強的示例代碼
由於我們的訓練圖像集只有大約 $22000$ 張圖像,因此,我們希望從訓練集中綜合得到更多的圖像,以確保模型不會發生過擬合,因爲神經網絡有數以百萬計的參數。圖像增強是一種通過改變寬度和/或高度、旋轉和/或縮放等操作來從原始圖像創建更多圖像的技術。要了解關於圖像增強的更多信息,請參閱這篇文章:How to Configure Image Data Augmentation in Keras(如何在 Keras 中配置圖像數據增強)。
對於我們的項目,圖像增強還有一些額外的優勢。有時,來自兩個不同類的圖像之間的差異可能非常微妙。在這種情況下,通過不同的角度對同一張圖片進行多次觀察將會有所幫助。如果你看下面的圖片,你會發現它們幾乎是相似的,但第一張圖片是屬於這個類:Talking on the Phone — Right(“用右手打電話”),而第二張圖片則屬於這個類“Hair and Makeup(“頭髮和化妝”)。
冗餘層
爲了使遷移學習的價值最大化,我們添加了一些冗餘層(Extra layers)來幫助模型適應我們的用例,每層的用途如下:
- 全局平均池化(Global average pooling) 層只保留每個 patch 中值的平均值。
- Dropout 層有助於控制過擬合,因爲它會丟棄一部分參數。(特別提示:嘗試不同的 Dropout 值是個好主意)
- 批歸一化(Batch normalization) 層對將下一層的輸入進行歸一化,從而使訓練更快、更具彈性。
- 密集(Dense) 層是具有特定激活函數的規則全連接層。
需要訓練哪些層?
在進行遷移學習時,要解決的第一個問題是,我們是應該只訓練添加到現有架構中的冗餘層呢,還是應該訓練所有層?當然,我們從使用 ImageNet 權重開始,只訓練新層,因爲要訓練的參數數量較少,模型訓練速度將會更快。我們看到,驗證集的正確率在歷經 25 個輪數後穩定在 $70%$。但是,通過訓練所有層的話,我們就能夠得到 $80%$ 的正確率。因此,我們決定繼續進行所有層的訓練。
使用哪個優化器?
優化器通過對參數的目標函數 w.r.t. 的梯度的相反方向上更新參數,使通過模型參數進行參數化的目標函數最小化。要了解有關不同優化器如何工作的更多信息,可以參考這個博客:An overview of gradient descent optimization(梯度下降優化綜述)。
深度學習領域中最流行的算法是 ADAM,它結合了 SGD 和 RMSProp 算法。對於大多數問題,它始終比其他優化器的表現得更好。然而,在我們的案例中,當 SGD 正在逐漸學習時,Adam 表現出不穩定的下降模式。通過文獻調研,我們發現,在少數情況下,SGD 優於 Adam,是因爲 SGD 具有更好的泛化(Generalizes)。(請參閱此論文:The Marginal Value of Adaptive Gradient Methods in Machine Learning)。由於 SGD 給出了穩定的結果,因此我們將其用於所有的模型。
使用哪種架構?
我們用在 ImageNet 數據集上訓練得到的權重,即預訓練的權重,嘗試了多種遷移學習模型。
- VGG16
VGG16 模型有 16 層。它主要採用卷積技術以及零填充、Dropout、最大池化和平坦化(Flattening)。
- RESNET50
RESNET50 是 VGG16 的擴展,有 50 層。針對較深層次網路難以訓練的問題,引入了參考層輸入的“shortcut connections”前饋神經網絡。
創建殘差網絡(RESNET)的目的是獲得層次更深的網絡,而創建 Xception 的目的是爲了通過引入深度可分離( Depthwise Separable Convolution)的卷積來獲得更廣泛的網絡。通過將標準卷積層分解爲深度卷積(Depthwise convolution)和逐點卷積(Pointwise convolutions),計算量顯著減少。由於多個過濾器處於同一級別上,因此模型的性能也有所提高。
- MobileNet
MobileNet 是 Google 爲基於移動的視覺應用開發的模型。它被證明可以減少至少 9 倍的計算成本。MobileNet 使用深度可分離卷積來構建輕量級的深度神經網絡。它有兩個簡單的全局超參數,可以有效地在延遲和正確率之間進行權衡。
遷移學習模型的性能
比較最佳模型
雖然上面的每個架構都給我們帶來了很好的結果,但是對於各個類,每個模型的性能還是存在很大的差異。從下表中,我們注意到不同的模型對每個類都有最佳的正確率。因此,我們決定構建一個這些模型的概觀。
上圖中列出了每個模型針對特定類的正確率。綠色到紅色的變化表示了正確率從高到低。
集成模型
現在,我們已經有了 7 個最佳模型,這些模型之間的後驗概率差異很大,我們嘗試了多種集成技術,以進一步改善對數損失。
- 均值集成(Mean Ensembling):這是最簡單,也是使用最廣泛的集成方法,其中後驗概率被計算爲來自組件模型的預測概率的平均值。
- 修剪均值集成(Trimmed Mean Ensembling):這是通過從每個圖像的組件模型中排除最大和最小的概率的均值集成。它有助於進一步使我們的預測平坦化,從而降低對數損失值。
- 用於集成的 K 近鄰算法(KNN for Ensembling):由於這些圖片都是在司機正在進行分心的活動或開車時從視頻片段中截取的,因此有相當數量的同一類的圖片是相似的。基於這一前提,找到相似的圖像,並對這些圖像的概率進行均值,可以幫助我們平滑每個類的預測概率。爲了找到 10 個最近的鄰居,我們使用 VGG16 遷移學習模型倒數第二層的輸出作爲驗證集的特徵。
模型 | 驗證損失 | 驗證正確率 |
---|---|---|
MobileNet | 0.4 | 85.7% |
均值集成 | 0.32 | 89/7% |
修剪均值集成 | 0.3 | 89.7% |
K 最近鄰算法集成 | 0.24 | 92.2% |
表:以 MobileNet 模型爲基準的集成模型比較。
學習
我們相信,從我們的經驗中學到的這些知識,將會使那些像我們這樣第一次從事深度學習項目的人們受益:
1. 使用 Pickle 文件: 你可以爲你的項目使用的一個免費資源是“Google Colab”。你可以使用 GPU 來處理並行計算產生的海量數據。使用 Colab 時,可以執行必要的預處理步驟,方法是讀取所有圖像一次並將其保存在 Pickle 文件中。這樣,你就可以通過直接加載 Pickle 文件來從上次終端的地方繼續之前的工作。然後你就可以開始訓練模型了。
2. 提前停止和回調: 一般來說,深度學習模型的訓練都會經過大量的輪數。在這個過程中,模型可能會在幾個輪數之內提高正確率,然後就開始偏離。訓練結束時所存儲的最終權重並不是最佳值,也就是說,它們可能不會給出最小的對數損失。我們可以使用 Keras 中的回調(CallBacks)函數,僅在模型經歷一個輪數之後出現改進時,它纔會保存模型的權重。你可以通過使用提前停止(Early Stopping)來減少訓練時間,也可以設置一個閾值,在模型停止改善後可以運行的輪數的數量。
3. 均值或修剪均值優於集合的模型融合(Model Stacking): 融合模型的輸入將具有很高的相關性,這會導致輸出較高的方差。因此,在這種情況下,更簡單的方法就是最佳方法。
4. 永遠不要忽視最終的應用:對 7 個模型進行集成,然後在輸出上運行 K 近鄰算法,我們得到了不錯的成績,但如果我們必須選擇一個單一模型,用最少的資源來得到良好但更快的預測,那麼,MobileNet 將是顯而易見的選擇。因爲 MobileNet 的開發特別考慮了計算限制,最適合汽車應用,在 7 種獨立模型中,它的對數損失最低。
我們相信,在汽車上安裝的攝像頭,是可以做到跟蹤司機的動作並向他們發出警報,這有助於防止事故的發生。
爲了真正理解這一點,我們製作了一個小視頻,演示如何使用我們這個模型:
請下載並上傳此視頻,網址爲
https://youtu.be/Cqmn_OoS6XY
參考文獻
- Stanford CS231N lecture series for CNN:
https://www.youtube.com/watch?v=vT1JzLTH4G4&list=PLzUTmXVwsnXod6WNdg57Yc3zFx_f-RYsq&index=1 - How to implement CNN using Keras, TensorFlow:
https://www.youtube.com/watch?v=wQ8BIBpya2k&list=PLQVvvaa0QuDfhTox0AjmQ6tvTgMBZBEXN - CNN Architectures:
https://medium.com/analytics-vidhya/cnns-architectures-lenet-alexnet-vgg-googlenet-resnet-and-more-666091488df5 - Transfer learning articles:
- https://towardsdatascience.com/transfer-learning-using-mobilenet-and-keras-c75daf7ff299
- https://github.com/bdutta19/kaggle_statefarm
- http://cs229.stanford.edu/proj2016/report/SamCenLuo-ClassificationOfDriverDistraction-report.pdf
- https://arxiv.org/abs/1704.04861
作者介紹:
Satya Naren Pachigolla,數據科學愛好者。目前在德克薩斯州大學奧斯汀分校攻讀商業分析碩士學位。
本文最初發表在 Medium 博客,經原作者 Satya Naren Pachigolla 授權,InfoQ 中文站翻譯並分享。
原文鏈接:
https://towardsdatascience.com/distracted-driver-detection-using-deep-learning-e893715e02a4