第1章:大資料分析

陳孟寒發表於2015-10-23

作者:Sandy Ryza

(資料應用)就像香腸,最好別看見它們是怎麼做出來的。 ——Otto von Bismarck

• 用數千個特徵和數十億個交易來構建信用卡欺詐檢測模型

• 向數百萬使用者智慧地推薦數百萬產品

• 通過模擬包含數百萬金融工具的投資組合來評估金融風險

• 輕鬆地操作成千上萬個人類基因的相關資料以發現致病基因

5 到10 年前想要完成上述任務困難重重。我們說生活在“大資料”時代,其意思是指我們擁有收集、儲存、處理大量資訊的工具,而這些資訊的規模以前我們聞所未聞。這些能力的背後是許多開源軟體組成的生態系統,它們能利用大量普通計算機處理大規模資料。Apache Hadoop 之類的分散式系統已經進入主流,並被廣泛部署在幾乎各個領域的組織裡。

但就像銼刀和石頭本身並不構成雕塑一樣,有了工具和資料並不等於就可以做有用的事情。這時我們就需要“資料科學”了。雕刻是利用工具將原始石材變成普通人都能看懂的雕塑,資料科學則是利用工具將原始資料變成對不懂資料科學的普通人有價值的東西。

通常“做有用的事情”指給資料加上模式並用SQL 來回答問題,比如:“註冊過程中許多使用者進入到第三個頁面,其中有多少使用者年齡超過25 歲?”如何結構化資料並組織資訊來回答此類問題涉及面很廣,本書不對其細節過多贅述。

有時候“產生價值”需要多付出一些努力。SQL 可能仍扮演重要角色,但為了處理資料的特質或進行復雜分析,人們需要一個更靈活、更易用的,且在機器學習和統計方面功能更豐富的程式設計模式。本書將重點討論此型別的分析。

長久以來,人們利用R、PyData 和Octave 等開源框架可以在小資料集上進行快速分析和建模。只需不到10 行程式碼,就可以利用資料集的一部分資料構建出機器學習模型,再利用該模型預測其餘資料的分類。如果多寫幾行程式碼,我們還能處理遺失資料,嘗試多個模型並從中找出最佳模型,或者用一個模型的結果作為輸入來擬合另一個模型。但如果資料集巨大,必須利用大量計算機來達到相同效果,我們該怎樣做呢?

一個可能正確的方法是簡單擴充套件這些框架使之能執行在多臺機器上,保留框架的程式設計模型,同時重寫其核心使之在分散式環境下能順利執行。但是,分散式計算難度大,我們必須重新思考在單機系統中的許多基本假設在分散式環境下是否依然成立。比如,由於叢集環境下資料需要在多個節點間切分,網路傳輸速度比記憶體訪問慢幾個數量級,如果演算法涉及寬資料依賴,情況就很糟糕。隨著機器數量的增加,發生故障的概率也相應增加。這些實際情況要求程式設計模式適配底層系統:程式設計模式要防止不當選項並簡化高度並行程式碼的編寫。

當然,除了像PyData 和R 這樣在軟體社群裡表現優異的單機工具,資料分析還用到其他工具。在科學領域,比如常常涉及大規模資料的基因學,人們使用平行計算框架已經有幾十年的歷史了。今天,在這些領域處理資料的人大多數都熟悉HPC(High-Performance Computing,高效能運算)叢集計算環境。然而,PyData 和R 的問題在於它們很難擴充套件。同樣,HPC 的問題在於它的抽象層次較低,難於使用。比如要並行處理一個大DNA 測序檔案,人們需要手工將該檔案拆成許多小檔案,併為每個小檔案向叢集排程器提交一個作業。如果某些作業失敗,使用者需要檢查失敗並手工重新提交。如果操作涉及整個資料集, 比如對整個資料集排序,龐大的資料集必須流入單個節點,否則科學家就要用MPI 這樣底層的分散式框架。這些底層框架使用難度大,使用者必須精通C 語言和分散式/ 網路系統。這些工具為HPC 環境編寫,往往很難將記憶體資料模型和底層儲存模型獨立開來。比如很多工具只能從單個流讀取POSIX 檔案系統資料,很難自然並行化,不能用於讀取資料庫等其他後臺儲存。最近,Hadoop 生態系統提供了抽象,讓使用者使用計算機叢集就像使用單臺計算機一樣。該抽象自動拆分檔案並在多臺計算機上分散式儲存,自動將工作拆分成若干粒度更小的任務並分散式執行,出錯時自動恢復。Hadoop 生態系統將大資料集處理涉及的許多瑣碎工作自動化,並且啟動開銷比HPC 小得多。

1.2  認識Apache Spark

該介紹Apache Spark 了。Spark 是一個開源框架,作為計算引擎,它把程式分發到叢集中的許多機器,同時它提供了一個優雅的程式設計模型。Spark 源自加州大學伯克利分校的AMPLab,現在已被捐獻給了Apache 軟體基金會。可以這麼說,對於資料科學家而言,真正讓分散式程式設計進入尋常百姓家的開源軟體,Spark 是第一個。

瞭解Spark 的最好辦法莫過於瞭解相比於它的前輩MapReduce,Spark 有哪些進步。MapReduce 革新了海量資料計算的方式,為執行在成百上千臺機器上的並行程式提供了簡單的程式設計模型。MapReduce 引擎幾乎可以做到線性擴充套件:隨著資料量的增加,可以通過增加更多的計算機來保持作業時間不變。而且MapReduce 是健壯的。故障雖然在單臺機器上很少出現,但在數千個節點的叢集上卻總是出現。對於這種情況,MapReduce 也能妥善處理。它將工作拆分成多個小的任務,能優雅地處理任務失敗,並且不影響任務所屬作業的正確執行。

Spark 繼承了MapReduce 的線性擴充套件性和容錯性,同時對它做了一些重量級擴充套件。首先, Spark 摒棄了MapReduce 先map 再reduce 這樣的嚴格方式,Spark 引擎可以執行更通用的有向無環圖(DAG)運算元。這就意味著,在MapReduce 中需要將中間結果寫入分散式檔案系統時,Spark 能將中間結果直接傳到流水作業線的下一步。在這方面,它類似於Dryad (http://research.microsoft.com/en-us/projects/dryad/)。Dryad 也是從MapReduce 衍生出來的, 起源於微軟研究院。其次,它也補充了這種能力,通過提供許多轉換操作,使用者可以更自然地表達計算邏輯。Dryad 更加面向開發人員,其流式API 可以做到用幾行程式碼表示覆雜的流水作業。

第三,Spark 擴充套件了前輩們的記憶體計算能力。它的彈性分散式資料集(RDD)抽象使開發人員將流水處理線上的任何點物化在跨越叢集節點的記憶體中。這樣後續步驟如果需要相同資料集時就不必重新計算或從磁碟載入。這個特性使Spark 可以應用於以前分散式處理引擎無法勝任的應用場景中。Spark 非常適合用於涉及大量迭代的演算法,這些演算法需要多次遍歷相同資料集。Spark 也適用於反應式(reactive)應用,這些應用需要掃描大量記憶體資料並快速響應使用者的查詢。

或許最重要的是,Spark 契合了前面提到的資料科學領域的硬道理。它認識到構建資料應用的最大瓶頸不是CPU、磁碟或者網路,而是分析人員的生產率。通過將預處理到模型評價的整個流水線整合在一個程式設計環境中,Spark 大大加速了開發過程。這一點尤為值得稱讚。Spark 程式設計模型富有表達力,在REPL 下包裝了一組分析庫,省去了多次往返IDE 的開銷。而這些開銷對諸如MapReduce 等框架來說是無法避免的。Spark 還避免了取樣和從HDFS 來回倒騰資料所帶來的問題,這些問題是R 之類的框架經常遇到的。分析人員在資料上做實驗的速度越快,他們能從資料中挖掘出價值的可能性就越大。

在資料處理和ETL 方面,Spark 的目標是成為大資料界的Python 而不是大資料界的Matlab。作為一個通用的計算引擎,它的核心API 為資料轉換提供了強大的基礎,它獨立於統計學、機器學習或矩陣代數的任何功能。它的Scala 和Python API 讓我們可以用表達力極強的通用程式語言編寫程式,還也可以訪問已有的庫。

Spark 的記憶體快取使它適應於微觀和巨集觀兩個層面的迭代計算。機器學習演算法需要多次遍歷訓練集,可以將訓練集快取在記憶體裡。在對資料集進行探索和初步瞭解時,資料科學家可以在執行查詢的時候將資料集放在記憶體,也很容易將轉換後的版本快取起來,這樣就節省了訪問磁碟的開銷。

最後,Spark 在探索型分析系統和操作型分析系統之間搭起一座橋樑。我們經常說,資料科學家比統計學家更懂軟體工程,而比軟體工程師更懂統計學。基本上講,Spark 比探索型系統更像操作型系統,而比操作型系統常見的技術則更善於資料探索。Spark 從根本上是為效能和可靠性而生的。由於構建於JVM 之上,它可以利用許多Java 技術棧裡的操作和除錯工具。

Spark 還緊密整合Hadoop 生態系統裡的許多工具。它能讀寫MapReduce 支援的所有資料格式,可以與Hadoop 上的常用資料格式,如Avro 和Parquet(當然也包括古老的CSV), 進行互動。它能讀寫NoSQL 資料庫,比如HBase 和Cassandra。它的流式處理元件Spark Streaming 能連續從Flume 和Kafka 之類的系統讀取資料。它的SQL 庫SparkSQL 能和Hive Metastore 互動,而且在另外一個專案中Spark 還能替代MapReduce 作為Hive 的底層執行引擎,該專案在本書撰寫時還在處於開發過程。它可以執行在Hadoop 叢集排程和資源管理器YARN 之上,這樣Spark 可以和MapReduce 和Impala 等其他處理引擎動態共享叢集資源和管理策略。

當然,Spark 並不完美。雖然它的核心引擎在成熟度上不斷進步,即使是在本書撰寫期間也是如此,但Spark 相比MapReduce 仍然很年輕,其批處理能力仍然比不過MapReduce。它的各個特殊子元件,比如流式處理、SQL、機器學習和圖處理,分別處在不同的成熟階段,每次升級API 變化較大。比如說,MLlib 的流水線和轉換API 模型在本書寫作時還在開發之中。它的統計和建模功能跟R 等單機版語言還沒有可比性。它的SQL 功能雖然豐富,但和Hive 的SQL 功能相比差距還非常大。

1.1  資料科學麵臨的挑戰

資料科學界有幾個硬道理是不能違背的,Cloudera 資料科學團隊的一項重要職責就是宣揚這些硬道理。一個系統要想在海量資料的複雜資料分析方面取得成功,必須要明白這些硬道理,至少不能違背這些硬道理。

第一,成功的分析中絕大部分工作是資料預處理。資料是混亂的,在讓資料產生價值之前,必須對資料進行清洗、處理、融合、挖掘和許多其他操作。特別是對大資料集,由於人們很難直接檢查,為了知道需要哪些預處理步驟,甚至需採用計算方法。一般情況下, 即使在模型調優階段,在整個資料處理管道各個作業中,花在特徵提取和選擇上的時間比選擇和實現演算法的時間還要多。

比如,在構建網站欺詐交易檢測模型時,資料科學家需要從許多可能的特徵中進行選擇。這些特徵包括必填項、IP 地址資訊、登入次數、使用者瀏覽網站時的點選日誌等。在將特徵轉換成適用於機器學習演算法的向量時,每個特徵可能都會有不同的問題。系統需要支援更靈活的轉換,遠遠不止是將二維雙精度陣列轉換成一個數學模型那麼簡單。

第二,迭代與資料科學緊密相關。建模和分析經常需要對一個資料集進行多次遍歷。這其中一方面是由機器學習演算法和統計過程本身造成的。常用的優化過程,比如隨機梯度下降和最大似然估計,在收斂前都需要多次掃描輸入資料。資料科學家自身的工作流程也涉及迭代。在初步調查和理解資料集時,一個查詢的結果往往給下一個查詢帶來啟示。在構建模型時,資料科學家往往很難在第一次就得到理想的結果。選擇正確的特徵,挑選合適的演算法,執行恰當的顯著性測試,找到合適的超引數,所有這些工作都需要反覆試驗。框架每次訪問資料都要讀磁碟,這樣會增加時延,降低探索資料的速度,限制了資料科學家進行試驗的次數。

第三,構建完表現卓越的模型不等於大功告成。資料科學的目標在於讓資料對不懂資料科學的人有用。把模型以許多回歸權值的形式存成文字檔案放在資料科學家的計算機裡,這樣做根本沒有實現資料科學的目標。資料推薦引擎和實時欺詐檢測系統是最常見的資料應用。這些應用中模型作為生產服務的一部分,需要定期甚至是實時重建。

在這些場景中,有必要區別分析是試驗環境還是生產環境。在試驗環境下,資料科學家進行探測式分析。他們想理解工作資料集的本質。他們將資料圖形化並用各種理論來測試。他們用各種特徵做試驗,用輔助資料來源來增強資料。他們試驗各種演算法,希望從中找到一兩個有效演算法。在生產環境下,構建資料應用時,資料科學家進行操作式分析。他們把模型打包成服務,這些服務可以作為現實世界的決策依據。他們跟蹤模型隨時間的表現,哪怕是為了將模型準確度提高一個百分點,他們都會精心調整模型並且樂此不疲。他們關心服務SLA 和線上時間。由於歷史原因,探索式分析經常使用R 之類的語言,但在構建生產應用時,資料處理過程則完全用Java 或C++ 重寫。

當然,如果用於建模的原始程式碼也可用於生產應用,那就能節省每個人的時間。但像R 之類的語言執行緩慢,很難將其與生產基礎設施的技術平臺進行整合,而Java 和C++ 之類的語言又很難用於探索式分析。它們缺乏互動式資料操作所需的REPL(Read-Evaluate- Print-Loop,讀取- 計算- 列印- 迴圈)環境,即使是簡單的轉換,也需要寫大量程式碼。人們迫切需要一個既能輕鬆建模又適合生產系統的框架。

1.3  關於本書

本書接下來的部分不會繼續討論Spark 的優缺點。本書也不會涉及其他幾個話題。本書會介紹Spark 的流式程式設計模型和Scala 基礎知識,但它不是一個Spark 的參考書或參考大全, 不會講Spark 技術細節。它也不是機器學習、統計學、線性代數的參考書,但在講到這些知識的時候,許多章節會提供一些背景知識。

另一方面,本書將幫助讀者建立用Spark 在大規模資料集上進行復雜分析的感覺。我們會講述整個處理過程:不但涉及模型的構建和評價,也會講述資料清洗、資料預處理和資料探索,並會花費筆墨描述怎樣將結果變成生產應用。我們認為最好的教學方法是例項,所以在快速介紹完Spark 及其生態系統之後,本書其餘各章分別討論了在不同領域使用Spark 進行資料分析的例項,每個例項都自成一體。

如果可能,我們儘可能做到不只是提供解決方案。我們會描述資料科學的整個工作流程, 包括它所有的迭代、無解以及需要重新開始的情況。本書將有助於讀者熟悉Scala、Spark、機器學習和資料分析。但這都是為了一個更大的目標服務,我們希望本書首先教會讀者如何完成本章開頭部分提到的任務。每一章雖然只有薄薄的20 來頁,但我們會力求把怎樣構建一個此類資料應用講清楚講透徹。

相關文章