使用Tensorflow和VGG16預訓模型進行預測
fast.ai的入門教程中使用了kaggle: dogs vs cats作為例子來讓大家入門Computer Vision。不過並未應用到最近很火的Tensorflow。Keras雖然可以調用Tensorflow作為backend,不過既然可以少走一層直接走Tensorflow,那秉着學習的想法,就直接用Tensorflow來一下把。
聽說工程上普遍的做法並不是從頭開始訓練模型,而是直接用已經訓練完的模型稍加改動(這個過程叫finetune)來達到目的。那么這里就需要用Tensorflow還原出VGG16的模型。這里借鑒了frossard的python代碼和他轉化的權重。架構具體如下:(cs231n有更詳細的介紹)
INPUT: [224x224x3] memory: 224*224*3=150K weights: 0
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*3)*64 = 1,728
CONV3-64: [224x224x64] memory: 224*224*64=3.2M weights: (3*3*64)*64 = 36,864
POOL2: [112x112x64] memory: 112*112*64=800K weights: 0
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*64)*128 = 73,728
CONV3-128: [112x112x128] memory: 112*112*128=1.6M weights: (3*3*128)*128 = 147,456
POOL2: [56x56x128] memory: 56*56*128=400K weights: 0
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*128)*256 = 294,912
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
CONV3-256: [56x56x256] memory: 56*56*256=800K weights: (3*3*256)*256 = 589,824
POOL2: [28x28x256] memory: 28*28*256=200K weights: 0
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*256)*512 = 1,179,648
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [28x28x512] memory: 28*28*512=400K weights: (3*3*512)*512 = 2,359,296
POOL2: [14x14x512] memory: 14*14*512=100K weights: 0
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
CONV3-512: [14x14x512] memory: 14*14*512=100K weights: (3*3*512)*512 = 2,359,296
POOL2: [7x7x512] memory: 7*7*512=25K weights: 0
FC: [1x1x4096] memory: 4096 weights: 7*7*512*4096 = 102,760,448
FC: [1x1x4096] memory: 4096 weights: 4096*4096 = 16,777,216
FC: [1x1x1000] memory: 1000 weights: 4096*1000 = 4,096,000
具體實現移步VGG16。這里要注意的一點就是最后的輸出是不需要經過Relu的。
預測貓和狗不能照搬這個架構,因為VGG16是用來預測ImageNet上1000個不同種類的。用來預測貓和狗兩種類別,需要在這個架構的基礎上再加一層FC把1000轉化成2個。(也可以把最后一層替換掉,直接輸出成2個)。我還在VGG16之后多加了一層BN,原來VGG16的時候並不存在BN。我也並沒有在每個CONV后面加,因為不想算...

FC的輸出在訓練的時候使用Cross Entropy損失函數,預測的時候使用Softmax。這樣就可以識別出給定圖片是貓還是狗了。具體代碼移步cats_model.py
我們來看一下效果如何。完整的:Jupyter Notebook
未經過Finetune直接運行VGG16改模型(加上了最后一層FC)的結果(預測非常不准,因為最后一層的權重都是隨機的)。這么做的目的是看一下模型是否能運行,順便看看能蒙對幾個。

經過一次迭代,准確率就達到95%了(重復過幾次,這次並不是最高的)。

再看一下同樣的圖片預測結果,似乎准確了很多。

Final Thoughts
圖像識別非常有趣,是一個非常有挑戰的領域。
