Kaggle Learn | Deep Learning 深度學習 | 學習資源介紹 (Part 2)

運算資源、訓練模型的資料不夠怎麼辦?Transfer Learning & Data Augmentation

Peter Y
YiYi Network
9 min readApr 24, 2018

--

站在巨人的肩膀上,小資料也能立大功

Photo by Stijn Swinnen on Unsplash

前一篇我們用別人已經訓練好的模型,分辨照片裡有沒有熱狗。這一篇我們要來分辨模型裡「沒有」的東西,例如多種的動物。

該怎麼做呢?第一直覺可能是重新架一個模型,用動物的照片重新訓練。我們的確可以這麼做,但世界上動物很多,要能分辨出多種動物的話,模型一定要夠複雜。

然而,模型愈複雜,需要的訓練資料 (training data)就愈多,訓練要花的硬體資源與時間也多,如果我們沒有這些資料、資源、時間怎麼辦?

在人工智慧時代,「資料」就像過去工業時代的「原油」一樣重要,尤其是「標記良好的資料」其實比想像中更難取得。大部分的模型都是使用透過大量人力標記好的圖片資料庫來訓練,例如上一篇提到的 ImageNet 資料庫,有 1000 種類別,大約 120 萬個標記好的資料。「運算資源」則是另外一個重點,因為深度學習的模型的參數都很多,例如 VGG16 Model 的參數有 1 億多個,要把模型訓練好所需的時間相當可觀。如果我們要分類的東西不在 ImageNet 裡,而資料不夠多,運算資源與時間又不夠時,該怎麼辦呢?

這篇文章導讀 Kaggle Learn 的第四課及第五課,就是在處理這幾個問題的。第四課 Transfer Learning 改裝已經訓練好的模型,讓資料的需求量降低、運算量降低 ; 第五課 Data Augmentation 則是對資料做處理、增加總資料量。

第四課:Transfer Learning

比起自己造輪子,我們應該先試著站在巨人的肩膀上,做一些模型改裝,讓小資料、低運算也能發揮作用。所謂「巨人」,就是別人已經用 ImageNet 訓練好的模型,例如 Google 的 Inception Model、Microsoft 的 Resnet Model 等等,把它當作 Pre-trained Model,幫助我們提取出照片的特徵(feature)。

Transfer Learning 的方法就是把 Pre-trained Model 最後一層拔掉 (註:最後一層是用來分類的),加入新的一層,然後用新資料訓練新層的參數。

舉例來說,別人已經用許多標記良好的照片訓練出可以分類「貓、狗、鳥、魚、老鼠」五種動物的 Pre-trained Model,而我們想分類「兔子、青蛙」這兩種動物,那我們就把 Pre-trained Model 最後一層的五個 neutron 拿掉,加入兩個 neuron,然後用兔子跟青蛙的照片來訓練最後一層的兩個 neuron。

由於 Pre-trained Model 已經被訓練過,可以提取有利於分類的基礎特徵,所以我們只需要較少的兔子、青蛙的照片,就可以順利完成分類。因為我們只調整最後一層的參數,運算量遠遠低於自己訓練模型。

看完了理論,就開始練習寫 Code 吧!

ps: 關於怎麼用 Kaggle Kernel 直接在 Chrome 瀏覽器上練習,請看前一篇文章的「練習單元」使用指南。

有遇過這樣的問題嗎?你把數位相機直立起來,拍了一張人像,原本這張照片應該是橫的,但相機偵測到你拍照時的狀態,所以幫你把它轉成直的。然而,當你把照片匯入電腦的相片編輯軟體時,有些照片的方向又旋轉成橫的了。

這個練習就是要透過 Transfer Learning 分出橫的照片(sideways)和直的照片(upright)。大部分的程式碼 Kaggle 都寫好了,我們只需要填___的部分,確保自己真的瞭解 Transfer Learning 的意涵。

Step One : 建模型

我們要預測的照片種類只有兩種:直的、橫的,所以 num_classes = 2。

我們建的模型 my_new_model 是序列式的(第 9 行的 Sequential)。模型前面放 ResNet50 模型,include_top=False 把 ResNet50 的最後一層拔掉(第 10 行),再加上用來做分類的 Dense 層(第 11 行)。

訓練模型時,模型愈複雜,所需的資料量愈大。而 Transfer Learning 只訓練最後一層,所以即使資料數少,還是能得到準確的結果。模型前面的 ResNet50 是不訓練的(第 15 行 trainable = False)。

Step Two : 編譯 Step One 建好的模型

編譯 my_new_model,接著設定優化模型的方法(optimizer)為:隨機梯度下降法 (Stochastic gradient descent, SGD),loss function 為 cross-entropy。

什麼是 optimizer?什麼是 loss function?什麼是 SGD?先不要害怕,這些東西涉及理論層面,會在 Kaggle Learn 第六課教到。

Step Three : 餵進照片資料、跑模型!

我們把可用的照片分成兩堆,一堆是 training data,用來做模型訓練,另一堆是 validation data,用來檢驗訓練成果的好壞。第 8 行、第 14 行分別填入 training data 跟 validation data 的資料夾位置,並按照題目要求 training data 一次丟入 10 張照片做訓練(第 10 行 batch_size = 10)。

因為 training data 有 220 張照片,一次丟入 10 張,所以總共要丟 220/10=22 次 (第 20 行 steps_per_epoch = 22)。

結果

這個模型的 validation accuracy 為 84.38%,意思是這個模型 (即 my_new_model) 對於分類照片的準確度是 84.38%。我們只用了 220 張照片資料就能做到八成以上的準確度,這就是 Transfer Learning 的威力!

註:或許有人會問,為什麼 training accuracy 比 validation accuracy 還低?Kaggle 教學上的回答是:training accuracy 是好幾個訓練時間點的平均,因此剛開始訓練那些不佳的結果會拉低平均,導致 training accuracy 比 validation accuracy 還低。

第五課:資料擴增 (Data Augmentation)

Data Augmentation 簡單來說,就是想辦法從舊照片生出新照片,讓總訓練的資料數增加。我們可以把照片旋轉、切割、放大縮小、改變顏色…做各種變形。

可以看看吳恩達在 Coursera 影片的實例講解。

練習四:承接練習三「分辨出顛倒的照片」,但透過 Data Augmentation 增加準確度

Step One:建模型 (跟練習三的 Step One&Step Two 一模一樣)

Step Two:使用 Data Augmentation 增加資料量

關於在 Keras 的 ImageDataGenerator 每個參數含義可以看這個文件

在第 7 行的 data_generator_with_aug 運用水平翻轉、寬度、高度變動等方式,從原本的圖片生出更多圖片,把 data_generator_with_aug 當作 training data,而沒有被變形過的圖片(data_generator_no_aug)則當作 validation data。

在訓練資料增加、steps_per_epoch 不變的情況下,總 epochs 數量增加了,即第 30 行的 epochs = 3。

結果

經過 Data Augmentation 的處理後,模型對於分類照片的準確度(validation accuracy) 從 84.38% 上升到 94.01%。

下一步

Kaggle Learn 的課程到現在,我們已經學會使用別人的模型,重新組裝,並且應用到自己想做的分類上。 下一步 Kaggle Learn 要教大家「如何建自己的模型」!

--

--