導讀
對神經網絡進行可視化分析不管是在學習上還是實際應用上都有很重要的意義,基于此,本文介紹了3種CNN的可視化方法:可視化中間特征圖,可視化卷積核,可視化圖像中類激活的熱力圖。每種方法均附有相關代碼詳解。
注:本文所有資料均來自Keras之父、Google人工智能研究員Francois Chollet的大作:《Python深度學習》,建議大家直接去看原文,這里只是結合樓主的理解做點筆記。
引言
有一些同學認為深度學習、神經網絡什么的就是一個黑盒子,沒辦法、也不需要分析其內部的工作方式。個人認為這種說法“謬之千里”。
首先,站在自動特征提取或表示學習的角度來看,深度學習還是很好理解,即通過一個層級結構,由簡單到復雜逐步提取特征,獲得易于處理的高層次抽象表示。其次,現在也已經有很多方法對神經網絡進行分析了,特別是一些可視化方法,可以很直觀的展示深度模型的特征提取過程。
對神經網絡進行可視化分析不管是在學習上還是實際應用上都有很重要的意義,基于此,本文將介紹以下3種CNN的可視化方法:
可視化中間特征圖。
可視化卷積核。
可視化圖像中類激活的熱力圖。
可視化中間特征圖
這種方法很簡單,把網絡中間某層的輸出的特征圖按通道作為圖片進行可視化展示即可,如下述代碼所示:
import matplotlib.pyplot as plt #get feature map of layer_activation plt.matshow(layer_activation[0, :, :, 4], cmap='viridis')
把多個特征圖可視化后堆疊在一起可以得到與下述類似的圖片。
上圖為某CNN 5-8 層輸出的某喵星人的特征圖的可視化結果(一個卷積核對應一個小圖片)。可以發現越是低的層,捕捉的底層次像素信息越多,特征圖中貓的輪廓也越清晰。越到高層,圖像越抽象,稀疏程度也越高。這符合我們一直強調的特征提取概念。
可視化卷積核
想要觀察卷積神經網絡學到的過濾器,一種簡單的方法是獲取每個過濾器所響應的視覺模式。我們可以將其視為一個優化問題,即從空白輸入圖像開始,將梯度上升應用于卷積神經網絡的輸入圖像,讓某個過濾器的響應最大化,最后得到的圖像是選定過濾器具有較大響應的圖像。
核心代碼如下所示(利用Keras框架):
def generate_pattern(layer_name, filter_index, size=150): layer_output = model.get_layer(layer_name).output loss = K.mean(layer_output[:, :, :, filter_index]) grads = K.gradients(loss, model.input)[0] grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5) iterate = K.function([model.input], [loss, grads]) input_img_data = np.random.random((1, size, size, 3)) * 20 + 128. step = 1. for i in range(40): loss_value, grads_value = iterate([input_img_data]) input_img_data += grads_value * step img = input_img_data[0] return deprocess_image(img)
將輸入圖片張量轉換回圖片后進行可視化,可以得到與下述類似的圖片:
block1_conv1 層的過濾器模式
block2_conv1 層的過濾器模式
block3_conv1 層的過濾器模式
block4_conv1 層的過濾器模式
隨著層數的加深,卷積神經網絡中的過濾器變得越來越復雜,越來越精細。模型第一層( block1_conv1 )的過濾器對應簡單的方向邊緣和顏色,高層的過濾器類似于自然圖像中的紋理:羽毛、眼睛、樹葉等。
可視化圖像中類激活的熱力圖
即顯示原始圖片的不同區域對某個CNN輸出類別的“貢獻”程度,如下面圖片所示:
可以看到,大象頭部對“大象”這個類別的“貢獻”程度較高,而且這種方法似乎可以在一定程度上進行無監督的目標檢測。
下面是書中原文,可能有點繞口。
我們將使用的具體實現方式是“Grad-CAM: visual explanations from deep networks via gradient-based localization”這篇論文中描述的方法。這種方法非常簡單:給定一張輸入圖像,對于一個卷積層的輸出特征圖,用類別相對于通道的梯度對這個特征圖中的每個通道進行加權。直觀上來看,理解這個技巧的一種方法是,你是用“每個通道對類別的重要程度”對“輸入圖像對不同通道的激活強度”的空間圖進行加權,從而得到了“輸入圖像對類別的激活強度”的空間圖。
這里談一下我的理解,給定線性函數,y為類別,等等為輸入??梢钥吹竭@里對y的貢獻為,恰好為。當然了,深度模型中有非線性激活函數,不能簡化為一個線性模型,所以這只是啟發性的理解。
代碼如下所示:
african_elephant_output = model.output[:, 386] last_conv_layer = model.get_layer('block5_conv3') grads = K.gradients(african_elephant_output, last_conv_layer.output)[0] pooled_grads = K.mean(grads, axis=(0, 1, 2)) iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]]) pooled_grads_value, conv_layer_output_value = iterate([x]) for i in range(512): conv_layer_output_value[:, :, i] *= pooled_grads_value[i] heatmap = np.mean(conv_layer_output_value, axis=-1) heatmap = np.maximum(heatmap, 0) heatmap /= np.max(heatmap) plt.matshow(heatmap)
得到的熱力圖如下所示:
經下述代碼處理后,可以得到本節開始時的圖片。
import cv2 img = cv2.imread(img_path) heatmap = cv2.resize(heatmap, (img.shape[1], img.shape[0])) heatmap = np.uint8(255 * heatmap) heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET) superimposed_img = heatmap * 0.4 + img cv2.imwrite('/Users/fchollet/Downloads/elephant_cam.jpg', superimposed_img)
結語
本文到這里就結束了,這里再次推薦一下Francois Chollet大佬的書,寫的很接地氣,建議新手們都看看。
責任編輯:lq
-
可視化
+關注
關注
1文章
1198瀏覽量
20987 -
深度學習
+關注
關注
73文章
5510瀏覽量
121332 -
cnn
+關注
關注
3文章
353瀏覽量
22265
原文標題:CNN 的一些可視化方法!
文章出處:【微信號:vision263com,微信公眾號:新機器視覺】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論