藉助Keras和Opencv實現的神經網絡中間層特徵圖的可視化功能,方便咱們研究CNN這個黑盒子裏到發生了什麼。python
代碼:網絡
# 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激活函數和尺度不等的池化操做,係數所有是隨機初始化。
輸入的原圖以下:app
第一層卷積後可視化的特徵圖:
函數
全部第一層特徵圖1:1融合後總體的特徵圖:
3d
第二層卷積後可視化的特徵圖:
code
全部第二層特徵圖1:1融合後總體的特徵圖:
orm
第三層卷積後可視化的特徵圖:
blog
全部第三層特徵圖1:1融合後總體的特徵圖:
utf-8
第四層卷積後可視化的特徵圖:
get
全部第四層特徵圖1:1融合後總體的特徵圖:
從不一樣層可視化出來的特徵圖大概能夠總結出一點規律:
代碼:
# 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比例融合後特徵依次爲: