Women in Data Science 與合作伙伴共同發起了 WiDS 資料馬拉松競賽(WiDS datathon)。賽題是建立一個能夠預測衛星影像上油棕種植園存在情況的模型。
Planet 和 Figure Eight 慷慨地提供了衛星影像的帶註釋資料集,而該衛星影像是最近由 Planet 衛星拍攝的。該資料集影像具有 3 米的空間解析度,並且每一副影像都基於是否含油棕種植園來標記(0 意為沒有油棕種植園,1 意為存在一個油棕種植園)。
競賽任務是訓練一個模型,該模型能夠輸入衛星影像,輸出包含油棕種植園影像的似然預測。在模型開發中,競賽舉辦者提供帶標籤的訓練和測試資料集。
詳細資訊參見:https://www.kaggle.com/c/widsdatathon2019
我和隊友(Abdishakur、Halimah 和 Ifeoma Okoh)使用 fast.ai 框架來迎接這項賽題。非常感謝 Thomas Capelle 在 kaggle 上的啟動核心,該核心為解決這個問題提供了諸多見解。
此外,還要感謝 fast.ai 團隊,該團隊建立了一門不可思議的深度學習課程,該課程簡化了大量困難的深度學習概念。現在,深度學習初學者也可以贏得 kaggle 競賽了。
課程地址:https://course.fast.ai/
從一個通俗易懂的深度學習指南開始
不要想著馬上就能理解所有東西,這需要大量的練習。本指南旨在向深度學習初學者展示 fast.ai 的魅力。假定你瞭解一些 python 知識,也對機器學習稍有涉獵。這樣的話,我們就走上了學習正軌。
(引用)本文展示的所有程式碼可在 Google Colaboratory 中找到:這是一個 Jupyter 筆記本環境,不需要進行任何設定就可以使用,並且完全在雲端執行。你可以通過 Colaboratory 編寫和執行程式碼,儲存和分享分析,訪問大量的計算資源,所有這些都是免費的。
程式碼參見:https://colab.research.google.com/drive/1PVaRPY1XZuPLtm01V2XxIWqhLrz3_rgX。
匯入 fast.ai 和我們將要使用的其他庫
輸入庫
獲取競賽資料
為了儘可能簡潔明瞭,Abdishakur 上傳競賽資料檔案至 dropbox.com。你可以在競賽頁面上找到這些資料。你需要接受競賽規則,並在參賽後訪問資料。
觀察資料
我們在解決一個問題時首先要做的是觀察可用資料。在想出解決方案之前,我們需要理解這個問題以及資料是什麼樣的。觀察資料意味著理解資料目錄的構成方式、資料標籤以及樣本影像是什麼樣的。
使用 pandas 庫來讀取資料。
訓練模型所要使用的資料標籤。
處理「影像分類資料集」和「表格資料集」的主要區別在於標籤的儲存方式。這裡的標籤指的是影像中的內容。在這個特定的資料集中,標籤以 CSV 檔案格式儲存。
想要了解更多計算「分數」列的方法,點選:
https://success.figure-eight.com/hc/en-us/articles/201855939-How-to-Calculate-a-Confidence-Score。
我們將使用 seaborn 的 countplot 函式來觀察訓練資料的分佈。我們從下圖中看到,大約 14300 個影像中沒有發現油棕種植園,而僅有 942 個影像中發現了油棕種植園。這就是所謂的不平衡資料集,但我們在這裡不討論這個深度學習問題。我們此刻正邁出了一小步。
統計兩個類別的樣本數。
訓練資料集中分佈
準備資料
提供的測試資料放置於兩個不同的資料夾中: leaderboard 留出資料和 leaderboard 測試資料。由於競賽要求提交這兩種資料集的預測,所以我們將兩者相結合。我們共獲得 6534 副影像。
結合 leaderboard 留出資料和 leaderboard 測試資料。
我們將使用 fast.ai 的 DataBlock API 來構成資料,這是一種將資料集呈現給模型的簡便方法。
建立一個 ImageList 來保留資料
我們將使用 ImageList 來儲存訓練資料,並使用 from_df 方法讀取資料。這樣做的原因是,我們將訓練集資訊儲存在了名為 df 的 DataFrame 中。
接下來需要隨機分割訓練集,並保留 20% 作為驗證集,從而在訓練中監督模型效能。我們選擇了一個 seed,以確保再一次訓練時能得到相同的結果,通過相同的 seed,我們就能知道哪些改進是好的,哪些是壞的。
此外,我們同樣還要把訓練集的標籤地址提供給 ImageList,並將資料與標籤合併。
最後,還需要在資料上執行轉換,通過設定 flip_vert = True 將翻轉影像,這能幫助模型識別不同朝向的影像。此外,還需要使用 imagenet_stats 來歸一化影像。
預覽影像
如下是有或沒有油棕種植園的衛星影像:
展示兩個 Batch 的影像。
有油棕的影像標記為 1,沒有油棕的標記為 0
訓練我們的模型
現在,開始訓練我們的模型。我們將使用卷積神經網路作為主體,並利用 ResNet 模型的預訓練權重。ResNet 模型被訓練用來對各種影像進行分類,不用擔心它的理論和實現細節。現在,我們構建的模型以衛星影像作為輸入,並輸出這兩個類別的預測概率。
卷積神經網路
搜尋最佳模型學習率。
接下來,我們用 lr_find() 函式找到了理想的學習率,並使用 recorder.plot() 對其進行了視覺化。
搜尋最佳模型學習率。
我們將選擇斜率最大的學習率,在這裡我們選擇的是 1e-2。
用學習率 1e-2 對模型展開 5 個週期的訓練。
我們將使用 fit_one_cycle 函式對模型進行 5 個 epoch 的訓練(遍歷所有資料 5 次)。
訓練和驗證損失。
注意展示的 metrics,即 training_loss 和 valid_loss。隨著時間的推移,我們使用它們來監控模型的改進。
最佳模型是在第四個 epoch 時獲得的。
訓練階段模型的輸出;訓練和驗證損失的變化過程。
在你進行訓練和驗證資料集時,fast.ai 只在內部挑選並儲存你的最佳模型。
評估我們的模型
競賽提交的材料是根據預測概率和觀測目標 has_oilpalm 之間的 ROC 曲線來評估的。預設情況下,Fast.ai 不會附帶這個指標,所以我們將使用 scikit-learn 庫。
列印驗證指標。
使用預訓練模型和 fast.ai 的妙處在於,你可以獲得很好的預測準確率。在我們的案例中,沒有費多大力就獲得了 99.44% 的準確率。
訓練第一階段的指標。
儲存模型,並繪製關於預測的混淆矩陣。
使用混淆矩陣檢視結果
繪製混淆矩陣
混淆矩陣是一種圖形化的方式,可以檢視模型準確或不準確的預測影像數量。
第一個訓練階段的混淆矩陣。
從這個矩陣中可以看出,模型準確地預測出有 2863 張影像中沒有油棕,168 張影像中有油棕。10 張有油棕的影像被分類為沒有,而 7 張沒有油棕的影像則被分類為有油棕。
對這種簡單的模型來說,這個結果不錯了。接下來,我們搜尋到了訓練的理想學習率。
搜尋理想的學習率。
我們在學習率 1e-6 和 1e-4 之間選擇了一個學習率。
在 7 個 epoch 內,使用 1e-6 和 1e-4 之間的最大學習率來擬合模型。
對模型進行 7 個週期的訓練,學習率應在 1e-6 和 1e-4 範圍內。
訓練和驗證損失。
以圖形方式觀察訓練指標,以監控每個訓練週期後模型的效能。
訓練階段模型的輸出;訓練和驗證損失的變化過程。
儲存模型的第二個訓練階段:
準確率、誤差率和 AUC 分數
列印模型的準確率、誤差率和 AUC 指標:
第二個訓練階段的指標。
如你所見,模型的準確率從 99.44% 上升到了 99.48%。誤差率從 0.0056 降到了 0.0052。AUC 也從 99.82% 上升為 99.87%。
繪製混淆矩陣。
與我們繪製的上一個混淆矩陣相比,你會發現模型的預測效果更好了。
第二個訓練階段的混淆指標
之前有 7 張不含油棕種植園的影像被錯誤分類,現在降到了 3 張,這就是進步。
我們在訓練和調參期間遵循了一種模式。大多數深度學習實驗都遵循類似的迭代模式。
影像轉換
我們將在資料上執行更多的影像轉換,這應該是能提升模型效果的。影像轉換的具體描述可以在 fast.ai 文件中找到:
應用不同的轉換以提升模型效果
max_lighting:如果超參不為 None,那麼以 p_lighting 為概率隨機進行亮度、對比度的調整,且最大亮度不超過 max_lighting。
max_zoom:如果超參不小於 1,那麼以 p_affine 為概率隨機放大 1 到 max_zoom 倍。
max_warp:如果超參不為 None,那麼以 p_affine 為概率在-max_warp 和 max_warp 之間隨機對稱變換。
我們再一次搜尋最優學習率:
搜尋一個合理的學習率
我們選擇的學習率是 1e-6
將模型訓練 5 個週期。
訓練 5 個週期
訓練和驗證損失
比較訓練指標,並與過去的指標進行比較。我們的模型在這次迭代中略遜於 0.0169 和 0.0163。先不要洩氣。
訓練階段模型的輸出;在第 3 個 epoch 時得到最佳模型
儲存模型訓練的第三個階段並列印出指標。如圖所示,當前模型的準確率為 99.38,上一個階段的準確率為 99.48%。AUC 分數從 99.87% 提高到了 99.91%,這是比賽評分的標準。
準確率、誤差率和 AUC 分數
第三個訓練階段的指標
最終訓練階段
你可能注意到了,我們剛開始使用的影像大小為 164,然後逐漸增加到 256(如下所示)。這麼做是為了利用 fast.ai 用於分類的漸進式影像大小縮放,即在一開始使用小影像,之後隨著訓練逐漸增加影像大小。如此一來,當模型早期非常不準確時,它能迅速看到大量影像並實現快速改進,而在後期訓練中,它可以看到更大的影像,學到更多細粒度的差別。(詳情請參見:現在,所有人都可以在 18 分鐘內訓練 ImageNet 了)
應用不同的變換來改進模型,將影像大小增加到 256
我們又發現了一個最佳學習率。
找到理想學習率
找到理想的學習率
以 1e-4 的學習率訓練 5 個 epoch 以擬合模型。
以 1e-4 的學習率對模型訓練 5 個週期
訓練和驗證損失
觀察訓練指標並與之前的指標對比。我們的模型有了小小的提升(損失從 0.169 降到了 0.168)。
模型訓練階段的輸出。在第 2 個 epoch 時得到最佳模型
儲存模型最後的訓練階段並列印出指標。
準確率、誤差率和 AUC 分數
如下所示,模型的準確率為 99.44%,優於上一個訓練階段 99.38% 的準確率。
第四個訓練階段的指標
準備一個競賽提交檔案
現在可以看到我們的模型對未見過的資料做出了多麼好的預測。
準備一個 CSV 提交檔案
將檔案提交給 WiDS Datathon
你仍然可以參加 WiDS 競賽並晚一點提交。進入參賽頁面,點選「Join Competition」,瞭解比賽規則。現在你可以提交作品,看看自己會排到第幾。
根據模型預測對提交的作品進行打分
原文連結:https://towardsdatascience.com/how-a-team-of-deep-learning-newbies-came-3rd-place-in-a-kaggle-contest-644adcc143c8