在過去十年左右的時間里,主要源于深度學(xué)習(xí)的進(jìn)展,計算機(jī)視覺取得了巨大的進(jìn)步。不僅是因為我們有了更新和更好的算法,數(shù)碼相機(jī)和互聯(lián)網(wǎng)為我們提供了近乎無限的訓(xùn)練數(shù)據(jù)。更重要的是,原本為計算機(jī)游戲所開發(fā)的顯卡被發(fā)現(xiàn)在訓(xùn)練深度神經(jīng)網(wǎng)絡(luò)方面具有超強(qiáng)的計算能力。
對于想要嘗試深度學(xué)習(xí)和圖像識別的人來說,這些都是好消息。如今開發(fā)一個貓與狗的分類器只需要Keras庫和一個有100行代碼的Python notebook文件。但只這樣做并不能告訴我們計算機(jī)看到了什么。
如果我們想要了解人類是如何看的,我們可以打開頭骨,然后試圖弄清楚信息如何從眼睛的感光細(xì)胞通過視覺皮層流向大腦的其他部分,不過這是相當(dāng)困難的。更簡單的方法是用電極刺激受試者的大腦直到他們能看到藍(lán)色。那么,我們?nèi)绾斡秒姌O刺激神經(jīng)網(wǎng)絡(luò)呢?
現(xiàn)代的神經(jīng)網(wǎng)絡(luò)通常由堆疊在彼此之上的很多神經(jīng)層組成。要識別的圖像被送入最低層,當(dāng)信息通過網(wǎng)絡(luò)傳播時,圖像的表征變得越來越抽象,直到傳播到末端,這時結(jié)果標(biāo)簽出現(xiàn)。神經(jīng)網(wǎng)絡(luò)說,我看到了一只貓!
用電極探測神經(jīng)網(wǎng)絡(luò)可以被歸結(jié)為反向運(yùn)行上述的過程。我們不是給神經(jīng)網(wǎng)絡(luò)顯示圖片并詢問它看到了什么,而是要給神經(jīng)網(wǎng)絡(luò)一些噪音并要求神經(jīng)網(wǎng)絡(luò)改變以便讓特定的神經(jīng)元具有最大激活輸出。具有這樣表征的圖像代表了這個特定的神經(jīng)元能看到的東西,就如同我們刺激那個神經(jīng)元,人類會看到什么。
讓我們用Keras導(dǎo)入一個預(yù)先訓(xùn)練好的圖像識別神經(jīng)網(wǎng)絡(luò):
model = vgg16.VGG16(weights=’imagenet’, include_top=False)
model.summary()
第二條語句會顯示這個神經(jīng)網(wǎng)絡(luò)的架構(gòu)。
我們定義一個優(yōu)化給定神經(jīng)元輸出的損失函數(shù),然后創(chuàng)建一個迭代Keras函數(shù),通過改變輸入圖像來優(yōu)化它。然后我們從充滿噪聲的圖像開始迭代運(yùn)行16次。(本文中提到的所有代碼在GitHub上都可以找到,既有可獨(dú)立運(yùn)行的腳本,也有Python notebook文件。請參閱本文末尾的參考資料。)
loss = K.mean(layer_output[:, :, :, neuron_idx])
grads = K.gradients(loss, input_img)[0]
iterate = K.function([input_img], [loss, grads])
img_data = np.random.uniform(size=(1, 256, 256, 3)) + 128.
for i in range(16):
? ? ? ? loss_value, grads_value = iterate([img_data])
? ? ? ? img_data += grads_value * step
我們可以在一些隨機(jī)挑選的神經(jīng)元上嘗試這個,我們看到一些看起來似乎關(guān)聯(lián)到這些神經(jīng)元的人造模式:

很漂亮!看起來并不像我想象的腦部手術(shù)引起的幻覺,但它是一個開始!這些神經(jīng)元是隨機(jī)地從層中挑選出來的。請記住,當(dāng)我們?yōu)g覽這些堆疊起來的層時,隨著層級的增加,抽象級別應(yīng)該會上升。我們現(xiàn)在可以做的是從不同層的神經(jīng)元抽樣,并按層排序。這樣我們就可以了解每個層發(fā)現(xiàn)的特征了:

這與我們的直覺完美地吻合,即當(dāng)我們遍歷層時抽象程度會增加。最底層會識別顏色和簡單的圖案。層級越高,模式會變得越復(fù)雜。
不幸的是,這個技巧有很多的局限。如果你看代表貓咪的最高層中的神經(jīng)元,盡管你可以優(yōu)化你想要的所有,但并沒有明顯的貓的樣子會出現(xiàn)。
但是,我們可以通過在運(yùn)行優(yōu)化函數(shù)時放大圖像來獲得更多的細(xì)節(jié)。這里的想法是,如果你為神經(jīng)元激活進(jìn)行圖像優(yōu)化,它往往會陷入局部最小值,因為沒有好的方法來影響圖像的整體結(jié)構(gòu)。因此,我們不是從大的完整的圖像開始,而是使用我們優(yōu)化的小圖像(64×64)開始。然后,我們將圖像放大一點(diǎn)并再次進(jìn)行優(yōu)化。這樣做20次能給我們一個很好的結(jié)果,它具有一定的可塑性。

這個放大的效果自身在某種程度上是挺好的,就像某種有機(jī)展開一樣。
圖片達(dá)到一定的尺寸后,我們就需要開始做中心裁剪,讓圖像始終保持相同的大小。這個視頻有一個很好的分形般的迷人效果。但為什么要停在這里?我們可以在縮放時循環(huán)觀察一組隨機(jī)神經(jīng)元,這樣能制作出相當(dāng)刺激的電影:
在這篇博文中,我們已經(jīng)看到了一些可視化神經(jīng)網(wǎng)絡(luò)能看到什么的技巧??梢暬慕Y(jié)果很有趣,并且自身在某種程度上也是吸引人的。但它們也幫助我們了解了計算機(jī)視覺的工作原理。當(dāng)信息流過神經(jīng)網(wǎng)絡(luò)時,抽象程度會隨著層級的升高而增加,我們可以在某種程度上展示這些抽象。
Notebook版本的代碼可以在這個GitHub里找到。腳本化的版本可以在GitHub里找到。
Douwe Osinga
Douwe Osinga是O'Reilly的圖書《深度學(xué)習(xí)Cookbook》的作者。他曾是谷歌的一位經(jīng)驗豐富的軟件工程師,一位全球旅行家,并是三家創(chuàng)業(yè)公司的創(chuàng)始人。他的頗受歡迎的軟件項目網(wǎng)站(https://douweosinga.com/projects)涵蓋了許多有趣的領(lǐng)域,包括機(jī)器學(xué)習(xí)。

