從VGG到ResNet,你想要的MXNet預訓練模型輕鬆學
選自AWS Blog
作者:Julien Simon
機器之心編譯
參與:Pedro、路
本文介紹了如何利用 Apache MXNet 預訓練出的多個模型。每個模型在特定圖像上的表現略有不同,訓練多個模型旨在找出更適合特定任務的模型。
在這篇博文中,你將會了解如何使用 Apache MXNet 預訓練出的多個模型。為什麼要嘗試多個模型呢?為什麼不直接選擇準確率最高的呢?稍後我們會在文章中看到,儘管這些模型是在相同的數據集上訓練的,並且都針對最大準確率進行了優化,但它們在特定圖像上的表現略有不同。此外,(不同模型)預測速度也不同,而對很多應用來說速度是一個重要的影響因素。嘗試這些模型,或許能找到一個合適的模型解決手頭上的難題。首先,我們先從 Apache MXNet 模型庫中下載三個圖像分類模型。(模型庫地址:http://mxnet.io/model_zoo/)
三個模型分別是:
VGG-16,獲得 2014 年 ImageNet 大規模視覺識別挑戰賽分類項目冠軍。
Inception v3,GoogleNet 的進化版,獲得 2014 年比賽的目標檢測項目冠軍。
ResNet-152,獲得 2015 年比賽的多個項目的冠軍。
我們需要為每一個模型下載兩個文件:
包含神經網路 JSON 定義的符號文件:層、連接、激活函數等。
網路在訓練階段學習到的存儲了所有連接權重、偏置項和 AKA 參數的權重文件。
讓我們來看看 VGG-16 符號文件的第一行。可以看到輸入層的定義("data"),第一個卷積層的權重和偏置項。卷積操作和線性修正單元激活函數分別用(『conv1_1』)和(『relu1_1』)定義。
三個模型都使用 ImageNet 訓練集進行預訓練。這個訓練集包含超過 120 萬張物體和動物的圖像,這些圖像被分成了 1000 個類別。我們可以在 synset.txt 文件中查看這些類別。
現在載入一個模型。
首先,我們需要從文件中載入權重和模型描述。MXNet 將此稱為檢查點。在每個訓練 epoch 之後保存權重是個好習慣。一旦訓練完成,我們可以查看訓練日誌,然後選擇最佳 epoch 的權重,最優 epoch 即具有最高驗證準確度的 epoch。一般來說它不會是最後一個 epoch。在模型載入完成之後,我們得到一個 Symbol 對象和權重、AKA 模型參數。之後我們創建一個新 Module 並為其分配 Symbol 作為輸入。我們可以選擇運行模型的環境:默認情況下使用 CPU 環境。這麼做有兩個原因:
第一,即使你的電腦沒有 GPU,你也能測試 notebook(https://s3.amazonaws.com/aws-ml-blog/artifacts/pre-trained-apache-mxnet-models/Pre-trained%2Bmodels.ipynb)。
第二,我們接下來只預測單個圖像,因此對性能沒有特殊要求。對於那些希望通過預測大量圖像以獲得最佳吞吐量的應用產品,GPU 肯定是最優選擇。
然後,我們將 Symbol 作為輸入數據。我們稱之為 data,為了與它在網路輸入層時的名字保持一致(JSON 文件的前幾行提過)。最後,我們將 data 的形態定義成 1 x 3 x 224 x 224。224 x 224 是圖像解析度:模型就是使用這個解析度的圖像來訓練的。3 是通道數量:紅色、綠色和藍色(按此順序)。1 是批量大小:一次預測一個圖像。
我們還需要載入存儲在 synset.txt 文件中的 1000 個類別。預測時會使用這些類別描述。
現在我們編寫一個從文件中載入圖像的函數。別忘了,模型需要一個四維的 NDArray,其中包含 224 x 224 圖像的紅色、綠色以及藍色通道。我們將利用 openCV 庫及輸入圖像來構建 NDArray。
下面是具體步驟:
讀取圖像:此步會返回一個形如(圖像高度,圖像寬度,3)的 numpy 數組。它包含三個 BGR 順序的通道(藍色、綠色、紅色)。
將圖像轉換為 RGB 順序(紅色、綠色、藍色)。
將圖像大小改為 224 x 224。
將數組從(圖像高度,圖像寬度,3)轉換為(3,圖像高度,圖像寬度)。
加上第四個維度,然後構建 NDArray。
現在我們把重點放在預測上。我們的參數是單個圖像、模型、類別列表以及我們想要優先返回的類別數量。
記住,Module 對象必須批量地向模型輸入數據。通常的做法是使用數據迭代器。此處,我們想要預測單個圖像,所以雖然我們可以使用數據迭代器,但它可能會越界。所以,我們創建一個叫 Batch 的元組,它將作為偽迭代器,在其 data 屬性被引用時返回輸入 NDArray。
在圖像饋送至模型後,模型輸出一個包含 1000 種可能性的 NDArray,對應 1000 個類別。NDArray 只有一行因為批大小為 1。
我們使用 squeeze() 將其轉換為數組。之後使用 argsort() 創建第二個數組用於存放這些降序排列的概率索引。最後我們返回前 n 個類別及其描述。
現在是時候將所有的模塊組裝起來了。載入這三個模型:
在進行圖像分類之前,我們來仔細查看一下之前從 .params 文件中載入得到的 VGG-16 模型參數。首先,我們輸出所有層的名字。
對每一層而言,有兩個部分值得我們關註:權重和偏置項。數一數這些權重你就會發現一共有 16 個層:13 個卷積層以及 3 個全連接層。現在你知道為什麼這個模型叫 VGG-16 了。現在輸出剩下的全連接層的權重:
你注意到這個矩陣的形狀了嗎?它是 1000×4096 的。這個層包含了 1000 個神經元:每一個神經元會存儲圖像屬於某個特定分類的概率。每個神經元也和前一層(『fc7』)所有的神經元(4096 個)全部連接。
現在開始使用這些模型來對我們自己的圖像進行分類:
再用 GPU 環境試試:
注意:如果遇到了關於 GPU 支持的錯誤,有可能是你的機器沒有配置 GPU,或者你使用的 MXNet 版本尚未提供 GPU 支持(USE_CUDA=1)。
構建提供 GPU 支持的 MXNet 教程可參考:https://mxnet.incubator.apache.org/get_started/build_from_source.html;你也可以安裝預製版本:https://mxnet.incubator.apache.org/install/index.html。
GPU 版本和 CPU 版本的性能差異非常明顯,在 15 倍到 20 倍之間。如果我們同時預測多個圖像,由於 GPU 架構的大規模並行性,二者差距會更大。
現在是時候用你自己的圖像試試了。只需將它們複製到此 notebook(https://s3.amazonaws.com/aws-ml-blog/artifacts/pre-trained-apache-mxnet-models/Pre-trained%2Bmodels.ipynb)所處的文件夾即可,更新上述模塊的文件名,然後再次運行 predict() 函數。
原文地址:https://aws.amazon.com/cn/blogs/machine-learning/use-pre-trained-models-with-apache-mxnet/
本文為機器之心編譯,轉載請聯繫本公眾號獲得授權。
------------------------------------------------
※你需要的Scikit-learn中文文檔:步入機器學習的完美實踐教程
※在有池化層、1步幅的CNN上減少冗餘計算,一種廣泛適用的架構轉換方法
TAG:機器之心 |