Kaggle競賽方案分享:如何分辨雜草和植物幼苗

編者按:本文是Kaggle的一項挑戰賽——Plant Seedings Classification的解決方案,作者Kumar Shridhar最終排名第五。其中的方法非常通用,可以用在其他圖像識別任務上。

任務概覽

你能分清楚雜草和莊稼苗嗎?

如果能高效識別雜草,就能有效地提高糧食產量,更好地管理環境。Aarhus University Signal Processing和University of Southern Denmark共同合作,發佈了一份含有12種植物的數據集,其中共有將近960棵植株,分別處於不同的生長階段。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

其中一個樣本植物

該數據集目前已經公開,其中的RGB圖像都經過了標註,其中物理分辨率大約為每毫米10像素。下面是數據集中12種植物的樣本示例:

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

要將每張圖片分到各自的類別中,這一任務可以分成5步:

第一步

首先,機器學習中最重要的任務是分析數據集,在開始著手涉及算法前,理解數據集的複雜程度是非常重要的。

數據集中各類圖片的分佈如下所示:

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

如之前所提到的,這裡總共有12種植物的類型,總共有4750張照片。然而,從上圖我們可以看出各種植物的分類並不平均,有些種類裡有654張圖片,而有的只有221張。這充分說明了數據是不平衡的,在第三步時我們會解決這一問題。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

圖片種類分佈

現在將圖片進行可視化能更好地理解數據。下面的圖片將每類植物都挑選了12張,互相對比看看它們之間都有什麼差別。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

圖中的各種植物看起來都長得很像,只看圖片也沒什麼特別之處。所以我決定用可視化技術t-SNE對圖像分類進行處理。

t-SNE是適用於高維數據集的降維技術,它可以通過Barnes-Hut技術應用到大型真實數據集上。論智君也曾報道過相關資訊:

谷歌實習生提出tSNE在大型高維數據集上實時可視化的方法可視化MNIST:探索圖像降維過程

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

數據集的t-SNE可視化

通過近距離觀察,我們很難看出各類之間的差異。所以重要的是弄清楚數據只是對人來說難以分辨還是對機器學習模型也很難分辨。所以我們需要為此制定一個基礎標準。

訓練和驗證集

在開始對模型設定基礎標準之前,我們需要把數據分成訓練集和驗證集兩部分。一般來說,模型首先在訓練集上訓練,之後在驗證集上測試,並隨著時間在驗證集上不斷提高性能。當我們得到滿意的驗證集的結果後,就可以將模型應用到真實的測試集上,看模型是否過度擬合或欠擬合,從而進行調整。

我們將數據集中的4750張圖片中的80%用作訓練集,20%用作驗證集。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

第二步

有了訓練集和驗證集,我們就開始設立數據集的基準。在這一任務中,我們將用刀卷積神經網絡架構。如果你是個初學者,建議先閱讀有關深度學習基礎知識的文章:深度學習入門筆記。

創建CNN模型的方法有很多,我們選擇了Keras深度學習庫。從頭開始訓練一個CNN效率非常低,所以我們選擇了一個在ImageNet上進行預訓練的模型權重,將其進行微調後加以訓練。其中頂層是用來學習簡單基礎特徵的,所以無需訓練可以直接應用。需要注意的是,我們要檢查一下我們的數據集和ImageNet之間的相似性,以及我們的數據集有多大。這兩個特徵將決定著我們應該如何進行調整。

在本次任務中,我們的數據及較小,但是和ImageNet很相似。所以我們首先可以直接用ImageNet的權重,然後在最後加入一個帶有12種植物種類的輸出層,得出第一個基準。之後我們再改變下面的幾層並進行訓練。

我們用Keras建立最初的基準,因為Keras能提供一些預訓練模型,我們選擇其中的ResNet50和InceptionResNetV2。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

同樣,我們可以根據在ImageNet數據集上檢測這些模型的性能和各模型參數的數量來選擇基準模型。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

對於第一個基準,我刪除了最後的輸出層,加上了一個有12個種類的輸出層。具體如下所示:

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

模型經歷了10次迭代,在第6次後結果達到飽和。訓練精確度達到了88%,驗證精確度達到了87%。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

為了進一步提高性能,有一些底部的層沒有被固定,其中的學習率呈指數衰減。最終將性能提高了兩個百分點。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

以下是這一過程中使用的超參數:

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

第三步

有了基礎標準之後,我們就要基於此改善模型。我們可以從增強更多數據開始,從而增加數據集中圖像的數量。畢竟數據是機器學習之本。

但是之前我們提到,數據是不平衡的,我們需要對其進行處理。

真實的數據集從來都是不平衡的,而模型在小型種類上的表現並不會很好。所以將少數種類中的數據錯分為正常樣本所付出的代價比正常分類錯誤要更高。

所以為了讓數據平衡,通常有以下兩種方法:

1.ADASYN算法。ADASYN可以對擁有較少樣本的種類合成數據,其核心思想是對不同的擁有少數樣本的種類根據學習難易程度進行加權分佈,其中學習難度更高的種類合成的數據越多,容易學習的種類數據越少。因此,ADASYN方法用兩種改變數據分佈的方式提升了學習性能:(1)減少分類不平衡引起的偏差,(2)自適應地將分類決策表姐移向困難的樣本。

2.SMOTE算法。SMOTE算法是對少類進行過採樣或者下采樣來得到最佳結果。通過對少數樣本進行過採樣,同時對多數類別進行下采樣可以讓分類器得到最佳水平。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

在這一情況下,SMOTE比ADASYN表現得更好。數據集平衡後,我們可以進行數據增強處理,所用方法有以下幾種:

  • 尺度變換
  • 裁剪
  • 翻轉
  • 旋轉
  • 平移
  • 添加噪聲
  • 改變光線條件
  • GAN

第四步

為了進一步提高性能,我們要對學習率進行改進。在這之前,首先需要找到模型的最佳學習率是多少。這就需要在學習率和損失函數之間繪圖,看看損失從哪開始減少。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

在我們的案例中,1e-1看上去是完美的學習率,但是當我們越來越接近全局最小值,我們就想邁出更小一步。其中一個方法是學習速率退火(learning rate annealing),但是我用的是熱重啟(warm restart)。同樣,優化器從Adam換成了SGD,並安裝了SGDR。

現在,我們要用以上技術訓練多個架構,然後將結果融合在一起,這被稱為模型集成。雖然這種方法已經很普遍了,但是卻十分耗費計算量。所以我決定用快照集成法(snapshot ensembling),即訓練單個神經網絡進行集成,並讓它在優化過程中收斂到幾個局部最小值,節省模型參數。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

搞定了學習速率方法後,我開始調整圖像尺寸。我訓練了一個模型,其中圖像尺寸為64×64(在ImageNet上進行微調),解鎖一些圖層後,應用了循環學習速率和快照集成,取模型的權重,將尺寸改變成299×299,再根據64×64的權重進行微調,之後進行快照集成和熱重啟。

第五步

最後一步是將結果進行可視化從而確定哪一種類有最佳表現(或最差表現),還需要做些什麼來提高結果。理解結果的一種好方法是建立一個混淆矩陣。

Kaggle競賽方案分享:如何分辨雜草和植物幼苗

我們可以看到模型預測的標籤和真實標籤的不同,我們可以慢慢改善這一狀況。我們還可以做更多數據增強的工作,讓模型學習更多種類。

方案提交後,我的排名位列第一(但隨著競賽展開,目前位列第五)。


分享到:


相關文章: