COS訪談第十八期:陳天奇
【COS編輯部按】 受訪者:陳天奇 采訪者:何通 編輯:王小寧
簡介:陳天奇,華盛頓大學計算機系博士生,研究方向為大規模機器學習。他曾獲得KDD CUP 2012 Track 1第一名,並開發了SVDFeature,XGBoost,cxxnet等著名機器學習工具,是Distributed (Deep) Machine Learning Common的發起人之一。
何:你的本科在上海交大的ACM班就讀,是怎么開始做機器學習研究的呢?
陳:我們當時的培養計划里面有一項,就是希望我們盡早地接觸學術研究。於是我們在大二暑假就要開始進實驗室了,在大三的暑假去微軟亞研(MSRA)實習,於是我大二暑假去的是俞勇老師的實驗室,當時戴文淵學長也在交大做遷移學習這一塊的研究,所以我就跟着他了,也就是這個時候開始接觸的機器學習。不過后面其實換了很多方向,因為戴文淵其實帶了我半個學期就畢業了。后來我到微軟實習做的是和廣告相關的東西。之后實驗室的一位老師建議我的畢設做深度學習。當時是2010年吧,深度學習還沒有完全火起來的時候,整體的趨勢是大家都在做無監督學習。當時實驗室正好有一塊比較老的顯卡,我就開始寫一些CUDA的程序。從畢設一直到研究生一年級我一直都在做無監督深度學習,也嘗試過ImageNet,但是沒有得到很好的結果。后來正好有KDD Cup這個機會,之后我們就逐漸往推薦系統的方向做了,因為2011和2012年的題目以推薦系統為主。
何:你在剛接觸深度學習的時候就開始寫CUDA程序,是一開始就想寫機器學習里面的各種工具了嗎?
陳:一開始我們在CUDA上面寫的是Restricted Boltzmann Machine(RBM),后來這一套代碼和其中的思想就逐漸演化成為現在的mshadow和cxxnet了。這個項目本身沒有特別成功,但是有一套思想保留了下來,就是寫機器學習代碼應該以矩陣運算為主,而不是一味的寫for循環,哪怕你是一個C++程序員(笑)。一開始在做這個項目的時候我是一個追求性能的C++程序員,就是我會用inline去優化所有東西,但是后來發現代碼很不可讀。接着我就把代碼重構了一遍,把矩陣運算的相關部分抽了出來。不過當時對Expression Template不太熟,於是我就寫了一套類似的機制,但是沒有現在的mshadow那么成熟。當時我們做了一個系統,相當於現在mshadow的雛形,可以去做一些矩陣的操作,並且在GPU上面跑。后來我寒假的時候到愛爾蘭交換,當時他們在做KDD Cup,正好RBM也可以用到推薦系統當中,於是我就想嘗試一下,結果最后效果不是特別好。不過有了這次嘗試之后,我在研一時也決定和實驗室的幾個同學參加KDD Cup 2011。當時我們就想到可以做一些基於特征的矩陣分解,就是factorization machine這一套,當時我們就開發了一個工具,不過並不完善。后來結合我們在深度學習上面的經驗,就做出了SVDFeature。KDD Cup是一個比較大的平台,我們希望能做一個比較強大的工具,從而嘗試各種各樣的想法。而且當時還有一些比較苛刻的要求:比如我們實驗室的Hadoop機器是32位的(笑),每台機器是4核8G的內存,我們如果想用機器去做分布式調參,那么每個模型只能用2G的內存。在這樣的環境下,我們必須在SVDFeature中增加外存計算(編者:將數據儲存在硬盤上,每次讀入適量數據進入內存的方法)的功能,這也是我真正意義上的第一個外存計算的項目。
何:一般來說,我們做一個工具的時候不會在一開始就去考慮增加外存計算的功能。
陳:是的,不過當時是我們的確需要,而且實現起來並不困難,因為矩陣分解本身就是一個在線的算法。我們的SVDFeature使用了之前的矩陣運算代碼,這個工具我自己整個研究生生涯都在使用。這讓我認識到非常重要的一點:寫的代碼要清楚,要寫矩陣運算的代碼,要用內聯和模板去優化這個代碼,而且后來我發現用矩陣運算的代碼比我自己另寫的代碼在編程速度和運行速度上反而都要快一點(笑)。SVDFeature是一個非常Hacky的項目,我們要能定制推薦系統中各種各樣我們能想到的模型,比如可以添加用戶特征,物品特征,全局特征,我們還實現了特殊的數據結構把數據安裝用戶分組從而提高效率。這個東西很高效,到現在還有人在使用。但是對用戶來說並不是特別好用,比如你需要知道並且能轉換出數據的正確輸入格式,然后再去SVDFeature里面寫一個很長的配置文件去讀它(笑)。我們作為開發者,用這個工具去參加了兩次KDD Cup,拿了第三名和第一名。我們組里面也有人用這個工具做研究,發了一些比較好的文章。所以它的自定義性很強大,適合用來做研究。我們在第二次比賽之前就開始往SVDFeature里加Gradient Boosting算法,所以可以說XGBoost的前身出現在了SVDFeature里。
何:你們拿KDD Cup第一名的比賽用的是12年的騰訊微博數據?
陳:對,那次比賽的題目是預測騰訊微博里的關注請求,提供的信息有社交網絡的信息,以及用戶的一些個人信息。因為我們有SVDFeature,所以就先拿來做了一遍矩陣分解。但是后來發現一些連續的信息用矩陣分解來處理並不是最好的,比如用戶的年齡以及發微博次數等變量。於是我們就想通過樹模型來利用這樣的信息,所以最后我們的模型是矩陣分解和樹模型的一個疊加:在矩陣分解的結果上用樹模型進行優化,所以我們在SVDFeature里加上了樹模型。 當時是每個人都有一個樹模型,然后每個物品都會通過這棵樹進行分類。后來我第一個發到ICML的工作就是在此基礎上的一個擴展,就是把每個物品通過矩陣分解進行分類,然后然后在每個類別里面構建一棵樹就行了。這篇文章是我在華為實習的時候與李航老師和楊強老師合作的。
何:你剛剛也提到了工具會對研究有幫助,對么?
陳:其實我做工具的目的就是希望它能對我的研究有幫助。我還有一篇論文是條件隨機場和樹模型的結合。所以你可以看到我需要有這么一個建立樹模型的工具。做XGBoost的原因是做實驗的時候發現效率太低了,因為原來SVDFeature里面的模型是單線程的。我在快從交大畢業時做的一個項目里接觸到了OpenMP,發現非常好用。所以我發現目前為止最適合寫多線程的語言不是Python不是Java,反而是有了OpenMP的C++。至少機器學習里的很多算法直接用它就可以解決了。於是我就想能不能利用它寫一個多線程的GBDT(Gradient Boosting Decision Trees)幫助我做研究。我給這個工具起名extreme gradient boosting,因為我自己比較喜歡把一件事情推到極限,就像當初開發SVDFeature時我們要利用2G內存訓練一個模型一樣。我剛到華盛頓大學的時候就在業余時間開始寫XGBoost,它的第一個版本是在14年的寒假做出來的。之后我做了一些比較,發現效率挺高的,就發布了出來,不過當時是沒有python接口的,只有C++接口。因為我那時的習慣仍然是類似於SVDFeature一樣有非常高的自定義性,從而支持我的研究。之后我對第一個版本做了一次代碼重構,正好碰上Kaggle的希格斯子競賽開始,第二天我就拿去跑了一遍,拿了當時排行榜的第一(笑)。之后許斌問我是不是可以把這個作為benchmark公開,並且建議我做一個python的接口。
何:python和R涵蓋了幾乎所有kaggle用戶的選擇。
陳:是的,於是我就去學習了一下python里一個叫做ctypes的功能,它可以直接調用C的代碼,於是我花了兩天時間寫了一個python的接口,並在比賽的論壇里發布了出來。到這時我開始改變了自己的想法:因為你不能讓用戶為了使用一個C++程序而去寫非常復雜的配置文件,只能盡讓他們設置最關鍵的參數。這個工具發布到了論壇之后,就有越來越多的人來使用,python接口也越來越完善。到最后我發現我自己都不願意去用C++接口了(笑)。在希格斯子比賽的時候,許斌還以這個工具拿了另一個比賽的第四名。那個暑假我去graphlab實習,於是我就把XGBoost放進了graphlab里面,就是它里面的BoostedTreesClassifier模型。后來我又對代碼進行了第二次設計上的重構,把單個的樹模型和對樹的控制分得很清楚,在這個版本的基礎上我又覺得應該加上R的接口(笑),因為似乎很多人也想用R。於是我就學習了怎么在R里調用C,並做了個比較簡單的R的腳本。接下來就找了你做這個XGBoost的R包。這個過程我覺得和做SVDFeature有一個非常大的差別:以前我認為一個工具基本能用就可以了,需要最大化自定義性來方便研究,而作為一個用戶我反而應該着重於它的易用性,讓用戶調控最少的參數,讓他們能更方便地使用這個工具。所以我也在開始想把SVDFeature也做一個這樣的工具出來,不過未來可能會有我的一位合作者來完成這件事。
何:這是你在XGBoost基本成型之后的下一個計划嗎?
陳:這應該算是dmlc的一個組件,但是我不會主要負責它的開發。因為每個人都會有自己感興趣的方面,我研究生階段着重於矩陣分解這方面的研究,然后接下來我想去做一些我不會的東西,而且我的這位合作者應該是這個項目比較合適的人選。
何:因為我參與了XGBoost的開發,所以我也了解你平時花在上面的時間很多,那么你是怎么平衡開發工具與做研究的時間的呢?
陳:我的這些工具最終都會用到研究里面。因為我的研究方向是大規模機器學習,所以最近我的一部分精力放到了dmlc的核心組件上,比如分布式文件讀寫,分布式的調度等項目。很多這些項目都是做分布式機器學習和系統研究的先決條件,這些項目包括XGBoost最后都會運用我的研究當中。
何:所以花時間打磨這些工具對你的研究是有幫助的。
陳:對的,不過這取決於研究的方向,比如我願意去探究如何將boosted tree應用在大規模數據集上。的確,我在寫這些工具上也花了一些時間,特別是在即將發布重要版本更新的時候:在發布python和R接口時,XGBoost逐漸成型;分布式版本發布后,XGBoost能支持各種各樣比較好的平台,這也和我的研究方向有關,現在它的分布式版本用到rabit庫就是我在做的另一個項目。分布式機器學習也需要有一些基礎的庫來支撐:文件讀入,通信等。在做這些項目的時候,我也會去思考怎么划分整個系統,哪些部分放到通信里,哪些部分放到模型里,這些思考也會有幫助。我也不會把所有的時間都投入進去,因為每年我會選很多的課,也要有上課的時間,所以就是每周花晚上的時間來做這些工具。
何:是每天晚上吧?
陳:有時候是每天晚上(笑)。花時間不少,但是我覺得做的事情還是很有趣的。其實去年我做的三個主要項目是mshadow,XGBoost和cxxnet。而mshadow和cxxnet是綁在一起的,大部分的雛形都是在去年暑假之前就做好了的,中間經歷了幾次比較大的重構。cxxnet和XGBoost是差不多同時發布的,不過我們最近拿它的2.0版本拿了個kaggle圖像識別比賽的第二名。因為我以前嘗試過深度學習但是沒有出什么成果,有點遺憾,所以想再去試一試,就做出來了cxxnet。這里面比較有意思的成果是mshadow庫,里面用到了很多c++的優化技術,使得你去控制你的資源,並且能夠高效的計算。cxxnet以后也可能慢慢發展為一個比較好的深度學習庫。我們也開始考慮做一些對用戶友好的R或python的接口,現在已經有了python的接口但是還不夠友好。其實dmlc里面有兩個深度學習的項目,一個是cxxnet,一個是minerva。后面我們希望能夠將這兩個項目合在一起,做出一個比較簡潔又比較高效的工具。
何:你經常會拿自己做的工具來參加比賽,那么這屬於你試驗自己工具的一種手段嗎?
陳:算是吧,比如第一次在希格斯子比賽上拿出來遛遛,就是試驗工具的一種手段。不過最近我基本不參加比賽了,因為參加比賽還是比較花時間的(笑)。上次cxxnet的比賽我其實沒有花很多時間參與在里面,不過這次也是為了測試它的極限在哪,因為有一個東西總想拿出來跑一跑。有時候也不需要刷成績,比如Michael寫的那個變量重要性的功能,我覺得也很有意思,能讓你對數據有更深刻的了解,可能比你直接把一個分數調到很高更有意義。
之后我會逐漸將精力往研究上靠,工具里面也許會出現一些我的研究課題,可能會有一些新功能但是不一定起效果(笑)。不過目前來看分布式訓練等功能還是很有用的。
何:那么你覺得現在的XGBoost是在一個比較成熟的階段了么?
陳:我覺得相對來說它確實到了一個比較成熟的階段了,可以說該有的東西基本都有了。未來需要完善的功能應該是外存計算,這是最近剛加進去的功能。其實出現這個功能的原因也是很直接的:我當時在20台機器上面跑400G的數據做分布式XGBoost實驗,於是每台機器就要分20G的原始數據,這些數據在內存里做一些數據結構的處理,可能就需要60G的內存,這就已經塞不下了。所以又想到了外部存儲這個解決方法,加入了這個功能。
何:所以這和你SVDFeature碰到的瓶頸一模一樣,殊途同歸呀。
陳:是啊,都是一樣的。開發工具總會在某個階段碰到各種各樣的問題,所以這也是為什么我希望把一個工具做到極限。即使內存這樣的資源很大,也會出現類似的問題。隨着計算架構的復雜,我們可以通過GPU來讀本地緩存,那么這時候本地緩存就相當於一個只有100K的內存,所以這時候你還是要很小心地優化。所以我在dmlc里,更希望能夠抽象出一些通用的庫,讓每個項目都可以共享。比如dmlc有一個稀疏矩陣的外存計算功能,比如你做矩陣分解的在線學習,直接用這個庫就可以了,用的時候感覺不到這是外存計算,因為后端已經幫你做好了。另一個方面是線程流水線,比如你在處理HDFS數據的時候會用一個線程讀數據,另一個線程做計算,上一塊數據計算完成之后這個線程可以直接在一個緩沖區中用之前讀好了的數據。所以這樣的流水線讓計算線程不需要考慮讀取數據的問題。我們實現了這樣的庫,就能夠讓其他的工具設計起來更方便。第三個方面是文件的讀寫,我們在dmlc里面實現了這樣的一個庫,比如現在XGBoost能直接讀寫hdfs等文件系統,在分布式系統上的配置就方便。我們就希望總結出機器學習中這些通用的組件,然后將它們放在dmlc-core里,最后會讓所有的其他庫受益。
何:所以你現在更希望先把這些通用的組件開發出來,再在這上面開發新的工具?
陳:其實時間順序是反過來的,我們一般沒法在一開始就能把抽象的結構給總結出來。因為我們同時開發了XGBoost,cxxnet,以及之后還有開發矩陣分解工具的需求,當我們發現了這些工具中有共同的需求之后,再將它們給抽象出來。現在dmlc里面的東西都是為了這些工具服務,做分布式工具畢竟繞不開這些需求。
何:你之前在開發SVDFeature時着重於可塑,而到了開發XGBoost時則轉變為重視易用性。那么未來的dmlc工具還會繼續堅持易用性么?
陳:我覺得易用性是一定要保持的,而且易用性和可塑性在比較好的設計下也不是矛盾的。可能為了可塑性和效率會做一些很復雜的設計,這時候為了易用性就需要這個接口非常干凈,這不是很容易的事情,不過我們至少要保證dmlc里面的工具有通用的配置文件這樣互相調用就很方便。我希望保持易用性,這樣才會有用戶來使用。
何:寫工具的目的也是希望有別的用戶來用。
陳:對的,我最后也會去用比較易用的接口(笑)。我本來的想法是我不需要用python或者R,我只需要用c++讀一個配置文件就行了,結果后來我也去用python了。
何:我之前也用XGBoost的python接口,自從寫了R包之后就再也沒用過python接口了(笑)。
陳:大家都比較懶嘛,而且這樣的偷懶挺好的。
何:那么現在你覺得dmlc的這一系列工具在機器學習圈里屬於什么樣的水平呢?因為現在開源工具越來越多了。
陳:我喜歡做的一件事情是把一個工具推到極限。需要能懂系統設計的東西,也要懂機器學習的知識。我現在希望能把這些系統方面的知識抽象成標准庫,然后讓別人用的時候不需要了解系統級別的知識也能得到很好的優化。我們現在已經做了一些這樣的事情,在這方面應該比現有的一些機器學習工具有一定的優勢。然后在易用性方面反而是要向其他工具多多學習的,比如R里面的caret包,mlr包,以及python的scikit-learn。sklearn的接口看上去比XGBoost的更友好一些,不過XGBoost現在也支持從sklearn中調用了,這是最近有人加上去的,因為他們想用sklearn嘛,他們覺得sklearn的接口更方便一點。我現在更關心易用性,而一部分合作者可能會更希望在性能方面下功夫。另一個有優勢的地方是dmlc對分布式的支持,我們希望能夠在單機上把一個工具做到最好,然后開發分布式的版本。不過一個比較成熟的模型可能會直接開發分布式的版本。這和我的研究興趣也相關,我希望探索一個工具在分布式環境下的表現能有多好,以及接口能做到多么易用。
何:你現在如何看待學術界與工業界中的機器學習研究與應用?
陳:因為我沒有在工業界呆過,所以不太好評價這個問題(笑)。不過工業界有很多好的機會,包括非常豐富的數據資源。不過相對而言學術界的研究方向更自由。所以我認為很重要的一點是如何將學術界的研究成果很快地應用到工業界,並逐漸發展起來。比如當前的深度學習就是一個例子,XGBoost里面也用了一些新的技術。再比如矩陣分解,word2vec,他們都首先是學術界的成果。所以我們希望dmlc能作為一個橋梁,作為一個社區吸引更多有興趣的人為此做貢獻。這樣這些工具能夠比較快地在工業界常用的平台上應用,並且發展起來。
何:如果你未來去工業界工作,那么什么樣的工作方向滿足你的期許?
陳:我覺得設計一個新系統是個很有意思的事情,或者是不斷地去做一些不一樣的事情。人很多時候會陷入一個舒適區(comfort zone)里,比如我們做完SVDFeature之后其實可以考慮用它來發一堆論文,因為在這個領域有積累就會傾向於在這方面做下去。但是至少在讀PhD或者未來更長的時間里,需要有機會來做一些不會做的事情。比如當初我們在SVDFeature上加入樹模型,其實就是一個探索的過程。等XGBoost成熟之后,或許我也不會永遠做樹模型,可以去做一些其他的模型。就是盡量不要讓自己陷入舒適區里,嘗試一些自己以前不能夠做的事情。
何:所以只要做的內容夠有吸引力,在工業界或者學術界中工作對你來說並沒有那么重要?
陳:其實他們還是有一些不一樣的。在公司里會更關心業務,在學術界也會受到基金等因素的制約。我覺得總的來說,如果我能預測明年我在做什么事情,那就沒有意思了(笑)。比如我剛開始做XGBoost的時候就沒法預料到它會發展成今天這個樣子,至少從工具的角度而言它比SVDFeature要成功很多。當然在整個過程中你是不斷積累的,在XGBoost里面也有SVDFeature甚至更早的深度學習代碼中的影子,這些經驗會慢慢地體現在你的項目里。
何:你覺得dmlc以后會發展成像graphlab一樣的工具集合么?
陳:我覺得應該不會。我覺得dmlc更像一個組成各個機器學習工具的組件集合。因為我們的初衷很簡單,就是把每個人項目里面要做的事情抽出來減少工作量,比如參數服務器和分布式模型都需要做文件的讀寫。你會發現寫C++的人很有意思,大家都認為自己是Hacker,喜歡從頭開始造輪子(笑)。但是有時候這樣並不好,一個人再強,他的精力也是有限的,不可能做到所有的東西。所以我們現在可以拿出更多的時間來做和自己的研究相關的工作。從更大的方面來說,既然C++有這么多hacker,是不是可以把大家聚集起來做一些更有意思的事情呢?所以我覺得它不會成為特別商業的東西。而且我們未來也會和包括Dato等公司有合作,他們現在也在用一些比如XGBoost和cxxnet等dmlc里面的工具。Graphlab有很多很獨到的東西,比如它的data.frame是目前為止唯一一個利用外存計算把單機性能推到極致的dataframe產品,還有他們的機器學習流水線和很不錯。我們的重點應該是把我們擅長的工具做到極限,完成各個核心組件,然后讓它們和已有的其他工具和平台更好地整合。