使用 PyTorch 提供的預訓練模型 (Pretrained Model) 做影像分類 (Image Classification)
PyTorch 提供的預訓練模型
隨著深度學習領域的飛速發展,PyTorch 官方很佛的將常見的模型整合在函式庫中,並且提供預訓練模型,供開發者直接利用。若預訓練模型的輸出剛好與開發功能相同,恭喜你 ㊗️ 🎊,直接收割 👨🌾 👩🌾 使用;若預訓練模型的輸出不巧的與開發功能不同 (通常都是這個情況吧),或是期待準確率可以更高的話,那就可以發揮資料科學家的才能,基於 PyTorch 提供的預訓練模型,做個遷移學習 (Transfer Learning) 的訓練吧!
說了這麼多,PyTorch 到底有多佛,提供哪些預訓練模型呢?依任務類型,可以分成以下種類:
- 影像分類 (Image Classification)
- 語義分割 (Semantic Segmentation)
- 物件偵測、實例分割、人體特徵點偵測 (Object Detection、Instance Segmentation、Person Keypoint Detection)
- 影片分類 (Video Classification)
本篇將以最常見的影像分類作為示範。
PyTorch 提供之影像分類的預訓練模型
截至 2020.05.23 為止,PyTorch 提供之影像分類預訓練模型共有 35 個,可參考連結。
表格中可以看見,預訓練模型網路架構包含 VGG、ResNet、SqueezeNet、DenseNet、Inception v3、GoogleNet、ShuffleNet、MobileNet、ResNeXt、Wide ResNet、MNASNet,以及上述各種不同的變形,官方也附上所有模型的原始論文連結,預訓練模型在 ImageNet 測試的 Top-1 error 和 Top-5 error 表現有高有低,越低代表越準確。
如下圖二,越往表格的左下角,代表有越少的 CPU 推論時間,以及越低的 Top-1 error,代表模型跑得越快也越準;泡泡大小代表的是模型權重參數量,因此通常泡泡越大,則 CPU 推論時間越多。所以說, ResNet50
、ResNeXt-50-32x4d
或是 MNasNet 1.0
都是蠻常用於做遷移學習的模型呢!
不過,我們可以依據使用的場合來選擇預訓練的模型:如果錯誤的容忍度低,就會越往 Top-1 error 低的模型挑選;如果需要較快速的推論時間,就會往 CPU 推論時間少的模型挑選。
隨著時間的演進,模型朝著更輕量、更高的準確率發展,如下圖三,SqueezeNet
、ShuffleNet v2
和 MobileNet V2
的參數量少,推論時間也越短,輕量的模型就越有可能在 Edge 端運行。
以上是影像分類的預訓練模型比較,接下來會說明如何直接使用預訓練模型進行推論,就讓我們繼續看下去吧 💪 😙 !
如何使用呢
包含✌步驟,影像前處理以及定義一個預訓練模型。
影像前處理
PyTorch 預訓練模型的輸入影像大小為 (B x 3 x H x W)
,值的範圍介於 [0.0, 1.0]
。
其中第一個維度 B
為批次 (mini-batch) 數量,可以將多張圖疊起來一次輸入;第二個維度 3
為影像通道數量,順序為 RGB
的三通道影像,因此使用 PIL 函式庫讀圖即為正確的通道順序,若使用 OpenCV 函式庫則為 BGR
順序,需顛倒過來哦;第三和四個維度分別為影像的高和寬,除非使用的是 Inception v3 模型,長與寬設定為 299
,其餘模型的長與寬皆設定為 224
(❗Inception v3 模型的 trns.Normalize()
方法也不同喔)。
因此,若輸入影像為一張圖片,以 MobileNet V2
進行預測,則需要把輸入大小調整為 (1 x 3 x 224 x 224)
。影像轉換的步驟如下,用 trns.Compose
將所有轉換依順序執行:
trns.Resize((h, w))
將PIL Image
影像大小調整至224 x 224
。trns.ToTensor()
將影像大小為(H x W x C)
,值的範圍介於[0, 255]
的PIL Image
或是numpy.ndarray
,轉換至影像大小為(C x H x W)
,值的範圍介於[0.0, 1.0]
的torch.FloatTensor
。trns.Normalize()
用來正規化,需給定影像平均值 (mean) 和標準差 (std) 。PyTorch 提供之預訓練模型 (pretrained model) 皆使用 ImageNet 資料集訓練,訓練集所計算出來的平均值 (mean) 和標準差 (std) 分別如下:mean = [0.485, 0.456, 0.406]
和std = [0.229, 0.224, 0.225]
。- 最後,
unsqueeze(0)
將torch.FloatTensor
在第零維,新增一個新的維度,代表批次 (mini-batch) 數量。
經過上述的轉換後,就能夠將一 PIL Image
轉換至大小為 (1 x 3 x 224 x 224)
,值的範圍介於 [0.0, 1.0]
的 torch.FloatTensor
。
定義一個預訓練模型
有了轉換後的影像後,則需要定義一個預訓練模型。如下,我們宣告了一個 MobileNet V2
模型,並將模型設定為 pretrained=True
使用預訓練的權重。列印出模型可以看出模型是由哪些層所組合而成,最後將模型設定為 eval
模式,取消 Dropout
層在模型中的功能,以及 BatchNormalization
層會依模型訓練後的結果來運作。
推論部分的程式如下:先讀入影像,再依照定義的 transforms
進行轉換,輸入模型後得到一個大小為 1 x 1000
的輸出,因為預訓練模型是以 ImageNet 的 1000 類圖片訓練,再印出 topk
個結果。
完整程式碼請參考這裡,並另外下載 ImageNet 類別定義表 imagenet_classes.txt,以及圖四範例圖片:
最後執行指令,給定 --image_path
和 --class_def
的位置:
python pretrained_infer_image_classification.py \
--image_path /path/to/maltese.jpeg \
--class_def /path/to/imagenet_classes.txt
前五名的輸出分別為 Maltese dog (賓果 👍 輸入照片正是瑪爾濟斯無誤 🐶)、miniature poodle、Old English sheepdog、Dandie Dinmont、toy poodle,而括弧內即為模型說出該答案的信心值。執行結果如下圖五:
來做個總結吧
本篇涵括 PyTorch 提供之預訓練模型種類,並使用視覺化方式,從 Top-1 error、模型權重參數量和 CPU 推論時間等三面向,進行影像分類的預訓練模型比較。最後,說明如何利用 PyTorch 提供的預訓練模型,直接進行推論。
若想知道使用 PyTorch 提供的預訓練模型 (Pretrained Model) 做物件偵測 (Object Detection),請見下方。
感謝您的閱讀,如果文章有益請在底下長按拍手
有任何問題歡迎在底下留言或是來信交流wanju.ts@gmail.com
連結有意思
[1] PyTorch 影像分類之預訓練模型
[2] 本篇之完整程式碼