本文作者Ryan Daul是Node.js的創(chuàng)始人,應(yīng)該算是軟件工程領(lǐng)域當(dāng)之無愧的大犇了。他和我們分享了自己在谷歌大腦見習(xí)項目一年中的工作,成果,失敗和思考。
去年,在通過對TensorFlow的研究得出一點點心得之后,我申請并入選了谷歌大腦舉辦的的首屆見習(xí)項目(Google Brain Residency Program)。該項目共邀請了24名在機(jī)器學(xué)習(xí)領(lǐng)域有著不同背景的人士,受邀者將在為期一年的時間里和Google的科學(xué)家及工程師們在位于山景城的Google深度學(xué)習(xí)研究實驗室中共同探索最前沿的深度學(xué)習(xí)科技。
這個為期一年的項目已經(jīng)結(jié)束了,在此我將就這一年的經(jīng)歷作一個總結(jié)與分享。
最初擬定的目標(biāo)是“修正”老電影或電視劇的畫面。想象一下,上世紀(jì)90年代電視劇的粗糙畫面或60年代的黑白電影,在色彩華麗的4K屏幕上播放的情景。
這應(yīng)該是完全可行的:把4K視頻轉(zhuǎn)換成滿是顆粒感的、低分辨率的、甚至是只有黑白兩色的視頻并不難,之后再通過某個訓(xùn)練出的監(jiān)督模型來反轉(zhuǎn)這個過程就可以“修正”了。而且,有數(shù)不盡的數(shù)據(jù)訓(xùn)練集,很棒不是嗎!
先別急著興奮——因為能做這事兒的技術(shù)還沒有出現(xiàn)......不過我們確實離目標(biāo)越來越近了。
為了更好地實現(xiàn)這個目標(biāo),以科技之名,我再一次搬離了布魯克林來到了灣區(qū)。幾天后我的日常生活就變成了與Google的機(jī)器學(xué)習(xí)專家進(jìn)行討論以及在龐大的軟件架構(gòu)中四處探索。
如果你想跳過技術(shù)細(xì)節(jié),可以直接跳到總結(jié)部分。
本文作者Ryan Daul開發(fā)了Node.js,一個流行的前端框架
超分辨率的像素遞歸
眾所周知,在美劇《CSI犯罪現(xiàn)場》中使用的縮放技術(shù)在現(xiàn)實中并不存在,你無法將照片放大到任意倍數(shù)。但可行的是,在放大照片的同時將像素可能構(gòu)成的合理圖形進(jìn)行推測并呈現(xiàn),這也是實現(xiàn)我目標(biāo)的第一步–逆向提高圖片的分辨率。
在文獻(xiàn)中,這一問題被稱之為“超分辨率”問題,是一個科學(xué)家們嘗試了很久都沒有解決的難題。
根據(jù)以往的經(jīng)驗,我們認(rèn)識到只是訓(xùn)練一個卷積模型最小化低分辨率圖像與高分辨率圖像的平均像素差值無法徹底地解決這一問題。因為這一類模型訓(xùn)練的目的是平均化輸入圖像和目標(biāo)圖像的整體差值,這就導(dǎo)致了生成的圖片非常模糊。
對我們而言,理想模型應(yīng)該針對不同區(qū)域做出一個最佳的選擇,盡可能的對細(xì)節(jié)做出全方位的優(yōu)化。比如說,輸入一張模糊的樹的圖片,我們希望我們的模型能分別對樹的軀干、樹枝、樹葉進(jìn)行優(yōu)化,哪怕原圖中沒有相應(yīng)的細(xì)節(jié)也沒有關(guān)系。
起初,我們打算用條件型生成對抗網(wǎng)絡(luò)(conditional GAN)來解決這個問題,但經(jīng)過幾次失敗的嘗試后,我們換成了另一種有望解決該問題的新型生產(chǎn)式模型——PixelCNN。(換成PixelCNN不久,SRGAN就發(fā)布了,它用GAN來解決超分辨率問題并能輸出相當(dāng)不錯的結(jié)果。)
PixelCNN和傳統(tǒng)的卷積神經(jīng)網(wǎng)絡(luò)十分不同,它將圖像生成問題轉(zhuǎn)化成了一個像素序列選擇問題。核心思想借鑒與于LSTM(長短時記憶網(wǎng)絡(luò))這樣的門控遞歸網(wǎng)絡(luò),盡管他們通常被應(yīng)用于單詞或字符序列的生成上,但無可否認(rèn)效果是非常好的。PixelCNN巧妙地構(gòu)建出一個卷積神經(jīng)網(wǎng)絡(luò)(CNN),它能基于先前的像素的概率分布來生成下一個像素,也就是說同時具備了序列模型和卷積神經(jīng)網(wǎng)絡(luò)的特點。
van den Oord 等人所繪
讓我沒想到的是,通過PixelCNN生成的圖像看起來非常自然。與對抗網(wǎng)絡(luò)試圖在生成與鑒別中找到一個精確的平衡不同,PixelCNN的目標(biāo)只有一個,所以面對超參數(shù)的變化,它有更好的穩(wěn)健性,也更容易被優(yōu)化。
對于用PixelCNN解決超分辨率問題的首次嘗試,我試圖用ImageNet提供的圖片進(jìn)行訓(xùn)練,但事實證明這個目標(biāo)還是有些太高了。(相較于很多生成式模型使用的CIFAR-10、CelebA或LSUN數(shù)據(jù)集,ImageNet更加的復(fù)雜)我很快地就發(fā)現(xiàn)——像素來序列生成圖像的過程極其緩慢。
當(dāng)輸出圖像的尺寸大于64x64時,生成一張圖片的耗時超過數(shù)個小時!但當(dāng)我降低了輸出圖像的尺寸并使用臉部或臥室類的小型數(shù)據(jù)集后,就開始慢慢得到了一些振奮人心的結(jié)果了。
用名人臉部圖像數(shù)據(jù)集訓(xùn)練出來的超分辨率像素遞歸模型所生成的高分辨率圖像。
左側(cè)為測試數(shù)據(jù)集所用的8x8低分辨率輸入圖像。中間為PixelCNN模型所輸出的32x32高分辨率圖像,右側(cè)是原始的32x32分辨率圖像。我們的模型優(yōu)先整合臉部特征,而后去合成較為逼真的頭發(fā)與皮膚方面的細(xì)節(jié)。
就計算資源而言,在Google不會因GPU或CPU的數(shù)量而受限,所以如何擴(kuò)大訓(xùn)練的規(guī)模便成為該項目的另一個目標(biāo)——因為即便采用這些小型的數(shù)據(jù)集,在單個GPU上完成訓(xùn)練也要花上數(shù)周的時間。
異步隨機(jī)梯度下降(Asynchronous SGD)是最理想的分布式訓(xùn)練方法。使用這種方法,你可以用N臺機(jī)器,每一臺都獨立訓(xùn)練同一模型,并在每個時間步長共享一次權(quán)重參數(shù)。
權(quán)重參數(shù)被托管在一臺單獨的“參數(shù)服務(wù)器”上,該服務(wù)器在每個時間步長內(nèi)都進(jìn)行“遠(yuǎn)程過程調(diào)用(RPC)”,以獲得最新數(shù)值并發(fā)送梯度更新。
如果整個數(shù)據(jù)流非常順暢,就可以通過增加線程的方式線性增加模型每秒內(nèi)的訓(xùn)練次數(shù)。但因為每個線程都是獨立訓(xùn)練的,隨著線程數(shù)的增加會越來越容易導(dǎo)致在當(dāng)前線程還沒有完成一次訓(xùn)練或更新時,它所使用的權(quán)重就已經(jīng)過期了。
如果是為了解決分類問題,這對神經(jīng)網(wǎng)絡(luò)的影響不大,把訓(xùn)練的規(guī)模擴(kuò)增到幾十臺機(jī)器不難。但PixelCNN卻對過時的梯度極其敏感,這就導(dǎo)致了通過增加硬件的數(shù)量來使用異步隨機(jī)梯度下降算法所帶來收益微乎其微。
另一個方法,是用同步隨機(jī)梯度下降算法(Synchronous SGD)。使用這一方法,所有線程在每個時間步長內(nèi)進(jìn)行同步,每次下降的梯度會被平均,這保證不會出現(xiàn)權(quán)重過期的問題。
從數(shù)學(xué)的角度看,它與隨機(jī)梯度下降算法是一樣的,既機(jī)器越多,批處理能力越強(qiáng)。但同步隨機(jī)梯度下降算法(Sync SGD)的優(yōu)勢是,它允許各線程使用更小、更快的批尺寸,從而來增加每秒訓(xùn)練的次數(shù)。
但同步隨機(jī)梯度下降算法也有自己的問題:首先,它需要大量的機(jī)器經(jīng)常進(jìn)行同步,這就無可避免的會導(dǎo)致停機(jī)時間的增加;其次,除非將每臺機(jī)器的批尺寸設(shè)為1,否則它無法通過增加機(jī)器的數(shù)量來增加每秒訓(xùn)練的次數(shù)。最終,我發(fā)現(xiàn)對我而言最簡單有效的設(shè)置是用一臺8GPU的機(jī)器使用同步隨機(jī)梯度下降算法進(jìn)行訓(xùn)練,即便如此每次訓(xùn)練仍需花上數(shù)天的時間。
擁有大量計算能力的另一好處是可以對超參數(shù)的優(yōu)化進(jìn)行大規(guī)模的暴力搜索。不確定該使用什么樣的批尺寸進(jìn)行訓(xùn)練?挨個試一遍!在找到論文中所用的配置前,我曾嘗試過數(shù)百種配置。
另一個難題是如何量化評估結(jié)果。如何才能證明我們的圖像比基準(zhǔn)模型更好?衡量超分辨率效果的傳統(tǒng)方法,是對比輸出圖像與原始圖像在對應(yīng)像素點之間的距離(峰值信噪比,PSNR)。
雖說我們的模型輸出的臉部圖像在質(zhì)量上明顯更好,但在像素對比上,平均看來還不如基準(zhǔn)模型所輸出的模糊圖像。我們還嘗試用PixelCNN本身的相似度測量來證明我們的樣本比基準(zhǔn)版本有著更佳的像素分布,但同樣失敗了。最后,我們把這項任務(wù)交給了大眾——詢問參與調(diào)查的人哪些圖像看上去更真實,這才證明了我們模型的價值。
超分辨率的像素遞歸論文:
https://arxiv.org/abs/1702.00783
PixColor:著色問題的另一次嘗試
PixColor輸出的雙色模式
Slim的創(chuàng)造者Sergio Guadarrama一直在研究圖像著色問題,他曾和我描述過這樣一個試驗:獲取一張224×224×3的圖像,將其置于YPbPr色彩空間中(該空間圖像的灰度、顏色相互分離),首先將顏色通道降至28×28×2的超低分辨率,再用雙線性插值法再把顏色通道放大,所得圖像與高色彩分辨率的原始圖像相比幾乎沒有差別。
你需要的只是幾種顏色。頂行是原始彩色圖像;中間是降低并采樣后的色度圖像,尺寸縮小至28像素;底行是雙線性提高中間行的采樣率并結(jié)合原始灰度圖像的結(jié)果。
這一現(xiàn)象表明,著色問題可以簡化成低分辨率顏色預(yù)測問題。我原本已準(zhǔn)備好徹底放棄PixelCNN了,因為顯然它無法輸出大尺寸的圖像,但轉(zhuǎn)念一想其用來生成28×28×2的圖像還是很可行的,并最終通過使用4位顏色數(shù)值而非8位,進(jìn)一步的簡化了著色問題。
Sergio構(gòu)建了一個“美化”神經(jīng)網(wǎng)絡(luò),它能美化低分辨率顏色的圖像,并將溢出邊界的顏色推回至正確位置–構(gòu)造僅僅是使用L2損失函數(shù)將圖片與圖片進(jìn)行比較。我們還用一個預(yù)訓(xùn)練好的ResNet作為輔助神經(jīng)網(wǎng)絡(luò),以避免需要額外添加一個新的損失函數(shù)的需求,這中做法我們在超分辨率項目中就使用過。
通過以上所有技巧,不論是通過大眾評估還是顏色直方圖交叉測量,我們能夠在ImageNet的訓(xùn)練集上實現(xiàn)最佳的結(jié)果。事實證明,一個訓(xùn)練好的PixelCNN模型產(chǎn)生的圖像具有良好的數(shù)據(jù)分布性,而且沒有發(fā)生過任何模型崩潰的問題。
Lab顏色空間中的顏色通道的邊緣統(tǒng)計數(shù)據(jù)。左:每種測試方法的直方圖以藍(lán)色顯示,ImageNet的測試數(shù)據(jù)集直方圖以黑色顯示。右圖:左圖顏色通道的相交比例
由于模型為每個灰度輸入的可能著色聲明了一個概率分布,我們可以對該分布進(jìn)行多次取樣,以獲取同一輸入的不同著色。下圖用結(jié)構(gòu)相似度(SSIM)很好地展示了分布的多樣性:
為證明我們的模型可生成不同的樣本,我們用多尺度SSIM對比了同一輸入的兩種輸出。上圖顯示了ImageNet測試數(shù)據(jù)集的SSIM距離直方圖。圖中在多個SSIM間距上分別顯示了每對圖像。SSIM值為1表示兩張圖像完全相同。
該模型還遠(yuǎn)稱不上“完美”,因為ImageNet盡管龐大,但不能代表所有的圖像。我們的模型在處理非ImageNet圖像時并不理想。真實的黑白照片(不同于彩色照片轉(zhuǎn)化出的黑白照片)會得出許多不同的分布數(shù)據(jù),也會出現(xiàn)很多彩色照片中所沒有的物體。比如,Model T汽車的彩色照片不多,ImageNet圖像集中可能一張都沒有。或許采用更大的數(shù)據(jù)集和更好的數(shù)據(jù)擴(kuò)增方法可以改善這些問題。
如果想了解輸出圖像的質(zhì)量,可以來看看這些圖:
當(dāng)我們模型處于訓(xùn)練中期時處理的一小組非常難處理的圖像:
http://tinyclouds.org/residency/step1326412_t100/index.html
用我們的模型處理ImageNet上的隨機(jī)數(shù)據(jù)集:
http://tinyclouds.org/residency/rld_28px3_t100_500_center_crop_224/
作為對比,下面是用其他算法來處理同一ImageNet測試數(shù)據(jù)集的結(jié)果:
http://hi.cs.waseda.ac.jp/~iizuka/projects/colorization/en/
http://richzhang.github.io/colorization/
http://people.cs.uchicago.edu/~larsson/colorization/
所有完整的細(xì)節(jié)都可以在我們的論文中找到:
https://arxiv.org/abs/1705.07208
失敗與未報告的實驗結(jié)果
這一年期間,我曾間歇性地投入過許多業(yè)余的小項目,盡管它們都沒成功,但其中有幾個值得一提的項目:
大數(shù)的素因數(shù)分解
素因數(shù)分解一向都是個難題,盡管近期在素數(shù)分布領(lǐng)域又有了突破,也依舊很有挑戰(zhàn)性。我們的想法是,如果為神經(jīng)網(wǎng)絡(luò)提供足夠多的訓(xùn)練樣本,看看它能否找出一些新的東西?
Mohammad和我嘗試過兩種方法:他修改了Google機(jī)器翻譯的seq2seq模型,該模型把一個半素大數(shù)的整數(shù)序列作為輸入,并以預(yù)測其素因數(shù)中的一個做為輸出;我則使用一個較為簡單的模型,它將定長整數(shù)作為輸入,并用幾個全連接層來預(yù)測輸入的分類:素數(shù)或合數(shù)。
但這兩種方法最后都只學(xué)到了最為明顯的規(guī)律(如果尾數(shù)為0,那它就不是素數(shù)!),最后我們只能拋棄這個想法。
對抗做夢
受Michael Gygli的項目啟發(fā),我想看看能否用一個鑒別器充當(dāng)它自己的生成器。為此,我構(gòu)建出一個簡單的二元分類卷積神經(jīng)網(wǎng)絡(luò)來判斷輸入的真假。
Michael Gygli的項目:
https://arxiv.org/abs/1703.04363
既給出一張噪點圖片并讓它使用梯度自我更新來生成圖像(也稱為deep dreaming),訓(xùn)練的目標(biāo)是令該網(wǎng)絡(luò)把“真實”類別的輸出達(dá)到最大化。該模型通過交替生成“假”實例來進(jìn)行訓(xùn)練,跟典型的GAN中的鑒別器一樣,通過升級權(quán)重來區(qū)分真假實例。
起初我的想法是,因為這個模型不需要像GAN那么復(fù)雜的架構(gòu)設(shè)計,所以應(yīng)該會極大地降低訓(xùn)練的難度。而事實上,這個模型在MNIST數(shù)據(jù)集上的確輸出了不錯的結(jié)果,如下欄所示:每一縱列都是由噪音圖片一步步推進(jìn)成為紅色的MNIST數(shù)值。
但我沒法在CIFAR-10 數(shù)據(jù)集上達(dá)到同樣的效果,并且它的實用性也極為有限。很遺憾,因為我覺得“對抗做夢(Adversarial Dreaming )”將會是一個很酷的論文標(biāo)題。
使用PixelCNN來訓(xùn)練生成器
鑒于PixelCNN訓(xùn)練一次需要很長的時間,我便想試試能不能用一個訓(xùn)練好的PixelCNN模型訓(xùn)練出前饋式、圖像對圖像卷積神經(jīng)網(wǎng)絡(luò)生成器(8x8至32x32尺寸的LSUN臥室圖片集)。我所設(shè)置的訓(xùn)練方法是:在前饋式網(wǎng)絡(luò)的輸出上進(jìn)行自動回歸,在PixelCNN下更新權(quán)重以便將兩張圖片的相似率最大化。但這個設(shè)計失敗了,它生成了非常奇怪的圖像:
探索“異步隨機(jī)梯度下降”的改進(jìn)方法
如前所述,很多模型都不適用于異步隨機(jī)梯度下降算法。最近,一篇名為DCASGD的論文提出了一種解決過時梯度問題的可能方法——在每一個線程更新自己的權(quán)重時使用差分向量。如果可以實現(xiàn),這種方法可以大大減少每次需要的訓(xùn)練時間。不幸的是,我沒能在TensorFlow上復(fù)原他們的結(jié)果,也就無法嘗試我基于此方法的幾個設(shè)想,可能還是哪里有Bug。
DCASGD的論文:
https://arxiv.org/abs/1609.08326
思考,結(jié)論
作為軟件工程師,我在機(jī)器學(xué)習(xí)方面并沒有什么經(jīng)驗。但基于過去一年對深度學(xué)習(xí)的研究,我想說一下對該領(lǐng)域的總體看法,以及與范圍更廣的軟件領(lǐng)域之間的關(guān)系。
我堅信,機(jī)器學(xué)習(xí)將改變所有行業(yè),并最終改善每個人的生活,許多行業(yè)都會因機(jī)器學(xué)習(xí)的發(fā)展而受益。我相信我在這個項目中嘗試的超分辨率問題在不久的將來就會被解決,所有人都可以看到查理·卓別林這類老電影的4K版。
不過,我確實發(fā)現(xiàn),這一模型的構(gòu)建、訓(xùn)練和調(diào)試都相當(dāng)困難。當(dāng)然,大部分的困難是由于我缺乏經(jīng)驗,這也表明有效訓(xùn)練這些模型是需要相當(dāng)豐富的經(jīng)驗的。我的工作集中在機(jī)器學(xué)習(xí)最為容易的分支上:監(jiān)督式學(xué)習(xí)。但即便有著完美的標(biāo)記數(shù)據(jù),開發(fā)模型可能仍然十分困難。
一般情況就是預(yù)測的維度越大,構(gòu)建模型所花的時間就越長(例如:花大把的時間進(jìn)行編程、調(diào)試和訓(xùn)練)。基于我的經(jīng)驗,建議所有人在開始時都盡可能的簡化和限制你的預(yù)測范圍。
舉一個我們在著色實驗中的例子:我們在開始時試圖讓模型預(yù)測整個RGB圖像,而非只去預(yù)測顏色通道。最開始的想法是,因為我們使用的是跳躍連接(skip connection),所以神經(jīng)網(wǎng)絡(luò)應(yīng)該容易就能處理好灰度圖并輸出可觀的結(jié)果。后來,我們通過只預(yù)測顏色通道這一做法極大的提高了模型的性能。
如果我用“工作”這一詞的直觀意義來描述軟件的話,那么圖像分類任務(wù)似乎“工作”的很穩(wěn)健;生成式模型幾乎很少能“工作”,人們也不太了解這種模型,GAN能輸出高質(zhì)量圖像,但同時卻極難構(gòu)建起來。我的經(jīng)驗是,對GAN的架構(gòu)作出任何小改動都有可能使它完全無法工作。我聽說強(qiáng)化學(xué)習(xí)與其相比更加困難,但因經(jīng)驗不足,在此就不作評價了。
另一方面,隨機(jī)梯度下降算法的性能十分強(qiáng)大,即使是嚴(yán)重的數(shù)學(xué)錯誤,可能也只是會使結(jié)果有一些失真,而不至于產(chǎn)生嚴(yán)重的偏差。
因為訓(xùn)練模型經(jīng)常需要花費很多天,這是一個非常緩慢的修改—運行循環(huán)。
機(jī)器學(xué)習(xí)領(lǐng)域的測試文化尚未完全興起。訓(xùn)練模型時我們需要更好的評斷方法,例如網(wǎng)絡(luò)的多個組成部分需要維持特定的均值和變量,不能過度擺動超出界定的范圍。機(jī)器學(xué)習(xí)的bug使heisenbugs一類的漏洞很輕松地通過了我寫的測試。
并行化(Parallelization)能帶來的好處很有限。增加計算機(jī)數(shù)量使大規(guī)模的超參數(shù)搜索會變得更加容易,但理想情況下,我們會設(shè)計不用特別仔細(xì)調(diào)試也能很好運轉(zhuǎn)的模型。(實際上,我懷疑超參數(shù)搜索能力有限的研究人員將不得不設(shè)計出更好的模型,因此他們設(shè)計出的模型更加穩(wěn)定)。
不好的是,對于很多模型而言,異步隨機(jī)梯度下降算法并沒有什么用處——更加精確的梯度通常用處不大。這就是為什么 DCASGD 的研究方向很重要的原因。
從軟件維護(hù)的角度看,關(guān)于如何組織機(jī)器學(xué)習(xí)項目大家鮮有共識——就像是Rails出現(xiàn)之前的網(wǎng)站:一群隨機(jī)PHP腳本,商業(yè)邏輯和標(biāo)記符號亂寫一氣。在TensorFlow項目中,數(shù)據(jù)通道、數(shù)學(xué)和超參數(shù)等配置無組織地混為一團(tuán)。
我認(rèn)為精美的機(jī)器學(xué)習(xí)類項目的結(jié)構(gòu)/組織還未被發(fā)現(xiàn)(或者說是還未被重新發(fā)現(xiàn),就像DHH重新發(fā)現(xiàn)并普及 MVC那樣)。我的項目結(jié)構(gòu)一直在進(jìn)步,但我現(xiàn)在還無法將它稱之為“精美”。
機(jī)器學(xué)習(xí)的框架會繼續(xù)快速迭代。我最初使用的是Caffe,后來又不得不稱贊TensorFlow帶來的好處,而PyTorch 和 Chainer之類的項目現(xiàn)在則使用動態(tài)計算圖來形吸引客戶。
但漫長的“修改 - 運行”循環(huán)是開發(fā)更好模型的主要阻礙,所以我認(rèn)為能優(yōu)先實現(xiàn)快速啟動和快速評估的框架最終會取得成功。盡管擁有TensorBoard和iPython之類的有用工具,但是檢查模型在訓(xùn)練期間的具體細(xì)節(jié)仍然很難。
論文中的信噪比很低。但是還有很大的改進(jìn)空間。人們通常不會坦率承認(rèn)他們模型的失敗之處,因為學(xué)術(shù)會議更看重的是準(zhǔn)確度而不是透明度。我希望學(xué)術(shù)會議能接受提交博客文章,并要求開源實現(xiàn),Distill在這方面的努力值得稱贊。
對機(jī)器學(xué)習(xí)而言,這是一個令人激動的時代。在各個層面上都有大量工作等待完成:從理論到框架,每一方面都有很多值得改進(jìn)的空間。它幾乎和互聯(lián)網(wǎng)的誕生一樣令人激動,加入這場技術(shù)革命吧!
原文鏈接:
http://tinyclouds.org/residency/
本文轉(zhuǎn)自公眾號:大數(shù)據(jù)文摘