這是眾多卷積神經網絡可視化方法之一,方法來自于論文《Learning Deep Features for Discriminative Localization》,論文譯文在[翻譯]Learning Deep Features for Discriminative Localization。
這篇文章的核心思想是提出了一種叫Class Activation Mapping(類激活圖)的方法,可以通過它將CNN在分類時“看”到的東西可視化出來。它的原理是:CNN的卷積層包含大量位置信息,使其具有良好的定位能力,但是全連接層使這種能力喪失,如果只保留最后一個用于分類的全連接層(特指softmax),把其余全連接層替換成全局平均池化層(Global Average Pooling)層,就可以保留這中定位能力,把最后一個softmax層各個單元的權重與最后一個卷積層的輸出相乘(求加權總和),繪制熱成像圖,得到的結果就是一個類激活圖。
舉個例子,假設圖片經過最后一個卷積層的shape為(14,14,512),第一維和第二維代表寬高,第三維代表卷積層深度,softmax層的shape為(512,10),第一維代表unit數,第二維代表分類數,想得到某一個類的類激活圖,就用通過最后一個卷積層的矩陣乘以sotfmax某類的矩陣,即(14,14,512)的矩陣乘以(512,1)的矩陣,得到(14,14,1)的矩陣,也就是那個類的類激活圖,下面是類激活圖

論文中提到最后一個卷積層輸出的分辨率越高,定位能力越強,得到的CAM圖越好。對應的處理方法就是不僅要砍掉全連接層,還要砍掉一些卷積層,使分辨率控制在14左右。下面是論文中圖,與上圖最大差別就是有紅色,原因可能是分辨率問題,也可能單純是顏色表示問題,還需要進一步實驗確定,但是并不影響可視化,分類準確率也在90%以上。

其實到這里很自然會有一個疑問:砍掉那么多層,準確率會不會降低?
答案是肯定的,但不會降低很多,可以通過微調來保持網絡準確率。
下面是大家最關心的代碼部分,我使用的基于TensorFlow的Keras,所以顏色通道在最后,使用其他框架的同學調一下就好,過段時間會放到Github倉庫
def visualize_class_activation_map(model, img_path, target_class):
'''
參數:
model:模型
img_path:圖片路徑
target_class:目標類型
'''
origin_img = get_im_cv2([img_path], 224, 224, 3) # 這是一個自定義讀取圖片函數
class_weights = model.layers[-1].get_weights()[0] # 取最后一個softmax層的權重
final_conv_layer = model.layers[17] # 這是最后一個卷積層的索引
get_output = K.function([model.layers[0].input],[final_conv_layer.output, model.layers[-1].output])
[conv_outputs, predictions] = get_output([origin_img])
conv_outputs = conv_outputs[0, :, :, :]
cam = np.zeros(dtype=np.float32, shape=(14, 14))
for i, w in enumerate(class_weights[:, target_class]):
cam += conv_outputs[:, :, i] * w
cam = cv2.resize(cam, (224, 224))
cam = 100 * cam
plt.imshow(origin_img[0])
plt.imshow(cam, alpha=0.8, interpolation='nearest')
plt.show()
以上內容來自822實驗室神經網絡知識分享
我們的822,我們的青春
歡迎所有熱愛知識熱愛生活的朋友和822思享實驗室一起成長,吃喝玩樂,享受知識。