1. 程式人生 > >【深度學習】CNN模型的視覺化-1

【深度學習】CNN模型的視覺化-1

CNN模型學到的東西很適合視覺化,這裡介紹三種方法:

  • 視覺化CNN模型的中間輸出(中間啟用):幫助我們理解CNN是如何對輸入進行變換,以及CNN每個卷積核的含義
  • 視覺化CNN的卷積核:幫助我們理解卷積核容易接受的視覺模式或概念
  • 客戶刷影象中類啟用的熱力圖:影象中哪些部分被識別為某個類別,輔助我們定點陣圖像中的物體

載入已儲存的模型的方法

from keras.models import load_model
model = load_model('cats_and_dogs_small_2.h5')
model.summary()
'''
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_6 (Conv2D)            (None, 148, 148, 32)      896       
_________________________________________________________________
max_pooling2d_6 (MaxPooling2 (None, 74, 74, 32)        0         
_________________________________________________________________
conv2d_7 (Conv2D)            (None, 72, 72, 64)        18496     
_________________________________________________________________
max_pooling2d_7 (MaxPooling2 (None, 36, 36, 64)        0         
_________________________________________________________________
conv2d_8 (Conv2D)            (None, 34, 34, 128)       73856     
_________________________________________________________________
max_pooling2d_8 (MaxPooling2 (None, 17, 17, 128)       0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 36992)             0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 36992)             0         
_________________________________________________________________
dense_3 (Dense)              (None, 512)               18940416  
_________________________________________________________________
dense_4 (Dense)              (None, 1)                 513       
=================================================================
Total params: 19,034,177
Trainable params: 19,034,177
Non-trainable params: 0
'''

處理待載入的模型的圖片

# 預處理單張影象
img_path = './data/cats_and_dogs_small/test/cats/cat.1700.jpg'
from keras.preprocessing import image
import numpy as np

img = image.load_img(img_path, target_size=(150, 150)) # 載入為Image物件
img_tensor = image.img_to_array(img) # 使用Numpy處理為張量

img_tensor.shape # (150, 150, 3)

img_tensor =
np.expand_dims(img_tensor, axis=0) # 新增一個軸,擴充套件為4D張量 img_tensor.shape # (1, 150, 150, 3) img_tensor /= 255. # 縮放 # 顯示圖片 import matplotlib.pyplot as plt plt.imshow(img_tensor[0]) plt.show()

檢視特徵圖

為了提取想要檢視的特徵圖,我們需要建立一個Keras模型,以影象批量作為輸入,同時輸出所有卷積層和池化層的啟用結果。

這裡需要用到的是Keras的Model類,不是我們建立模型時用到的Sequential

類,得到的模型也是將特定輸入對映為特定輸出,但是**Model類允許模型有多個輸出。而Sequential不行。**之前的模型都是,一端進一端出,即一個輸入和一個輸出。

# 使用Model類建立模型
# 輸入一張影象,模型輸出前8層的啟用值
from keras import models
layer_outputs = [layer.output for layer in model.layers[:8]] # 前8層的輸出
activation_model = models.Model(inputs=model.input, outputs=layer_outputs)

activations = activation_model.predict(img_tensor) # 返回8個Numpy陣列組成的列表,每個Numpy陣列對應的是每層的輸出

activations[0].shape # (1, 148, 148, 32)
# 返回的結果是148x148大小,且有32個通道
# 我們繪製啟用層的第4個通道
import matplotlib.pyplot as plt
plt.matshow(activations[0][0, :, :, 4], cmap='viridis')

在這裡插入圖片描述

繪製全部輸出的全部通道:

# 繪製8個特徵圖的每一個通道
layer_names = []
for layer in model.layers[:8]:
    layer_names.append(layer.name)
images_per_row = 16

for layer_name, layer_activation in zip(layer_names, activations):
    n_features = layer_activation.shape[-1] # 特徵圖中的特徵個數,即卷積核的通道數
    size= layer_activation.shape[1] # (1, size, size, n_features)
    
    n_cols = n_features // images_per_row 
    
    display_grid = np.zeros((size * n_cols, images_per_row * size))
    
    for col in range(n_cols):
        for row in range(images_per_row):
            channel_image = layer_activation[0, :, :, col * images_per_row + row]
            channel_image -= channel_image.mean()
            channel_image /= channel_image.std()
            channel_image *= 64
            channel_image += 128
            channel_image = np.clip(channel_image, 0, 255).astype('uint8')
            display_grid[col * size : (col + 1) * size, row * size: (row + 1) * size] = channel_image
            scale = 1. / size
            plt.figure(figsize=(scale * display_grid.shape[1], 
                               scale * display_grid.shape[0]))
            plt.title(layer_name)
            plt.grid(False)
            plt.imshow(display_grid, aspect='auto', cmap='viridis')

剩下的兩類繪圖後面再補全。

END.

參考:

《Deep Learning with Python》