亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

利用Python實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)的可視化

light / 1674人閱讀

摘要:卷積神經(jīng)網(wǎng)絡(luò)模型可視化的重要性正如上文中介紹的癌癥腫瘤診斷案例所看到的,研究人員需要對(duì)所設(shè)計(jì)模型的工作原理及其功能掌握清楚,這點(diǎn)至關(guān)重要。研究人員使用張迷彩坦克照片及張樹林照片來訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)。

摘要: 本文簡單說明了CNN模型可視化的重要性,以及介紹了一些可視化CNN網(wǎng)絡(luò)模型的方法,希望對(duì)讀者有所幫助,使其能夠在后續(xù)深度學(xué)習(xí)應(yīng)用中構(gòu)建更好的模型。

對(duì)于深度學(xué)習(xí)這種端到端模型來說,如何說明和理解其中的訓(xùn)練過程是大多數(shù)研究者關(guān)注熱點(diǎn)之一,這個(gè)問題對(duì)于那種高風(fēng)險(xiǎn)行業(yè)顯得尤為重視,比如醫(yī)療、軍事等。在深度學(xué)習(xí)中,這個(gè)問題被稱作“黑匣子(Black Box)”。如果不能解釋模型的工作過程,我們怎么能夠就輕易相信模型的輸出結(jié)果呢?

以深度學(xué)習(xí)模型檢測癌癥腫瘤為例,該模型告訴你它能夠檢測出癌癥的準(zhǔn)確率高達(dá)99%,但它并沒有告訴你它是如何工作并給出判斷結(jié)果的。那么該模型是在核磁共振掃描片子中發(fā)現(xiàn)了重要線索嗎?或者僅僅是將掃描結(jié)果上的污點(diǎn)錯(cuò)誤地認(rèn)為是腫瘤呢?模型的輸出結(jié)果關(guān)系到病人的生死問題及治療方案,醫(yī)生是不能承擔(dān)起這種錯(cuò)誤的。

在本文中,將探討如何可視化卷積神經(jīng)網(wǎng)絡(luò)(CNN),該網(wǎng)絡(luò)在計(jì)算機(jī)視覺中使用最為廣泛。首先了解CNN模型可視化的重要性,其次介紹可視化的幾種方法,同時(shí)以一個(gè)用例幫助讀者更好地理解模型可視化這一概念。

1.卷積神經(jīng)網(wǎng)絡(luò)模型可視化的重要性

正如上文中介紹的癌癥腫瘤診斷案例所看到的,研究人員需要對(duì)所設(shè)計(jì)模型的工作原理及其功能掌握清楚,這點(diǎn)至關(guān)重要。一般而言,一名深度學(xué)習(xí)研究者應(yīng)該記住以下幾點(diǎn):

理解模型是如何工作的

調(diào)整模型的參數(shù)

找出模型失敗的原因

向消費(fèi)者/終端用戶或業(yè)務(wù)主管解釋模型做出的決定

現(xiàn)在讓我們看一個(gè)例子,可視化一個(gè)神經(jīng)網(wǎng)絡(luò)模型有助于理解其工作原理和提升模型性能。

曾幾何時(shí),美國陸軍希望使用神經(jīng)網(wǎng)絡(luò)自動(dòng)檢測偽裝的敵方坦克。研究人員使用50張迷彩坦克照片及50張樹林照片來訓(xùn)練一個(gè)神經(jīng)網(wǎng)絡(luò)。使用有監(jiān)督學(xué)習(xí)方法來訓(xùn)練模型,當(dāng)研究人員訓(xùn)練好網(wǎng)絡(luò)的參數(shù)后,網(wǎng)絡(luò)模型能夠?qū)τ?xùn)練集做出正確的判斷——50張迷彩坦克全都輸出“Yes”,50張樹林照片全都輸出“No”。但是這并不能保證模型對(duì)于新的樣本也能正確分類。聰明的是,研究人員最初拍攝了200張照片,其中包含了100張迷彩坦克照片、100張樹木照片。從中分別選取50張照片合計(jì)100張照片作為訓(xùn)練集,剩余的100張照片作為測試集。結(jié)果發(fā)現(xiàn),模型對(duì)測試集也能正確分類。因此,研究人員覺得模型沒有問題了,就將最終成果交付給軍方。原以為軍方會(huì)很滿意這份研究成果,結(jié)果軍方做出的反饋是他們進(jìn)行測試后發(fā)現(xiàn)效果并不好。

研究人員感覺此事有點(diǎn)蹊蹺,為什么之前測試時(shí)百分百準(zhǔn)確,而軍方測試的時(shí)候又掉鏈子了呢?最后終于發(fā)現(xiàn),原來是研究者的數(shù)據(jù)集出現(xiàn)了問題,采集迷彩坦克的時(shí)候是陰天,而采集樹林的時(shí)候是晴天,神經(jīng)網(wǎng)絡(luò)最終學(xué)會(huì)的是區(qū)分晴天和陰天,而不是區(qū)分迷彩坦克和樹林。這真是令人哭笑不得啊,那造成這個(gè)問題的主要原因還是沒有弄清楚模型的具體的工作原理及其功能。

2.可視化CNN模型的方法

根據(jù)其內(nèi)部的工作原理,大體上可以將CNN可視化方法分為以下三類:

初步方法:一種顯示訓(xùn)練模型整體結(jié)構(gòu)的簡單方法

基于激活的方法:對(duì)單個(gè)或一組神經(jīng)元的激活狀態(tài)進(jìn)行破譯以了解其工作過程

基于梯度的方法:在訓(xùn)練過程中操作前向傳播和后向傳播形成的梯度

下面將具體介紹以上三種方法,所舉例子是使用Keras深度學(xué)習(xí)庫實(shí)現(xiàn),另外本文使用的數(shù)據(jù)集是由“識(shí)別數(shù)字”競賽提供。因此,讀者想復(fù)現(xiàn)文中案例時(shí),請(qǐng)確保安裝好Kears以及執(zhí)行了這些步驟。

1初步方法

1.1 繪制模型結(jié)構(gòu)圖

研究者能做的最簡單的事情就是繪制出模型結(jié)構(gòu)圖,此外還可以標(biāo)注神經(jīng)網(wǎng)絡(luò)中每層的形狀及參數(shù)。在keras中,可以使用如下命令完成模型結(jié)構(gòu)圖的繪制:

model.summary()

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 12, 12, 64)        0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 9216)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               1179776   
_________________________________________________________________
dropout_2 (Dropout)          (None, 128)               0         
_________________________________________________________________
preds (Dense)                (None, 10)                1290      
=================================================================
Total params: 1,199,882
Trainable params: 1,199,882
Non-trainable params: 0

還可以用一個(gè)更富有創(chuàng)造力和表現(xiàn)力的方式呈現(xiàn)模型結(jié)構(gòu)框圖,可以使用keras.utils.vis_utils函數(shù)完成模型體系結(jié)構(gòu)圖的繪制。

1.2 可視化濾波器

另一種方法是繪制訓(xùn)練模型的過濾器,這樣就可以了解這些過濾器的表現(xiàn)形式。例如,第一層的第一個(gè)過濾器看起來像:

top_layer = model.layers[0]
plt.imshow(top_layer.get_weights()[0][:, :, :, 0].squeeze(), cmap="gray")

一般來說,神經(jīng)網(wǎng)絡(luò)的底層主要是作為邊緣檢測器,當(dāng)層數(shù)變深時(shí),過濾器能夠捕捉更加抽象的概念,比如人臉等。

2.激活方法

2.1 最大化激活

為了理解神經(jīng)網(wǎng)絡(luò)的工作過程,可以在輸入圖像上應(yīng)用過濾器,然后繪制其卷積后的輸出,這使得我們能夠理解一個(gè)過濾器其特定的激活模式是什么。比如,下圖是一個(gè)人臉過濾器,當(dāng)輸入圖像是人臉圖像時(shí)候,它就會(huì)被激活。

from vis.visualization import visualize_activation
from vis.utils import utils
from keras import activations

from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams["figure.figsize"] = (18, 6)

# Utility to search for layer index by name.
# Alternatively we can specify this as -1 since it corresponds to the last layer.
layer_idx = utils.find_layer_idx(model, "preds")

# Swap softmax with linear
model.layers[layer_idx].activation = activations.linear
model = utils.apply_modifications(model)

# This is the output node we want to maximize.
filter_idx = 0
img = visualize_activation(model, layer_idx, filter_indices=filter_idx)
plt.imshow(img[..., 0])

同理,可以將這個(gè)想法應(yīng)用于所有的類別,并檢查它們的模式會(huì)是什么樣子。

for output_idx in np.arange(10):
   # Lets turn off verbose output this time to avoid clutter and just see the output.
   img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))
   plt.figure()
   plt.title("Networks perception of {}".format(output_idx))
   plt.imshow(img[..., 0])

2.2 圖像遮擋

在圖像分類問題中,可能會(huì)遇到目標(biāo)物體被遮擋,有時(shí)候只有物體的一小部分可見的情況?;趫D像遮擋的方法是通過一個(gè)灰色正方形系統(tǒng)地輸入圖像的不同部分并監(jiān)視分類器的輸出。這些例子清楚地表明模型在場景中定位對(duì)象時(shí),若對(duì)象被遮擋,其分類正確的概率顯著降低。

為了理解這一概念,可以從數(shù)據(jù)集中隨機(jī)抽取圖像,并嘗試?yán)L制該圖的熱圖(heatmap)。這使得我們直觀地了解圖像的哪些部分對(duì)于該模型而言的重要性,以便對(duì)實(shí)際類別進(jìn)行明確的區(qū)分。

def iter_occlusion(image, size=8):
    # taken from https://www.kaggle.com/blargl/simple-occlusion-and-saliency-maps

   occlusion = np.full((size * 5, size * 5, 1), [0.5], np.float32)
   occlusion_center = np.full((size, size, 1), [0.5], np.float32)
   occlusion_padding = size * 2

   # print("padding...")
   image_padded = np.pad(image, ( 
   (occlusion_padding, occlusion_padding), (occlusion_padding, occlusion_padding), (0, 0) 
   ), "constant", constant_values = 0.0)

   for y in range(occlusion_padding, image.shape[0] + occlusion_padding, size):

       for x in range(occlusion_padding, image.shape[1] + occlusion_padding, size):
           tmp = image_padded.copy()

           tmp[y - occlusion_padding:y + occlusion_center.shape[0] + occlusion_padding, 
             x - occlusion_padding:x + occlusion_center.shape[1] + occlusion_padding] 
             = occlusion

           tmp[y:y + occlusion_center.shape[0], x:x + occlusion_center.shape[1]] = occlusion_center

           yield x - occlusion_padding, y - occlusion_padding, 
             tmp[occlusion_padding:tmp.shape[0] - occlusion_padding, occlusion_padding:tmp.shape[1] - occlusion_padding]

i = 23 # for example
data = val_x[i]
correct_class = np.argmax(val_y[i])

# input tensor for model.predict
inp = data.reshape(1, 28, 28, 1)

# image data for matplotlib"s imshow
img = data.reshape(28, 28)

# occlusion
img_size = img.shape[0]
occlusion_size = 4

print("occluding...")

heatmap = np.zeros((img_size, img_size), np.float32)
class_pixels = np.zeros((img_size, img_size), np.int16)

from collections import defaultdict
counters = defaultdict(int)

for n, (x, y, img_float) in enumerate(iter_occlusion(data, size=occlusion_size)):

    X = img_float.reshape(1, 28, 28, 1)
    out = model.predict(X)
    #print("#{}: {} @ {} (correct class: {})".format(n, np.argmax(out), np.amax(out), out[0][correct_class]))
    #print("x {} - {} | y {} - {}".format(x, x + occlusion_size, y, y + occlusion_size))

    heatmap[y:y + occlusion_size, x:x + occlusion_size] = out[0][correct_class]
    class_pixels[y:y + occlusion_size, x:x + occlusion_size] = np.argmax(out)
    counters[np.argmax(out)] += 1

3. 基于梯度的方法

3.1 顯著圖

正如之前的坦克案例中看到的那樣,怎么才能知道模型側(cè)重于哪部分的預(yù)測呢?為此,可以使用顯著圖解決這個(gè)問題。顯著圖首先在這篇文章中被介紹。

使用顯著圖的概念相當(dāng)直接——計(jì)算輸出類別相對(duì)于輸入圖像的梯度。這應(yīng)該告訴我們輸出類別值對(duì)于輸入圖像像素中的微小變化是怎樣變化的。梯度中的所有正值告訴我們,像素的一個(gè)小變化會(huì)增加輸出值。因此,將這些梯度可視化可以提供一些直觀的信息,這種方法突出了對(duì)輸出貢獻(xiàn)最大的顯著圖像區(qū)域。

class_idx = 0
indices = np.where(val_y[:, class_idx] == 1.)[0]

# pick some random input from here.
idx = indices[0]

# Lets sanity check the picked image.
from matplotlib import pyplot as plt
%matplotlib inline
plt.rcParams["figure.figsize"] = (18, 6)

plt.imshow(val_x[idx][..., 0])


from vis.visualization import visualize_saliency
from vis.utils import utils
from keras import activations

# Utility to search for layer index by name. 
# Alternatively we can specify this as -1 since it corresponds to the last layer.
layer_idx = utils.find_layer_idx(model, "preds")

# Swap softmax with linear
model.layers[layer_idx].activation = activations.linear
model = utils.apply_modifications(model)

grads = visualize_saliency(model, layer_idx, filter_indices=class_idx, seed_input=val_x[idx])
# Plot with "jet" colormap to visualize as a heatmap.
plt.imshow(grads, cmap="jet")


# This corresponds to the Dense linear layer.
for class_idx in np.arange(10): 
    indices = np.where(val_y[:, class_idx] == 1.)[0]
    idx = indices[0]

    f, ax = plt.subplots(1, 4)
    ax[0].imshow(val_x[idx][..., 0])
 
    for i, modifier in enumerate([None, "guided", "relu"]):
        grads = visualize_saliency(model, layer_idx, filter_indices=class_idx, 
        seed_input=val_x[idx], backprop_modifier=modifier)
        if modifier is None:
            modifier = "vanilla"
        ax[i+1].set_title(modifier) 
        ax[i+1].imshow(grads, cmap="jet")

3.2 基于梯度的類別激活映射

類別激活映射(CAM)或grad-CAM是另外一種可視化模型的方法,這種方法使用的不是梯度的輸出值,而是使用倒數(shù)第二個(gè)卷積層的輸出,這樣做是為了利用存儲(chǔ)在倒數(shù)第二層的空間信息。

from vis.visualization import visualize_cam

# This corresponds to the Dense linear layer.
for class_idx in np.arange(10): 
 indices = np.where(val_y[:, class_idx] == 1.)[0]
 idx = indices[0]

f, ax = plt.subplots(1, 4)
 ax[0].imshow(val_x[idx][..., 0])
 
for i, modifier in enumerate([None, "guided", "relu"]):
    grads = visualize_cam(model, layer_idx, filter_indices=class_idx, 
    seed_input=val_x[idx], backprop_modifier=modifier) 
    if modifier is None:
        modifier = "vanilla"
    ax[i+1].set_title(modifier) 
    ax[i+1].imshow(grads, cmap="jet")

總結(jié)

本文簡單說明了CNN模型可視化的重要性,以及介紹了一些可視化CNN網(wǎng)絡(luò)模型的方法,希望對(duì)讀者有所幫助,使其能夠在后續(xù)深度學(xué)習(xí)應(yīng)用中構(gòu)建更好的模型。

更為詳細(xì)的內(nèi)容請(qǐng)查看原文

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/44677.html

相關(guān)文章

  • 初學(xué)者怎么選擇神經(jīng)網(wǎng)絡(luò)環(huán)境?對(duì)比MATLAB、Torch和TensorFlow

    摘要:本報(bào)告面向的讀者是想要進(jìn)入機(jī)器學(xué)習(xí)領(lǐng)域的學(xué)生和正在尋找新框架的專家。其輸入需要重塑為包含個(gè)元素的一維向量以滿足神經(jīng)網(wǎng)絡(luò)。卷積神經(jīng)網(wǎng)絡(luò)目前代表著用于圖像分類任務(wù)的較先進(jìn)算法,并構(gòu)成了深度學(xué)習(xí)中的主要架構(gòu)。 初學(xué)者在學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)的時(shí)候往往會(huì)有不知道從何處入手的困難,甚至可能不知道選擇什么工具入手才合適。近日,來自意大利的四位研究者發(fā)布了一篇題為《神經(jīng)網(wǎng)絡(luò)初學(xué)者:在 MATLAB、Torch 和 ...

    yunhao 評(píng)論0 收藏0
  • 最新Github上各DL框架Star數(shù)量大PK

    摘要:下圖總結(jié)了絕大多數(shù)上的開源深度學(xué)習(xí)框架項(xiàng)目,根據(jù)項(xiàng)目在的數(shù)量來評(píng)級(jí),數(shù)據(jù)采集于年月初。然而,近期宣布將轉(zhuǎn)向作為其推薦深度學(xué)習(xí)框架因?yàn)樗С忠苿?dòng)設(shè)備開發(fā)。該框架可以出色完成圖像識(shí)別,欺詐檢測和自然語言處理任務(wù)。 很多神經(jīng)網(wǎng)絡(luò)框架已開源多年,支持機(jī)器學(xué)習(xí)和人工智能的專有解決方案也有很多。多年以來,開發(fā)人員在Github上發(fā)布了一系列的可以支持圖像、手寫字、視頻、語音識(shí)別、自然語言處理、物體檢測的...

    oogh 評(píng)論0 收藏0
  • 全面整理30個(gè)重要深度學(xué)習(xí)庫:按Python和C++等10種語言分類

    摘要:本文介紹了包括等在內(nèi)的一系列編程語言的深度學(xué)習(xí)庫。是一個(gè)在中用于帶有神經(jīng)網(wǎng)絡(luò)的深度學(xué)習(xí)的庫,它通過使用帶有的加速。是一個(gè)用和開發(fā)的深度學(xué)習(xí)庫。是第一個(gè)為和編寫的消費(fèi)級(jí)開元分布式深度學(xué)習(xí)庫。它帶有豐富的作為機(jī)器學(xué)習(xí)庫一部分的深度學(xué)習(xí)庫。 本文介紹了包括 Python、Java、Haskell等在內(nèi)的一系列編程語言的深度學(xué)習(xí)庫。PythonTheano 是一種用于使用數(shù)列來定義和評(píng)估數(shù)學(xué)表達(dá)的 ...

    weij 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<