使用 PyTorch 提供的預訓練模型 (Pretrained Model) 做影像分類 (Image Classification)

rowan.ts
8 min readMay 24, 2020

--

圖一、CIFAR-10 資料集

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 推論時間越多。所以說, ResNet50ResNeXt-50-32x4d 或是 MNasNet 1.0 都是蠻常用於做遷移學習的模型呢!

圖二、從一張圖挑選影像分類的預訓練模型。

不過,我們可以依據使用的場合來選擇預訓練的模型:如果錯誤的容忍度低,就會越往 Top-1 error 低的模型挑選;如果需要較快速的推論時間,就會往 CPU 推論時間少的模型挑選。

隨著時間的演進,模型朝著更輕量、更高的準確率發展,如下圖三,SqueezeNetShuffleNet v2MobileNet V2 的參數量少,推論時間也越短,輕量的模型就越有可能在 Edge 端運行。

圖三、CPU 推論時間與模型權重參數量,往往呈現正相關的關係。

以上是影像分類的預訓練模型比較,接下來會說明如何直接使用預訓練模型進行推論,就讓我們繼續看下去吧 💪 😙 !

如何使用呢

包含✌步驟,影像前處理以及定義一個預訓練模型。

影像前處理

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 將所有轉換依順序執行:

  1. trns.Resize((h, w))PIL Image 影像大小調整至 224 x 224
  2. trns.ToTensor() 將影像大小為 (H x W x C) ,值的範圍介於 [0, 255]PIL Image 或是 numpy.ndarray ,轉換至影像大小為 (C x H x W) ,值的範圍介於 [0.0, 1.0]torch.FloatTensor
  3. trns.Normalize() 用來正規化,需給定影像平均值 (mean) 和標準差 (std) 。PyTorch 提供之預訓練模型 (pretrained model) 皆使用 ImageNet 資料集訓練,訓練集所計算出來的平均值 (mean) 和標準差 (std) 分別如下:mean = [0.485, 0.456, 0.406]std = [0.229, 0.224, 0.225]
  4. 最後,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,以及圖四範例圖片:

圖四、請下載此影像,檔名設定為 maltese.jpeg,作為示範輸入哦!

最後執行指令,給定 --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

--

--