CNN可視化技術總結(三)--類可視化python
導言:網絡
上篇文章咱們介紹了特徵圖可視化方法,對於特徵圖可視化的方法(或者說原理)比較容易理解,即把feature map從特徵空間經過反捲積網絡映射回像素空間。app
那捲積核怎樣可視化呢,基於什麼原理來可視化?卷積核的尺寸通常只有3x3, 5x5大小,如何可視化?本文將介紹這個兩個內容。dom
卷積核,在網絡中起到將圖像從像素空間映射到特徵空間的做用,可認爲是一個映射函數,像素空間中的值通過卷積核後獲得響應值,在特徵提取網絡中,基本都是使用最大池化來選擇最大響應值進入下一層繼續卷積,其他響應值低的都進入待定。也就是說,咱們認定只有響應值大的纔會對最終的識別任務起做用。函數
根據這個思路,給定一個已經訓練好的網絡,如今想要可視化某一層的某一個卷積核,咱們隨機初始化生成一張圖(指的是對像素值隨機取值,不是數據集中隨機選一張圖),而後通過前向傳播到該層,咱們但願這個隨機生成的圖在通過這一層卷積核時,它的響應值能儘量的大,換句話說,響應值比較大的圖像是這個卷積核比較承認的,是與識別任務更相關的。而後不斷調整圖像像素值,直到響應值足夠大,咱們就能夠認爲此時的圖像就是這個卷積核所承認的,從而達到可視化該卷積核的目的。oop
理解了它的原理後,它的實現方法就比較簡單了,設計一個損失函數,即以通過該層卷積核後的響應值爲目標函數,使用梯度上升,更新像素值,使響應值最大。ui
Setupthis
import numpy as np import tensorflow as tf from tensorflow import keras # The dimensions of our input image img_width = 180 img_height = 180 # Our target layer: we will visualize the filters from this layer. # See `model.summary()` for list of layer names, if you want to change this. layer_name = "conv3_block4_out"
Build a feature extraction model設計
# Build a ResNet50V2 model loaded with pre-trained ImageNet weights model = keras.applications.ResNet50V2(weights="imagenet", include_top=False) # Set up a model that returns the activation values for our target layerlayer = model.get_layer(name=layer_name) feature_extractor = keras.Model(inputs=model.inputs, outputs=layer.output)
Set up the gradient ascent process
loss函數取最大化指定卷積核的響應值的平均值,爲了不邊界的影響,邊界的響應值不計。
def compute_loss(input_image, filter_index): activation = feature_extractor(input_image) # We avoid border artifacts by only involving non-border pixels in the loss. filter_activation = activation[:, 2:-2, 2:-2, filter_index] return tf.reduce_mean(filter_activation)
@tf.function def gradient_ascent_step(img, filter_index, learning_rate): with tf.GradientTape() as tape: tape.watch(img) loss = compute_loss(img, filter_index) # Compute gradients. grads = tape.gradient(loss, img) # Normalize gradients. grads = tf.math.l2_normalize(grads) img += learning_rate * grads return loss, img
Set up the end-to-end filter visualization loop
def initialize_image(): # We start from a gray image with some random noise img = tf.random.uniform((1, img_width, img_height, 3)) # ResNet50V2 expects inputs in the range [-1, +1]. # Here we scale our random inputs to [-0.125, +0.125] return (img - 0.5) * 0.25 def visualize_filter(filter_index): # We run gradient ascent for 20 steps iterations = 30 learning_rate = 10.0 img = initialize_image() for iteration in range(iterations): loss, img = gradient_ascent_step(img, filter_index, learning_rate) # Decode the resulting input image img = deprocess_image(img[0].numpy()) return loss, img def deprocess_image(img): # Normalize array: center on 0., ensure variance is 0.15 img -= img.mean() img /= img.std() + 1e-5 img *= 0.15 # Center crop img = img[25:-25, 25:-25, :] # Clip to [0, 1] img += 0.5 img = np.clip(img, 0, 1) # Convert to RGB array img *= 255 img = np.clip(img, 0, 255).astype("uint8") return img
可視化vgg16卷積核
總結:本節內容介紹了一種可視化卷積核的方法,即經過生成指定卷積核響應值儘量大的圖像來達到可視化卷積核的目的,使用的方法是梯度上升。
在很多論文的末尾都有可視化卷積核來分析提出的模型,該方法值得了解。
下一篇咱們將介紹最經常使用的可視化方法--CAM系列,其做用是給出圖像中對類別識別起做用的區域的熱力圖。
代碼與可視化圖的參考連接
https://keras.io/examples/vision/visualizing_what_convnets_learn/
https://blog.keras.io/how-convolutional-neural-networks-see-the-world.html
本文來源於公衆號《CV技術指南》的技術總結部分,更多相關技術總結請掃描文末二維碼關注公衆號。