1. 程式人生 > >深度學習:卷積,反池化,反捲積,卷積可解釋性,CAM ,G_CAM

深度學習:卷積,反池化,反捲積,卷積可解釋性,CAM ,G_CAM

憑什麼相信你,我的CNN模型?(篇一:CAM和Grad-CAM):https://www.jianshu.com/p/1d7b5c4ecb93

憑什麼相信你,我的CNN模型?(篇二:萬金油LIME):http://bindog.github.io/blog/2018/02/11/model-explanation-2/

卷積和反捲積 :https://blog.csdn.net/Fate_fjh/article/details/52882134

視覺化理解卷積神經網路:https://blog.csdn.net/lemianli/article/details/53171951?utm_source=blogxgwz0

 

影象-》特徵圖-》影象:

假如你想要檢視Alexnet 的conv5提取到了什麼東西,我們就用conv5的特徵圖後面接一個反捲積網路,然後通過:反池化、反啟用、反捲積,這樣的一個過程,把本來一張13*13大小的特徵圖(conv5大小為13*13),放大回去,最後得到一張與原始輸入圖片一樣大小的圖片(227*227)。

 

1、卷積:

影象5*5 卷積核

圖2

2維卷積的計算分為了3類,1.full   2.same   3. valid 

圖3

圖3中藍色為原影象,白色為對應卷積所增加的padding,通常全部為0,綠色是卷積後圖片。圖3的卷積的滑動是從卷積核右下角與圖片左上角重疊開始進行卷積,滑動步長為1,卷積核的中心元素對應卷積後圖像的畫素點。可以看到卷積後的影象是4X4,比原圖2X2大了,我們還記1維卷積大小是n1+n2-1,這裡原圖是2X2,卷積核3X3,卷積後結果是4X4,與一維完全對應起來了。其實這才是完整的卷積計算,其他比它小的卷積結果都是省去了部分畫素的卷積。下面是WIKI對應影象卷積後多出部分的解釋:

Kernel convolution usually requires values from pixels outside of the image boundaries. There are a variety of methods for handling image edges.意思就是多出來的部分根據實際情況可以有不同的處理方法。(其實這裡的full卷積就是後面要說的反捲積)

這裡,我們可以總結出full,same,valid三種卷積後圖像大小的計算公式
1.full: 滑動步長為1,圖片大小為N1xN1,卷積核大小為N2xN2,卷積後圖像大小:N1+N2-1 x N1+N2-1
如圖3, 滑動步長為1,圖片大小為2x2,卷積核大小為3x3,卷積後圖像大小:4x4
2.same: 滑動步長為1,圖片大小為N1xN1,卷積核大小為N2xN2,卷積後圖像大小:N1xN1
3.valid:滑動步長為S,圖片大小為N1xN1,卷積核大小為N2xN2,卷積後圖像大小:(N1-N2)/S+1 x (N1-N2)/S+1
如圖2,滑動步長為1,圖片大小為5x5,卷積核大小為3x3,卷積後圖像大小:3x3

 

二、反捲積(後卷積,轉置卷積) 視覺化

為了解釋卷積神經網路為什麼work,我們就需要解釋CNN的每一層學習到了什麼東西。為了理解網路中間的每一層,提取到特徵,paper通過反捲積的方法,進行視覺化。反捲積網路可以看成是卷積網路的逆過程。反捲積網路在文獻《Adaptive deconvolutional networks for mid and high level feature learning》中被提出,是用於無監督學習的。然而本文的反捲積過程並不具備學習的能力,僅僅是用於視覺化一個已經訓練好的卷積網路模型,沒有學習訓練的過程。

反捲積視覺化以各層得到的特徵圖作為輸入,進行反捲積,得到反捲積結果,用以驗證顯示各層提取到的特徵圖。舉個例子:假如你想要檢視Alexnet 的conv5提取到了什麼東西,我們就用conv5的特徵圖後面接一個反捲積網路,然後通過:反池化、反啟用、反捲積,這樣的一個過程,把本來一張13*13大小的特徵圖(conv5大小為13*13),放大回去,最後得到一張與原始輸入圖片一樣大小的圖片(227*227)。

1、反池化過程 pooling uppooling 

我們知道,池化是不可逆的過程,然而我們可以通過記錄池化過程中,最大啟用值得座標位置。然後在反池化的時候,只把池化過程中最大啟用值所在的位置座標的值啟用,其它的值置為0,當然這個過程只是一種近似,因為我們在池化的過程中,除了最大值所在的位置,其它的值也是不為0的。剛好最近幾天看到文獻:《Stacked What-Where Auto-encoders》,裡面有個反捲積示意圖畫的比較好,所有就截下圖,用這篇文獻的示意圖進行講解:

以上面的圖片為例,上面的圖片中左邊表示pooling過程,右邊表示unpooling過程。假設我們pooling塊的大小是3*3,採用max pooling後,我們可以得到一個輸出神經元其啟用值為9,pooling是一個下采樣的過程,本來是3*3大小,經過pooling後,就變成了1*1大小的圖片了。而upooling剛好與pooling過程相反,它是一個上取樣的過程,是pooling的一個反向運算,當我們由一個神經元要擴充套件到3*3個神經元的時候,我們需要藉助於pooling過程中,記錄下最大值所在的位置座標(0,1),然後在unpooling過程的時候,就把(0,1)這個畫素點的位置填上去,其它的神經元啟用值全部為0。再來一個例子:

 

在max pooling的時候,我們不僅要得到最大值,同時還要記錄下最大值得座標(-1,-1),然後再unpooling的時候,就直接把(-1-1)這個點的值填上去,其它的啟用值全部為0。

2、反啟用

我們在Alexnet中,relu函式是用於保證每層輸出的啟用值都是正數,因此對於反向過程,我們同樣需要保證每層的特徵圖為正值,也就是說這個反啟用過程和啟用過程沒有什麼差別,都是直接採用relu函式

3、反捲積

對於反捲積過程,採用卷積過程轉置後的濾波器(引數一樣,只不過把引數矩陣水平和垂直方向翻轉了一下),這一點我現在也不是很明白,估計要採用數學的相關理論進行證明。

最後視覺化網路結構如下:

 

網路的整個過程,從右邊開始:輸入圖片-》卷積-》Relu-》最大池化-》得到結果特徵圖-》反池化-》Relu-》反捲積

總的來說演算法主要有兩個關鍵點:1、反池化  2、反捲積,這兩個原始碼的實現方法,需要好好理解。

計算方式

 這裡提到的反捲積跟1維訊號處理的反捲積計算是很不一樣的,FCN作者稱為backwards convolution,有人稱Deconvolution layer is a very unfortunate name and should rather be called a transposed convolutional layer. 我們可以知道,在CNN中有con layer與pool layer,con layer進行對影象卷積提取特徵,pool layer對影象縮小一半篩選重要特徵,對於經典的影象識別CNN網路,如IMAGENET,最後輸出結果是1X1X1000,1000是類別種類,1x1得到的是。FCN作者,或者後來對end to end研究的人員,就是對最終1x1的結果使用反捲積(事實上FCN作者最後的輸出不是1X1,是圖片大小的32分之一,但不影響反捲積的使用)。
    這裡影象的反捲積與圖3的full卷積原理是一樣的,使用了這一種反捲積手段使得影象可以變大,FCN作者使用的方法是這裡所說反捲積的一種變體,這樣就可以獲得相應的畫素值,影象可以實現end to end

卷積 padding 卷積,transposed就是代表反捲積(轉置卷積) 

圖7
    這裡說另外一種反捲積做法,假設原圖是3X3,首先使用上取樣讓影象變成7X7,可以看到影象多了很多空白的畫素點。使用一個3X3的卷積核對影象進行滑動步長為1的valid卷積,得到一個5X5的影象,我們知道的是使用上取樣擴大圖片,使用反捲積填充影象內容,使得影象內容變得豐富,這也是CNN輸出end to end結果的一種方法。韓國作者Hyeonwoo Noh使用VGG16層CNN網路後面加上對稱的16層反捲積與上取樣網路實現end to end 輸出,其不同層上取樣與反捲積變化效果如下,

                                                                                                                                                   圖8

    到這裡就把影象卷積與反捲積解釋完成,如有不妥,請學者們指證。
    
    補充一個資料:
    圖6與圖7出處,https://github.com/vdumoulin/conv_arithmetic     

------------新增反捲積過程解釋----------------
經過上面的解釋與推導,對卷積有基本的瞭解,但是在影象上的deconvolution究竟是怎麼一回事,可能還是不能夠很好的理解,因此這裡再對這個過程解釋一下。
目前使用得最多的deconvolution有2種,上文都已經介紹。 
方法1:full卷積, 完整的卷積可以使得原來的定義域變大
方法2:記錄pooling index,然後擴大空間,再用卷積填充

影象的deconvolution過程如下,

輸入:2x2, 卷積核:4x4, 滑動步長:3, 輸出:7x7
即輸入為2x2的圖片經過4x4的卷積核進行步長為3的反捲積的過程
:1.輸入圖片每個畫素進行一次full卷積,根據full卷積大小計算可以知道每個畫素的卷積後大小為 1+4-1=4, 即4x4大小的特徵圖,輸入有4個畫素所以4個4x4的特徵圖
2.將4個特徵圖進行步長為3的fusion(即相加); 例如紅色的特徵圖仍然是在原來輸入位置(左上角),綠色還是在原來的位置(右上角),步長為3是指每隔3個畫素進行fusion,重疊部分進行相加,即輸出的第1行第4列是由紅色特陣圖的第一行第四列與綠色特徵圖的第一行第一列相加得到,其他如此類推。

可以看出翻卷積的大小是由卷積核大小與滑動步長決定, in是輸入大小, k是卷積核大小, s是滑動步長, out是輸出大小
得到 out = (in - 1) * s + k
上圖過程就是, (2 - 1) * 3 + 4 = 7
 

 

三、卷積解釋性:

談談如何讓看似黑盒的CNN模型“說話”,對它的分類結果給出一個解釋。注意,本文所說的“解釋”,與我們日常說的“解釋”內涵不一樣:例如我們給孩子一張貓的圖片,讓他解釋為什麼這是一隻貓,孩子會說因為它有尖耳朵、鬍鬚等。而我們讓CNN模型解釋為什麼將這張圖片的分類結果為貓,只是讓它標出是通過圖片的哪些畫素作出判斷的。(嚴格來說,這樣不能說明模型是否真正學到了我們人類所理解的“特徵”,因為模型所學習到的特徵本來就和人類的認知有很大區別。何況,即使只標註出是通過哪些畫素作出判斷就已經有很高價值了,如果標註出的畫素集中在地面上,而模型的分類結果是貓,顯然這個模型是有問題的)

1、卷積視覺化

1、特徵視覺化結果

總的來說,通過CNN學習後,我們學習到的特徵,是具有辨別性的特徵,比如要我們區分人臉和狗頭,那麼通過CNN學習後,背景部位的啟用度基本很少,我們通過視覺化就可以看到我們提取到的特徵忽視了背景,而是把關鍵的資訊給提取出來了。從layer 1、layer 2學習到的特徵基本上是顏色、邊緣等低層特徵;layer 3則開始稍微變得複雜,學習到的是紋理特徵,比如上面的一些網格紋理;layer 4學習到的則是比較有區別性的特徵,比如狗頭;layer 5學習到的則是完整的,具有辨別性關鍵特徵

2、特徵學習的過程。作者給我們顯示了,在網路訓練過程中,每一層學習到的特徵是怎麼變化的,上面每一整張圖片是網路的某一層特徵圖,然後每一行有8個小圖片,分別表示網路epochs次數為:1、2、5、10、20、30、40、64的特徵圖:

結果:(1)仔細看每一層,在迭代的過程中的變化,出現了sudden jumps;(2)從層與層之間做比較,我們可以看到,低層在訓練的過程中基本沒啥變化,比較容易收斂,高層的特徵學習則變化很大。這解釋了低層網路的從訓練開始,基本上沒有太大的變化,因為梯度彌散嘛。(3)從高層網路conv5的變化過程,我們可以看到,剛開始幾次的迭代,基本變化不是很大,但是到了40~50的迭代的時候,變化很大,因此我們以後在訓練網路的時候,不要著急看結果,看結果需要保證網路收斂。

3、影象變換。從文獻中的圖片5視覺化結果,我們可以看到對於一張經過縮放、平移等操作的圖片來說:對網路的第一層影響比較大,到了後面幾層,基本上這些變換提取到的特徵沒什麼比較大的變化。

個人總結:我個人感覺學習這篇文獻的演算法,不在於視覺化,而在於學習反捲積網路,如果懂得了反捲積網路,那麼在以後的文獻中,你會經常遇到這個演算法。大部分CNN結構中,如果網路的輸出是一整張圖片的話,那麼就需要使用到反捲積網路,比如圖片語義分割、圖片去模糊、視覺化、圖片無監督學習、圖片深度估計,像這種網路的輸出是一整張圖片的任務,很多都有相關的文獻,而且都是利用了反捲積網路,取得了牛逼哄哄的結果。所以我覺得我學習這篇文獻,更大的意義在於學習反捲積網路。

 

2、 反捲積和導向反向傳播

關於CNN模型的可解釋問題,很早就有人開始研究了,姑且稱之為CNN視覺化吧。比較經典的有兩個方法,反捲積(Deconvolution)和導向反向傳播(Guided-backpropagation),通過它們,我們能夠一定程度上“看到”CNN模型中較深的卷積層所學習到的一些特徵。當然這兩個方法也衍生出了其他很多用途,以反捲積為例,它在影象語義分割中有著非常重要的作用。(ps:目前網上有一些關於反捲積的文章,我感覺沒有說的特別到位的,當然也有可能是大家理解的角度不同,但是另外一些解讀那就是完全錯誤的了,包括某乎。不得不說,真正要深入理解反捲積還是要去啃論文,很多人嫌麻煩總是看些二手的資料,得到的認識自然是有問題的。當然這些都是題外話,我也有寫一篇關於反捲積的文章的計劃。看以後的時間安排)

從本質上說,反捲積和導向反向傳播的基礎都是反向傳播,其實說白了就是對輸入進行求導,三者唯一的區別在於反向傳播過程中經過ReLU層時對梯度的不同處理策略在這篇論文中有著非常詳細的說明,如下圖所示:

雖然過程上的區別看起來沒有非常微小,但是在最終的效果上卻有很大差別。如下圖所示:

使用普通的反向傳播得到的影象噪聲較多,基本看不出模型的學到了什麼東西。使用反捲積可以大概看清楚貓和狗的輪廓,但是有大量噪聲在物體以外的位置上。導向反向傳播基本上沒有噪聲,特徵很明顯的集中貓和狗的身體部位上。

雖然藉助反捲積和導向反向傳播我們“看到”了CNN模型神祕的內部,但是卻並不能拿來解釋分類的結果,因為它們對類別並不敏感,直接把所有能提取的特徵都展示出來了。在剛才的圖片中,模型給出的分類結果是貓,但是通過反捲積和導向反向傳播展示出來的結果卻同時包括了狗的輪廓。換句話說,我們並不知道模型到底是通過哪塊區域判斷出當前圖片是一隻貓的。要解決這個問題,我們必須考慮其他辦法。

3、 CAM

大家在電視上應該都看過熱成像儀生成的影象,就像下面這張圖片。

影象中動物或人因為散發出熱量,所以能夠清楚的被看到。接下來要介紹的CAM(Class Activation Mapping)產生的CAM圖與之類似,當我們需要模型解釋其分類的原因時,它以熱力圖(Saliency Map,我不知道怎麼翻譯最適合,叫熱力圖比較直觀一點)的形式展示它的決策依據,如同在黑夜中告訴我們哪有發熱的物體。

對一個深層的卷積神經網路而言,通過多次卷積和池化以後,它的最後一層卷積層包含了最豐富的空間和語義資訊,再往下就是全連線層和softmax層了,其中所包含的資訊都是人類難以理解的,很難以視覺化的方式展示出來。所以說,要讓卷積神經網路的對其分類結果給出一個合理解釋,必須要充分利用好最後一個卷積層。

CAM借鑑了很著名的論文Network in Network中的思路,利用GAP(Global Average Pooling)替換掉了全連線層。可以把GAP視為一個特殊的average pool層,只不過其pool size和整個特徵圖一樣大,其實說白了就是求每張特徵圖所有畫素的均值,一個特徵層,average pool 變成一個平均值,即特徵層所有的的值的平均數。

GAP的優點

在NIN的論文中說的很明確了:由於沒有了全連線層,輸入就不用固定大小了,因此可支援任意大小的輸入;此外,引入GAP更充分的利用了空間資訊,且沒有了全連線層的各種引數,魯棒性強,也不容易產生過擬合;還有很重要的一點是,在最後的 mlpconv層(也就是最後一層卷積層)強制生成了和目標類別數量一致的特徵圖,經過GAP以後再通過softmax層得到結果,這樣做就給每個特徵圖賦予了很明確的意義,也就是categories confidence maps。如果你當時不理解這個categories confidence maps是個什麼東西,結合CAM應該就能很快理解。

我們重點看下經過GAP之後與輸出層的連線關係(暫不考慮softmax層),實質上也是就是個全連線層,只不過沒有了偏置項,如圖所示:

從圖中可以看到,經過GAP之後,我們得到了最後一個卷積層每個特徵圖的均值,通過加權和得到輸出(實際中是softmax層的輸入)。需要注意的是,對每一個類別C,每個特徵圖k的均值都有一個對應的w,記為w_k^c。CAM的基本結構就是這樣了,下面就是和普通的CNN模型一樣訓練就可以了。訓練完成後才是重頭戲:我們如何得到一個用於解釋分類結果的熱力圖呢?其實非常簡單,比如說我們要解釋為什麼分類的結果是羊駝,我們把羊駝這個類別對應的所有w_k^c取出來,求出它們與自己對應的特徵圖的加權和即可。由於這個結果的大小和特徵圖是一致的,我們需要對它進行上取樣,疊加到原圖上去,如下所示。

這樣,CAM以熱力圖的形式告訴了我們,模型是重點通過哪些畫素確定這個圖片是羊駝了

4、 Grad-CAM方法

前面看到CAM的解釋效果已經很不錯了,但是它有一個致使傷,就是它要求修改原模型的結構,導致需要重新訓練該模型,這大大限制了它的使用場景。如果模型已經上線了,或著訓練的成本非常高,我們幾乎是不可能為了它重新訓練的。於是乎,Grad-CAM橫空出世,解決了這個問題。

Grad-CAM的基本思路和CAM是一致的,也是通過得到每對特徵圖對應的權重,最後求一個加權和。但是它與CAM的主要區別在於求權重w_k^c的過程。CAM通過替換全連線層為GAP層,重新訓練得到權重,而Grad-CAM另闢蹊徑,用梯度的全域性平均來計算權重。事實上,經過嚴格的數學推導,Grad-CAM與CAM計算出來的權重是等價的。為了和CAM的權重做區分,定義Grad-CAM中第k個特徵圖對類別c的權重為\alpha_k^c,可通過下面的公式計算:

\alpha_k^c=\frac{1}{Z}\sum\limits_{i}\sum\limits_{j}\frac{\partial y^c}{\partial A_{ij}^k}

其中,Z為特徵圖的畫素個數,y^c是對應類別c的分數(在程式碼中一般用logits表示,是輸入softmax層之前的值),A_{ij}^k表示第k個特徵圖中,(i,j)位置處的畫素值。求得類別對所有特徵圖的權重後,求其加權和就可以得到熱力圖。

L_{Grad-CAM}^c=ReLU(\sum\limits_k\alpha_k^cA^k)

Grad-CAM的整體結構如下圖所示:

注意這裡和CAM的另一個區別是,Grad-CAM對最終的加權和加了一個ReLU,加這麼一層ReLU的原因在於我們只關心對類別c有正影響的那些畫素點,如果不加ReLU層,最終可能會帶入一些屬於其它類別的畫素,從而影響解釋的效果。使用Grad-CAM對分類結果進行解釋的效果如下圖所示:

除了直接生成熱力圖對分類結果進行解釋,Grad-CAM還可以與其他經典的模型解釋方法如導向反向傳播相結合,得到更細緻的解釋。

這樣就很好的解決了反捲積和導向反向傳播對類別不敏感的問題。當然,Grad-CAM的神奇之處還不僅僅侷限在對圖片分類的解釋上,任何與影象相關的深度學習任務,只要用到了CNN,就可以用Grad-CAM進行解釋,如影象描述(Image Captioning),視覺問答(Visual Question Answering)等,所需要做的只不過是把y^c換為對應模型中的那個值即可。限於篇幅,本文就不展開了,更多細節,強烈建議大家去讀讀論文,包括Grad-CAM與CAM權重等價的證明也在論文中。如果你只是想在自己的模型中使用Grad-CAM,可以參考這個連結,熟悉tensorflow的話實現起來真的非常簡單,一看就明白。

5、 擴充套件

其實無論是CAM還是Grad-CAM,除了用來對模型的預測結果作解釋外,還有一個非常重要的功能:就是用於物體檢測。大家都知道現在物體檢測是一個非常熱門的方向,它要求在一張圖片中準確的識別出多個物體,同時用方框將其框起來。物體檢測對訓練資料量的要求是非常高的,目前常被大家使用的有 PASCAL、COCO,如果需要更多資料,或者想要識別的物體在這些資料庫中沒有話,那就只能人工來進行標註了,工作量可想而知。

仔細想想我們不難發現,Grad-CAM在給出解釋的同時,不正好完成了標註物體位置的工作嗎?雖然其標註的位置不一定非常精確,也不一定完整覆蓋到物體的每一個畫素。但只要有這樣一個大致的資訊,我們就可以得到物體的位置,更具有誘惑力的是,我們不需要人工標註的方框就可以做到了。

順便吐槽下當前比較火的幾個物體檢測模型如Faster-RCNN、SSD等,無一例外都有一個Region Proposal階段,相當於“胡亂”在圖片中畫各種大小的方框,然後再來判斷方框中是否有物體存在。雖然效果很好,但是根本就是違揹人類直覺的。相比之下,Grad-CAM這種定位方式似乎更符合人類的直覺。當然這些純屬我個人的瞎扯,業務場景中SSD還是非常好用的,肯定要比Grad-CAM這種弱監督條件下的定位要強的多。

6、小結

試想如果當時五角大樓的研究人員知道本文介紹的這些方法,並對他們的分類結果用熱力圖進行解釋,相信他們能很快發現熱力圖的紅色區域主要集中在天空上,顯然說明模型並沒有真正學到如何判別一輛坦克,最後也就不至於鬧笑話了。

回顧本文所介紹的這些方法,它們都有一個共同前提:即模型對我們來說是白盒,我們清楚的知道模型內部的所有細節,能夠獲取任何想要的資料,甚至可以修改它的結構。但如果我們面對的是一個黑盒,對其內部一無所知,只能提供一個輸入並得到相應的輸出值(比如別人的某個模型部署在線上,我們只有使用它的權利),在這種情況下,我們如何判斷這個模型是否靠譜?能不能像Grad-CAM那樣對分類結果給出一個解釋呢?憑什麼相信你,我的CNN模型?(篇二:萬金油LIME)