賈揚清分享_深度學習框架caffe

查志強發表於2015-08-04

【原文:http://www.datakit.cn/blog/2015/06/12/online_meet_up_with_yangqing_jia.html

Caffe是一個清晰而高效的深度學習框架,其作者是博士畢業於UC Berkeley的 賈揚清,目前在Google工作。本文是根據機器學習研究會組織的online分享的交流內容,簡單的整理了一下。

目錄

1、caffe分享

我用的ppt基本上和我們在CVPR上要做的tutorial是類似的,所以大家如果需要更多的內容的話,可以去tutorial.caffe.berkeleyvision.org,也歡迎來參加我們的tutorial。網頁上應該還有一些python的樣例幫助大家上手,所以歡迎參觀。ppt比較長,所以我想我主要就介紹一下背景以及high level的內容,然後更多關注大家有一些什麼具體的問題,希望大家覺得OK。slider here

1.1、caffe起源

大家最近一段時間應該已經聽到很多關於deep learning的八卦了,deep learning比較流行的一個原因,主要是因為它能夠自主地從資料上學到有用的feature,特別是對於一些不知道如何設計feature的場合,比如說影象和speech deep learning可以學習到比以往比如說sift或者MFCC這樣手工設計的feature更好的方法, 而且像slide 4顯示的一樣,這些feature有很強的semantic的含義。所以很多時候在用到其他的一些task的時候會很有效,這也是為什麼我們可以用一個feature來實現很多比如說識別,檢測,物體分割這樣的不同task的緣故。

anyway,deep learning其實說回來是個挺久的話題了,Yann Lecun在89年的時候就提出了convolutional Neural Net的idea 然後在手寫數字上獲得了很大的成功。最近deep learning重新受到關注,最大的原因是兩個:

  • 一個是大規模的資料集使得我們可以學習到遠比digit更加複雜的概念
  • 另外一個是大規模平行計算讓我們可以做很快的優化,使得以前我們沒法想象的計算量都變成小case了

所以這些都很美好。但是問題是寫code還挺麻煩的。所以大家肯定希望有個比較好用的框架來很快上手和試試這些deep learning的演算法。 所以這就是Caffe了!Caffe是我在Berkeley寫thesis的時候想學習C++和cuda寫的,然後寫完了覺得我自己用太虧了,所以想貢獻給community讓大家來用。所以如果你看見一些寫得很爛的code,不要罵我。

1·2、caffe介紹

caffe的好處是,我們基本上可以用一個比較簡單的語言(google protobuffer)來定義許多網路結構,然後我們可以在CPU或者GPU上面執行這些程式碼,而且cpu和gpu在數學結果上是相容的。然後,所有的模型和recipe我們都會公佈出來,使得我們可以很容易地reproduce互相釋出的結果。這也是我感到很幸運的一個地方,大家都很喜歡caffe,也很喜歡分享自己paper裡的成果(比如說MIT的place net和VGG的模型)。

anyway,這就是Caffe的簡單介紹了,最開始是一個hobby project,但是最近Berkeley和其他公司比如說NVidia,Yahoo在很認真地maintain它,希望能夠把整個架構做的更好用。

然後我大概講一下caffe的design吧。

基本上,caffe follow了神經網路的一個簡單假設 - 所有的計算都是以layer的形式表示的layer做的事情就是take一些資料,然後輸出一些計算以後的結果 比如說卷積,就是輸入一個影象,然後和這一層的引數(filter)做卷積,然後輸出卷積的結果。每一個layer需要做兩個計算:forward是從輸入計算輸出,然後backward是從上面給的gradient來計算相對於輸入的gradient。只要這兩個函式實現了以後,我們就可以把很多層連線成一個網路,這個網路做的事情就是輸入我們的資料(影象或者語音或者whatever),然後來計算我們需要的輸出(比如說識別的label)。只要這兩個函式實現了以後,我們就可以把很多層連線成一個網路,這個網路做的事情就是輸入我們的資料(影象或者語音或者whatever),然後來計算我們需要的輸出(比如說識別的label)。在training的時候,我們可以根據已有的label來計算loss和gradient,然後用gradient來update網路的引數。這個就是Caffe的一個基本流程!

如果大家需要自己實現一個layer的話,可以參考slide28的格式。比如說輸入是x,我們可以想象一個layer的forward function就是y=f(x) 然後,我們會有一個loss function,記成L(.)。在做backward的時候,網路得到的是上層給出的gradient,dL/dy,然後網路需要做的計算是dL/dx = dL/dy * dy/dx,dy/dx也就是f’(x)。於是,這樣我們就可以一層一層往後計算gradient。slide 31簡單介紹了一下這個forward和backward的結構 anyway,Caffe裡面實現的solver主要也是為了神經網路設計的。

在做training的時候,我們一般都會做SGD,就是每次輸入一個小batch,做計算,update引數,然後再輸入下一個batch Caffe也實現了許多實際應用上比簡單SGD要更有效的演算法,比如說momentum 和Adagrad (順便插一句,Ilya Sutskever有paper解釋說,momemtum其實已經可以很好地實現quasi second order的優化,所以建議大家可以從momentum sgd開始嘗試做training).

基本上,最簡單地用caffe上手的方法就和slide 35說的一樣。先把資料寫成caffe的格式,然後設計一個網路,然後用caffe提供的solver來做優化看效果如何。如果你的資料是影象的話,可以從現有的網路,比如說alexnet或者googlenet開始,然後做fine tuning。如果你的資料稍有不同,比如說是直接的float vector,你可能需要做一些custom的configuration。caffe的logistic regression example(slide 36)興許會很有幫助。

我在和人聊的時候發現大家都比較喜歡fine tune的方法,所以我也簡單介紹一下。基本上,finetuning的想法就是說,我在imagenet那麼大的資料集上train好一個很牛的網路了,那別的task上肯定也不錯。所以我可以把pretrain的網路拿過來,然後只重新train最後幾層。重新train的意思是說,比如我以前需要classify imagenet的一千類,現在我只想識別是狗還是貓,或者是不是車牌。於是我就可以把最後一層softmax從一個40961000的分類器變成一個40962的分類器。這個strategy在應用中非常好使,所以我們經常會先在imagenet上pretrain一個網路,因為我們知道imagenet上training的大概過程會怎麼樣。

1.3、caffe其他方向

我覺得演算法上主要就是以上這些了,大概再講一下最近一些比較有意思的方向吧。首先是multi-GPU的訓練,caffe有一個Flickr的branch可以用來做multi-GPU,不過目前好像把它merge進master得過程有點慢。不過,如果你有興趣的話,其實multi-GPU不是很難。比如說,用MPI實現一個GPU之間的synchronization,然後把data transfer和computation 並行起來,基本上就可以實現一個比較直接的single machine multi-gpu training了。當然希望flickr的branch儘早merge。

另外,sequence model (RNN, LSTM)也是一個比較熱門的方向,一個比較簡單地實現RNN的方法是unrolling。就是說,我不來實現一個for loop,而是確定地說我的sequence就是一個固定的長度,這樣,整個網路就依然是一個feed forward的網路,除了需要一些weight sharing以外,依然是可以用原先的架構來實現的。

另外就是NVidia的cuDNN,NVidia在cuda上做了很多的優化,所以無論大家是用caffe還是實現自己的code,都可以關注一下它。cudnn最近會準備出v3,效果應該比v2還會更快一些。

另外一個比較值得關注的數學計算庫是Eigen,在CPU上的優化還是挺顯著的。Caffe沒有太多地用到Eigen,但是我覺得值得提一下。anyway,我覺得我們們要不還是多留一些時間來討論大家關注的問題,所以我就先打住了,我們Caffe的主要的contributer都在slide 89上,大家都很nice,如果你在CVPR上碰見我們的話歡迎來聊天:)

2、討論

討論部分,這裡把一些問題合併,方便檢視和閱讀。

2.1、caffe演算法與結構

multi-gpu其實是在最近的model,比如說googlenet上,只需要model parallelism就可以了,因為引數的數量很少:)。 caffe內部的Convolution計算是影象拉伸成向量進行的計算,這種方式會比普通的方法和fft的方法計算更快嗎?放大點說,caffe做了哪些演算法上的優化 使得計算速度比較快呢?那個其實是我的weekend hack,所以推薦大家用其他的優化,比如說cudnn等等。說實話寫caffe的時候我沒太關注速度。在神經網路的訓練過程中,如何能夠並行或者說更快地計算?主要是靠兩點吧,一個是寫更快的code(比如說用cudnn優化convolution),一個是寫平行計算的框架(這方面我推薦用MPI入手,因為MPI雖然沒有fault tolerance等等的好處,但是並行非常簡單,可以作為最開始的測試)。使用gpu對計算效能進行優化,這個更多的是在code層面上調速度了,如果有興趣的話,nvidia的nvprof應該會很有幫助。目前,caffe也有很多的branch,比如對分散式的支援,可以在parallel branch裡面找到。

目前dl近幾年在siamese nets distances結構上的進展如何?研究思路如何?” Yann Lecun有paper:Learning a Similarity Metric Discriminatively with Application to Face Verification講這個,值得看看。

dl能實現FFT嗎? facebook其實有fft的code,參見fbfft。facebook是利用了FFT去快速計算,不是我問的意思。用傅立葉變換其實是提取了頻域特徵,根據應用的不同,最優的變換不一定是FT,可能是時頻變換、分數階FT等等變換。那麼問題就來了:利用深度學習演算法,能否學習到最優的時頻特徵表出?如果可以,是不是可以把訊號處理裡面的固定分析方法都扔掉?” 這個我就的確不是專家了,我覺得這個有點類似於model design的問題,深度學習相當於也是設計了一大類的model,然後在這一類model當中尋找最優的,所以如果有一些oracle knowledge(比如說已有的固定分析的經驗)可以知道如何rectify資料,我覺得應該還是有幫助的。

用caffe純粹做分類的話(前向),需要softmax層嗎?看程式碼有個pro層和softmax一樣嗎?不是很清楚pro層是哪個,不過也可以用logistic,任何傳統的分類函式應該都是可以的。對於,softmax_layer和softmax_loss_layer的區別,softmax_layer是做softmax變換(就是把輸入的score變成sum to 1的概率值), softmax_loss是計算prediction和true label之間的cross entropy loss function

現在也有用權值不共享的卷積網路的,請問這個和權值共享網路分別更適合什麼樣的問題?權值不共享的問題是引數太多,所以不是很好控制overfit,一般都是在網路的後期做locally connected,這對一些問題(比如說face)是個很好地tradeoff,但是還是得實際應用來測試:)

用hdf5layer實現多label的過程不是很清楚,舉個例子說,比如,輸入低分辨影象,label是高分辨影象,這種有沒有詳細一點的教程,或者師兄能不能簡單提一下?這個主要就是要設計一個input層能夠輸出不同的top blob,其實caffe在這一點上做的不是很好(因為太關注classification了),可能看一下這些典型的輸入層的實現會有幫助。

caffe能否在多個層都連線loss函式,同時進行反向傳播?可以的,關鍵是要處理好gradient merge的問題,其他都是OK的。caffe實現多層loss反向傳播,即在prototxt裡,每一層後加上需要的loss函式,那麼caffe最終的反向傳播會是怎樣進行的?應該是這樣的,每一層後面需要一個split層,把這一層的輸入變成兩個blob,一個繼續往下傳播,一個輸入到loss層裡面。在backprop的時候,split層會把這兩條路徑的gradient加起來。對於loss是什麼了,比如說googlenet用到了幾個branch來inject softmax,所以基本上還是要尋找和問題相關的loss term。

用SGD的時候,收斂充分的前提下,不同的學習率衰減策略是不是結果都差不多?恩,一般會差不多。autoencoder 模型中,單個隱含層和多隱層 模型,效果差別很多啊嗎?這個可能和具體實現有關,隱層多了以後,representation power增加,很可能會提升效果,但是也可能會overfit,所以需要更仔細的training。

2.2、caffe工程與應用

目前Caffe主要面對CV或影象的任務,但是也可以做nlp。那在移動端用深度學習可以實現實時人臉檢測麼?人臉檢測可能目前用傳統方法還是很competitive的,但是做一些識別等等,我覺得目前的移動裝置應該是可以支援的。DL也能和傳統特徵結合,即傳統特徵可以作為feature輸入到網路裡面,然後再繼續做計算。

對於多工學習的DL有什麼經驗可以分享嗎?比如資料分佈的均勻性的影響。資料分佈均勻性一般都還是挺tricky的,實際操作上一般我覺得cap一些frequency(如果某一類太多了,就downsample一下)會使得training更好一些。

caffe能支援lstm、rnn的訓練嗎?另外,對於百度的dlmc您有什麼看法?Jeff Donahue有一個branch可以來做lstm,我自己在refactor的一些code應該也是可以的,但是因為公司review政策的緣故沒法保證什麼時候能release :) dmlc我覺得是個挺好的effort,在開源界看到更多中國學生的身影很興奮!

目前deep learning用在小資料集上有什麼好的方法嗎?在小資料集的問題上是不是可以通過減少網路的層數來減少過擬合?小資料集基本上需要通過小的模型來防止overfit,當然如果資料集是影象等等,也可以通過finetuning。另外一個可能是直接手標更多資料,有時候糙快猛但是還挺好使的。caffe對不同尺度的同一物件的分類和識別有哪些特殊的處理方法?這個倒也不單是caffe的問題,在影象識別上如果需要處理不同尺度,一般就是做multi-scale的detection,可以參考一下selective search,R-CNN等等的工作。

如果不使用matlab或python介面,直接在C++的caffe程式碼裡對影象進行分類有什麼好的方式嗎,速度會不會比matlab和python更快?我覺得速度應該差不多,因為matlab和python的overhead不會太大。(可以不使用python,直接使用c++, chrispher經過測試,速度差距還是很大的(至少一倍以上),python在預處理影象方面比較慢)。

CNN可以應用到對影象進行深度圖提取嗎?效果會怎樣呢?最近nyu應該有一篇stereo的文章,應該比較類似。caffe的訓練過程能否保持物件的旋轉不變性 怎樣做到這點?目前不是很好explicit地輸入這樣的constraint,主要還是靠data augmentation(輸入各種旋轉以後的圖)來實現。怎麼處理變長的圖片,因為Conv對變長不明感,而且可以用Dynamic Pooling?變長的圖片可以用SPPNet這樣的思路,最後做一個固定輸出大小的pooling。

用自己的資料(並不屬於imagenet的1000個類)在imagenet訓練的網路上做finetune時,發現怎麼調整引數最後幾乎都無法用來分類,這是什麼原因呢?這個可能需要看一下圖片是否類似,比如說imagenet的模型用來做醫學影象識別效果就很可能會不是很好,還是需要看這兩個task的資料之間是否有相似性。用自己的資料集,且型別和和imagenet的型別不太一樣(比如細胞型別),想用caff訓練的話,最少得需要多少資料量,才比較好?這個說不太好,所以最好還是先用一部分資料測試一下,然後你可以用從少到多的資料來訓練,然後外推一下可能會需要多少資料。DL中,能否預知到底學到了一個怎樣的物理模型,來實現分類的?參見上面的回答:)目前比較困難,在圖片上,大家做過一些有意思的實驗來檢測模型到底學了什麼,可以參考karen simonyan的文章(用CNN來生成一個”最像”某一個類別的影象)

dl 在ctr預測上有什麼好的論文或者資料麼?我不是很清楚,不過餘凱師兄以前講過百度用DL做CTR效果很好,所以還是很promising的。 請問除了從分類結果看特徵表出的優劣,有沒有一種通行的方式去看特徵表出的優劣?還有一個問題:lstm簡直就是一個編碼模型…以後機器學習的結構都要往電子工程上靠了嗎?我覺得結構越來越複雜正背離dl的初衷了?其實大家經常批評DL的問題就是說,我們從設計feature變成了設計model(我記得原話是jitendra malik講的,我太八卦了)。所以這個的確也是一個難解的問題,興許我們可以做一個演算法來自動生成很多model然後evolve這些model?MIT曾經有一篇paper來自動學習網路的結構,但是目前state of the art的模型還經常靠手調。

2.3、模型訓練與調參

引數設定其實有點tricky,我覺得更多的還是通過已有的架構然後來做一些微調,個人也沒有太好的insights可以分享,更多的是一些經驗型的東西,推薦大家讀一下kaiming he最近的paper,很有效果,此外微軟的paper,vgg,googlenet可能有幫助。。受限於gpu記憶體,batchsize不能選太大,這會導致結果的不收斂,話句話說那訓練過程中batch的大小對結果影響大嗎?理論上batch小是不會影響收斂的。小batch主要的問題是在FC層的計算可能會不是很efficient,但是數學上沒有問題。

對於2-GPU(AlexNet裡的group引數),其實AlexNet可以直接用單GPU來實現,大家覺得AlexNet是2GPU的緣故是,Alex當年train網路的時候GPU記憶體太小,他只好用兩個GPU來實現:)後來大家一般都是用一個GPU的。

finetuning過程是用已有的模型來初始化現有的模型,在caffe裡面可以設定一些layer的learning rate為零來實現不更新某些層的引數。此外,在finetuning的時候,新問題的影象大小不同於pretraining的影象大小時,只能縮放到同樣的大小嗎?對的。

請問在s層,如何確定該用mean pooling還是max pooling?基本上靠試。在調參方面有什麼比較細緻的資料或文獻集,比如solver裡的 lr_policy 選擇有什麼規律麼? 這兩個問題,基本上我覺得還是靠經驗。marc’aurelio ranzato曾經有一個presentation講一些有用的trick,marc’aurelio的網站在這,應該是其中的某一個slides。

在自己的資料集上訓練,訓練的loss函式一直不降低,調小過偏置大小,學習率也改過很多,但是每次都很快的迭代到一個大的值,不再變化,而且測試準確率就等於瞎猜的準確率。這個可能是learning rate太大或者初始值的問題?可以縮小初始值的scale試試。

記得有一篇說論文:trainning_convolutional_networks_with_noisy_labels說在imagenet上,把30%的標籤打亂,反而使得最後的結果更好和更魯棒。那麼是不是意味著我們不需要強定義的資料(不需要那麼仔細的標註資料) 就可以訓練得到一個不錯的模型呢?我覺得基本上就是資料越乾淨,資料越多,效果一般就越好(實際應用上我們有時候會讓human rater去再次確認一些不確定的標註)。魯棒性的問題,我覺得可能是因為增加了regularization?imagenet上基本上還是標準的protocol來training效果最好。。。

2.4、caffe與DL的學習與方向

我覺得主要還是follow tutorial,另外網上(比如知乎)也有很多解析。 現在是在做機器學習,還沒有深入deep learning,是不是要先打好機器學習的基礎再學DL會好一點?這個我其實也不是很清楚,很多想法其實都是相通的(比如說優化的問題),所以可以都看一些,然後按照自己的需求深入:)

如何將已知的世界知識,比如說語法規則等有效融入到深度學習中?這個是個好問題,目前大家都有點傾向於learning from scratch,所以我也說不好怎麼做融合,但是應該是一個值得考慮的研究方向。

可否評論一下nature 新出的DL文章?reinforcement learning之類的會是下一個主要結合的點嗎?哈,Hinton本人的說法是“you won’t learn much from that paper”。那個更多的是一個overview,如果希望瞭解一下DL的來龍去脈的話值得讀一下。RL其實還是挺熱門的,deepmind做的就有點像RL,berkeley Pieter Abbeel組也做了很多RL的工作。

像cxxnet,這些新的框架,也整合了bn,prelu等新的模組,caffe是否會內建這些模組呢?我覺得會的,這個在code層面上其實沒有太大的問題。我最近主要在做一些refactor,然後還有一些公司的事情,所以沒有關注在push新的模組上:)

目前dl在時序序列分析中的進展如何?研究思路如何,能簡單描述一下麼。這個有點長,可以看看google最近的一系列machine translation和image description的工作。關於時序的問題統一回答一下,大家可以參考最近的machine translation,im2txt等等的一系列文章。DL在時序方面的應用主要是RNN/LSTM這方面,主要是用來理解sequence的資訊,兩個用法:(1)提取sequence的feature,然後來做classification或者embedding,(2)從sequence到sequence,比如說輸入語音,輸出識別的句子。

2.5、其他

google brain和human brain project,恕我不好評論。公司政策:)。對於cxxnet,您是怎麼看待的呢?我還挺喜歡cxxnet的一些設計的,基本上就是大家選自己喜歡的codebase來用吧:)

3、附錄

賈揚清的知乎以及他的個人主頁,微信可以關注機器學習研究會,當然也可以加一下我個人的群資料,為夢想而生(更推薦比較高大上的機器學習狂熱分子群)



相關文章