1. 程式人生 > >程式設計師如何開啟機器學習之路

程式設計師如何開啟機器學習之路

我曾是一名想進入AI行業的軟體開發者。為了更快熟悉這裡邊的門道,我閱讀了機器學習的書籍,瀏覽了不少帖子,還學習了Coursera上關於機器學習的課程。

但是,但是,依然不知道如何開始……

你是否也有這樣的經歷呢?

很多開發者都問我:我該如何開始學習機器學習?

記不清有多少人問過這個問題了。鑑於此,我專門寫了一篇文章來解答大家的疑惑。通過本文,你會知道:

為什麼傳統的教學方法不管用? 
如何把傳統的教授機器學習方法的框架顛倒過來。

此外,我還會跟你分享我在學習機器學習方面積累的經驗。

進入正題:

做過各種嘗試,但依然無從下手

根據我以往的經歷,我可以想象得出你做過哪些嘗試,比如海淘各種部落格帖子,學習斯坦福大學的機器學習公開課,嘗試深入理解機器學習的相關概念和模型,嘗試處理一些小資料集,不過依然會覺得不得其門而入。

做過各種嘗試,但依然無從下手

在我看來,問題在於你還沒有將從課本和視訊中學習的理論、演算法和數學形成一個知識體系。

在真實工作場景中加深理解

假設你已經掌握了很多個分散的知識點,那麼要考慮將其形成一個體系,最好的辦法是在真實的場景中思考這些知識。比如下邊列舉的幾個場景:

場景1:一次性模型

某天你的老闆跟你說:小李啊,你懂機器學習嗎?你能不能使用去年的客戶資料來預測一下在我們銷售渠道中哪些客戶有可能繼續跟我們續約?

我把這種情況稱之為一次性模型。

問題由你的老闆來提出。他給的資料非常小,甚至可以在微軟Excel中開啟。但他卻需要精確並且穩定的預測。你可以交付,你還可以對最終結果進行相關補充說明。

場景2:嵌入式模型

你和你的團隊對甲方軟體專案進行需求收集。你瞭解到解決某個問題最好(或者唯一切實可行)的方法是設計並訓練一個預測模型,並把它嵌入到你們的軟體產品中。

我把這種情況稱之為嵌入式模型。

這當中還有一些變體(比如這個模型是固定的呢,還是以後會自動定期更新?是在本地執行呢?還是通過API遠端訪問?),但這些都是隻是細節而已。

這個場景中的重點是你具有的經驗:識別一個需求,它的最好解決方式是使用一個預測模型,並且你具備設計、訓練和部署這個模型的能力。

場景3:深度模型

你開始了一項新工作,工作的系統至少由一個預測模型組成。不管是維護系統,還是新增功能,都需要具備對這個模型的理解,它的輸入是什麼,輸出是什麼。

模型的預測精度是軟體產品非常重要的一個指標,而你的工作職責包括提升模型預測精度。比如,測試預釋出系統時,你展示的模型的準確度不能低於上個版本,或者要高於上個版本。

我把這種情況稱之為深度模型。

你需要建立對一個特定預測模型的深入理解,並且用你的經驗和技能來提升並且驗證它的準確度。

以上這三個場景都是我曾經經歷過的。

它讓一件事情非常明確——雖然機器學習是非常吸引人的一個領域,但對一個軟體開發者來說,機器學習只是另外一堆技巧,就像多執行緒程式設計或者3D圖形程式設計。然而,機器學習是針對特定類別的問題進行設計的。

傳統方法如何開啟機器學習之路

找幾本機器學習相關的書,你會發現這些書往往從基本的定義開始,然後是相關的數學公式闡述,最後是非常複雜的演算法。

傳統的解答是自下而上的

基本概念的定義和數學理論的表述都是非常清楚、簡潔並且絕不模稜兩可的。但是,它們非常枯、無聊,並且需要具備一定的數學背景來分析和理解。

這也是大學將機器學習放在研究生課程中的原因?因為教授機器學習的基本原理需要具備多年基礎積累。

比如,它建議你具備如下基礎: 
統計 
概率 
線性代數 
多元變數統計 
微積分

如果你誤入了某些奇怪的、有趣的演算法,那你的機器學習之路將會更糟糕。

這個學習機器學習的自下而上和基於演算法的方法無處不在。

MOOCs和YouTube上的線上課程也是仿效大學的方式來教授機器學習,如果你具備相關基礎或者你已經投入了大量的時間來學習這些高階課程,這沒什麼問題。但是,這對於大多數的軟體開發者並不管用。

如果你到Quora, StackExchange, Reddit這些網站求助如何開始機器學習,你大概會收到同樣的答覆。

難怪一些軟體開發者會不斷尋求正確的方法,但結果是不得不回到學校並獲得研究生或者博士學歷,只有這樣他們才覺得可以開始學習機器學習了。

仔細思考一下這個自下而上的機器學習學習方法。它非常縝密、也更系統化,聽起來沒什麼問題,但怎麼可能出錯呢?

為什麼傳統的學習方法是錯的?

假設你是一個年輕的軟體開發者。你已經或多或少學了一些程式語言。現在,你準備開始學習如何開發一個獨立的軟體。

你告訴你的朋友和家人,你希望以後你的工作是每天都在程式設計。但他們告訴你,在成為一名程式設計師之前,你需要一個電腦科學學位。

就這樣,你開始了計算機學位的學習。一學期又一學期,你在學習著難解的線性代數,微積分和離散數學。你使用著過時的程式語言。這些都在消磨著你對程式設計和軟體開發的熱情。

傳統的學習方法與成為一名實踐者之間有一個鴻溝

或許你成功的完成了學業,但回過頭才發現你並沒有學習到任何一個關於現代軟體開發的技能、語言、工具,或者其它任何你能夠用來開發軟體的知識。

看到過與教授機器學習類似的案例嗎?

幸運的是,程式設計已經具有很長的歷史了,我們已經找到了正確的方式來教授年輕程式設計師相關的技能。

對於一個正在學習的程式設計師,沒有必要讓他學習計算理論或者計算複雜度理論,或者演算法和資料結構的細枝末節。這些知識(演算法複雜度和資料結構的細節內容)可以晚點再學。或許應該關注一些特定組合的工具,站在一個從事程式設計工作且能夠交付軟體的工程師的角度來看這件事。

如果一個軟體開發者想要進行機器學習,他們真的有必要花費多年的時間和大量的金錢去獲得數學和更高的學位嗎?

答案肯定是否定的!還有更好的方式。

以正確的姿勢開始機器學習

像電腦科學課程從來沒有關注實踐中需要的開發和交付軟體的技能一樣,機器學習課程和書籍也同樣有這樣的缺點。

對於機器學習,你需要自上而下的學習方法。這個方法更關注結果:採用最佳的工具組合和平臺,解決真實的機器學習問題。

自上而下學習機器學習

以下是我推崇的學習方法:

1.通過系統化流程迭代結果

一旦你會使用工具,那麼通過機器學習演算法解決問題就相對容易了,你稱之為“完美”。

這就非常危險了。

你怎麼知道你已經完美解決問題了呢?你怎麼知道這個結果是最好的?你怎麼就知道這個結果在這個資料集上面是可靠的?

使用機器學習解決相關問題時,你需要系統化。這是一個專案,和軟體開發一樣,通過良好的處理可以獲得高質量的結果,通過不斷地迭代得到進一步提升。

仔細思考這樣一個系統的流程,你可以想到一些明確的要求,比如:

一個系統的流程可以帶你貫穿始終,從特定的問題到結果的呈現或者部署。與軟體開發專案一樣,你可能認為你已經完成了,但是你很可能沒有。 
一個系統的流程可以帶著你一步一步地完成你的任務,這樣你就明確地知道下一步該做什麼。不知道下一步該做什麼簡直就是專案的剋星。 
一個系統的流程可以保證良好的結果,也就是說這個結果會比一般的好,或者遠超專案的需求。在專案中經常要求提交有一定可靠度的結果,而並不一定是那個最好準確度的結果。 
一個系統的流程不拘泥於特定的工具、程式語言、演算法模型。使用的工具在不斷更新,因此這個流程必須具備適應性。考慮到學界對於演算法的追求,時常會出現新的,更好的演算法。

選擇一個系統的、可迭代的流程,從而可以不斷地提升你所交付的結果。

有非常多的高質量的系統流程,包括一些比較老的系統流程,你都可以稍加調整使之能夠滿足你的要求。

2.為你的系統流程選擇最佳的工具組合

機器學習的工具和庫在不斷地更新迭代,但在任何時候你都得選擇與所選系統流程最適合的工具組合。

你不用驗證和選擇任何老的演算法或者庫,你需要所謂的最好組合,它可以給你快速的、可靠的、高質量的結果,並且能夠儘可能地自動進行。

但是,你得根據自己的需要選擇工具組合。

比如,對於以上三種場景,我建議使用的工具組合如下所示:

一次性模型:使用Weka平臺,可以在很短的時間載入CSV,設計一個實驗,並獲得最好的模型,並且幾乎不用程式設計(請參考我對這流程的整理)。 
嵌入式預測模型:通過python使用Scikit-learn庫,我可以使用同樣的語言來開發模型。IPython是一個非常好的方式,可以向團隊展示你的模型執行情況。MLaaS對於大資料而言是個很好的選擇。 
深度模型:R語言,在R平臺上,我可以快速並且自動地嘗試很多最高水平的模型。

實際上,這三種情況下的三種工具組合也要依賴於特定的應用場景。

和軟體開發一樣,你需要學習如何使用這些工具,從而可以最大程度地利用它們。此外,你也需要隨時關注業界的發展,並且使用更好的工具。當更好的工具釋出後,你可以不斷調整工具來適應你那個系統流程。

1.有選擇性地開放你的專案

軟體開發技能是通過開發大量軟體產品得到的。對於機器學習,你可以使用類似的方法。

2.仔細選擇練習資料集

你最好選擇一個真實的資料集,而不是人為杜撰的資料集。現在外面有大量的各種複雜度的資料集合。

我建議從一些小的資料集開始,可以從UCI機器學習庫中獲得。它們都非常有名,相對簡潔,適合新手學習使用機器學習算法系統流程和相關工具。

之後,非常推薦使用一些更大的資料集,比如Kaggle和KDD比賽提供的資料集。它們相對會有點亂,要求使用更多不同的技能。

3.堅持使用表列資料,這是我對所有學生的建議。

處理影象和文字資料(分別是計算機視覺和自然語言處理)是一個新興且不同的領域。它們會要求你使用該領域裡面特定的某些方法和工具。如果你是想處理這型別的資料,那麼你最好從那裡開始。

在另外一篇部落格中,我對於如何把練習做成開放式作品集進行了詳細的闡述。“如何練習機器學習演算法,從UCI機器學習資料庫的小資料開始”

4.記錄結果,並建立公開專案集

在一個單獨的檔案中記錄你做了什麼,學到了什麼。以便於你在其他專案中作參考。

這類似於軟體開發者經常把每一個軟體專案放在一個資料夾中一樣,並使用以前工程中的程式碼和想法。這可以很大程度上加快研發速度,強烈地推薦這種方式。

整理好你的筆記、程式碼和生成的圖片,但寫下你的發現也是非常重要的。把這想成是對你程式碼的註釋。一個獨立的文件可以是一個簡單的PPT或者文字檔案,也可以製作得像演講那種那麼精緻,或者像YouTube上面的視訊一樣好。

把每一個專案都提交到一個公開的版本管理庫中(比如Github),這樣其它新手就可以學習你的經驗,並進行一定的拓展。可以把專案連結放在你的部落格,LinkedIn或者以其它任何公開的形式來展示你的精湛技能和能力。

關於這個想法更多的資訊請參考我的另一篇部落格“建立一個機器學習公開專案集:專注於完成一些小的專案並展現你的相關技能”

對於開發者來說,在Github上釋出和維護專案已經成為簡歷中必不可少的一部分,尤其是特別關注技能和專案經驗的公司。

以上是為軟體開發者定製的學習方法,對於以上學習方法,你可以將其應用在機器學習領域。

學習機器學習,以上就夠了嗎?

不過,你也會有疑問。比如作為一個初學者,我需不需要寫程式碼,是不是要求數學特別好,需不需要更高的學歷,是否需要學習大資料相關的知識等。

哈,彆著急,我們一個一個說。

1.需要寫大量程式碼?

不一定。

你可能是一個網頁開發者或者其它領域,你不用寫很多程式碼。你可以使用這個方法來開始學習和使用機器學習。像Weka這樣的工具,使得設計機器學習實驗和建立模型變的非常簡單,甚至於完全不需要什麼程式設計。

能寫程式碼方便你使用更多不同的工具,但這並不是必須的,而且也不是必須先學習的。

2.要精通數學嗎?

不必。

就像軟體開發一樣,你不必非得了解像計算複雜度或者big O這樣的概念過後才能寫程式碼,才能交付有用並且可靠的軟體產品,你可以從事機器學習方面的工作,不需要有統計學,概率論和線性代數相關的背景。

雖然我們並不是從理論學習開始,但是並不忽略它。當需要某個演算法時,深入學習並理解相關方法或者演算法就非常重要了。你會主動學習數學相關的知識,因為在追求更好的結果和更精確的預測時,你會盡可能地去查詢資料,學習到足夠多知識來解決你現有的問題。

如果你的目標是掌握理論,這個方法就會更慢,並且不是那麼有效。但是,對一個致力於要從事機器學習工作的軟體開發者而言,這個方法是行之有效的。

3.我需要一個更高的學位嗎?

不需要。

當前網路這麼發達,你可以輕鬆獲得機器學習相關的知識,如非必要,不用花大量時間和金錢來獲取更高的學位。

推薦你在思考獲得更高學位之前,先想下一個實實在在的機器學習問題,並通過一段時間了來詳細瞭解和構建一個專案,再去想是否真的需要一個更高的學歷,這樣你對這個領域也會理解的更加清晰。

對於我本人來說,我是考到了更高的學位,我喜歡做研究,但我也喜歡解決實際的問題,客戶對我的方案也比較滿意。不過我是從事機器學習工作一段時間後才去考了更高的學位。我都沒意識到我已經掌握了相關資源和學習方法。

這也是我想說服你開始機器學習的原因,其實你已經具備一定的基礎了

4.需要從大資料開始嗎?

不需要。

機器學習演算法的學習和理解最好通過從小的資料開始。小到可以使用微軟的Excel軟體開啟,可以載入到記憶體中,或者可以在你的工作站中執行。

大資料!=機器學習。你可以使用大資料構建一個預測模型,但是,這僅僅是你所擁有的技能在特定領域的特定表現。我一般建議我的學生在開始學習機器學習的時候,使用小的資料開始。

如果你學習機器學習是為了處理大資料,那麼就從大資料開始吧。

5.我必須有一個高配電腦嗎?

不需要。

確實,現在一些最高水平的演算法,比如,深度學習,需要數以千萬的計算單元,多個GPU協同工作。但是,這些演算法依然可以用來解決一些比較小的問題,而這樣的計算量是你當前電腦CPU就可以承受的。

你不必因為接觸不到高效能的計算機而在機器學習上停滯不前。

在你準備購買一臺高效能運算機或者租用一臺非常大的EC2虛擬雲伺服器之前,花點時間學習如何儘可能地利用現有的演算法,在較小且容易理解的資料上。

6.新手是不是需要花費大量時間

正如我之前所說,從事機器學習演算法工作會讓人上癮。如果你參加了一個機器學習的演算法比賽,你會很樂意犧牲一個月晚上看電視的時間來提升演算法的準確度。

也就是說,如果你開始學習時,使用著清晰的系統流程和最佳的工具組合,那可能會耗費一個或者兩個小時,也可能是一個或者兩個晚上。

你可以把任務拆分成多個小任務,把它們都貼在看板上面逐個解決。

開發者容易犯哪些明顯的錯誤, 
如何避免?

1.不採取行動

所有的一切都安排好了,但是,我依然看到一些軟體開發者並不採取行動。看電視或者新聞遠比苦坐建立一個新的模型和學習一個重要的技能容易。

2.選擇了一個太難的問題

我經常看到一些軟體開發者一開始就選擇了一個或者兩個非常難的資料集開始。那是非常大,非常複雜的資料集。然而,這些軟體開發者他們並不具備分析這些資料的能力。更可怕的是,這樣的挫敗將會抹殺掉他們的學習動力,以至於軟體開發者們都退出了原有的學習計劃。

選擇一個小的問題,最好你可以在60分鐘以內完成。堅持這樣訓練一段時間,再進行更大的挑戰。

3.不堅持既定的流程

參與了一個敏捷開發過程中,如果你從這個過程當中偏離了,這個過程就會很難進行,並且結果往往會很糟糕。堅持從一而終地完成敏捷流程,這是一個系統地解決問題的方法,是非常重要的。

你可能會在開發過程中發現一些“有趣的問題”,但是,一定要先完成既定的開發過程,並及時交付。

4.不懂得利用資源

對於機器學習,網上充斥著各種各樣的優質論文、書籍和大量的部落格。你可以利用這些資源來改善你的系統流程,使用工具的技能,和模型的準確度。使用第三方資源來獲取更多的演算法和資料集,深入理解演算法和問題框架,一個具創意的想法將會改變你專案的程序。記住,如果你是採用的自上而下的方式,那必須在收尾階段進行相關理論研究。花點時間來理解你最終的模型。

千萬不要犯以上這些錯誤。

下一步

我們已經討論了很多內容了,同時,我希望我已經說服了你,你可以開始並且不斷在機器學習中取得進展。在未來你作為一名軟體開發者,同時又懂機器學習演算法將會非常搶手。

你的下一步是: 
選擇一個設計和使用機器學習算法系統的流程 
選擇適合的工具和平臺 
選擇你的第一個資料集合 

小福利:下邊這個思維導圖總結了這個部落格中非常重要的一些概念。