瞎談CNN:通過優化求解輸入圖像

機器學習和優化問題

很多機器學習方法可以歸結為優化問題,對於一個參數模型,比如神經網路,用y=f(x;theta)來表示的話,訓練模型其實就是下面的參數優化問題:

hat theta= arg min_theta L(theta;x,y)

其中L是loss function,比如神經網路中分類常用的cross-entropy。

CNN學到了什麼?

特徵(Representation)。把原始圖像看做一個維度是像素×通道的向量,經過各種複雜的CNN結構,其實只不過成了另一個向量。這個向量所在的空間也許有更好的線性可分性,也許是相似樣本的「距離」更近,原始的數據經過變換到了這裡之後,就是特徵。

可視化CNN

那麼有個問題來了,如何可視化一個CNN結構學到的特徵呢?答案有很多,其中一種就是本文的主題:不再通過優化求解網路的參數,而是求解輸入圖像

優化網路的輸入,是相對於「正統」的機器學習優化參數而言的。當一個CNN訓練完全後,我們可以固定好參數,把輸入作為可訓練的量,根據目的給定一個新的目標函數。

把這種方法最早用在深度學習里大概是Bengio組在2009年的一個Tech report:《Visualizing Higher-Layer Features of a Deep Network》。文章里提出了下面的優化問題

hat x = arg max_{x} left( h_{ij}(x;theta) right) n

text {subject to}  left| left| x right| right|=rho

其中h_{ij}代表第j層中的第i個神經元的響應。很直觀的,這是要尋找什麼樣的圖像可以最大程度地激活這個神經元,這種方法就叫做activation maximization。利用這種辦法,原文中得到了類似下面的可視化,從左至右依次是一個DBN中從低到高的三層:

也許很多人一提起特徵可視化首先想到的是可視化特徵圖或是直接把卷積核畫出來,就像Caffe的Tutorial(Image Classification and Filter Visualization)中一樣。這樣的可視化其實是很不直觀的,尤其是卷積核的可視化,第一層之後的卷積核到底學到了什麼內容只能靠腦補。基於這個思路,Cornell的Jason Yosinski把公式改了改

hat x = arg max_x left( h_{ij}(x;theta)-R(x) right)

其實就是Regularization項R(x)放到了目標函數里。然後他把這種可視化作為功能之一,基於Caffe製作了一個年久失修的用於CNN可視化的工具包:yosinski/deep-visualization-toolbox。用在AlexNet上的效果是下面樣子:

注意到這個可視化結果還考慮到了感受野,也就是實際優化的目標是響應圖中心的點,所以越高層的可視化圖像越大。

直接把某一類別的分數作為優化值可以得到關於該類別更直觀的可視化結果,比如下圖是這個工具包對幾個類別的可視化:

每個類別學到的視覺上的特徵一目了然。另外注意到這種方法因為是基於優化,所以每次優化的結果會有不同。

藉助這種可視化,我們能夠分析出網路是不是真的學習到了我們希望其所學的特徵,比如Google的Research Blog中提到過啞鈴的例子:

可視化的類別是啞鈴,可是結果里包含了一些我們不希望出現的元素:胳膊。這是因為用於訓練的啞鈴圖片中,大都有握著啞鈴的胳膊。

可視化網路的方法有很多,以簡單粗暴為最大特點的大概只是activation maximization。

對抗樣本(Adversarial Examples)

對抗樣本也是機器學習中的一種常用概念,通常指人為製造的,讓一個機器學習模型發生錯誤的樣本。Anh Nguyen的論文《Deep Neural Networks are Easily Fooled: High Confidence Predictions for Unrecognizable Images》中有個比較形象的示意:

要理解這個圖,還要提一句機器學習的一個基本問題:學習數據的分布。具體到方法就是從訓練數據中進行學習,如果學習成功,則可以泛化到所有數據,包含沒見過的測試數據。回到這個圖,數據的分布就是最上邊那三坨。一種造對抗樣本的方法就是從一個類別的樣本出發,做一些小修改,讓模型將修改後的樣本判斷為另一個類別,而實際上(或是人的,顯然的判斷)該樣本仍為原來類別,這就是圖中從藍色原點到白色小方塊的方法。

當然更容易的方法是利用分類邊界的不可確定性。比如上圖中除了最上面部分的空間可以認為是數據存在概率極低的區域,從實際應用的角度甚至可以認為是我們完全不關心的區域。因為演算法學習的樣本只有實心的小圓點,所以遠離小圓點的部分,分類邊界是難以控制的。在這裡面很容易輕鬆取到演算法高概率認為是一個類別的樣本,而實際上卻難以辨認的對抗性樣本。

所以大體來說,對抗性樣本的存在是因為數據維度通常過高,即使考慮所在的子區域,往往還是過高,對整個(數據分布的)空間的搜索是不可行的。在訓練樣本沒有覆蓋的區域,無論該區域是否屬於數據分布所在的區域,無論模型的capacity夠不夠,都有出現對抗性樣本的可能。儘管深度學習中一直主張distributed representation已大幅優於局部泛化,維度的詛咒仍是一個無法擺脫的難題。

具體到CNN,下邊這個例子可能不少人見過:

熊貓的圖片上加上一個人眼難以察覺的噪音,對於人眼而言看上去還是熊貓,可是對於一個CNN而言,右邊的圖片以99%高概率被判斷為了長臂猿。上句話其實已經很清楚地指出了得到右邊圖片的方法,還是一個優化輸入圖像的問題:加上一個盡量小的噪音,並通過優化這個噪音,讓優化後的圖像具有另一個類別的高概率:

hat n = arg min_{n} left( alpha  left| left| n right| right| + Lleft( x+n, c right) right) n

text {subject to}  x+n in [0,1]^m

其中n是要求的噪音,alpha是相應的係數,L是x+n屬於某個類別的loss,c是某個錯誤類別的標籤。這大概是基於深度學習的計算機視覺中第一個討論造對抗樣本的方法,見於Christian Szegedy的論文《Intriguing properties of neural networks》。同樣是在這篇論文中,Christian描述了一個比較令人擔憂的發現:就是這種樣本居然可以泛化,同一個對抗樣本,對於不同的CNN結構,在不同數據子集下訓練的模型,是可以達到一定程度的「通用」性的。也就是說對於一些涉及到安全的應用,攻擊者即使不知道部署的模型是什麼,通過某種手段猜測數據的分布,也是可以得到有效的攻擊樣本的。

語義信息和高層神經元

對於CNN,有個很基礎的認識:低層的部分學習紋理等簡單信息,高層部分學習語義信息。在《Intriguing properties of neural networks》中的另一個發現是,CNN中表示高層學習到的語義信息的,並不是某一個神經元,而是高層神經元構成的空間。這個看上去有些顯然的結論的一種佐證方式又是對輸入圖像進行優化:

x=arg max_{x in text{images}} <phi(x), v>

其中phi(x)是神經元激活值對應的向量,v是一個隨機向量。另外這和前邊的優化有些許不同,x的取值範圍限定在已有的圖片集里。其實就是在某個高層響應的空間里,沿著某個方向挑選了一些該方向上值最大的圖片。最後的結論是,無論是沿著某個隨機方向找到的圖片,還是以某一個神經元響應最大找到的圖片,都能看出一些語義上的共性,比如下圖:

黑線以上是最大化某個神經元響應的樣本,共性挺明顯,黑線以下是最大化某層特徵空間中某個方向響應的樣本,共性也挺明顯。

Deep Dream

很多人小時候都有這樣的經歷:抬頭看天空的雲彩,或是觀察地面的紋路,甚至是凝視廁所里髒兮兮的牆面,這時候看到的卻是各種機器人大戰,武打畫面,或是動畫片中的人物和故事。

Deep Dream和這很像,輸入任何一幅圖像,都會得到在不同層的響應,前面已經提到過,低層的響應是紋理和細節的相應,高層的響應是語義信息的響應。所以Deep Dream的思想是:

對於某個高層的得到的語義信息響應,加強這些信息。這相當於讓網路自己決定從輸入圖像中「看到」了什麼,並把「看到」的東西加強,所以又是一個優化問題。

要優化的目標,就是最大化輸入圖像在某個高層已有的響應,優化的初始值就是輸入圖像,當然還有一些其他項,比如不同的包含不同尺度,或是抑制梯度及高頻成分的約束,這些是否加上視情況而定。這並不是一個典型的優化問題,反而更像是一個單純的梯度下降問題,所以梯度下降通常也不會進行到底,而是進行若干步直到輸入圖像中出現一個「夢境」。下面是TensorFlow的官方tutorial里,Inception模型在一幅圖片上生成的夢境:

基於Inception的DeepDream有個特點,就是夢境里的狗很多,就像上面這幅圖一樣。

在電影《Inception》里,夢境是可以操控的,DeepDream也可以,按照可視化中的思路,把優化目標換成某一層響應圖中的某個channel,這就是一個傳統的優化問題了:

hat x = arg max_x left( h_{ij}(x;theta)-R(x) right)

和第一部分中的差別在於初始化的是一幅圖像,並且優化不會進行到底。比如一個對花朵一樣圖案敏感的channel,對應的夢境里畫面中就會開滿了花:

其實那些隱藏在白雲里和牆上的圖案,長大後也是能看到的,只不過大多數人不看了。

Neural Art/Style

2016年,如果要評選一款和神經網路相關的最火爆的APP,一定非Prisma莫屬。其背後的演算法,也是對輸入圖像的優化。關於神經網路的藝術風格學習,首先要追溯到更早的一篇利用優化輸入方法的論文《Understanding DeepnImage Representations by Inverting Them》,裡面討論的問題之一是通過優化演算法和神經網路中的特徵重建一幅圖像:

hat x = arg min_x  ||phi(x)-phi_0||^2+lambda R(x)

其中phi_0是某幅圖像在網路中的特徵,這個特徵可以是部分層的響應,或者全部的響應。如果phi_0取低層的特徵,那麼細節的還原度就會很好,如果phi_0是高層的特徵,則畫面中的紋理和細節會丟失很多信息。比如下面的圖像:

用Vgg16模型執行一遍前向計算,然後分別取relu1~relu5的特徵作為phi_0,重建的結果如下:

在基於神經網路的圖像風格藝術化中,通常的輸入是一幅原始圖像,經過處理具有了其他畫面,比如一幅油畫的藝術風格。所以是原始圖像的內容+其他圖像的風格,那麼上面討論的部分就是內容的重建,所以接下來要討論的是風格的重建。

圖像風格其實是個很難定義的東西,不過在神經網路中,談到風格,一般指的是紋理。紋理的特點是什麼呢?又是一個很難定義的東西……不過紋理有個特點是和所在位置無關,基於這個特點,只要是和位置無關的統計信息,都可以試著來表示紋理的特徵,Gram矩陣,就是在CNN中表示這種特徵辦法的一種:

G_{ij}^l=sum_{k}{F_{ik}^lF_{jk}^l}

其中G^l代表第l層響應圖對應的Gram矩陣,F_{i}^l代表該層第i個卷積核對應的響應圖。通常一個響應圖是二維的,這裡把響應圖展開為一個一維向量,其中F_{ik}^l代表該層第i個響應圖的第k個元素。所以Gram矩陣的每一個元素就是求了個內積,把兩個響應圖之間,和位置無關的一種相關性給求了出來。nn

接下來的套路就和上一小節一樣了,把每層Gram矩陣作為特徵,讓重建圖像的Gram矩陣盡量接近原圖的Gram矩陣,也是個優化問題:

hat x = arg min_x sum_l w_lE_l

其中E_l是每一層的loss,w_l是該層loss的權重。E_l的形式是考慮到每層響應圖大小後的Gram矩陣差異:

E_l=frac 1 {4N_l^2M_l^2} sum_{i,j} left( G_{ij}^l -G_{ij}^{l,text {img}} right)^2

同樣是用Vgg16,用不同層的特徵,對梵高的星空進行風格重建,結果如下:

至於Gram矩陣為什麼能作為重建風格的依據,論文《Demystifying Neural Style Transfer》(感謝@Lyken 在評論中的分享)中給出了一個思路,是一個不錯的參考。比起原文中相關性的解釋,這篇論文更進一步把Gram矩陣轉化成了squared Maximum Mean Discrepancy,這直接把圖像和CNN中響應的分布聯繫了起來,並且可以通過替換計算MMD的方式嘗試其他風格重建的目標計算方式。

總之,重建內容和風格的方法都已有,接下來就很自然了,把某個較高層的特徵作為內容重建的目標,同時把每層響應的Gram矩陣以某個比例求和作為風格的重建目標,對輸入圖像進行優化:

hat x = arg min_x   (alpha L_{text {content}}(x,x_{text{content}})+beta L_{text {style}}(x,x_{text{style}})+lambda R(x))

這就是論文《A Neural Algorithm of Artistic Style》中的方法,也是Prisma背後的演算法。

推薦閱讀:

神經網路之梯度下降與反向傳播(上)
梯度下降法快速教程 | 第三章:學習率衰減因子(decay)的原理與Python實現
為什麼梯度的負方向是局部下降最快的方向?
詳解softmax函數以及相關求導過程
為什麼梯度下降演算法(BGD批量梯度下降)用的是所有樣本點梯度的均值作為最終的梯度方向?

TAG:卷积神经网络CNN | 梯度下降 | 深度学习DeepLearning |