劉俊利
(西南科技大學(xué)計算機科學(xué)與技術(shù)學(xué)院,綿陽621000)
在過去的幾年中,隨著AI(人工智能)的快速崛起,許多科技公司、研究機構(gòu)順勢展開了人工智能進軍藝術(shù)領(lǐng)域的探索。截至目前,一直被認(rèn)為是只有人類才可以步入的藝術(shù)領(lǐng)域人工智能已經(jīng)闖入,雖然它目前只是參與,還未達到真正意義上藝術(shù)創(chuàng)作的水平,但前景值得期待。Deep Dream 是Google 在2015 年推出的一款人工智能系統(tǒng),它可以通過識別圖像,重新作畫。Deep Dream 模型打破了給定相同輸入只產(chǎn)生一種輸出的傳統(tǒng)思路,利用不斷修改輸入的方法最終獲取最佳輸出。其核心思想是利用反向傳播更新輸入圖像中的像素點,通過不斷迭代放大某一指定特征,最終達到輸入圖像向指定特征逼近的效果。本文將選取Inception模型的mixed4d_3x3_bottleneck_pre_relu 卷積層的第139 個通道進行最大化,結(jié)合TensorFlow[1]的算力實現(xiàn)Deep Dream 生成模型。
深度學(xué)習(xí)以及神經(jīng)網(wǎng)絡(luò)的快速發(fā)展讓人們越來越意識到想要擁有性能和速度的提升僅僅是靠更給力的硬件、更大的數(shù)據(jù)集、更大的模型是不夠的,新的結(jié)構(gòu)、新的算法以及對模型的改進才是實現(xiàn)突破的關(guān)鍵。自2012 年AlexNet[2]做出歷史性突破以來,一直到GoogLeNet[3]的提出,傳統(tǒng)的CNN[4]模型設(shè)計,其提高網(wǎng)絡(luò)性能的方法大多是直接增加網(wǎng)絡(luò)的深度和寬度。但這種簡單粗暴的方法會帶來一些問題:
(1)容易發(fā)生過擬合,這種增加層數(shù)及增寬層的通道數(shù)的設(shè)計思路不可避免地需要在高密度計算的單元上實現(xiàn),它必然會導(dǎo)致訓(xùn)練參數(shù)增加,巨大的參數(shù)容易發(fā)生過擬合;
(2)網(wǎng)絡(luò)越大計算復(fù)雜度越大,單純地增加密集計算單元的層數(shù)或每層寬度都會招至后續(xù)擴展計算量呈指數(shù)增加,應(yīng)用難度大;
(3)容易造成梯度彌散問題,反向傳播梯度的時候,梯度隨著傳播深度(網(wǎng)絡(luò)越深傳播深度越大)的增加越來越小,最終沒有變化,導(dǎo)致優(yōu)化困難,不能有效學(xué)習(xí)。
為了規(guī)避這些缺陷,提升神經(jīng)網(wǎng)絡(luò)的性能,GoogLeNet 團隊經(jīng)研究后提出了一種Inception 網(wǎng)絡(luò)結(jié)構(gòu)。這種結(jié)構(gòu)通過早期將卷積轉(zhuǎn)化為稀疏連接,后期再將稀疏矩陣聚類為較為密集的子矩陣的方法實現(xiàn)了稀疏連接和密集矩陣的互補,進而達到既降低了計算開銷,又提高了計算性能還擴大了表達特征范圍的效果。
Inception 結(jié)構(gòu)的主要思路是怎樣用密集成分來近似最優(yōu)的局部稀疏結(jié)構(gòu)。Inception 結(jié)構(gòu)最原始的版本如圖1 所示。

圖1 Inception module,Naive version
圖1 中,Inception 的基本組成結(jié)構(gòu)包括四個部分:1×1 卷積、3×3 卷積、5×5 卷積、3×3 最大池化,這四個部分堆疊在一起,最后再將這四個成分運算結(jié)果進行通道上組合。一方面增加了網(wǎng)絡(luò)的寬度,另一方面增加了網(wǎng)絡(luò)對尺度的適應(yīng)性。提取圖像不同尺度的信息,然后進行融合,最終得到圖像更好的表征正是Inception Module 的核心思想。
不過,如圖1 所示,顯然其在計算開銷上隱藏著重大問題,即所有的卷積核都在上一層的所有輸出上來做。這勢必會導(dǎo)致特征圖厚度很大,造成計算量指數(shù)級增加。為了避免這一現(xiàn)象,借鑒Network in Network[5]的思想,在3×3 前,5×5 前,max pooling 后分別加上了1×1 的卷積核進行降維。最終Inception 的網(wǎng)絡(luò)結(jié)構(gòu)具體如圖2 所示。

圖2 Inception module with dimension reductions
Deep Dream 是對卷積神經(jīng)網(wǎng)絡(luò)(CNN)進行可視化的一種方法[6],在2015 年由Google 公司發(fā)布。其本質(zhì)是使用梯度上升的方法可視化網(wǎng)絡(luò)每一層的特征,特別之處在于反向更新的是初始圖像的像素值而不是網(wǎng)絡(luò)權(quán)重。在一般在實踐中,我們常用卷積神經(jīng)網(wǎng)絡(luò)(CNN)來進行圖像識別,根據(jù)大量標(biāo)有l(wèi)abel 的圖像來訓(xùn)練卷積神經(jīng)網(wǎng)絡(luò)的梯度,通過訓(xùn)練好的卷積神經(jīng)網(wǎng)絡(luò),即可得到圖片的分類結(jié)果。而Deep Dream 模型恰恰相反,它不是輸入一些圖片去測試神經(jīng)元提取的特征,而是我們選出一些神經(jīng)元,看它能夠模擬出最可能的圖片是什么,將這些信息反向傳回網(wǎng)絡(luò),每個神經(jīng)元將會顯示出它想增強的模式或者特征,如果我們不停地迭代輸出,不斷地激活特征,那么輸出結(jié)果會和目標(biāo)圖像會越來越像。假設(shè)輸入網(wǎng)絡(luò)的圖像為x,一共有n種分類,則設(shè)有n 維向量,其中pi表示圖像x 為第i 類的概率。若該圖像為第a 類的概率為pa,則pa的值越高,為圖像x 為第a 類的概率就越高。那么我們反過來想,將pa作為我們的優(yōu)化目標(biāo),不斷調(diào)整圖像的值,使得pa的值盡可能的大,同時,圖像也越來越具有a 類的特征,進而就達到了放大特征生成Deep Dream 圖片的效果。簡單的Deep Dream 模型實現(xiàn)過程如圖3 所示。

圖3 Deep Dream模型實現(xiàn)過程
原始的Deep Dream 模型只需要優(yōu)化ImageNet 模型卷積層某個通道的激活值就可以。因此,應(yīng)該先導(dǎo)入一個在ImageNet 上預(yù)訓(xùn)練的卷積神經(jīng)網(wǎng)絡(luò),此處采用Inception 模型。
model_fn='tensorflow_inception_graph.pb'#導(dǎo)入inception網(wǎng)絡(luò)結(jié)構(gòu)及其對應(yīng)的數(shù)據(jù)
with tf.gfile.FastGFile(model_fn,'rb')as f:
graph_def=tf.GraphDef()
graph_def.ParseFromString(f.read())
#定義t_input 為我們輸入的圖像
t_input=tf.placeholder(np.float32,name='input')
imagenet_mean=117.0
#輸入圖像需要經(jīng)過處理才能送入網(wǎng)絡(luò)中
#expand_dims 是添加一維
#t_input-imagenet_mean 是減去一個均值
t_preprocessed=tf.expand_dims(t_input-imagenet_mean,0)
tf.import_graph_def(graph_def,{'input':t_preprocessed})
由于在后面的程序中需要輸入圖像,所以此處需要設(shè)置占位符t_input 用于接收圖像的傳遞;由于格式(height,width,channel)只能表示一張圖像,而實際上訓(xùn)練神經(jīng)網(wǎng)絡(luò)時往往需要同時送入多張圖像所以需要添加一維,將輸入圖像格式改為(batch,height,width,channel),只輸入1 張圖像時batch 為1;由于在訓(xùn)練Inception 模型時已經(jīng)完成了為圖像減去一個像素均值的預(yù)處理,因此為了保持輸入一致,t_input 需要完成同樣的預(yù)處理此處減去一個均值117。
(1)生成初始圖像
生成一張尺寸為(224,224,3)的隨機噪聲圖片表示初始化圖像優(yōu)化起點。
img_noise = np.random.uniform(size=(224,224,3))+100.0
(2)選擇優(yōu)化目標(biāo)
定義卷積層、通道數(shù),并取出對應(yīng)的Tensor。
name='mixed4d_3x3_bottleneck_pre_relu'#定義卷積層
channel=139#選擇任意的通道,這里是139
# 取出mixed4d_3x3_bottleneck_pre_relu 卷積層的輸出層
layer_output = graph.get_tensor_by_name("import/% s:0"%name)
(3)渲染圖片
t_obj 為卷積層某個通道的值;img0 對應(yīng)初始圖像;iter_n 為迭代步數(shù);step 為學(xué)習(xí)率。render_naive 函數(shù)利用梯度下降下降法不斷調(diào)整輸入圖像來使得優(yōu)化目標(biāo)t_score 盡可能的大。最后經(jīng)過iter_n 步迭代生成原始的Deep Dream 圖片。
def render_naive(t_obj,img0,iter_n=60,step=1.0):
#t_score 是優(yōu)化目標(biāo)。它是t_obj 的平均值
t_score=tf.reduce_mean(t_obj)
#計算t_score 對t_input(初始圖像)的梯度
t_grad=tf.gradients(t_score,t_input)[0]
#創(chuàng)建新圖
img=img0.copy()
for i in range(iter_n):
#在sess 中計算梯度,以及當(dāng)前的score
g,score=sess.run([t_grad,t_score],{t_input:img})
#對img 應(yīng)用梯度。step 可以看做“學(xué)習(xí)率”
g/=g.std()+1e-8
img+=g*step
print('score(mean)=%f'%(score))
#保存圖片
scipy.misc.toimage(img).save('naive.jpg')
生成更大尺寸的Deep Dream 圖像與生成原始的Deep Dream 圖像相比,前者的實現(xiàn)方法需要在后者的實現(xiàn)方法的基礎(chǔ)上做出一些必要的改進。主要需要解決圖片越大,內(nèi)存占用越大導(dǎo)致圖片渲染失敗的問題。此處的解決方案為將圖片分為幾部分,每次只對一部分進行優(yōu)化,每次優(yōu)化只消耗固定大小的內(nèi)存。函數(shù)calc_grad_tiled 利用圖片分塊化的方法可以計算任意大小的梯度。其中img 對應(yīng)初始圖像;t_grad 為優(yōu)化目標(biāo)對初始圖像的梯度;tile_size 表示將初始圖像分成多張tile_size*tile_size 大小的圖像分別進行優(yōu)化。
def calc_grad_tiled(img,t_grad,tile_size=512):
#每次只對tile_size×tile_size 大小的圖像計算梯度,避免內(nèi)存問題
sz=tile_size
h,w=img.shape[:2]
# img_shift:先在行上做整體移動,再在列上做整體移動
#防止在tile 的邊緣產(chǎn)生邊緣效應(yīng)
sx,sy=np.random.randint(sz,size=2)
img_shift=np.roll(np.roll(img,sx,1),sy,0)
grad=np.zeros_like(img)
#y,x 是開始位置的像素
for y in range(0,max(h-sz//2,sz),sz):
for x in range(0,max(w-sz//2,sz),sz):
# 每次對sub 計算梯度。sub 的大小是tile_size×
tile_size
sub=img_shift[y:y+sz,x:x+sz]
g=sess.run(t_grad,{t_input:sub})
grad[y:y+sz,x:x+sz]=g
#使用np.roll 移動回去
return np.roll(np.roll(grad,-sx,1),-sy,0)
利用深度學(xué)習(xí)框架TensorFlow 導(dǎo)入Inception 模型進而實現(xiàn)Deep Dream 生成模型的運行結(jié)果:原始的Deep Dream 圖像和更大尺寸的Deep Dream 圖像,分別如圖4 和圖5 所示。運行效果非常直觀,Deep Dream模型可以實現(xiàn)圖像的自動生成,且當(dāng)面對較大的圖片時,利用將圖片分成小塊再分別優(yōu)化的方法也可以實現(xiàn)大尺寸圖像的自動生成。

圖4 原始的Deep Dream圖像

圖5 更大尺寸的Deep Dream圖像
本文首先介紹了Inception v1 模型,之后給出了Deep Dream 模型的基本原理,然后利用TensorFlow 導(dǎo)入訓(xùn)練好的Inception 模型并合理地選取了卷積層和通道,最后實現(xiàn)了Deep Dream 生成模型,完成了原始的Deep Dream 圖像和更大尺寸的Deep Dream 圖像的生成,兩張圖片均取得了較好的效果,證明了mixed4d_3x3_bottleneck_pre_relu 層的第139 個通道學(xué)習(xí)到的特征為花的紋理圖特征。Deep Dream 模型是人工智能向繪畫領(lǐng)域探索的標(biāo)志性成果,雖然只是初期,但是它向我們展示了人工智能繪畫的可能,未來,人工智能必將給藝術(shù)領(lǐng)域帶來新的靈感和驚喜。