“Spark上流式機器學習算法實現”終期檢查報告

    自6月底申請項目到現在9月初撰寫項目結題報告,眨眼一瞬間兩個半月很快成爲過去,在這兩個半月的時間裏,在不斷的看文章和調試代碼,首先我得感謝和我一起合作的賴百勝同學與我並肩作戰,是他給了我一次次戰勝bug的勇氣,是他讓我感覺到整個項目做下來而不覺得孤單。當然還要感謝intel中國研究院的尹老師,是他指導我們一步步由淺入深地學習spark程序設計,給我們指明研究的方向。最後,必須要感謝CSDN能提供此次實習機會,讓我們在暑假還能收穫這麼一段珍貴的實習經歷。經歷過這次開源實習後,我們團隊成員都深深的感受到開源項目的重要性和巨大的意義。

   下面我們通過三個部分來介紹整個項目執行過程中的情況並進行總結。

一、項目實施情況

   在這兩個半月的時間裏面,我們牢牢按照項目初期安排實施項目的工作。

1、項目背景

   Scala語言是近10年來逐漸發展起來的一種函數式的面嚮對象語言,語法類似於java,其良好的併發特性受到很多開發者的喜愛。另外目前國外的大型網站如Twitter,Amazon等也宣佈其後端程序都用的是Scala語言。可以說Scala語言有巨大的潛力等待着人們發掘。

   Spark是UCBerkeley開發的基於mapreduce算法實現的通用並行計算框架,其主要優點在於job的中間輸出結果可以保存在內存中,從而不一定需要讀寫HDFS,因而spark能更好地適用於數據挖掘與及機器學習等算法。

   Spark streaming是構建在spark上的一個處理流數據的框架,接收到的數據流分成小的時間片,以類似批量處理的方式來處理這部分的數據,非常適合與一些需要歷史數據和實時數據聯合分析的場合使用。

   MLlib是spark中常用的機器學習算法的實現庫,支持四種常見的機器學習問題:二元分類、迴歸、聚類以及協同過濾。但是spark自帶的機器學習算法都是基於已有的數據進行模型訓練然後對訓練的模型進行預測和評估。如果需要對新的訓練數據進行訓練, MLlib中的模型需要重新訓練,必將消耗很多的較多時間和CPU計算資源。

   隨着機器學習領域的發展,近些年來一些在線的機器學習算法也不斷涌現,這些在線的機器學習算法在能以較低的計算複雜度對模型中新進入的數據進行學習和改進模型,使得新得到的模型具有更高的預測準確性,在目前基於地理位置的帶有推薦功能的軟件(如大衆點評、淘點點等)中有巨大的應用。我們的項目也即基於這個背景出發,希望能改進MLlib庫中的現有的機器學習算法,使其能成爲在線的機器學習算法,爲開源社區做出一點貢獻。

2、熟悉scala和spark開發環境和編程語言

   俗話說的好“工欲善其事,必先利其器”。我們在接到項目後花了大約一週左右的時間搭建開發環境,併購置了由瑞士洛桑理工(EPFL)的Martin Odersky撰寫的scala語言的經典教科書《Programmingin Scala》。

   spark官方網站建議在linux平臺上運行spark程序,我們藉助scala和spark官方網站及其他一些網站的相關操作介紹在實驗室的linux服務器上搭建好可以運行spark程序的環境。詳見博文《基於linux的spark與scala開發環境搭建》和《基於spark運行scala程序》。在試着運行spark自帶的計算π和單詞統計的例程時候發現spark的獨特的基於內存的分佈式計算的特性,這個特性可以使程序的運行速度成倍的提高。爲了更好地理解spark底層工作原理,我們還學習了項目導師(尹老師)在小象學院開設的公開課《Spark上機器學習方法的模式與性能》,受益匪淺。

   另外,由於linux上一般是用命令行或者腳本進行操作,執行程序很方便並且效率高,但是寫程序顯得並不是那麼方便,我們在coursa上的《Functional ProgrammingPrinciples in Scala》課程中學習到了在windows環境下用scala-IDE這個平臺編輯代碼非常的好用,這個軟件是基於eclipse開發的scala語言的編程環境。我們只需要在scala-IDE中將scala代碼可以打包成jar文件,然後上傳到linux服務器上,然後就可以歡快地跑起來了,這樣編輯程序和運行程序兩不誤。

3、廣義線性線性模型的流式機器學習

   我們實現的基於sparkStreaming的廣義線性模型包含最小線性二乘、邏輯斯特迴歸、嶺迴歸和Lasso。

   假設每個數據爲a_i(i=1,2,…,n),所有數據按行排列成數據矩陣爲A,所有數據的觀測爲向量y,模型參數爲x,最小線性二乘的模型如下:

   邏輯斯特迴歸的模型如下:

   嶺迴歸的模型如下:

   λ是正則參數。

   上述三種模型中的目標優化函數都可以對x求梯度,因此可以直接用梯度下降法對它們進行求解。我們只需要求上述三種模型的梯度即可。其中最小線性二乘關於x的梯度爲:

   邏輯斯特迴歸模型關於x的梯度爲:

   嶺迴歸模型關於x的梯度爲:

   而對於Lasso,它的模型爲

   注意到正則項不能對x求梯度,所以不能直接用梯度下降法,爲了解決這個問題,我們參照spark中的方法,使用HuberFunction對正則項 進行逼近。HuberFunction的定義爲:

   使用HuberFunction替換L1項後,我們可以對目標優化函數求關於x的梯度,它是:

   其中:


   有了四種模型的目標優化函數關於求解變量x的梯度後,梯度下降更新模型參數x的方法是:


   其中,η是更新的步長。

   上述四種廣義線性模型還不是流式的學習算法,爲了用流式的數據對模型進行訓練,我們將上述提到的梯度下降法改爲隨機梯度下降法,即每次計算梯度只用當前數據進行計算。爲了減小調用函數的頻率,實際的實現中,我們使用一組(batch)數據進行梯度的計算,這一點和spark中的隨機梯度下降法也是一致的。

   我們利用sparkstreaming,從網絡端口或文件夾中讀取DStream的流式數據,先對數據進行解析,然後輸入模型進行流式訓練。

   我們使用上述模型在數據集breast-cancer-wisconsin(詳見我們的Code庫)上進行測試,其中共有700個數據,將其中560個數據用來流式地訓練,即每次只接收一個batch的數據,每次一個batch的數據進行訓練後,我們都對測試集上140個數據進行測試,計算其準確率,可以看到測試誤差會呈現下降的趨勢。以下是邏輯斯特迴歸的訓練結果:


   每個算法我們有兩種實現,第一種實現中,每個算法單獨使用,並且訓練過程是我們編寫的;第二種實現,我們藉助了spark中的非基於Streaming的廣義線性模型的實現,新寫了StreamingGeneralizedLinearAlgorithm類,這個類調指定了模型和算法後,會用spark自帶的各種線性模型和隨機梯度下降算法,因此細節是被封裝了的。

4、基於ALS算法的簡易在線推薦系統

   在前期實現了廣義線性模型的流式機器學習算法後,我們轉向了對推薦系統的研究,因爲網絡上充滿着各種各樣的信息,而且數量相當龐大,並且還在以相當驚人的速度增長,如何在海量的信息中快速的找到我們所需要的信息並快速的反饋給用戶,是互聯網推薦系統需要考慮的一個十分重要的問題。

   推薦系統中最核心和關鍵的部分就是使用的推薦算法,其在很大程度上決定了推薦系統性能的優劣。推薦算法大致可以分爲以下幾類:①基於內容的推薦算法(content-basedrecommendation)②協同過濾推薦算法(collaborativefiltering recommendation)③基於知識的推薦算法(knowledge-basedrecommendation)。

   最初我們想基於協同過濾推薦算法在目前廣泛應用的movielens數據集上計算和推薦用戶電影根據推薦結果和已有的樣本數據進行比較在模型不斷學習過程中推薦的準確性。後面我們發現在spark的MLlib庫中自帶有基於ALS(迭代最小二乘法)算法的推薦程序,雖然ALS算法由於其計算複雜度較大,在實際應用中並不是很多,但是在movielens這個數據集上卻顯示出其優越性。

   因此我們改寫了spark中的ALS模型訓練的程序,使其可以對新的數據進行學習,詳見博文《基於ALS算法的簡易在線推薦系統》。但是在博文中我們也提到了,由於目前的spark框架對於矩陣的運算操作支持的並不是特別好,因此將ALS算法改進爲可以流式學習的算法有較大的難度,我們僅僅加入了將TCP流獲得的數據合併到以前的數據集中,然後再進行模型訓練,但是這樣做的話由於元素過多和算法複雜度過高的關係,在小內存的機器上難以完美地運行,有待改進爲算法複雜度更低的ALS模型更新算法。

    在movielens數據集上,我們測試的效果如下,由於初始接收的數據不夠多,無法對測試集中的所有的數據進行預測,因此RMSE偏小,隨着到達的數據樣本不斷增多,學習後的模型在測試集上的的誤差也在不斷的減小。

5、在線的PCA算法

   PCA是大規模機器學習中常用的工具,可以大量降低數據的維度,減少運算量。我們找到了在線PCA的具體算法,但是由於Spark中分佈式的矩陣操作,特別是把多個矩陣拼接在一起,沒有現成的函數,而實現這樣的功能有比較複雜,我們在最後不得已放棄了在線PCA算法的實現。但是我們在Matlab上進行了如下的仿真。

   在線PCA算法通過流式的數據訓練一個映射矩陣,將高維的數據降到低維。可以想象,用來訓練的數據越多,映射矩陣也就越高,即主成分的選取越準確。我們在MIT的人臉識別數據集CBCL上,對數據分成三個部分,PCA訓練數據,SVM訓練數據,SVM測試數據。其中,將PCA訓練數據等分成20份,用不同數量的PCA訓練數據進行PCA訓練,然後對這些不同數據量訓練出來的映射矩陣對同樣的SVM訓練數據進行降維,使用降維後的數據進行SVM訓練,然後在SVM測試數據上進行測試,計算錯誤率。得到以下結果:

   這個仿真說明,隨着PCA訓練數據的增加,其得到的主成分也越好。

二、項目的一些遺憾

   前面第一部分主要闡述了我們在實施項目過程中所獲得的一些小的階段性成果,但是回首過去,在執行項目過程中總有一些遺憾的事情沒能很好的完成,這裏也做一個簡要的回顧。

1、Scala編程規範

   儘管我們盡力按照scala和spark的編程規範去寫代碼,但是第一次寫這種代碼,心裏總是心有餘悸,得先把算法實現了再去改代碼規範,因此寫出來的代碼並不是那麼的清楚易懂,另外,scala語言那種良好的封裝特性,也讓我們理解算法遇到了一定的障礙。

2、基於ALS模型的在線算法改進

   其實我們挺想將ALS模型的在線學習改進爲算法複雜度更低的算法,但是真的受制於spark的發展,讓我們難以像在matlab一樣對矩陣進行靈活的操作,因此改進ALS模型遇到了極大的阻力,希望後續更新spark的程序員能加強spark對矩陣操作的支持,這樣改進其他的相關算法就容易多了。

3、在線PCA算法未能實現

   同樣是受限於spark對矩陣操作的支持,我們沒能實現在線的PCA算法。還有一個原因是我們對spark中運用到的breeze庫不是很熟悉,這個庫可以用來做local矩陣和向量的操作。

三、項目結語

   在這個臨近中秋的夜晚寫這份結題報告心中真是悲喜交加,喜的是兩個月多月的實習期終於結束了,悲的是在執行的項目中總會留下那麼一些遺憾感覺難以實現,並且感覺還有很多等待我們去實現的地方沒有完成。

   但是無論如何在我們的項目過程中,我們充分認識到了開源工作真的是非常的有意義,但是是一種長期漫長的工作,需要很多感興趣寫代碼的人的不斷的努力才能完成一個比較偉大的project。最後再次感謝CSDN提供的這次開源項目實習機會,讓我們受益匪淺。


附:項目代碼見下面鏈接

https://code.csdn.net/zhangyuming010/zju_spark_2014




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章