Python+大數(shù)據(jù)計算平臺,PyODPS架構(gòu)手把手教你搭建
數(shù)據(jù)分析和機器學習
大數(shù)據(jù)基本都是建立在Hadoop系統(tǒng)的生態(tài)上的,其實一個Java的環(huán)境。很多人喜歡用Python和R來進行數(shù)據(jù)分析,但是這往往對應(yīng)一些小數(shù)據(jù)的問題,或者本地數(shù)據(jù)處理的問題。如何將二者進行結(jié)合使其具有更大的價值?Hadoop現(xiàn)有的生態(tài)系統(tǒng)和現(xiàn)有的Python環(huán)境如上圖所示。
MaxCompute
MaxCompute是面向離線計算的大數(shù)據(jù)平臺,提供TB/PB級的數(shù)據(jù)處理,多租戶、開箱即用、隔離機制確保安全。MaxCompute上主要分析的工具就是SQL,SQL非常簡單、容易上手,屬于描述型。Tunnel提供數(shù)據(jù)上傳下載通道,不需要經(jīng)過SQL引擎的調(diào)度。
Pandas
Pandas是基于numpy的數(shù)據(jù)分析的工具,里面最重要的結(jié)構(gòu)是DataFrame,提供一系列繪圖的API,背后是matplotlib的操作,非常容易和Python第三方庫交互。
PyODPS架構(gòu)
PyODPS即利用Python進行大數(shù)據(jù)分析,其架構(gòu)如上圖所示。底層是基礎(chǔ)API,可以利用其操作MaxCompute上的表、函數(shù)或者資源。再上面是DataFrame框架,DataFrame包括兩部分,一部分是前端,定義了一套表達式的操作,用戶寫的代碼會轉(zhuǎn)化成表達式樹,這與普通的語言是一樣的。用戶可以自定義函數(shù),也可以進行可視化,與第三方庫進行交互。后端最下面是Optimizer,其作用是對表達式樹進行優(yōu)化。ODPS和pandas都是通過compiler和analyzer提交到Engine來執(zhí)行。
背景
為什么要做DataFrame框架?
對于任何一個大數(shù)據(jù)分析工具,都會面臨三個維度上的問題:表達力,API、語法、編程語言是否簡單、符合直覺?數(shù)據(jù),存儲、元數(shù)據(jù)是否能壓縮、有效?引擎,計算的性能是否足夠?所以就會面臨pandas和SQL兩個選擇。
如上圖所示,pandas的表達力非常好,但是其數(shù)據(jù)只能放在內(nèi)存中,引擎是單機的,受限于本機的性能。SQL的表達力有限,但是可以用于大量的數(shù)據(jù),數(shù)據(jù)量小的時候沒有引擎的優(yōu)勢,數(shù)據(jù)量大的時候引擎會變得很有優(yōu)勢。ODPS的目標是綜合這兩者的優(yōu)點。
PyODPS DataFrame
PyODPS DataFrame是使用Python語言寫的,可以使用Python的變量、條件判斷、循環(huán)??梢允褂胮andas類似的語法,定義了自己的一套前端,有了更好的表達力。后端可以根據(jù)數(shù)據(jù)來源來決定具體執(zhí)行的引擎,是visitor的設(shè)計模式,可擴展。整個執(zhí)行是延遲執(zhí)行,除非用戶調(diào)用立即執(zhí)行的方法,否則是不會直接執(zhí)行的。
從上圖中可以看出,語法非常類似于pandas。
表達式和抽象語法樹
從上圖可以看出,用戶從一個原始的Collection來進行GroupBy操作,再進行列選擇的操作,最下面是Source的Collection。取了兩個字段species,這兩個字段是做By操作的,pental_length是進行聚合的操作取聚合值。Species字段是直接取出來,shortest字段是進行加一的操作。
Optimizer(操作合并)
后端首先會使用Optimizer對表達式樹進行優(yōu)化,先做GroupBy,然后在上面做列選擇,通過操作合并可以去除petal_length做聚合操作,再加一,最終形成了GroupBy的Collection。
Optimizer(列剪枝)
用戶join了兩個data frame,再取來自data frame 的兩個列的時候,如果提交到一個大數(shù)據(jù)的環(huán)境,這樣一個過程是非常低下的,因為不是每個列都用到了。所以要對joined下的列進行剪枝操作。比如,data frame1我們只用到了其中的一個字段,我們只需要將字段截取出來做一個projection來形成新的Collection,data frame2也類似。這樣,對這兩部分進行校驗操作的時候就能極大的減少數(shù)據(jù)的輸出量。
Optimizer(謂詞下推)
如果對兩個data frame進行joined然后再分別進行過濾的話,這個過濾操作是應(yīng)該下推到下面來執(zhí)行的,這樣就能減少joined 的輸入的量。
可視化
提供了visualize()來方便用戶進行可視化。在右邊的例子中可以看到,ODSP SQL后端會compile成一條SQL執(zhí)行。
后端
從上圖中可以看出,計算后端是非常靈活的。用戶甚至可以joined一個pandas的data frame和maxcompute上一個表的數(shù)據(jù)。
Analyzer
Analyzer的作用是針對具體的后端,將一些操作進行轉(zhuǎn)化。比如:
- 有些操作比如value_counts,pandas本身支持,因此對于pandas后端,無需處理;對于ODPS SQL后端,沒有一個直接的操作來執(zhí)行,所以在analyzer執(zhí)行的時候,會被改寫成groupby + sort的操作;
- 還有一些算子,在compile到ODPS SQL時,沒有內(nèi)建函數(shù)能完成,會被改寫成自定義函數(shù)。
ODPS SQL后端
ODPS SQL后端怎么進行SQL編譯再執(zhí)行的操作?編譯器可以從上到下遍歷表達式樹,找到Join或者Union。對于子過程,進行遞歸compile。再到Engine來具體執(zhí)行時,會使用Analyzer對表達式樹進行改寫,compile自上而下的子過程,自底向上compile成SQL子句,最終得到完整的SQL語句,提交SQL并返回任務(wù)。
pandas后端
首先訪問這個表達式樹,然后對每個表達式樹節(jié)點對應(yīng)到pandas操作,整個表達式樹遍歷完之后就會形成DAG。Engine執(zhí)行按DAG拓撲順序執(zhí)行,不斷地把它應(yīng)用到pandas操作,最終得到一個結(jié)果。對于大數(shù)據(jù)環(huán)境來說,pandas后端的作用是做本地DEBUG;當數(shù)據(jù)量很小時,我們可以使用pandas進行計算。
難點+坑
- 后端編譯出錯容易丟失上下文,多次optimize和analyze,導(dǎo)致難以查出是之前哪處visit node導(dǎo)致。解決:保證每個模塊獨⽴立性、測試完備;
- bytecode兼容問題,maxcompute只支持Python2.7的自定義函數(shù)的執(zhí)行;
- SQL的執(zhí)行順序。
ML機器學習
機器學習是輸入輸出一個data frame。比如,有一個iris的data frame,先用name字段來做一個分類字段,調(diào)用split方法將其分成60%的訓(xùn)練數(shù)據(jù)和40%的測試數(shù)據(jù)。然后初始化一個RandomForests,其里面有一棵決策樹,調(diào)用train方法訓(xùn)練訓(xùn)練數(shù)據(jù),調(diào)用predict方法形成一個預(yù)測數(shù)據(jù),調(diào)用segments[0]就可以看到可視化結(jié)果。
未來計劃
分布式numpy,DataFrame基于分布式numpy的后端;
內(nèi)存計算,提升交互式體驗;
Tensorflow。