前言
根據我個人的經驗,學好AI,有五個必修:數學、數據結構、Python數據分析、ML、DL,必修之外,有五個選修可供選擇:NLP、CV、DM、量化、Spark,然后配套七月在線的這些必修和選修課程刷leetcode、kaggle,最后做做相關開源實驗。
今天,咱們就來看一看:如何用百行代碼實現Kaggle排名Top 5%的圖像分類比賽。
1、NCFM圖像分類任務簡介
為了保護和監控海洋環境及生態平衡,大自然保護協會(The Nature Conservancy)邀請Kaggle[1]社區的參賽者們開發能夠出機器學習算法,自動分類和識別遠洋捕撈船上的攝像頭拍攝到的圖片中魚類的品種,例如不同種類的吞拿魚和鯊魚。大自然保護協會一共提供了3777張標注的圖片作為訓練集,這些圖片被分為了8類,其中7類是不同種類的海魚,剩余1類則是不含有魚的圖片,每張圖片只屬於8類中的某一類別。
圖1給出了數據集中的幾張圖片樣例,可以看到,有些圖片中待識別的海魚所占整張圖片的一小部分,這就給識別帶來了很大的挑戰性。此外,為了衡量算法的有效性,還提供了額外的1000張圖片作為測試集,參賽者們需要設計出一種圖像識別的算法,盡可能地識別出這1000張測試圖片屬於8類中的哪一類別。Kaggle平台為每一個競賽都提供了一個榜單(Leaderboard),識別的准確率越高的競賽者在榜單上的排名越靠前。
圖1. NCFM圖像分類比賽
2、問題分析與求解思路
2.1、卷積神經網絡
從問題的描述我們可以發現,NCFM競賽是一個典型的“單標簽圖像分類”問題,即給定一張圖片,系統需要預測出圖像屬於預先定義類別中的哪一類。在計算機視覺領域,目前解決這類問題的核心技術框架是深度學習(Deep Learning),特別地,針對圖像類型的數據,是深度學習中的卷積神經網絡(Convolutional Neural Networks, ConvNets)架構(關於卷積神經網絡的介紹和算法,這里有個視頻教程可以看下:CNN之卷積計算層,本博客也寫過:CNN筆記)。
總的來說,卷積神經網絡是一種特殊的神經網絡結構,即通過卷積操作可以實現對圖像特征的自動學習,選取那些有用的視覺特征以最大化圖像分類的准確率。
圖2. 卷積神經網絡架構
圖2給出了一個簡單的貓狗識別的卷積神經網絡結構,在最底下(同時也是最大的)的點塊表示的是網絡的輸入層(Input Layer),通常這一層作用是讀入圖像作為網絡的數據輸入。在最上面的點塊是網絡的輸出層(Output Layer),其作用是預測並輸出讀入圖像的類別,在這里由於只需要區分貓和狗,因此輸出層只有2個神經計算單元。而位於輸入和輸出層的,都稱之為隱含層(Hidden Layer),圖中有3個隱含層,正如前文提到的,圖像分類的隱含層都是由卷積操作完成的,因此這樣的隱含層也成為卷積層(Convolutional Layer)。
因此,輸入層、卷積層、輸出層的結構及其對應的參數就構成了一個典型的卷積神經網絡。當然,我們在實際中使用的卷積神經網絡要比這個示例的結構更加復雜,自2012年的ImageNet比賽起,幾乎每一年都會有新的網絡結構誕生,已經被大家認可的常見網絡有AlexNet[5], VGG-Net[6], GoogLeNet[7], Inception V2-V4[8, 9], ResNet[10]等等。
2.2、一種有效的網絡訓練技巧—微調
我們沒有必要從頭開始一個一個的參數去試驗來構造一個深度網絡,因為已經有很多公開發表的論文已經幫我們做了這些驗證,我們只需要站在前人的肩膀上,去選擇一個合適的網絡結構就好了。且選擇已經公認的網絡結構另一個重要的原因是,這些網絡幾乎都提供了在大規模數據集ImageNet[11]上預先訓練好的參數權重(Pre-trained Weights)。這一點非常重要!因為我們只有數千張訓練樣本,而深度網絡的參數非常多,這就意味着訓練圖片的數量要遠遠小於參數搜索的空間,因此,如果只是隨機初始化深度網絡然后用這數千張圖片進行訓練,非常容易產生“過擬合”(Overfitting)的現象。
所謂過擬合,就是深度網絡只看過了少量的樣本,因而“坐井觀天”,導致只能識別這小部分的圖片,喪失了“泛化”(Generalization)能力,不能夠識別其它沒見過、但是也是相似的圖片。為了解決這樣的問題,我們一般都會使用那些已經在數百萬甚至上千萬上訓練好的網絡參數作為初始化參數,可以想象這樣一組參數的網絡已經“看過”了大量的圖片,因此泛化能力大大提高了,提取出來的視覺特征也更加的魯棒和有效。
接下來我們就可以使用已經標注的三千多張海魚圖片接着進行訓練,注意為了防止錯過了最優解,此時的訓練節奏(其實應該稱為“學習速率”)應該比較緩慢,因此這樣的訓練策略我們稱為“微調技術”(Fine-tune)。
當我們使用自己的標注數據微調某個預先訓練的網絡時候,有一些經驗值得借鑒。以總圖3為例,假設我們的網絡結構是類似AlexNet這樣的7層結構,其中前5層是卷積層,后2層是全連接層。
(1)
(1)我們首先微調最后一層Softmax分類器,假設原來的網絡是用來分類1000類物體的(例如ImageNet的目標),而現在我們的數據只有10個類別標簽,因此我們最后一層輸出層(FC8)的神經元個數變為10。我們使用很小的學習率來學習層FC7與FC8之間的權重矩陣而固定這之前所有層的權重;
(2)
(2)一旦網絡趨於收斂,我們進一步擴大微調的范圍,這時微調兩個全連接層,即FC6與FC7,以及FC7與FC8之間的權重,與此同時固定FC6之前的所有卷積層權重不變;
(3)
(3)我們將微調的范圍擴大至倒數第一個卷積層C5;
(4)
(4)我們將微調的范圍擴大至更多的卷積層。不過事實上,我們會認為位置相對靠前的卷積層提取出來的特征更加的底層和具有通用性,而位置相對靠后的卷積層以及全連接層更加與數據集的相關性大一些,因此有時候我們並不會微調前幾個卷積層。
3、算法實現和分析
在NCFM這個比賽的論壇里已經有開源的實現供大家參考(https://www.kaggle.com/c/the-nature-conservancy-fisheries-monitoring/discussion/26202),
在這里分析一下模型訓練文件train.py的邏輯結構。
-
ü Import相關的模塊以及參數的設置——圖4;
-
ü 構建Inception_V3深度卷及網絡,使用在ImageNet大規模圖片數據集上已經訓練好的參數作為初始化,定義回調函數保存訓練中在驗證集合上最好的模型——圖5;
-
ü 使用數據擴增(Data Augmentation)技術加載訓練圖片,數據擴增技術是控制過擬合現象的一種常見的技巧,其思想很簡單,同樣是一張圖片,如果把它水平翻轉一下,或者邊角裁剪一下,或者色調再調暗淡或者明亮一些,都不會改變這張圖片的類別——圖6;
-
ü Inception_V3網絡模型訓練;
圖4. Import和參數設置
圖5. 構建Inception_V3網絡並加載預訓練參數
圖6. 使用數據擴增技術加載訓練和驗證圖片集
圖7. 模型訓練
4、提升排名的若干技巧
一旦我們訓練好了模型,我們就用這個模型預測那些測試圖片的類別了,論壇中predict.py中的代碼就是預測魚類的並且生成提交文件。這里我們給大家分享一下在機器學習和圖像識別類競賽中常見的兩個技巧,簡單而有效。它們的思想都是基於平均和投票思想。其背后的原理用一句話總結就是:群眾的眼睛是雪亮的!
技巧1:同一個模型,平均多個測試樣例
這個技巧指的是,當我們訓練好某個模型后,對於某張測試圖片,我們可以使用類似數據擴增的技巧生成與改張圖片相類似的多張圖片,並把這些圖片送進我們訓練好的網絡中去預測,我們取那些投票數最高的類別為最終的結果。Github倉庫中的predict_average_augmentation.py實現的就是這個想法,其效果也非常明顯。
技巧2:交叉驗證訓練多個模型
還記得我們之前說到要把三千多張圖片分為訓練集和驗證集嗎?這種划分其實有很多種。一種常見的划分是打亂圖片的順序,把所有的圖片平均分為K份,那么我們就可以有K種<訓練集,驗證集>的組合,即每次取1份作為驗證集,剩余的K-1份作為訓練集。因此,我們總共可以訓練K個模型,那么對於每張測試圖片,我們就可以把它送入K個模型中去預測,最后選投票數最高的類別作為預測的最終結果。我們把這種方式成為“K折交叉驗證”(K-Fold Cross-Validation)。圖9表示的就是一種5折交叉驗證的數據划分方式。
圖9. 五折交叉驗證
當然,技巧1和2也可以聯合在一起使用。假設我們做了5折交叉驗證,並且對於每一張測試圖片都用5次數據擴增,那么不難計算,每一張測試圖片的投票數目就是25個。采用這種方式,我們的排名可以更進一步。
5、后記
我們回顧了深度學習中的深度卷積網絡的典型結構和特點,並且知道了如何使用梯度下降算法來訓練一個深度網絡。我們展示了如何用微調技術,使用Inception_V3網絡來解決Kaggle的NCFM海魚分類比,並且通過兩個簡單而有效的小技巧,使得我們的排名能夠進入Top 5%。
如果讀者對該比賽有興趣,想進一步提升名次,那么一種值得嘗試的方法是:物體檢測(Object Detection)技術。試想一下,其實我們只要區分海魚的品種,由於攝像頭遠近等關系,圖片中海魚的區域其實只占據一小部分像素點,更多的區域都是船體、桅桿或是海洋等噪音。如果有一種算法能夠幫我們把海魚從照片中“扣”(檢測)出來,那么可以想象,深度網絡的准確率就能夠進一步提升了,這部分的工作就留給有興趣的同學自己做進一步研究了。
七月在線彭老師、二零一七年五月十日。
參考資料
-
[1] https://www.kaggle.com/
-
[2] http://cs231n.github.io/neural-networks-3/
-
[3] https://github.com/tensorflow/tensorflow
-
[4] https://github.com/fchollet/keras
-
[5] Image Classification with Deep Convolutional Neural Networks. NIPS 2012.
-
[6] Very Deep Convolutional Networks for Large-Scale Image Recognition. ICLR 2015.
-
[7] Going Deep with Convolutions. CVPR 2015.
-
[8] Rethinking the Inception Architecture for Computer Vision. CVPR 2016.
-
[9] Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning. ICLR 2016.
-
[10] Deep Residual Learning for Image Recognition. CVPR 2016.
-
[11] http://www.image-net.org/
-
七月在線《kaggle案例實戰班》
-
kaggle實戰公開課《模型分析與模型融合》