距離上次寫博客已經(jīng)好久好久好久了,真是懈怠的生活節(jié)奏,整天混吃等死玩游戲,前些日子做畢業(yè)設(shè)計(jì)時(shí)總算又學(xué)了點(diǎn)新東西。學(xué)了一點(diǎn)深度學(xué)習(xí)和卷積神經(jīng)網(wǎng)絡(luò)的知識(shí),附帶著詳細(xì)學(xué)習(xí)了一下前段時(shí)間我覺(jué)得比較有意思的圖像風(fēng)格轉(zhuǎn)換。畢竟是初學(xué),順便把神經(jīng)網(wǎng)絡(luò)方面的知識(shí)也寫在前面了,便于理解。若有不對(duì)的地方的話,希望指正。

 

       主要參考的文獻(xiàn)有《A Neural Algorithm of Artistic Style》《Perceptual Losses for Real-Time Style Transfer and Super-Resolution》這兩篇論文,以及深度學(xué)習(xí)實(shí)踐:使用Tensorflow實(shí)現(xiàn)快速風(fēng)格遷移等文章,代碼參考了OlavHN/fast-neural-stylehzy46/fast-neural-style-tensorflow等大神的。

 

        先說(shuō)一下卷積神經(jīng)網(wǎng)絡(luò)。卷積神經(jīng)網(wǎng)絡(luò)(CNN)是一種前饋神經(jīng)網(wǎng)絡(luò),了解機(jī)器學(xué)習(xí)中人工神經(jīng)網(wǎng)絡(luò)的話應(yīng)該對(duì)這個(gè)概念不陌生。神經(jīng)網(wǎng)絡(luò)中的感知器模型如下圖所示。

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

       輸入神經(jīng)元與其各自權(quán)重相乘再相加得到z,利用激活函數(shù)g(z)進(jìn)行變換得到神經(jīng)元y。輸入層神經(jīng)元與其權(quán)重相乘再相加的過(guò)程可以用矩陣相乘相乘來(lái)表示,這點(diǎn)在下面的卷及神經(jīng)網(wǎng)絡(luò)里可以看到。神經(jīng)網(wǎng)絡(luò)里輸入層和輸出層中間的是隱藏層。

       在卷積神經(jīng)網(wǎng)絡(luò)里,網(wǎng)絡(luò)結(jié)構(gòu)一般是由多個(gè)卷積層、非線性化層、池化層以及最后的全連接層組成。卷積層對(duì)輸入進(jìn)行卷積計(jì)算,得到的結(jié)果經(jīng)過(guò)非線性化層的激活函數(shù),再經(jīng)過(guò)池化層進(jìn)行采樣,最后是全連接層。

       先介紹卷積操作。假設(shè)輸入圖片是二維矩陣,每個(gè)像素值都是輸入層的一個(gè)神經(jīng)元,權(quán)值也用矩陣來(lái)表示,這個(gè)權(quán)值矩陣叫做卷積核,也可以成為濾波器,卷積核代表了你看這個(gè)圖像時(shí)的感受野。不過(guò)卷積核是與輸入圖片的二維矩陣滑動(dòng)計(jì)算的,這里涉及到了權(quán)值共享的問(wèn)題。計(jì)算的過(guò)程如下圖所示。

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

         圖中黃色部分為3x3卷積核,綠色的為5x5輸入矩陣。卷積核在輸入矩陣上滑動(dòng)計(jì)算,每次都計(jì)算相應(yīng)位置的乘積再相加,得到卷積后的矩陣中的新的元素。每次滑動(dòng)的一格代表步長(zhǎng)(stride)為1,也可以為其它值。然后再對(duì)右面矩陣的每一個(gè)得到的元素的值通過(guò)激勵(lì)函數(shù)進(jìn)行非線性化處理,一般是用的ReLU函數(shù)。如下圖所示。

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

           池化層進(jìn)行下采樣,目的是減小特征圖,池化規(guī)模一般為2×2。常用的池化方法之一是最大池化(Max Pooling),即取4個(gè)點(diǎn)的最大值,如下圖所示,非常簡(jiǎn)單。

 

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

        卷積神經(jīng)網(wǎng)絡(luò)通過(guò)這樣可以不斷提取圖像的不同層次的特征圖,然后用于分類問(wèn)題等等。關(guān)于卷積神經(jīng)網(wǎng)絡(luò)的詳細(xì)解釋可以參考卷積神經(jīng)網(wǎng)絡(luò)全面解析卷積神經(jīng)網(wǎng)絡(luò)的理解這兩篇文章,這里就不多作解釋了。下面進(jìn)入正題,圖像風(fēng)格轉(zhuǎn)換的原理。

 

圖像風(fēng)格轉(zhuǎn)換

       

       以目前的深度學(xué)習(xí)技術(shù),如果給定兩張圖像,完全有能力讓計(jì)算機(jī)識(shí)別出圖像具體內(nèi)容。而圖像的風(fēng)格是一種很抽象的東西,人眼能夠很有效地的辨別出不同畫家不同流派繪畫的風(fēng)格,而在計(jì)算機(jī)的眼中,本質(zhì)上就是一些像素,多層網(wǎng)絡(luò)的實(shí)質(zhì)其實(shí)就是找出更復(fù)雜、更內(nèi)在的特性(features),所以圖像的風(fēng)格理論上可以通過(guò)多層網(wǎng)絡(luò)來(lái)提取圖像里面可能含有的一些有意思的特征。

       根據(jù)前面第一篇論文中提出的方法,風(fēng)格遷移的速度非常慢的。在風(fēng)格遷移過(guò)程中,把生成圖片的過(guò)程當(dāng)做一個(gè)“訓(xùn)練”的過(guò)程。每生成一張圖片,都相當(dāng)于要訓(xùn)練一次模型,這中間可能會(huì)迭代幾百幾千次。從頭訓(xùn)練一個(gè)模型相對(duì)于執(zhí)行一個(gè)已經(jīng)訓(xùn)練好的模型來(lái)說(shuō)相當(dāng)費(fèi)時(shí)?,F(xiàn)在根據(jù)前面第二篇論文提出的另一種模型,使得把生成圖片當(dāng)做一個(gè)“執(zhí)行”的過(guò)程,而不是一個(gè)“訓(xùn)練”的過(guò)程。

       快速風(fēng)格遷移的網(wǎng)絡(luò)結(jié)構(gòu)包含兩個(gè)部分。一個(gè)是“生成網(wǎng)絡(luò)”(Image Transform Net),一個(gè)是“損失網(wǎng)絡(luò)”(Loss Network)。生成網(wǎng)絡(luò)輸入層接收一個(gè)輸入圖片,最終輸出層輸出也是一張圖片(即風(fēng)格轉(zhuǎn)換后的結(jié)果)。模型總體分為兩個(gè)階段,訓(xùn)練階段和執(zhí)行階段。模型如圖所示。 其中左側(cè)是生成網(wǎng)絡(luò),右側(cè)為損失網(wǎng)絡(luò)。

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

       訓(xùn)練階段:選定一張風(fēng)格圖片。訓(xùn)練過(guò)程中,將數(shù)據(jù)集中的圖片輸入網(wǎng)絡(luò),生成網(wǎng)絡(luò)生成結(jié)果圖片y,損失網(wǎng)絡(luò)提取圖像的特征圖,將生成圖片y分別與目標(biāo)風(fēng)格圖片ys和目標(biāo)輸入圖片(內(nèi)容圖片)yc做損失計(jì)算,根據(jù)損失值來(lái)調(diào)整生成網(wǎng)絡(luò)的權(quán)值,通過(guò)最小化損失值來(lái)達(dá)到目標(biāo)效果。

       執(zhí)行階段:給定一張圖片,將其輸入已經(jīng)訓(xùn)練好的生成網(wǎng)絡(luò),輸出這張圖片風(fēng)格轉(zhuǎn)換后的結(jié)果。

 

生成網(wǎng)絡(luò)

     

       對(duì)于生成網(wǎng)絡(luò),本質(zhì)上是一個(gè)卷積神經(jīng)網(wǎng)絡(luò),這里的生成網(wǎng)絡(luò)是一個(gè)深度殘差網(wǎng)絡(luò),不用任何的池化層,取而代之的是用步幅卷積或微步幅卷積做網(wǎng)絡(luò)內(nèi)的上采樣或者下采樣。這里的神經(jīng)網(wǎng)絡(luò)有五個(gè)殘差塊組成。除了最末的輸出層以外,所有的非殘差卷積層都跟著一個(gè)空間性的instance-normalization,和RELU的非線性層,instance-normalization正則化是用來(lái)防止過(guò)擬合的。最末層使用一個(gè)縮放的Tanh來(lái)確保輸出圖像的像素在[0,255]之間。除開第一個(gè)和最后一個(gè)層用9x9的卷積核(kernel),其他所有卷積層都用3x3的卷積核。

 

損失網(wǎng)絡(luò)

       

        損失網(wǎng)絡(luò)φ是能定義一個(gè)內(nèi)容損失(content loss)和一個(gè)風(fēng)格損失(style loss),分別衡量?jī)?nèi)容和風(fēng)格上的差距。對(duì)于每一張輸入的圖片x我們有一個(gè)內(nèi)容目標(biāo)yc一個(gè)風(fēng)格目標(biāo)ys,對(duì)于風(fēng)格轉(zhuǎn)換,內(nèi)容目標(biāo)yc是輸入圖像x,輸出圖像y,應(yīng)該把風(fēng)格ys結(jié)合到內(nèi)容x=yc上。系統(tǒng)為每一個(gè)目標(biāo)風(fēng)格訓(xùn)練一個(gè)網(wǎng)絡(luò)。

        為了明確逐像素?fù)p失函數(shù)的缺點(diǎn),并確保所用到的損失函數(shù)能更好的衡量圖片感知及語(yǔ)義上的差距,需要使用一個(gè)預(yù)先訓(xùn)練好用于圖像分類的CNN,這個(gè)CNN已經(jīng)學(xué)會(huì)感知和語(yǔ)義信息編碼,這正是圖像風(fēng)格轉(zhuǎn)換系統(tǒng)的損失函數(shù)中需要做的。所以使用了一個(gè)預(yù)訓(xùn)練好用于圖像分類的網(wǎng)絡(luò)φ,來(lái)定義系統(tǒng)的損失函數(shù)。之后使用同樣是深度卷積網(wǎng)絡(luò)的損失函數(shù)來(lái)訓(xùn)練我們的深度卷積轉(zhuǎn)換網(wǎng)絡(luò)。

        這里的損失網(wǎng)絡(luò)雖然也是卷積神經(jīng)網(wǎng)絡(luò)(CNN),但是參數(shù)不做更新,只用來(lái)做內(nèi)容損失和風(fēng)格損失的計(jì)算,訓(xùn)練更新的是前面的生成網(wǎng)絡(luò)的權(quán)值參數(shù)。所以從整個(gè)網(wǎng)絡(luò)結(jié)構(gòu)上來(lái)看輸入圖像通過(guò)生成網(wǎng)絡(luò)得到轉(zhuǎn)換的圖像,然后計(jì)算對(duì)應(yīng)的損失,整個(gè)網(wǎng)絡(luò)通過(guò)最小化這個(gè)損失去不斷更新前面的生成網(wǎng)絡(luò)權(quán)值。

 

感知損失

     

       對(duì)于求損失的過(guò)程,不用逐像素求差構(gòu)造損失函數(shù),轉(zhuǎn)而使用感知損失函數(shù),從預(yù)訓(xùn)練好的損失網(wǎng)絡(luò)中提取高級(jí)特征。在訓(xùn)練的過(guò)程中,感知損失函數(shù)比逐像素?fù)p失函數(shù)更適合用來(lái)衡量圖像之間的相似程度。

(1)內(nèi)容損失

        上面提到的論文中設(shè)計(jì)了兩個(gè)感知損失函數(shù),用來(lái)衡量?jī)蓮垐D片之間高級(jí)的感知及語(yǔ)義差別。內(nèi)容的損失計(jì)算用VGG計(jì)算來(lái)高級(jí)特征(內(nèi)容)表示,因?yàn)閂GG模型本來(lái)是用于圖像分類的,所以一個(gè)訓(xùn)練好的VGG模型可以有效的提取圖像的高級(jí)特征(內(nèi)容)。計(jì)算的公式如下:

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

        找到一個(gè)圖像 y使較低的層的特征損失最小,往往能產(chǎn)生在視覺(jué)上和y不太能區(qū)分的圖像,如果用高層來(lái)重建,內(nèi)容和全局結(jié)構(gòu)會(huì)被保留,但是顏色紋理和精確的形狀不復(fù)存在。用一個(gè)特征損失來(lái)訓(xùn)練我們的圖像轉(zhuǎn)換網(wǎng)絡(luò)能讓輸出非常接近目標(biāo)圖像y,但并不是讓他們做到完全的匹配

 

       (2)風(fēng)格損失

       內(nèi)容損失懲罰了輸出的圖像(當(dāng)它偏離了目標(biāo)y時(shí)),所以同樣的,我們也希望對(duì)輸出的圖像去懲罰風(fēng)格上的偏離:顏色,紋理,共同的模式,等方面。為了達(dá)成這樣的效果,一些研究人員等人提出了一種風(fēng)格重建的損失函數(shù):讓?duì)誮(x)代表網(wǎng)絡(luò)φ的第j層,輸入是x。特征圖譜的形狀就是Cj x Hj x Wj、定義矩陣Gj(x)為Cj x Cj矩陣(特征矩陣)其中的元素來(lái)自于:

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

       如果把φj(x)理解成一個(gè)Cj維度的特征,每個(gè)特征的尺寸是Hj x Wj,那么上式左邊Gj(x)就是與Cj維的非中心的協(xié)方差成比例。每一個(gè)網(wǎng)格位置都可以當(dāng)做一個(gè)獨(dú)立的樣本。這因此能抓住是哪個(gè)特征能帶動(dòng)其他的信息。梯度矩陣可以很高效的計(jì)算,通過(guò)調(diào)整φj(x)的形狀為一個(gè)矩陣ψ,形狀為Cj x HjWj,然后Gj(x)就是ψψT/CjHjWj。風(fēng)格重建的損失是定義的很好的,甚至當(dāng)輸出和目標(biāo)有不同的尺寸是,因?yàn)橛辛颂荻染仃嚕詢烧邥?huì)被調(diào)整到相同的形狀。

 

具體實(shí)現(xiàn)

       

       GitHub地址mrxlz/ImageStyleTransform,實(shí)現(xiàn)基本上參考了hzy的代碼,代碼從原版遷移到了python3.5,TensorFlow1.0,具體實(shí)現(xiàn)代碼基本沒(méi)變,加了一些注釋,添加了一個(gè)web頁(yè)面,效果如下。

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

 

移動(dòng)開發(fā)培訓(xùn),Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),手機(jī)維修培訓(xùn),手機(jī)軟件培訓(xùn)

csdn博客:欠扁的小籃子

http://www.cnblogs.com/z941030/p/7056814.html