這是一個轉型AI的勵志故事,從非科班到拿下競賽一等獎

這是一個轉型AI的勵志故事,從非科班到拿下競賽一等獎

作者:智亮,魯朗軟體聯合創始人
責編:胡永波
本文為《程式設計師》原創文章,未經允許不得轉載,更多精彩文章請訂閱《程式設計師》

在計算機行業,關於從業人員的素質,一直都有一個樸素的認識——科班出身好過非科班,學歷高的好過學歷低的。大部分時候,這個看法是對的。在學校學習,有老師指點,有同學討論,有考試壓迫,有專案練手。即便不大用心的學生,幾年耳濡目染下來,畢業後作為半個專業人士,還是沒什麼問題的。

不過,量子物理告訴我們,這個世界的本質要看概率。所以,科班出身的同學,在技術上好過非科班出身的同學,這是大概率事件;相反,非機器學習專業,甚至非計算機專業的同學,在這個領域做的比本專業同學更好,則就是小概率事件了。但小概率事件並非“不可能事件”,國內很多做機器學習公司的CTO,都不是機器學習專業的科班出身,卻能夠抓住這裡的“小概率”,讓自己華麗地轉身並實現彎道超車。

他們是怎麼做到的?

如果在上學的時候,我們沒能嗅到機器學習領域的機會,而是選擇其他領域來學習和工作……如今卻打算半路出家、改行機器學習,應該怎麼做,才能做到跟這些人一樣好?或者,至少是足夠好?

我自己痛苦轉型的經歷,說出來可以供大家參考一下。

我也是非科班出身,但因為工作,一直需要接觸計算機視覺的一些傳統演算法。後來,看到ImageNet競賽的結果,我意識到了深度學習在視覺領域的巨大優勢,遂決定開始轉型深度學習和神經網路,走上了這條學習的不歸路(笑)。

想要轉型,跟上學的時候不同,因為手頭正在做的工作意味著,自己需要從沒有時間的情況下擠出時間,需要把別人睡覺、打遊戲的時間用來學習,而所學的又是一種頗為艱深晦澀的學問。

轉型,其實很容易,需要做到的只有一件事:學習。

轉型,其實很困難,因為必須做到一件事:堅持學習。

最難的不是下定決心,而是貫徹到底。所以,在開始之前,不妨先問問自己這樣幾個問題:

“我真的已經想清楚,要踏足這個行業嗎?”
“我能夠付出比其他人更多的辛苦汗水,在這條路上堅定地走下去嗎?”
“在遭受了痛苦甚至打擊之後,我對機器學習的熱愛,仍然能夠維持我繼續前進嗎?”

根據我掌握的資料,100個程式設計師裡大概有30個考慮過轉型,而真正付諸行動的不過10個。一個月以後仍然在堅持的僅有5個,最終能完成第一個階段學習的,最多兩三個而已。

真的這麼困難嗎?是的。特別是你要白天上班,晚上才能學習,獨學而無友,有問題又只能自己查。而要系統地入門,又不是咬牙一天兩天就能學出來,恐怕得堅持幾個月才能get到點。

我個人的經歷是這樣:一開始接觸時,每週一、三、五固定3天時間,每晚花兩個小時去學習、看視訊、翻書,週六週日則用來完成課程附帶的程式設計作業,大概也是每天兩小時左右。在這種強度下堅持了三個月,我才算是完成了入門的第一步。

也許有的人效率更高一些,也許有的人步子更慢一些,但快和慢不是關鍵,即使學習最慢的人,也要比一開始放棄學習的人走得更遠。

所以,其實真正重要的,不是“我該學什麼”,或者“我該怎麼學”;而是“我是不是真的有足夠的決心”,以及“我是不是能堅持到底”。

上手的課程

定好決心後,我們就能看看:在學機器學習的時候,我們到底在學什麼?

幾乎所有人都知道人工智慧這個概念;有一部分人知道“機器學習”這個概念;其中一小部分人能清楚描述“深度學習”、“機器學習”和“神經網路”的關係; 很少一部分人能夠正確說明“卷積”、“池化”、“CTC”這些名詞的正確含義與計算/實現的方法;非常少的人能清楚地理解損失函式和反向傳播的數學表達;極少極少的人能夠闡述網路的一個修改(比如把卷積核改小)對precision/recall會產生什麼影響;幾乎沒有人能描述上述影響到底是什麼原理。

這就是目前“程式設計師”這個群體,對於機器學習的瞭解程度。

我個人的經驗,適用於“很少一部分人”之外的那“很大一部分人”,也就是說,他們最多知道深度學習是什麼意思,神經網路又是什麼概念,卻並未真正系統地學習接觸過這個領域。

而我們的目標,則定位成為“非常少的人”,也就是能夠理解損失函式/反向傳播這些較為基礎、較為底層的知識,使得自己能夠設計新的演算法或網路,或至少能輔助大牛去實現他們所設想的演算法和神經網路。

要實現這個小目標,我們就必須掌握最基礎的知識,就好像學寫漢字時,不練橫豎撇捺折是不現實的。

但是,作為“不明真相的廣大群眾”,從哪裡入手好呢? 線性代數?概率論?那是最糟糕的選擇!它們只會讓你入門之前就徹底喪失信心,其漫長而陡峭的學習曲線還會讓你誤以為這是一個不友好的領域。事實上,只有成為“很少一部分人”(能夠正確說明“卷積”,“池化”,“CTC”這些名詞的正確含義和計算/實現方法)之後,你才真正需要去複習它們。

在這之前,你所要用到的數學知識,只有以下這三點:

  1. 懂得矩陣運算的基本計算方法,能夠手動計算[3×4]×[4×3]的矩陣,並明白為什麼會得到一個[3×3]的矩陣。
  2. 懂得導數的基本含義,明白為什麼可以利用導數來計算梯度,並實現迭代優化。
  3. 能夠計算基本的先驗及後驗概率。

只要大學考試不是完全靠抄答案,稍微翻翻書,你就能把這點知識找回來,可能半天都用不上。

然後就可以入門了,對於所有零基礎的同學,我都建議從吳恩達的機器學習課程開始: Machine Learning – Stanford University | Coursera(https://www.coursera.org/learn/machine-learning)。

這是唯一的推薦,也是最好的入門教程,沒有之一:因為吳恩達的英語又慢又清晰,課程字幕的翻譯又到位,課程設定與課中測驗及時而又合理,重點清晰、作業方便,再加上吳恩達教授深入淺出的講解,講解過程中不時的鼓勵和調侃,都能讓你更為積極地投入到機器學習的學習之中,讓你紮實而快速地掌握機器學習的必備基礎知識。

這門線上課程,相當於斯坦福大學CS229的簡化版,涵蓋內容包括機器學習最基礎的知識、概念及其實現,以及最常用的演算法(例如PCA、SVM)和模型(全連線神經網路)。學習這門課程,重要的是基礎的概念與實現。作為一名具備程式設計基礎的開發人員,在這個階段要將自身理論同實踐相結合的優勢發揮出來,充分利用它所提供的程式設計作業,儘可能多地實踐,從理論和程式碼兩個角度去理解課程中的知識點。

學習完成後,你能瞭解到機器學習的一些基本名詞和概念,並具備一定的演算法層面的編碼能力。打好理論和實踐的基礎,你就可以進行下一階段的學習了,其中有兩大的方向:夯實基礎和選擇領域。

夯實基礎的意思,就是這門課的完成,並不代表自己學會了機器學習,只不過是從門外漢進了一步,一隻腳踏進了門,但其實也僅僅是一些基本的瞭解。這個時候,你也許會覺得自己有很多的奇思妙想,卻難以評估這些想法的價值和正確的可能性,這就是基礎不夠的緣故。

所以,在繼續學習深度神經網路之前,建議結合自己所學到的知識,回頭去看一遍CS229,將傳統演算法整體熟悉一遍,儘可能把所有的基本概念都掌握紮實。

而選擇領域,則是由於任務目標的不同,深度學習領域已在大體上分成了計算機視覺(CV)、自然語言處理(NLP)以及其他一些子領域,例如語音和更為特殊的強化學習等。在每個領域下,都有大量的研究者在投入精力鑽研,發表論文和成果。考慮到個人精力的限度,建議選擇一到兩個方向作為主攻,跟上學術界主流的進展,其他子領域有基礎的瞭解即可,必要時作為參考即可。

以計算機視覺為例,在完成CS229的課程之後,可以繼續學習CS231n,作為進一步學習的材料;而自然語言處理則可以選擇CS224d。在完成了相應領域的學習後,下一步要做的就是嘗試閱讀最新的經典論文並試圖復現它們了。

程式語言與深度學習框架的選擇

當然,作為開發者,想要去實現一個模型,繞不開的問題便是:

應該選擇什麼語言?應該選擇什麼框架?

對於開發人員而言,語言的選擇其實不是問題。但作為入門,最為理所當然的建議則是Python,原因也非常簡單:Python最好學。

對於機器學習的學習,使用Python就意味著你不必分心去學習那些複雜的資料型別約束以及轉化、指標、記憶體管理或垃圾收集之類的“高階”(一般同時也代表著複雜)的特性,將精力集中在自己的目標上。當然,一些Python特有的方法(如lambda、yield或reduce)以及工具(如NumPy、pandas),還是需要多多使用,儘快熟練。

而框架方面,從使用者的維度去劃分,當前數量非常之多的機器學習框架,則可大體上分為兩大陣營。

學術友好型: Theano、Torch與Caffe

學術研究時,弄出來一個新模型、新演算法、新函式是常有的事,做出新的突破也是學術研究最基本的要求。所以,這些框架通常都便於定製模型,也可深入修改內部實現。很多新成果都會在發表論文的同時,提供這些框架上的實現程式碼以供參考。它們在效能方面也比較出色。

其代價就是,要麼是使用了困難(Caffe:C )或小眾(Torch:Lua)的開發語言,要麼是有一些古怪的缺點(Theano:編譯超級慢)。

而且,這些框架似乎都沒怎麼考慮過“怎麼提供服務”的問題。想要部署到伺服器上?Caffe已算是最簡單的了,但仍要經歷漫長而痛苦的摸索歷程。

工業友好型: Tensorflow、MXNet與Caffe

工業上往往更注重“把一個東西做出來,並且讓它執行得良好”。所以這些框架首先就需要支援並行訓練。其中Tensorflow和MXNet支援多機多卡、單機多卡、多機單卡並行,Caffe則支援單機多卡,雖然效能還不是特別理想。

在我們的測試中,Tensorflow的雙卡並行只能達到單卡的1.5倍左右效能,卡越多,這個比例越低。Caffe要好一些,但引數同步和梯度計算無論如何也都需要時間,所以沒有哪個框架能在沒有效能損失的情況下實現擴充套件。而多機情況下,效能損失更大,很多時候都讓人感到無法接受。

相對來說,只有Tensorflow提供了比較好的部署機制(Serving),並且有直接部署到移動端的方案。而MXNet和Caffe則是直接編譯的方式,雖然也能實現,但是說實話,依然很麻煩。

至於缺點,除Caffe之外,其他兩種框架對於學術界動態的跟蹤都不太緊,Tensorflow到現在都沒有PReLU的官方實現,前不久才剛推出一系列檢測(Detection)的模型。MXNet這一點上要積極些,可是受限於較小的開發者社群,很多成果都只能等待大神們的contribution,或是自行實現。

這樣看來,難道最好的框架是Caffe?既能兼顧學術和實現,又能兼備靈活性和效能兼備……說實話,我的確是這麼認為的。但前提是你懂C ,如果出身不是C 開發人員,相信我,這門語言也不比機器學習容易多少。

所以,對於大多數有志於投身於機器學習開發(而非研究)的同學們來說,我推薦首選Tensorflow作為你的第一個開發框架。除了上述的優點之外,最主要的因素是它人氣高。遇到任何問題,你都可以找到一群志同道合的夥伴們去諮詢,或是一起研究。對於初學者而言,其重要程度不言而喻。

實戰上手的資料

上過課程、學好語言、裝好框架之後,自然就要通過親手程式設計,來把自己的模型實現出來。

但在深度學習領域,沒有資料的模型就是無源之水,毫無價值。而目前流行的監督學習,要求必須有足夠的帶標註資料來作為訓練資料。那麼,從哪裡能得到這樣的資料以進行學習呢?答案就是公開資料集。

例如,在學習論文時,如果它提出了一個效能優異的模型或者方法,通常會附有在幾個公開的標準資料集上的成績,這些標準資料集就是可以去下載來學習和使用的資源。另外,諸如Kaggle和天池之類的機器學習競賽,其比賽專案中也會提供很多資料集供學習和測試。這些就是學習階段的主要資料來源。

以CV領域為例,常見的公開資料集就包括以下這些。

MNIST

不論選擇哪本教材、哪個框架,在剛剛接觸機器學習的時候,一定會接觸到MNIST。它是由Yann LeCun所建立的手寫數字庫,每條資料是固定的784個位元組,由28×28個灰度畫素組成,大概長成這樣:

這裡寫圖片描述
圖1 MNIST手寫數字

目標是對輸入進行10-分類,從而輸出每個手寫數字所表示的真實數字。
因為它體積小(10M左右)、資料多(6萬張訓練圖片)、適用範圍廣(NN/CNN/SVM/KNN都可以拿來跑跑)而聞名天下,其地位相當於機器學習界的Hello World。在LeCun的MNIST官方網站上(yann.lecun.com/exdb/mnist/),還貼有各種模型跑這個資料集的最好成績,當前的最好得分是CNN的,約為99.7%。

由於該資料集非常之小,所以即便是在CPU上,也可以幾秒鐘就跑完NN的訓練,或是幾分鐘跑完一個簡單的CNN模型。

CIFAR

而打算從影象方面入手的同學,CIFAR資料庫(官網:www.cs.toronto.edu/~kriz/cifar.html)則是一個更好的入門選項。
該資料庫分為2個版本,CIFAR-10和CIFAR-100。顧名思義,CIFAR-10有10個分類,每個分類有5000張訓練圖片和1000張測試圖片,每張圖片是32×32畫素的3通道點陣圖,如圖2所示。

這裡寫圖片描述
圖2 CIFAR-10資料集的隨機圖片

而CIFAR-100則有100個分類,每個分類變成500張訓練圖片與100張測試圖片,但圖片的大小並沒有什麼變化。

之所以它比MNIST更適合作為圖片處理的入門,是因為它儘管解析度較低,但卻是三通道、真實拍攝的照片。其中有些圖片的背景還略微複雜,更貼近我們真實的圖片處理場景。相對而言,MNIST的灰度輸入和乾淨背景就顯得過於簡單,況且99.7%的準確率也確實難有提升的空間。

Tensorflow給出了CIFAR的例程,並附有程式碼

ImageNet和MS COCO

至於ImageNet(www.image-net.org/)和COCO(http://mscoco.org/),則是兩個工業級別的影象資料集。通常提到它們時,ImageNet指的是ILSVRC2012的訓練集,而COCO則是COCO-2014訓練集。

ImageNet有大量的圖片(一百多萬張,分成1000個分類)和標註,大部分都是圖3這樣的。

這裡寫圖片描述
圖3 ImageNet資料集的標註圖片

COCO雖然圖片數量少一些(8萬多張,80個分類),但每張圖片都有輪廓標記,並且附帶分類標註和5句描述話語(英文)。其圖片大致如圖4。

這裡寫圖片描述
圖4 COCO-2014圖片的物體輪廓

所以當我們進入實際工作的階段,就要根據具體的需要從中選擇適合自己的資料集,以作為benchmark或是pretrain資料集。

實戰階段的學習用機配置

接下來,我們就需要一臺機器來把框架搭建起來,以編寫和執行我們的helloAI。然而,我在很多地方都看到小夥伴們在問:

我需要什麼樣的配置能學機器學習?
我需要買塊GTX1080/TITAN/Tesla嗎?
我應該裝幾塊顯示卡?一塊?兩塊?還是四塊?

而答案也往往傾向於:

“必須得有GPU啊,至少1080,沒有四路Titan你都不好意思跟人打招呼!”

其實,並不完全是這樣。

如果僅僅是入門和學習,CPU或GPU完全不影響你對程式碼和框架的學習。執行MNIST或CIFAR之類的玩具資料集,它們的差距並不大。以我的機器為例,執行自帶的CIFAR demo,i7 CPU和GTX 1080 Ti的速度分別是770 pics/s和2200 pics/s。GPU大概有不到三倍的效能優勢。所以,差距其實也沒多大。

這裡還有一個小竅門,就是想用CPU版本的Tensorflow,最好不要用pip下載的方式,而是自行編譯。因為在開發機上編譯時,它會自動開啟所有支援的加速指令集(SSE4.1/SSE4.2/AVX/AVX2/FMA),從而使CPU的運算大大加快。根據我們的測試,在開啟全部加速指令集的情況下,訓練速度大概會有30%的提升,而預測的速度大概能提升一倍。

當然,如果真想用一個複雜模型去處理實際的生產問題,模型的複雜度和資料量都不是CIFAR這樣的玩具資料集可以比擬的。如果用我們的一個生產模型來執行CIFAR資料集,其他引數和條件完全相同,它在i5/i7/960/GTX1080/GTX1080Ti下的速度分別是:

19/25/140/460/620(單位pics/s,越大越好)。這裡就能看出差距了,1080Ti大概是i7 CPU的25倍。而在模型上線使用(inference)時,GPU也會有10-20倍的效能優勢。模型越複雜,GPU的優勢越明顯。

綜合來看,如果僅僅是入門時期的學習,我建議先不用專門購買帶GPU的機器;而是先用你現有的機器,使用CPU版本,去學習框架和一些基礎。等到你對基礎已經掌握得比較紮實,那麼自然就會形成跑一些更復雜的模型和更“真實”的資料的想法,這時候再考慮買一塊GPU,以縮短訓練時間。

在選GPU時,我聽過一些朋友們推薦GTX1070×2這樣的選擇。理論上講,1070的效能大概能達到1080的75%,而價格只有1080的一半,從各個方面看,似乎都是雙1070更有優勢。然而不要忘記,雙卡的效能是不可能達到單卡的2倍的,在目前的Tensorflow上,大概只能達到1.5倍上下,算下來其實和1080單卡差不多。而雙顯示卡的主機板、電源與機箱散熱都需要做更多的考慮,從價效比上來看,未必真的划算。

不過,如果顯示卡預算剛好卡在5000-6000的檔位,雙1070也有它的優勢。比如,可以學習使用多顯示卡平行計算的用法,在不著急的時候可以用兩塊顯示卡同時跑兩個不同的任務,合併起來就相當於有了16G的視訊記憶體等等。考慮到這些因素,雙1070的確是最適合入門學習的選擇——如果買不起雙1080/雙TITAN的話(笑)。

如果你有打算用筆記本來作為主力學習用機,我的建議是:最好不要,除非你使用Linux的經驗很豐富,或是不打算用GPU加速。很多筆記本在安裝Liunx後會出現驅動方面的問題,而且使用GPU加速時的高熱量也會非常影響系統的穩定性。如果沒有很豐富的經驗,經常會在一個小問題上卡掉幾個小時寶貴的學習時間。

然後,要不要來試試第一個模型?

在Tenforflow安裝完成後,我們可以用這種方式來最快地把第一個CIFAR demo跑起來:

git clone https://github.com/tensorflow/models.git my_models cd my_models/tutorials/image/cifar10/ python cifar10_train.py

OK,只需幾分鐘來下載資料,我們就能看到我們的第一個“影象識別模型”正在訓練了。

訓練過程中我們可以看到log中在不斷地輸出loss資訊,但除了想要跟蹤loss之外,我們還希望看到當前訓練模型的識別準確率到底如何,這就不是cifar10_train.py這個指令碼能夠提供的了。我們還需要執行

python cifar10_eval.py

這個指令碼會不斷地驗證最近的檢查點的識別準確率。

如果使用GPU的話,就會發現訓練指令碼執行起來之後,所有的視訊記憶體都已被這個程序佔滿;再啟動驗證指令碼的話,就會報錯一大堆的記憶體不足(OOM),這是Tensorflow的機制決定的,它會預設佔據所有顯示卡的所有視訊記憶體,而不管自己是否真能用到那麼多。

解決這個問題的辦法也很簡單。

首先,我們可以指定Tensorflow使用哪幾塊顯示卡進行訓練。要做到這一點,可以在執行較本前,用命令列指定環境變數:

export CUDA_VISIBLE_DEVICES="0,2"

其中的“0,2”就是希望使用的GPU編號,從0開始,用逗號分隔開。
或者在程式碼中建立一個GPUOption,設定visible_device_list=‘0,2’,也能起到同樣的效果。

然後,我們還可以限制Tensorflow所用的視訊記憶體,使其動態增長而非一啟動就佔滿。方法和上面的類似,在程式碼中建立一個GPUOption,並設定allow_growth=True即可。

官方的CIFAR例程大概能達到86%的準確率,這個成績在現在來說可以算是比較差的,最新模型的準確率通常都在97%左右,即便不經仔細調參而隨意訓練也能輕鬆達到93%左右。大家可以嘗試修改cifar10.py中定義的模型,以得到更好的效果。

最後,也是最初在經歷過如此漫長、痛苦但也充滿樂趣的學習和實踐之後,你應該可以算是機器學習的一個業內人士了。但這並不意味這條道路已經走到了盡頭,恰恰相反,在完成這一切之後,你才剛剛踏出了機器學習從業生涯的第一步。

在目前這個階段,業內還處於演算法紅利期,新的演算法、新的模型層出不窮,僅僅在CV領域,每天就有二三十篇paper被髮布到arXiv上,每年的頂會頂刊收錄的成果都在大幅度重新整理上一年甚至上一個月的記錄。

打好基礎之後,跟蹤論文並復現、學習和思考,這樣的任務將成為你現階段的一項日常作業,如果你已經進入或是決定進入這個行業的話。因為稍有懈怠,便要面臨著被時代拋棄、跟不上節奏的情況。所以,到這一步,對於有些人來說是一個結束,而對另一些人來說,則才剛剛是開始。

這個時候,我們可以回過頭來重新問問自己前面那幾個問題:

“我真的已經想清楚,要踏足這個行業嗎?”
“我能夠付出比其他人更多的辛苦汗水,在這條路上堅定地走下去嗎?”
“在遭受了痛苦甚至打擊之後,我對機器學習的熱愛,仍然能夠維持我繼續前進嗎?”

這條路,我在走,很多人在走,那麼,你來嗎?


最後,再說一點題外話。

看到這裡的各位,一定很希望自己的深度學習路上,能有這樣一位具備成功轉型經驗的先行者來幫助自己趟坑。

智亮老師的想法也是一樣的,為了讓自身的實踐經驗能夠轉化成對大家真正有幫助的東西,他特地在CSDN學院開設了《人工智慧工程師》實訓班課程。

這是一項為期100天的趟坑實踐,目的是通過全程的實戰案例學習,能直接讓你從AI小白晉級為具備一年實踐經驗的人工智慧工程師。

課程內容包括機器學習和深度學習需要掌握的知識和系統圖譜,每節課都配有實戰案例,並提供GPU雲實驗平臺進行案例實操,將理論知識與實際案例應用相結合,反覆鞏固,力助你成為一名合格的AI工程師。

在這三個階段的學習中,你將掌握機器學習原理和推薦系統的實現、深度學習入門與影象語義分割及寫詩機器人的部署,還有專屬GPU雲平臺上的四大工業級實戰專案,全程實操大量工業級真實資料。

同時,會有專人來跟蹤你的學習進度,並根據你的數學和程式設計基礎來制定專屬學習計劃,保證不掉隊。兩位大咖講師在計算機視覺的產業界和學術界分別都有著深厚的經驗,產、學、研結合緊密。

學成之日,還會有來自AI產業界的專業講師來做就業指導,甚至有可能直接推薦就業並全額返還學費。

歡迎踏上這趟人工智慧工程師的直通車,掃碼聯絡小助手,成功轉型的經驗正在向你招手。

備註:人工智慧

這裡寫圖片描述

點選圖片進入課程詳情,檢視學習路線和課程大綱

這裡寫圖片描述