從CUDA到Keras,這些年你應(yīng)該了解的深度學(xué)習(xí)工具
“風(fēng)起于青萍之末”,十年前,Nvidia被人工智能(AI)清風(fēng)拂面,推出CUDA,成功把自己打造成風(fēng)口上的飛豬。“Nvidia還從沒有搶到過像人工智能這樣強(qiáng)的風(fēng)口,這意味著我們?cè)贕PU領(lǐng)域的成就無以倫比”,在AI淘金熱潮中,N記這家“賣水的”走到了2017CES聚光燈下?!皳?jù)估計(jì),世界上目前有3000家AI初創(chuàng)公司,大部分都采用了Nvidia提供的硬件平臺(tái)”,如果大家最近在某東關(guān)注過游戲本,可以直觀感受到N記這種成功。
一切得從GPU說起。GPU(Graphic Processing Unit)即“圖形處理器”,區(qū)別于CPU (Central Processing Unit)即“中央處理器”。CPU敢稱“中央”是有道理的,他是電腦的核心大管家,負(fù)責(zé)各種計(jì)算任務(wù),通才多面手,因而其在架構(gòu)選擇上重控制與緩存、少執(zhí)行單元,以提升執(zhí)行單元的效率。GPU則是為圖形渲染而生,特定用于G(Graphics)任務(wù)的,磚家能手,其架構(gòu)上雖然跟CPU同根同源,但選擇輕控制、多執(zhí)行單元,以提升并行處理能力。說的專業(yè)點(diǎn),就是GPU在浮點(diǎn)運(yùn)算能力上,相對(duì)CPU有數(shù)量級(jí)上的提升。架構(gòu)選擇由計(jì)算任務(wù)的特點(diǎn)決定,CPU面對(duì)不同類型的計(jì)算任務(wù)會(huì)有不同的性能表現(xiàn),而GPU在圖形渲染領(lǐng)域有CPU無法比擬的性能優(yōu)勢(shì)。
GPU為圖形渲染而生,但人們很快發(fā)現(xiàn)這個(gè)家伙對(duì)“運(yùn)算密集”、“高度并行”、“控制簡(jiǎn)單”的其他任務(wù)也能得心應(yīng)手,這是某種程度的“通用”計(jì)算,比如矩陣運(yùn)算與方程求解。在強(qiáng)烈的需求驅(qū)動(dòng)下,GPU向SIMD(Single Instruction Multiple Data,單指令多數(shù)據(jù)流)處理器方向不斷演化。SIMD 是個(gè)什么鬼?簡(jiǎn)單說就是一個(gè)教官喊“稍息”,大家都稍息,教官再喊“立正”,大家一起立正。對(duì)應(yīng)SIMD,還有MIMD(Multiple Instruction Multiple Data)架構(gòu),多個(gè)教官,一個(gè)教官喊“稍息”,只有你稍息,另一個(gè)教官可能已經(jīng)讓他的兵“臥倒”“匍匐前進(jìn)”了。MIMD能比較有效率地執(zhí)行分支程序,而SIMD體系結(jié)構(gòu)運(yùn)行分支或條件語句時(shí)會(huì)造成很低的資源利用率。
說到這里,你可能已經(jīng)覺得GPU這個(gè)東西酷斃了,可以像部隊(duì)一樣成軍團(tuán)的戰(zhàn)斗,實(shí)現(xiàn)真正意義上的硬件層面的并行。現(xiàn)在我們有這么個(gè)大錘子,釘子在哪,在哪???打住,還有個(gè)重要的問題沒有解決,錘子的比喻不妥,其實(shí)我們是有了個(gè)大篩子,胃口大得很,你怎么及時(shí)喂飽它呢?數(shù)據(jù)庫天才 Jim Gray曾經(jīng)打過比方,存在硬盤上的數(shù)據(jù)離CPU是宇宙距離,遙遠(yuǎn)不可及,放到內(nèi)存里,就變成銀河系內(nèi)了,放到Cache里,就到了太陽,放到寄存器里,才到手邊。 這些存儲(chǔ)器對(duì)于輸運(yùn)數(shù)據(jù)到CPU至關(guān)重要,也是決定處理能力的關(guān)鍵。為此,CPU配置了主存儲(chǔ)器,而GPU則配置了顯存。顯存目前以領(lǐng)先主存兩代的技術(shù)配置,加之執(zhí)行部件的并行存取,其存儲(chǔ)帶寬也是數(shù)倍于主存,為強(qiáng)大的浮點(diǎn)運(yùn)算提供穩(wěn)定充足的數(shù)據(jù)吞吐。
GPU火了,但仍是馮諾依曼的處理器架構(gòu)方式,有通用的執(zhí)行單元,接受軟件指令,處理復(fù)雜的控制邏輯,有繞不開的局限性,SIMD影響靈活并行, MIMD方式教官又不能太多,它并沒有把各司其職的理念推到極致。讓專業(yè)的人做專業(yè)的事,效率一定是最高的,硬件層面做事,比用軟件效率高、能耗低。為追求極致性能,在一些特定的領(lǐng)域,人們?cè)O(shè)計(jì)了專用集成電路(ASIC)來處理固定的運(yùn)算邏輯。ASIC邏輯是死的,無法更改,有諸多不便,這催生了介于處理器與ASIC之間的 FPGA.
FPGA學(xué)名“現(xiàn)場(chǎng)可編程門陣列”,一頭霧水??!其實(shí)可以簡(jiǎn)單理解成可回收利用的專用集成電路,也就是你可以對(duì)他編程,知乎網(wǎng)友形象的解釋“你所寫的代碼其實(shí)是在描繪一個(gè)數(shù)字邏輯電路”。這個(gè)數(shù)字邏輯電路定義好之后,“燒”到FPGA中,他就可以作為專用集成電路用了,下次處理邏輯變了,再編程,再燒。邏輯燒入FPGA中,就是個(gè)硬件電路了,沒有指令,按照電路自身邏輯運(yùn)行,不需要誰來控制。FPGA中邏輯單元之間的通信也是固定的,不需要協(xié)商。對(duì)于計(jì)算與通信密集型任務(wù),F(xiàn)PGA天然能耗更低、效率更高。
到此,聰明的你肯定能夠想到,一個(gè)復(fù)雜的計(jì)算任務(wù),首先交給CPU去控制運(yùn)算,其中對(duì)運(yùn)算密集、帶寬要求高的部分,分給GPU或者FPGA去做,從而各司其職,優(yōu)化資源配置,達(dá)到最佳的計(jì)算效果,(此處應(yīng)該有掌聲)。N記推出的 CUDA (統(tǒng)一計(jì)算設(shè)備架構(gòu))就是這么干的,科學(xué)家比普通人強(qiáng),不是在于常識(shí),而是在于對(duì)常識(shí)的組合運(yùn)用 :D 。
學(xué)過計(jì)算機(jī)原理,大家肯定記得,CPU上有匯編,有硬件驅(qū)動(dòng),有操作系統(tǒng)內(nèi)核,有調(diào)用的API, 有編譯器,有高級(jí)語言,有開發(fā)庫,你用高級(jí)語言寫程序,然后用編譯器編譯,編譯生成對(duì)操作系統(tǒng)API的調(diào)用,進(jìn)一步變成二進(jìn)制指令,在CPU運(yùn)行。CUDA 遵循這樣的邏輯,協(xié)同CPU與GPU, 并且特別的在GPU上提供硬件驅(qū)動(dòng),設(shè)備操作內(nèi)核函數(shù),系統(tǒng)調(diào)用,編譯器,高級(jí)語言(C或Fortran)支持,開發(fā)庫(例如用于矩陣運(yùn)算的cuBLAS,用于快速傅立葉變換的cuFFT等等),你依然用C或Fortran寫程序,用CUDA 編譯器編譯,生成含有CPU端與GPU端邏輯的二進(jìn)制指令,在CPU與GPU上協(xié)同運(yùn)行??梢韵胂驝UDA程序有兩個(gè)蓬勃的心臟。
不過CUDA是N記的,側(cè)重于GPU,一騎絕塵。那AMD家咋辦,眾多的FPGA咋辦? 行業(yè)需要一個(gè)開放的標(biāo)準(zhǔn),面向CPU、 GPU、FPGA 等異構(gòu)的系統(tǒng),提供通用的并行開發(fā)與運(yùn)行環(huán)境。OpenCL(全稱Open Computing Language,開放運(yùn)算語言)就是眾多領(lǐng)導(dǎo)廠商共同努力的結(jié)果,從名稱上看,OpenCL分離了硬件核心驅(qū)動(dòng)層與編程開發(fā)層,將硬件核心驅(qū)動(dòng)交給不同的廠家自行提供。你用C語言在OpenCL標(biāo)準(zhǔn)上開發(fā)編譯的程序,可以透明的跑在從CPU、GPU、到FPGA等設(shè)備上。目前OpenCL相對(duì)與CUDA在性能、成熟度、易用性以及市場(chǎng)占有率上都有相當(dāng)大的差距,但跨平臺(tái)與開放的通用性是優(yōu)勢(shì),也是趨勢(shì)。
上文中提到CUDA提供了不少類似矩陣運(yùn)算、FFT等的開發(fā)庫,CuDNN就是其中的網(wǎng)紅,江湖地位堪比Papi醬,它是N記充分利用其GPU的性能創(chuàng)建的深度神經(jīng)網(wǎng)絡(luò)加速庫,可以方便的集成到諸如TensorFlow、MXNet、Theano等流行的更高級(jí)別的機(jī)器學(xué)習(xí)框架之中。 CuDNN實(shí)現(xiàn)了典型的深度學(xué)習(xí)算法例如,卷積、Pooling、SoftMax、ReLU、Sigmoid、LSTM、RNN等等數(shù)據(jù)科學(xué)家們?nèi)鐢?shù)家珍的函數(shù),屏蔽了GPU加速的技術(shù)細(xì)節(jié),讓深度學(xué)習(xí)人員專注自己的高層模型,厲害了word CuDNN!
在《站在香農(nóng)與玻爾茲曼肩上,看深度學(xué)習(xí)的術(shù)與道》一文中,我提到“深度學(xué)習(xí)領(lǐng)域的三類最典型問題,無監(jiān)督學(xué)習(xí)(Unsupervided learning),有監(jiān)督學(xué)習(xí)的分類(Classification)與預(yù)測(cè)(Prediction)歸根結(jié)底都是用神經(jīng)網(wǎng)絡(luò)來近似概率分布,訓(xùn)練的過程就是找到這個(gè)近似概率分布函數(shù)的過程?!庇?xùn)練模型求解這些概率分布函數(shù)的過程是異常復(fù)雜的,無論CNN、RNN還是別的什么NN, 你都得綜合運(yùn)用各種數(shù)學(xué)工具,設(shè)計(jì)調(diào)整神經(jīng)網(wǎng)絡(luò)架構(gòu)、處理正則化與約束、反復(fù)優(yōu)化求極值,這些離不開深度學(xué)習(xí)框架與工具??梢院敛徊豢鋸埖恼f,人類的歷史就是不斷制造、使用與改進(jìn)工具的歷史,用工具延伸我們的手、腳、牙齒、眼睛,還有頭腦。
幸運(yùn)的是,在深度學(xué)習(xí)領(lǐng)域,人們已經(jīng)創(chuàng)造了許多優(yōu)秀的工具,Caffe、CNTK、Theano、Tensorflow、Torch等等,各有千秋,而且蘿卜白菜。由于在IT界,不同的技術(shù)特區(qū)都帶著濃濃的“宗教色彩”,為避免出現(xiàn)類似“你在PHP社區(qū)說Python好,會(huì)有人跟你吵上三天三夜”這樣的局面出現(xiàn),接下來對(duì)各種工具的比較盡量不帶個(gè)人主觀成分,實(shí)在需要“深入探討”,請(qǐng)想辦法與作者直接聯(lián)系 :D。
2015年年底,Google開源了其深度學(xué)習(xí)框架 TensorFlow, 引起業(yè)界震動(dòng),這無異于當(dāng)年大數(shù)據(jù)平臺(tái)中的 Hadoop發(fā)布。帶著谷歌的光環(huán),TensorFlow也迅速流行。學(xué)過SQL的朋友都知道 SQL = Table + Flow, Table是輸入輸出、是Flow中流轉(zhuǎn)的數(shù)據(jù),F(xiàn)low中的節(jié)點(diǎn)對(duì)應(yīng)著不同的處理與加工邏輯。 將這個(gè)概念應(yīng)用于更高維度輸入輸出數(shù)據(jù),就是Tensor+Flow。 Tensor 這里可簡(jiǎn)單比作多維度Table (或者多維度矩陣,亦或多維度向量),F(xiàn)low是Graph(計(jì)算任務(wù)的圖表示),Tensor是輸入輸出、是Flow中流轉(zhuǎn)的數(shù)據(jù),F(xiàn)low中的節(jié)點(diǎn)就是神經(jīng)網(wǎng)絡(luò)的“神經(jīng)元”,對(duì)應(yīng)著不同的處理與加工邏輯。就是這么簡(jiǎn)單。
曾經(jīng),性能是TensorFlow廣受質(zhì)疑的一個(gè)點(diǎn),但集成了CuDNN 充分利用GPU之后,性能大為提升,并通過與Spark的整合,實(shí)現(xiàn)大型分布式的模型訓(xùn)練,回應(yīng)了人們對(duì)其擴(kuò)展能力的擔(dān)心。TensorFlow有強(qiáng)大的谷歌背書,良好的網(wǎng)絡(luò)架構(gòu)與建模能力,豐富的開發(fā)語言支持(根植于Python,對(duì)R也有不錯(cuò)的集成),具備活躍的開源社區(qū),因而有著巨大的發(fā)展?jié)摿?。不過,成也蕭何敗也蕭何,谷歌全力支持,是Tensorflow大發(fā)展的基礎(chǔ),卻使得谷歌的競(jìng)爭(zhēng)對(duì)手們?cè)诓捎门c推動(dòng)TensorFlow方面就顯得十分糾結(jié)了。微軟推出了自己的CNTK, 而亞馬遜則選擇了另外一個(gè)優(yōu)秀的框架 MXNet。
來自MXNet核心團(tuán)隊(duì)的觀點(diǎn)是: MXNet 專注深度學(xué)習(xí)運(yùn)行的高效性與定制的靈活性,支持多操作系統(tǒng)與Python、R等多種語言,可以多機(jī)、多GPU并行, 同時(shí)支持命令式(類似Torch)和符號(hào)式(類似TensorFlow)兩種編程模式,因而有較好的遷移能力。“Mxnet 的輕量化路線使得我們可以在花費(fèi) Google brain 1/10 的人力的情況下做到類似 TF 技術(shù)深度的系統(tǒng)”,MXNet作者李沐如是說。而且這個(gè)核心團(tuán)隊(duì)多是這樣有識(shí)有為的華人同胞,支持下!
相比MXNet, Keras選擇了對(duì)成熟框架Theano與TensorFlow做易用性的封裝,站在巨人的肩膀上,又不讓大家覺得高不可攀。用搭積木的方式組織你的神經(jīng)網(wǎng)絡(luò)模型,易學(xué)易用,大大降低了上手的門檻,這就是深度學(xué)習(xí)領(lǐng)域的樂高啊。傍上老大哥TensorFlow, 對(duì)主流模型完美的封裝,加上豐富的示例,十分有利于快速模型搭建。在Lean Startup (精益創(chuàng)業(yè))的MVP (最小化可行產(chǎn)品 Minimum Viable Product)理念盛行的今天,Keras必定有旺盛的生命力,我們拭目以待。
最后提下Jupyter Notebook(原名IPython Notebook), 它是目前一個(gè)較為流行的交互式集成開發(fā)環(huán)境(IDE),支持Python、R等幾十種語言;方便易用,打開瀏覽器,像寫筆記一樣寫代碼、做分析,交互式,幾乎沒有什么學(xué)習(xí)成本;生成的筆記也是簡(jiǎn)潔優(yōu)雅,人家叫“筆記本”可是名副其實(shí),功能強(qiáng)大而且免費(fèi)。注意到本文提到的軟件組件都是“功能強(qiáng)大而且免費(fèi)”,感謝開源打破了技術(shù)壁壘,給整個(gè)技術(shù)社區(qū)帶來福利。
從底層硬件到上層框架,啰嗦了一大堆,其實(shí)用下面一張簡(jiǎn)圖就可以概括常見深度學(xué)習(xí)組件、工具與其生態(tài)關(guān)系。不少東西,作者也是道聽途說,本文目的是從關(guān)于深度學(xué)習(xí)平臺(tái)的繁雜的信息中,理出些頭緒, 文中難免不嚴(yán)謹(jǐn)?shù)牡胤?,僅作交流學(xué)習(xí)心得用。
