[AI開發]小型數據集解決實際工程問題——交通擁堵、交通事故實時告警


這篇文章其實主要是想介紹在深度學習過程中如何使用小型數據集,這種數據集樣本數量一般在1000以下,有時候甚至只有幾百。一般提到神經網絡,大家都會說數據量越豐富,准確性越高,但是實際工作中,可能收集不了大量的訓練樣本,那么這時候該如何利用有限的數據集去實現我們想要的功能,並且還能得到相對不錯的效果呢?本篇文章以擁堵(事故)檢測為例,為大家介紹小型數據集在深度學習中的應用,這是一個二分類的分類任務,最終分類結果為“擁堵(疑似事故)”和“正常”,分別包含大約500個樣本(包含訓練、驗證和最后拿來測試模型的樣本)。下面是最終效果:

上圖顯示路況由“通暢”慢慢變成“擁堵”,然后再由“擁堵”變為“通暢”,頂部顯示判斷擁堵的概率(1.0最高),可以看到在兩種狀態切換過程中,並不是平滑切換,而是有一個來回抖動的過渡期。下圖顯示發生追尾車禍時出現擁堵的過程:

上圖剛開始車輛行駛緩慢,檢測結果不斷在兩種狀態之間切換,之后出現追尾事故,發生擁堵,檢測狀態穩定。實際使用過程中,我們需要增加一個狀態緩存邏輯,去避免這種來回抖動的問題。

 

小型數據集存在的問題

機器學習包括現在流行的深度學習(關於兩者的區別后面打算專門寫一篇文章介紹一下),都是在已有數據集中學習規律,然后再將學習到的經驗應用到其他數據上,這種經驗應用效果的好壞我們稱之為“泛化能力”的強弱。如果一個算法學習過大量數據,充分找到了其中規律,那么它的泛化能力可能就比較強,因為見多識廣;相反,如果用於學習的數據集不大,那么就不會見多識廣了,泛化能力就比較弱,小型數據集就存在這種缺陷。

神經網絡的訓練過程就是找到合適的參數,讓神經網絡的預測值和實際值誤差最小,如果一個神經網絡很復雜,層數多,那么相應需要訓練的參數也就多,這時候訓練時需要的數據集就必須大一些,否則很難將每個參數調成相對最好的值。

對於小型數據集,有兩種方式可以去嘗試規避它的缺陷,一種就是使用遷移學習(transfer learning),在已經訓練好的復雜模型(參數)基礎上,做一些調整,讓其適應自己的任務,這種方式的原理就是使用一部分預訓練的模型參數,參數訓練無需從零開始,這就可以避免前面提到的數據集太小參數調整困難的問題。另外一種方式就是使用簡單網絡,不要使用類似ResNet、Inception等系列這些比較復雜的卷積網絡,這些網絡適用於大型數據集,參數多,如果數據量不夠,很難訓練好它,我們可以根據需要自定義網絡結構,比如本篇文章我自定義了一個類似AlexNet的網絡結構,5個卷積層外加3個全連接層,相對來說要簡單很多。

 

遷移學習

前面說過,神經網絡學習的過程其實就是找到最合適的參數,讓網絡的預測結果和實際結果之間的誤差盡量最小,這個過程一般以優化損失函數的方式來完成(比如尋找損失函數的最小值),為了簡化說明,假設我們神經網絡最終的損失函數為Loss=W^2-2W+1,形狀是一個拋物線:

如上圖所示,當W=1時,Loss的值最小,也就是說我們需要通過不斷訓練,去調整參數W,使其盡量靠近W=1的位置。神經網絡在初始化時,參數W的值是隨機初始化的,假設隨機初始化W=5,那么我們需要一步一步去調整W,使其讓左慢慢移動(比如使用梯度下降優化算法),最終W有可能不能剛好落到W=1的位置,但是如果非常接近就已經足夠好了,比如W=1.1的時候。注意這里,我們初始化的W=5,它往W=1的位置移動時,距離為4,如果我們每步走的步長(學名叫學習率)比較小,比如為0.0001,那么調整W的次數就需要非常多了(比如4/0.0001),這時候就說明訓練很困難。那么如何快速學習、能讓W盡快落到W=1的位置呢?答案就在W初始化這一步,我們可以不隨機初始化W,而是使用之前訓練好的W來初始化,如下圖:

如上圖,如果我們初始化W=3,那么使其往W=1的位置移動的次數就要少很多了(2/0.001次),這樣相比隨機初始化W的做法要好很多了。

遷移學習的做法其實說白了就是上面提到初始化W的過程。如果從零開始訓練一個網絡,那么W可能初始化為5(甚至更大w=10),如果使用遷移學習的方法訓練一個網絡,那么W可以初始化為3,這個3就是預訓練好的參數,然后我們根據實際情況看是否需要再繼續調整W(甚至直接使用初始化的W即可,不用再調了)。

遷移學習的前提是,這個預訓練的模型要和我們待解決的問題有一定的聯系,比如預訓練的模型使用的數據集是各種自然花朵的照片,主要用於花型識別,而我們要解決的問題是手工繪圖分類,那么這兩種任務其實聯系不是很大(自然花朵和手工繪圖特征相差明顯),這時候遷移學習沒什么意義(或者說價值不大),這個時候如果使用遷移學習,那么上面W初始化的值可能就不是3了,很可能是20,那么還不如隨機初始化W那種方法有效。

Tensorflow2.0中遷移學習的實現過程很簡單,有很多內置的網絡結構,比如ResNet、Inception系列等等,實例化對應網絡類型的對象,加載預訓練的權重值,然后截取該網絡的一部分(主要是前面提取特征的卷積層),然后在截取的網絡之上再新增自定義的分類層,主要是全連接層就行了。最后凍結截取下來的層(不用更新參數),直接用小型數據集訓練新增的層參數即可。根據實際情況,我們有時候還需要解凍截取下來的若干層,讓其參與一起訓練,這個要看具體情況

 

使用簡單網絡

對於我們本篇文章的二分類問題,我們只需要定義一個相對簡單的網絡結構就可以了,比如類似AlexNet的網絡結構(甚至LeNet-5可能也可以),然后我們使用已有的小型數據集從零開始訓練這個網絡即可。因為網絡足夠簡單,所以相對更容易訓練好。

本次任務中,我們判斷道路擁堵與否,是不需要顏色信息的,因此在自定義的簡單網絡結構中,我們增加了一個Lambda層,該層能將輸入進行一些變換,產生輸出,不需要訓練任何參數。這里Lambda層主要負責去色功能,將輸入的RGB圖片轉成灰度圖片,然后再參與后面的特征提取環節。下面是我自定義的簡單網絡結構:

如上圖所示,網絡開始一個Lambda層,直接將輸入的RGB圖片(224*224*3)轉換成灰度圖片(224*224*1),然后緊接着5個卷積層(包含其他池化、歸一化等層),最后加2個全連接層(神經元分別為4096和1000),最后是我們的輸出層,包含2個神經元,輸出一個2維向量,代表每個分類的概率。注意這里的二分類,我們也可以使用一個神經元,但是需要將輸出層的softmax激活函數換成sigmoid函數,后者能將任何輸入映射到0~1之間,0和1分別代表2個不同分類,同時在模型訓練時我們需要選擇另外一個損失函數binary_crossentropy(二分交叉熵損失函數)代替現在的categories_crossentropy損失函數(分類交叉熵損失函數)。機器學習中損失函數主要是用來衡量損失大小,也就是實際值和預測值之間的誤差。再看看我們訓練過程,loss值和accuracy的變化過程:

效果還不錯,驗證准確率最后可以到達95%,再來看看100多張測試集上的效果:

可以看到測試集上的准確率在95.8%,已經不錯了。

上面這個截圖主要是為了說明如何使用小型數據集,可能網絡設計、數據集豐富性上還不夠完善,后面在實際工程中使用時,還需要根據需要增加部分場景的訓練素材(同樣,少量即可)。

 

數據集的‘數量’和‘質量’

深度學習中的數據集不僅對數量有要求,對質量同樣有要求。數量一般是越大越好,同樣要求樣本標注准確,比如目標檢測數據集,要求標注的矩形方框大小、位置都要盡量合理,能完整將目標包含進來,同樣數據集應該盡可能包含各種場景,也就是數據集的豐富性要高,就是前面提到的“見多識廣”。對於監督學習而言,主要是通過訓練素材得到X->Y的映射關系,如果你給出的訓練樣本本身不具備X->Y的映射關系,或者說這種映射關系沒有任何規律、甚至摻雜了很多錯誤映射關系,那么數據集在怎么大,都沒有什么用處,因為你這是在愚弄神經網絡,會把它整懵逼了,最后得不償失。對於深度學習來講,數據集的數量、質量都同等重要。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM