VGG19 特徵
VGG19 總共有 16個捲積層及3個全連接層。詳細圖示如下

上圖中,共有 5 個 block, 分別為 block1~5 ,這 5 個 block 就是以前所稱的隱藏層。block1及 block2 分別有 2 個conv(捲積層)及1個maxpool,block3~5 分別有 4 個捲積層及 1 個 maxpool。最後還有 FC1, FC2, softmax 三個輸出層。另外還有一個上圖沒畫出來的,也就是最前面的輸入層 (input_1)。
5 個 block 隱藏層的作用,就是在取得每張圖片的特徵,本篇的目的就是要探討什麼叫特徵,特徵長什麼樣子。
底下代碼,使用 model.layers 可以印出輸入層,隱藏層,及輸出層共有 26 層的名稱。model.output 是使用Tensorflow 格式印出輸出層,model.outputs 則是使用字典格式印出輸出層,二者皆是同一個物件,而且只印出最後的 predictions 層。
from keras import applications model = applications.vgg19.VGG19(weights="imagenet", include_top=True) for i, layer in enumerate(model.layers): print(i+1, layer.name, layer) print("input",model.inputs) print("outputs",model.outputs) print("output",model.output) 結果 : 1 input_1 2 block1_conv1 3 block1_conv2 4 block1_pool 5 block2_conv1 6 block2_conv2 7 block2_pool 8 block3_conv1 9 block3_conv2 10 block3_conv3 11 block3_conv4 12 block3_pool 13 block4_conv1 14 block4_conv2 15 block4_conv3 16 block4_conv4 17 block4_pool 18 block5_conv1 19 block5_conv2 20 block5_conv3 21 block5_conv4 22 block5_pool 23 flatten 24 fc1 25 fc2 26 predictions
input [<KerasTensor: shape=(None, 224, 224, 3) dtype=float32 (created by layer 'input_1')>]
outputs [<KerasTensor: shape=(None, 1000) dtype=float32 (created by layer 'predictions')>] output KerasTensor(type_spec=TensorSpec(shape=(None, 1000), dtype=tf.float32, name=None), name='predictions/Softmax:0', description="created by layer 'predictions'")
如果 model = applications.vgg19.VGG19(weights=”imagenet”, include_top=False) 將 include_top 設為 False 時,則 23~26 的輸出層就不會產生。
from keras import applications model = applications.vgg19.VGG19(weights="imagenet", include_top=False) for i, layer in enumerate(model.layers): print(i+1, layer.name, layer) print("input",model.inputs) print("outputs",model.outputs) print("output",model.output) 結果 : 1 input_1 2 block1_conv1 3 block1_conv2 4 block1_pool 5 block2_conv1 6 block2_conv2 7 block2_pool 8 block3_conv1 9 block3_conv2 10 block3_conv3 11 block3_conv4 12 block3_pool 13 block4_conv1 14 block4_conv2 15 block4_conv3 16 block4_conv4 17 block4_pool 18 block5_conv1 19 block5_conv2 20 block5_conv3 21 block5_conv4 22 block5_pool outputs [<KerasTensor: shape=(None, None, None, 512) dtype=float32 (created by layer 'block5_pool')>]
output KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 512), dtype=tf.float32, name=None), name='block5_pool/MaxPool:0', description="created by layer 'block5_pool'") output KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 512), dtype=tf.float32, name=None), name='block5_pool/MaxPool:0', description="created by layer 'block5_pool'")
每層的結構
每個區塊中的每一層,比如 block1_conv1 又有 “輸入” 及 “輸出”單元。請注意,這只是每一層的接收神經元及傳遞神經元,跟整個模型最前面的輸入層及整個模型最後的輸出層,是完全不一樣的。底下代碼可印出input/output 的型態,只是目前還沒送進圖片,所以維度類似像 (None, None, None, 64) 等 4 維格式。
from keras import applications
model = applications.vgg19.VGG19(weights="imagenet", include_top=False)
for layer in model.layers:
print(layer.name)
print("input:", layer.input)
print("output:", layer.output)
結果 :
input_1
input: KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 3), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'input_1'")
output: KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 3), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'input_1'")
block1_conv1
input: KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 3), dtype=tf.float32, name='input_1'), name='input_1', description="created by layer 'input_1'")
output: KerasTensor(type_spec=TensorSpec(shape=(None, None, None, 64), dtype=tf.float32, name=None), name='block1_conv1/Relu:0', description="created by layer 'block1_conv1'")
block1_conv2
.........
特徵存取
將圖片使用 model(img),即可取得最後輸出層的特徵。不過在原本的模型中,輸出層只有 predictions 這1000 種狀況,無法取得中間 5 個 block 隱藏層所計算出來的結果。所以如果要取得中間隱藏層的資料,就必需把 block 隱藏層中的 output 傳遞神經元移到輸出層。
import keras
import tensorflow as tf
import cv2
import numpy as np
from keras import applications
model = applications.vgg19.VGG19(weights="imagenet", include_top=False)
#將隱藏層移到輸出層
outputs_dict = dict([(layer.name, layer.output) for layer in model.layers])
model = keras.Model(inputs=model.inputs, outputs=outputs_dict)
開始計算特徵
模型調整好後,就可以將圖片傳入 model(img) 或是 model.predict(img),然後特徵就會儲存到輸出層中每一捲積層的 output 中,由下面代碼可印出每一層 output 的維度。
以 block1_conv1 這層來說,其維度為 (1, 224,224,64),表示這一層的每一個特徵大小為 224*224 圖片,然後共有 64 種特徵,也就是說這一層共有 64 張 224*224 的圖片。
最後需注意一件事,將圖片傳入 model 前,需先將圖片擴展成 4 維,並進行預處理。圖片最前維加入一空白維度後,再用 preprocess_input() 對圖片預處理,將RGB 轉成 BGR格式,然後將所有點的B值減掉B的平均數,G及R亦同。如此就可以讓每個點的每個顏色值分佈在 0 的左右二邊。
底下是我們用來測試的圖片。


老師您好
我最近上您聯成電腦的深度學習課程
是使用錄影檔回放的方式學習
請問老師能否提供您網站上內容的密碼
以利學生學習
謝謝老師
我的聯成電腦學號為 105724356