1. 程式人生 > 其它 >【學術】實踐教程:使用神經網路對犬種進行分類

【學術】實踐教程:使用神經網路對犬種進行分類

幾天前,我注意到由Kaggle主辦的犬種識別挑戰賽。我們的目標是建立一個模型,能夠通過“觀察”影象來進行犬種分類。我開始考慮可能的方法來建立一個模型來對犬種進行分類,以及瞭解該模型可能達到的精度。

在現代機器學習框架中,像TensorFlow,公開可用的資料集和預先訓練的影象識別模型,可以在不應用過多的工作和花費過多的時間和資源的情況下,以相當好的準確性解決問題。我將分享使用TensorFlow構建犬種分類器的端到端流程。

repo包含了使用經過訓練的模型進行訓練和執行推斷所需的一切。 repo地址:https://github.com/stormy-ua/dog-breeds-classification

訓練資料集

擁有一個良好的培訓資料集是向健壯的模型邁出的一大步。斯坦福的犬種資料集有20K影象,包含120個品種的狗。資料集裡的每一個影象都標註了狗的品種。你可能已經注意到了,只有20K張的120個不同品種的影象(每品種200個影象)不足以訓練一個深度神經網路。卷積神經網路(CNN)是影象分類中最好的機器學習模型,但在這種情況下,沒有足夠的訓練例項來訓練它。它將無法從這個資料集上學習到足夠通用的模式來對不同的犬種進行分類。最可能的是,它會過度擬合這些少量的訓練示例,這樣測試集的精確度就會降低。有兩種可能的方法來減緩訓練示例缺乏的情況:

  • 將犬種影象資料集與另一個更大的影象資料集(如ImageNet),並在合併的例子上訓練CNN;
  • 在更大的資料集上接受預先訓練的深層神經網路,切入它,附加一個額外的“分類頭[classification head]”,即帶有Softmax的幾個額外的完全連線的層。

第一種方法有兩大缺點:需要分析大量的資料,而這個大資料集的訓練將花費更多的時間和資源。第二種方法似乎更可行:訓練必須在原始資料集上執行,並且訓練的“分類頭[classification head]”只有幾個完全連線的層,不需要大量的時間和資源。

訓練將“分類頭[classification head]”連線在一個較小資料集上的預訓練的模型的方法叫做轉移學習。

轉移學習發揮作用是因為CNNs的工作原理。有相當多的資源描述了工作原理的細節,例如http://cs231n.stanford.edu/。簡而言之,在一個大資料集上訓練的深層神經網路的底層,以捕獲了影象的低階原語[low-level primitives](例如輪廓和簡單的形狀),這樣所有的影象都是通用的,並且可以被“轉移”到任何影象識別問題。

神經網路模型

最終的神經網路模型如下:

影象被送入初始[Inception]模型。初始[Inception]模型的輸出通過幾個完全連線的(FC)層,最後,softmax輸出影象的概率屬於每個類。只有FC層代表的“分類頭[classification head]”必須接受訓練。初始模型使用已預定義的模型引數保持凍結。

下載並準備資料

下一個步驟是下載犬種資料集和預先訓練的谷歌初始[Inception]模型。從repo的根目錄執行setup / setup.sh指令碼將下載所有內容,解壓縮並放入適當的目錄中。下載和提取的資料集是一組資料夾,其中包含單獨檔案中的影象和註釋。TensorFlow有一個數據集API,它使用TF記錄資料格式可以更好地工作。它的工作原理是將所有的訓練示例和它們的註釋放在一個檔案中,其中所有的例子都儲存為protobuf序列化格式。在使用最小磁碟I / O操作和記憶體需求的訓練過程中,TensorFlow資料集API可以有效地使用這種資料格式,並載入儘可能多的示例。有一個python指令碼將原始的狗資料集轉換為TF記錄檔案,準備用於訓練:

setup / setup.sh地址:https://github.com/stormy-ua/dog-breeds-classification/blob/ master/setup/setup.sh 資料集API地址:https://www.tensorflow.org/versions/r1.4/programmers_guide/datasets python指令碼地址:https://github.com/stormy-ua/dog-breeds-classification/blob/ master/src/data_preparation/stanford_ds_to_tfrecords.py

python-m src.data_preparation.stanford_ds_to_tfrecords

它必須從repo的根目錄執行。轉換資料集需要大約1小時。每個映像都被輸入到初始[Inception]模型,並將其帶有影象的輸出與和其他註釋儲存在一起。這簡化了訓練,因為我們不需要在培訓期間為每個示例計算初始輸出,而是預先計算以備使用。結果TF記錄檔案位於data/stanford.tfrecords中。setup.sh指令碼還下載並提取谷歌的初始模型,將其表示為凍結的TensorFlow圖。凍結意味著所有變數都被常量替換,並嵌入到圖形本身中,這樣就不需要攜帶檢查點檔案和圖形,以便將模型載入到TensorFlow會話中並開始使用它。初始模型可以在frozen/inception/classify_image_graph_def.pb中獲得。

訓練

下一步是執行訓練。首先,為模型提供一個獨特的名稱。其次,應該配置一些完全連線的層和這些層中的單元數。可以在src/common/consts.py模組中配置。

src/common/consts.py模組地址:https://github.com/stormy-ua/dog-breeds-classification/blob/master/src/common/consts.py

CLASSES_COUNT= 120
INCEPTION_CLASSES_COUNT= 2048

# name of the model being referenced by all other scripts
CURRENT_MODEL_NAME= 'stanford_5_64_0001'
# sets up number of layers and number of units in each layer for
# the "head" dense neural network stacked on top of the Inception
# pre-trained model.
HEAD_MODEL_LAYERS= [INCEPTION_CLASSES_COUNT,1024, CLASSES_COUNT]

預設情況下,有2個完全連線的層,分別帶有1024個單元和120個單元。而輸入層有2048個單元,與初始模型最後一層的單元數相同。

用src/training/train.py訓練,學習率、epochs的數量和小批量的大小可以在該指令碼中配置。

src/training/train.py地址:https://github.com/stormy-ua/dog-breeds-classification/blob/master/src/training/train.py

python-m src.training.train

除此之外,TensorBoard還可以開始訓練監測。

TensorBoard地址:https://www.tensorflow.org/get_started/summaries_and_tensorboard

tensorboard--logdir=./summary

有三個度量指標:成本、測試集的誤差和訓練集的誤差。預設情況下,計算訓練集中的3000個示例的誤差率,並計算包含3000個示例的測試集的誤差率。我用以下超引數訓練了模型:

  • 小批量的大小=64
  • 學習率=0.0001
  • Epoch數量=5000

以下是我在TensorBoard中得到的關於這三個指標的資料:

成本

測試集的誤差

訓練集樣本的誤差

用大約1小時執行5K個epochs。訓練結束後,指標有以下值:

  • 成本=0.1
  • 測試誤差2.7%
  • 訓練誤差=2.5%

在測試和訓練集上兩個誤差都很低,而且兩個誤差大致相同,所以訓練集沒有嚴重的過度適合的症狀。

凍結模型

一旦模型被訓練,它的優化引數就儲存在./checkpoints dir的檢查點檔案中。為了有效地重新利用模型進行推理,將其作為一個具有將引數嵌入到圖形本身的凍結TensorFlow圖形是很好的。可以使用src/freezing/freezy.py進行此操作:

src/freezing/freezy.py地址:https://github.com/stormy-ua/dog-breeds-classification/ blob/master/src/freezing/freeze.py

python-m src.freezing.freeze

此指令碼按以下順序執行幾項操作:

  • 將初始模型和“分類頭[classification head]”模型載入到相同的TensorFlow會話中,並將它們繫結在一起,形成一個單一的計算圖形,以便初始模型的輸出直接進入“分類頭[classification head]”模型的輸入。一旦繫結完成,指令碼將在檔案系統的圖形中序列化複合模型。在這一點上,圖形還沒有被凍結,因為在訓練過程中計算的模型引數仍然處於檢查點檔案中。
  • 使用TensorFlow freeze_graph函式凍結在前一步中生成的圖形。它從檢查點檔案中提取模型引數並將它們注入到圖形變數中。圖形變數轉換為常數。生成的檔案將到名為模型的./frozen目錄。

freeze_graph函式地址:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/tools/freeze_graph.py#L206

推理

一旦凍結模型準備好,就可以用於對任意影象進行分類。src/inference/classify.py指令碼可以將儲存在檔案系統上或者可用的狗的影象歸類為HTTP資源。在幕後,它載入凍結圖形並將影象輸入其中。以下是關於 Airedale Terrie和Shih-Tzu的推理工作的兩個例子:

python-m src.inference.classifyfile images/airedale.jpg

                   breed      prob
                airedale 0.979627
              otterhound 0.009855
           irish_terrier 0.007160
chesapeake_bay_retriever 0.001507
 wire-haired_fox_terrier 0.000824
python-m src.inference.classify uri https://raw.githubusercontent.com/stormy-ua/dog-breeds-classification/master/images/shih-tzu.jpg

           breed      prob
        shih-tzu 0.669201
           lhasa 0.319596
 tibetan_terrier 0.005996
japanese_spaniel 0.001398
        pekinese 0.000928

如果你想知道推理是如何工作的,那就需要有一個docker容器,它包含所有的程式碼和凍結模型。它公開Python的筆記本進行推斷。實際上,它甚至在docker容器內完成了所有的工作。可以使用以下命令啟動容器:

docker容器地址:https://hub.docker.com/r/kirillpanarin/dog_breed_classification/

docker run-p8888:8888 -p6006:6006 kirillpanarin/dog_breed_classification

一旦容器開始,導航到瀏覽器http://localhost:8888/notebooks/Inference.ipynb,你就可以使用自己的影象分類器了。

誤差分析

更仔細地研究一個機器學習模型未能正確分類的例子是一個好想法。指令碼src/analysis/training_perf_analysis.py生成預測的CSV檔案(它用於metrics/training_confusion.csv),併為所有訓練示例提供實際的品種。

src/analysis/training_perf_analysis.py指令碼地址:https://github.com/stormy-ua/dog-breeds-classification/blob/master/src/analysis/training_perf_analysis.py

通過載入training_confusion的資料,csv可以繪製混淆矩陣:

由於狗的品種太多,很難在這裡進行詳細的分析。讓我們試著分析前30個誤分類的品種(Confusion.ipynb中提供了一個例子):

Confusion.ipynb地址:https://github.com/stormy-ua/dog-breeds-classification/blob/ master/Confusion.ipynb

正如所看到的,“絲質小獵犬”和“約克郡犬”誤分類的概率上是最高的,如果我們研究一下這兩種狗的樣子,就會覺得很有道理。

約克郡犬

絲質小獵犬

看起來絲質小獵犬和約克郡犬經常被人混淆。更多細節在下面這篇文章中。

文章地址:https://www.cuteness.com/article/difference-between-yorkie-silky-terrier

你是一個愛狗的人嗎?

如果你認為自己是一個愛狗的人,你可以繼續問問你的模型下圖中的狗是什麼品種:)在我的情況下,我得到了以下答案:

迷你品犬

結論

正如我們所看到的那樣,即使沒有足夠的訓練影象和/或計算資源,如果你可以使用預訓練的深層神經網路和現代機器學習庫(如TensorFlow),也可以訓練一個強大的影象分類器。