Keras實現(xiàn)卷積神經(jīng)網(wǎng)絡(CNN)可視化

卷積神經(jīng)網(wǎng)絡(Convolutional Neural Network, CNN)是一種前饋神經(jīng)網(wǎng)絡岖赋,它的人工神經(jīng)元可以響應一部分覆蓋范圍內(nèi)的周圍單元,對于大型圖像處理有出色表現(xiàn)赘来。通過卷積旭贬、池化瘩将、激活等操作的配合吟税,卷積神經(jīng)網(wǎng)絡能夠較好的學習到空間上關(guān)聯(lián)的特征凹耙。以VGG16為例,我們將利用Keras觀察CNN到底在學些什么肠仪,它是如何理解我們送入的訓練圖片的肖抱。

githubhttps://github.com/xiaochus/VisualizationCNN
參考Kerasdeep-learning-with-python-notebooks

主要的四種可視化模式:
1. 卷積核輸出的可視化异旧,即可視化卷積操作后的結(jié)果意述,幫助理解卷積核的作用。
2. 卷積核的可視化吮蛹,對卷積核本身進行可視化荤崇,對卷積核學習到的行為進行解釋。
3. 類激活圖可視化潮针,通過熱度圖术荤,了解圖像分類問題中圖像哪些部分起到了關(guān)鍵作用,同時可以定位圖像中物體的位置然低。
4. 特征可視化喜每,與第一種方法類似,但是輸出的不再是卷積層的激活值雳攘,而是使用反卷積與反池化來可視化輸入圖像的激活特征。

環(huán)境

  • Python 3.6
  • Keras 2.2.2
  • Tensorflow-gpu 1.8.0
  • OpenCV 3.4

卷積輸出可視化

卷積輸出可視化可以通過將不同的卷積層設置為輸出層來實現(xiàn)枫笛,如下所示:

def conv_output(model, layer_name, img):
    """Get the output of conv layer.

    Args:
           model: keras model.
           layer_name: name of layer in the model.
           img: processed input image.

    Returns:
           intermediate_output: feature map.
    """
    # this is the placeholder for the input images
    input_img = model.input

    try:
        # this is the placeholder for the conv output
        out_conv = model.get_layer(layer_name).output
    except:
        raise Exception('Not layer named {}!'.format(layer_name))

    # get the intermediate layer model
    intermediate_layer_model = Model(inputs=input_img, outputs=out_conv)

    # get the output of intermediate layer model
    intermediate_output = intermediate_layer_model.predict(img)

    return intermediate_output[0]

我們對四個block下不同的卷積層輸出進行了可視化處理吨灭,可視化結(jié)果如下所示⌒糖桑可以看出淺層的卷積層獲得的特征數(shù)量還比較多喧兄,特征數(shù)據(jù)與原始的圖像數(shù)據(jù)很接近。隨著層數(shù)越深啊楚,得到的有效特征越來越少吠冤,特征也變得越來越抽象。

conv_block1_conv1
conv_block2_conv2
conv_block3_conv3
conv_block4_conv3

卷積核可視化

解釋CNN模型的另一個簡單方法是顯示每個卷積核響應的視覺模式, 卷積核可視化通過輸入空間中的梯度上升來完成恭理。
卷積核可視化的過程:我們要定義一個損失函數(shù)拯辙,這個損失函數(shù)將用于最大化某個指定濾波器的激活值。以該函數(shù)為優(yōu)化目標優(yōu)化后颜价,后我們將使用隨機梯度下降來調(diào)整輸入圖像的值涯保,以便最大化該激活值。

def conv_filter(model, layer_name, img):
    """Get the filter of conv layer.

    Args:
           model: keras model.
           layer_name: name of layer in the model.
           img: processed input image.

    Returns:
           filters.
    """
    # this is the placeholder for the input images
    input_img = model.input

    # get the symbolic outputs of each "key" layer (we gave them unique names).
    layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]])

    try:
        layer_output = layer_dict[layer_name].output
    except:
        raise Exception('Not layer named {}!'.format(layer_name))

    kept_filters = []
    for i in range(layer_output.shape[-1]):
        loss = K.mean(layer_output[:, :, :, i])

        # compute the gradient of the input picture with this loss
        grads = K.gradients(loss, input_img)[0]

        # normalization trick: we normalize the gradient
        grads = utils.normalize(grads)

        # this function returns the loss and grads given the input picture
        iterate = K.function([input_img], [loss, grads])

        # step size for gradient ascent
        step = 1.
        # run gradient ascent for 20 steps
        fimg = img.copy()

        for j in range(40):
            loss_value, grads_value = iterate([fimg])
            fimg += grads_value * step

        # decode the resulting input image
        fimg = utils.deprocess_image(fimg[0])
        kept_filters.append((fimg, loss_value))

        # sort filter result
        kept_filters.sort(key=lambda x: x[1], reverse=True)

    return np.array([f[0] for f in kept_filters])

可視化結(jié)果如下所示周伦∠Υ海可以看出最淺層的卷積核傾向于學習點、顏色等基礎(chǔ)特征专挪;接下來開始學習到線段及志、邊緣等特征片排。層數(shù)越深,學習到的特征就越具體越抽象速侈。

filter_block1_conv1
filter_block2_conv2
filter_block3_conv3
filter_block4_conv3

類激活圖可視化

類激活圖(CAM)可視化率寡,包括在輸入圖像上產(chǎn)生類激活的熱圖。 類激活熱圖是與特定輸出類相關(guān)聯(lián)的分數(shù)的2D網(wǎng)格锌畸,針對任何輸入圖像中的每個位置計算勇劣,指示每個位置相對于所考慮的類的重要程度。例如潭枣,給定一個圖像輸入我們的“貓與狗”之一比默,類激活圖可視化允許我們?yōu)轭悺柏垺鄙蔁釄D,指示圖像的貓狀不同部分是如何盆犁,同樣對于“狗”類命咐,表示圖像的狗狀不同部分。換句話時候谐岁,假設最后一層卷積層有512個卷積核醋奠,我想了解這512個卷積核對該圖片是”貓”分別投了幾票。投票越多的卷積核伊佃,就越確信圖片是“貓”窜司,因為它們提取到的特征趨向貓的特征。

CAM的原理:它包括在給定輸入圖像的情況下獲取卷積層的輸出特征圖航揉,并通過目標類相對于通道的梯度對該特征圖中的每個通道進行加權(quán)塞祈。簡單的講,我們獲取到最后一個卷積層的卷積輸出以及目標類別神經(jīng)元相對于每一個通道的梯度帅涂,使用這個梯度對卷積核的每一個通道進行加權(quán)處理议薪,最后對通道求均值并且對重要度進行歸一化處理。

def output_heatmap(model, last_conv_layer, img):
    """Get the heatmap for image.

    Args:
           model: keras model.
           last_conv_layer: name of last conv layer in the model.
           img: processed input image.

    Returns:
           heatmap: heatmap.
    """
    # predict the image class
    preds = model.predict(img)
    # find the class index
    index = np.argmax(preds[0])
    # This is the entry in the prediction vector
    target_output = model.output[:, index]

    # get the last conv layer
    last_conv_layer = model.get_layer(last_conv_layer)

    # compute the gradient of the output feature map with this target class
    grads = K.gradients(target_output, last_conv_layer.output)[0]

    # mean the gradient over a specific feature map channel
    pooled_grads = K.mean(grads, axis=(0, 1, 2))

    # this function returns the output of last_conv_layer and grads 
    # given the input picture
    iterate = K.function([model.input], [pooled_grads, last_conv_layer.output[0]])
    pooled_grads_value, conv_layer_output_value = iterate([img])

    # We multiply each channel in the feature map array
    # by "how important this channel is" with regard to the target class

    for i in range(conv_layer_output_value.shape[-1]):
        conv_layer_output_value[:, :, i] *= pooled_grads_value[i]

    # The channel-wise mean of the resulting feature map
    # is our heatmap of class activation
    heatmap = np.mean(conv_layer_output_value, axis=-1)
    heatmap = np.maximum(heatmap, 0)
    heatmap /= np.max(heatmap)

    return heatmap

可視化結(jié)果如下所示媳友∷挂椋可以看出對于這張貓的圖片,頭部耳朵貢獻了最重要的特征醇锚,其次就是爪子哼御,最后是身體部分。

heatmap

特征可視化

特征可視化主要使用目標卷積層的輸出作為輸入搂抒,利用反卷積艇搀、反池化、反激活等方法得到反向操作的結(jié)果求晶,用以驗證顯示各層提取到的特征圖派撕。由于Keras還沒有提供反池化的方法誓军,這里提供一些相關(guān)的論文與工具作為參考逸月。

paper
Visualizing and Understanding Convolutional Networks
Understanding Neural Networks Through Deep Visualization
tools
DeepVis Toolbox
tf_cnnvis

Deconv

網(wǎng)絡的整個過程,從右邊開始:輸入圖片→卷積→Relu→最大池化→得到結(jié)果特征圖→反池化→Relu→反卷積辟宗。
對于反卷積過程,這里不用進行訓練而是采用卷積過程轉(zhuǎn)置后的濾波器(參數(shù)一樣吝秕,把參數(shù)矩陣水平和垂直方向翻轉(zhuǎn)了一下)泊脐。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市烁峭,隨后出現(xiàn)的幾起案子容客,更是在濱河造成了極大的恐慌,老刑警劉巖约郁,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缩挑,死亡現(xiàn)場離奇詭異,居然都是意外死亡鬓梅,警方通過查閱死者的電腦和手機供置,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绽快,“玉大人芥丧,你說我怎么就攤上這事》话眨” “怎么了续担?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長活孩。 經(jīng)常有香客問我赤拒,道長,這世上最難降的妖魔是什么诱鞠? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮这敬,結(jié)果婚禮上航夺,老公的妹妹穿的比我還像新娘。我一直安慰自己崔涂,他們只是感情好阳掐,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著冷蚂,像睡著了一般缭保。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蝙茶,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天艺骂,我揣著相機與錄音,去河邊找鬼隆夯。 笑死钳恕,一個胖子當著我的面吹牛别伏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播忧额,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厘肮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了睦番?” 一聲冷哼從身側(cè)響起类茂,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎托嚣,沒想到半個月后巩检,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡注益,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年碴巾,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丑搔。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡厦瓢,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出啤月,到底是詐尸還是另有隱情煮仇,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布谎仲,位于F島的核電站浙垫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏郑诺。R本人自食惡果不足惜夹姥,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辙诞。 院中可真熱鬧辙售,春花似錦、人聲如沸飞涂。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽较店。三九已至士八,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梁呈,已是汗流浹背婚度。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留捧杉,地道東北人陕见。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓秘血,卻偏偏與公主長得像,于是被迫代替她去往敵國和親评甜。 傳聞我的和親對象是個殘疾皇子灰粮,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內(nèi)容