卷積神經網路特徵圖視覺化(自定義網路和VGG網路)
阿新 • • 發佈:2019-01-11
藉助Keras和Opencv實現的神經網路中間層特徵圖的視覺化功能,方便我們研究CNN這個黑盒子裡到發生了什麼。
自定義網路特徵視覺化
程式碼:
# coding: utf-8 from keras.models import Model import cv2 import matplotlib.pyplot as plt from keras.models import Sequential from keras.layers.convolutional import Convolution2D,MaxPooling2D from keras.layers import Activation from pylab import * import keras def get_row_col(num_pic): squr = num_pic ** 0.5 row = round(squr) col = row + 1 if squr - row > 0 else row return row,col def visualize_feature_map(img_batch): feature_map = np.squeeze(img_batch,axis=0) print feature_map.shape feature_map_combination=[] plt.figure() num_pic = feature_map.shape[2] row,col = get_row_col(num_pic) for i in range(0,num_pic): feature_map_split=feature_map[:,:,i] feature_map_combination.append(feature_map_split) plt.subplot(row,col,i+1) plt.imshow(feature_map_split) axis('off') title('feature_map_{}'.format(i)) plt.savefig('feature_map.jpg') plt.show() # 各個特徵圖按1:1 疊加 feature_map_sum = sum(ele for ele in feature_map_combination) plt.imshow(feature_map_sum) plt.savefig("feature_map_sum.jpg") def create_model(): model = Sequential() # 第一層CNN # 第一個引數是卷積核的數量,第二三個引數是卷積核的大小 model.add(Convolution2D(9, 5, 5, input_shape=img.shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(4, 4))) #第二層CNN model.add(Convolution2D(9, 5, 5, input_shape=img.shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(3, 3))) # 第三層CNN model.add(Convolution2D(9, 5, 5, input_shape=img.shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) # 第四層CNN model.add(Convolution2D(9, 3, 3, input_shape=img.shape)) model.add(Activation('relu')) # model.add(MaxPooling2D(pool_size=(2, 2))) return model if __name__ == "__main__": img = cv2.imread('001.jpg') model = create_model() img_batch = np.expand_dims(img, axis=0) conv_img = model.predict(img_batch) # conv_img 卷積結果 visualize_feature_map(conv_img)
這裡定義了一個4層的卷積,每個卷積層分別包含9個卷積、Relu啟用函式和尺度不等的池化操作,係數全部是隨機初始化。
輸入的原圖如下:
第一層卷積後視覺化的特徵圖:
所有第一層特徵圖1:1融合後整體的特徵圖:
第二層卷積後視覺化的特徵圖:
所有第二層特徵圖1:1融合後整體的特徵圖:
第三層卷積後視覺化的特徵圖:
所有第三層特徵圖1:1融合後整體的特徵圖:
第四層卷積後視覺化的特徵圖:
所有第四層特徵圖1:1融合後整體的特徵圖:
從不同層可視化出來的特徵圖大概可以總結出一點規律:
- 1. 淺層網路提取的是紋理、細節特徵
- 2. 深層網路提取的是輪廓、形狀、最強特徵(如貓的眼睛區域)
- 3. 淺層網路包含更多的特徵,也具備提取關鍵特徵(如第一組特徵圖裡的第4張特徵圖,提取出的是貓眼睛特徵)的能力
- 4. 相對而言,層數越深,提取的特徵越具有代表性
- 5. 影象的解析度是越來越小的
VGG19網路特徵視覺化
程式碼:
# coding: utf-8 from keras.applications.vgg19 import VGG19 from keras.preprocessing import image from keras.applications.vgg19 import preprocess_input from keras.models import Model import numpy as np import matplotlib.pyplot as plt from pylab import * def get_row_col(num_pic): squr = num_pic ** 0.5 row = round(squr) col = row + 1 if squr - row > 0 else row return row,col def visualize_feature_map(img_batch): feature_map = img_batch print feature_map.shape feature_map_combination=[] plt.figure() num_pic = feature_map.shape[2] row,col = get_row_col(num_pic) for i in range(0,num_pic): feature_map_split=feature_map[:,:,i] feature_map_combination.append(feature_map_split) plt.subplot(row,col,i+1) plt.imshow(feature_map_split) axis('off') plt.savefig('feature_map.jpg') plt.show() # 各個特徵圖按1:1 疊加 feature_map_sum = sum(ele for ele in feature_map_combination) plt.imshow(feature_map_sum) plt.savefig("feature_map_sum.jpg") if __name__ == "__main__": base_model = VGG19(weights='imagenet', include_top=False) # model = Model(inputs=base_model.input, outputs=base_model.get_layer('block1_pool').output) # model = Model(inputs=base_model.input, outputs=base_model.get_layer('block2_pool').output) # model = Model(inputs=base_model.input, outputs=base_model.get_layer('block3_pool').output) # model = Model(inputs=base_model.input, outputs=base_model.get_layer('block4_pool').output) model = Model(inputs=base_model.input, outputs=base_model.get_layer('block5_pool').output) img_path = '001.jpg' img = image.load_img(img_path) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) x = preprocess_input(x) block_pool_features = model.predict(x) print(block_pool_features.shape) feature = block_pool_features.reshape(block_pool_features.shape[1:]) visualize_feature_map(feature)
從第一到第五層的特徵圖分別如下:
從第一層到第五層各特徵圖按1:1比例融合後特徵依次為: