什麼是實踐中真正在用的數據科學係統?
在過去的幾年間,數據科學這個概念已經被非常多的行業所接受。數據科學(源自於一個科學研究課題)最早是來自於一些試圖去理解人類的智能並創造人工智能的科學家,但現在它已經被證明是完全可以帶來真正的商業價值。
例如,我所在的公司:Zalando(歐洲最大的時尚品零售店)。在這裏,數據科學和其他工具一起被用來提供數據驅動的推薦。推薦本身作為後端服務,被提供給很多地方,包括產品頁麵、分類目錄頁麵、通訊電郵以及重新定位目標客戶等。
圖1:圖片來自Mikio Braun的演講頁
◆ ◆ ◆
產生推薦
實際上,有非常多的方法可以由數據驅動產生推薦。例如在所謂的“協同過濾”裏,所有用戶的行為(比如瀏覽商品、對想買商品列表的操作、以及購買行為)都可以被收集起來作為推薦的基礎,然後分析發現哪些商品有相似的用戶行為模式。這種方法的優美之處在於計算機根本不用知道這些商品是什麼。而它的缺點則是商品必須要有足夠多的用戶行為信息數據才能保證這個方法起作用。另外一類產生推薦的方法是隻看商品的屬性。例如,推薦具有相同品牌的或者相同顏色的商品。當然,對這些方法還有非常多的擴展或者組合。
圖2:圖片由Antonio Freno友情提供並授權使用。引用自發表在KDD 2015會議的《One-Pass Ranking Models for Low-Latency Product Recommendations》論文
更簡單一些的方法就是隻通過計數來做推薦。但這種方法在實踐裏會有非常多的複雜的變形。例如,對個性化推薦,我們曾使用過“學習排序”的方法,即對商品集做個性化的排序。上圖裏所顯示的就是這個方法需要最小化的損失函數。不過,這裏畫出這個圖的主要目的還是來展示數據科學可能會引入的複雜度。這個函數自身使用了成對的加權指標,並帶有正則化條件。這個函數的數學展現是很簡化的,當然也就很抽象。這個方法不僅對於電商的推薦場景有用,還對當物品有足夠特征的時候的所有類型的排序問題也有用。
◆ ◆ ◆
將數據科學方法引入工業界
為了把類似上圖的非常複雜的數學算法引入到生產係統中,我們需要做什麼?數據科學和軟件工程之間的界麵應該是什麼樣?什麼樣的組織架構和隊伍結構才最適合使用這些數據科學的方法。這些都是非常相關和合理的問題。因為這些問題的答案將會決定對於一個數據科學家或者是整個數據科學團隊的投資是否能最終得到回報。
在下文裏,我會根據我作為一個機器學習的研究人員以及在Zalando帶領一個數據科學家和工程師團隊的經驗,來對這些問題做一些探討。
◆ ◆ ◆
理解數據科學(係統)與生產係統的關係
讓我首先從了解數據科學係統與後端生產係統的關係開始,看看如果將兩者進行集成。
圖3:圖片來自Mikio Braun的演講頁
典型的數據科學工作流程(管道)如上圖裏所示:第一步總是從發現問題和收集一些數據(來自於數據庫或者生產係統的日誌)開始。取決於機構的數據準備好的程度,這一步有可能就是很困難的。首先,你有可能需要搞清楚誰能讓你接觸到所需的數據,並搞清楚誰能給你權限去使用這個數據。當數據可用後,它們就可能需要被再次處理,以便提取特征值。你希望這些特征可以為解決問題提供有用的信息。接著這些特征值被導入學習的算法,並用測試數據對產生的結果模型做評估,以決定這個模型是否能較好地對新數據做預測。
上述的這個分析管道通常都是短期一次性的工作。一般是由數據科學家手工完成所有的步驟。數據科學家可能會用到如Python這樣的編程語言,並包括很多的數據分析和可視化的庫。取決於數據數量,有時候數據科學家也使用類似Spark和Hadoop這樣的計算框架。但一般他們在一開始都隻會使用整個數據集的一小部分來做分析。
◆ ◆ ◆
為什麼開始隻用一小部分數據
開始隻用一小部分數據的主要原因是:整個分析管道過程並不是一錘子買賣,而是非常多次反複迭代的過程。數據科學項目從本質上講是探索性的,甚至在某種程度上是開放式的命題。雖然項目目標很清楚,但什麼數據可用,或可用的數據是否適合分析,這些在項目一開始都不是很清楚。畢竟,選擇機器學習作為方法就已經意味著不能僅僅隻是通過寫代碼來解決問題。而是要訴諸於數據驅動的方法。
這些特點都意味著上述的分析管道是迭代的,並需要有多次改進,嚐試不同的特征、不同的預處理模式、不同的學習方法,甚至是重回起點並尋找和實驗更多的數據來源。
這整個過程本質上就是反複的,而且經常是高度探索性的。當做出的模型的整體的表現不錯後,數據科學家就會對真實的數據運用開發的分析管道。到這時,我們就會麵臨與生成係統的集成問題。
圖4:圖片來自Mikio Braun的演講頁
◆ ◆ ◆
區分生產係統和數據科學係統
生產係統和一個數據科學係統的最主要區別就是生產係統是一個實時地、在持續運行的係統。數據一定要被處理而模型必須是經常更新的。產生的事件也通常會被用來計算關鍵業務性能指標,比如點擊率等。而模型則通常會每隔幾個小時就被用新數據再進行訓練,然後再導入生產係統中去服務於新來的(例如通過REST接口送入的)數據。
這些生產係統一般都是用如Java這樣的編程語言寫的,可以支持高性能和高可靠性。
圖5:圖片來自Mikio Braun的演講頁
如果你把生產係統和數據科學係統並排放置,那麼就會得到一個類似上圖的情況。在右上角,是數據科學的部分。其典型特征是使用類似Python的語音或者是Spark的係統,但一般是一次性的手工觸發的計算任務,並經過迭代來優化整個係統。它的產出就是一個模型,本質上就是一堆學習到的數字。這個模型隨後被導入進生成係統。而生產係統則是一個典型的企業應用係統,用諸如Java語言寫成的,並持續運行。
當然,上麵的這個圖有一些簡化了。現實中,模型都是需要被重新訓練的,所以一些版本的數據處理管道會和生成係統集成在一起,以便不時地更新生產係統裏的模型。
請注意那個在生成係統裏運行的A/B測試。它對應於數據科學一側的評估部分。但這兩部分經常並不完全具有可比性。例如不把離線的推薦結果展示給客戶,就很難去模擬一個推薦的效果,但有這樣做可能會帶來性能的提升。
最後,必須要意識到,這個係統並不是在安裝部署完成後就“萬事大吉了”。就如數據科學側的人需要迭代多次來優化數據分析管道,整個實時係統也必須隨著數據分布漂移來做迭代演進。由此新的數據分析任務就成為可能。對我而言,能正確做好這個“外部迭代”是對生產係統的最大的挑戰,同時也是最重要的一步。因為這將決定你能否持續地改善生產係統,並確保你在數據科學上的初期投資取得回報。
◆ ◆ ◆
數據科學家和程序員:合作的模式
到目前為止,我們主要關注的是生產環境裏的係統是什麼樣。當然對於如何保證生產係統穩定和高效則有很多種方法。有時候,直接部署Python寫的模型就足夠了,但生產係統和探索分析部分的分離是肯定存在的。
你將會麵對的艱巨挑戰之一就是如何協調數據科學家與程序員的合作。“數據科學家”依然是一個新的角色,但他們所做的工作與典型的程序員有著明顯差異。由此導致的誤解和溝通障礙就不可避免了。
數據科學家的工作通常是探索性的。數據科學項目一般始於一個模煳的目標、哪些數據可用的一些想法、以及可能的算法。但非常常見的情況是,數據科學家必須嚐試多種想法,並從數據裏獲取洞察。數據科學家會寫很多的代碼,但是大部分都是用於測試想法,並不會被用於最終的解決方案。
圖6:圖片來自Mikio Braun的演講頁
與數據科學家相反,程序員通常非常關注於編程。他們的目標是開發一個係統,實現所要求的功能。程序員有時會做一些探索性的工作,比如構建原型、驗證概念或是測試性能基準。但他們的工作的主要目標還是寫代碼。
他們間的不同還明顯地體現在代碼的變化上。程序員通常會堅持一個非常明確定義的代碼開發流程。一般包括創建自己工作流的分支,在開發完成後做評測檢查,然後把自己的分支合並進主分支。大家可以並行開發,但必須在協商後才能把他們的分支合並進主分支。然後這個過程再重複進行。這整個過程都是確保主分支會以一個有序的方式演進。
圖7:圖片來自Mikio Braun的演講頁
數據科學家也會寫很多的代碼。但正如我之前所說的,這些代碼通常是為了驗證想法。所以數據科學家可能是會寫出一個版本1,但它並沒有實現需求。然後又針對一個新的想法寫了版本2,隨後是2.1和2.2,直到發現還是不能實現需求而停止。再對更新的想法去寫版本3和3.1。也許在這個時候,數據科學家意識到,如果采用2.1版裏的某些方法並結合3.1版裏的某些方法,就能獲得一個更好的解決方案。這就帶來了版本3.3和3.4,並可能由此形成了最終解決方案。
圖8:圖片來自Mikio Braun的演講頁
一個有意思的事情是,數據科學家實際上可能希望保留所有這些沒成功的版本。因為之後的某個時間,也許它們又會被拿來測試新的想法。也許有些部分可以被放入一個“工具箱”裏,逐步形成數據科學家自己的私人機器學習庫。程序員更希望去刪除“無用的代碼”(因為他們知道如何快速地找回這些代碼),而數據科學家則喜歡保留代碼以防萬一。
上述的兩大不同意味著,在現實中,直接讓程序員和數據科學家共同工作可能會出問題。標準的軟件工程流程對數據科學家的探索性工作模式並不合適,因為他們的目標是不同的。引入代碼評測檢查和有序的分支管理、評測、合並分支的工作流對數據科學家而言並不合適,還會減慢他們的工作。同樣的,把探索性的模式引入生產係統開發也不會成功。
為此,如何才能構建一個合作模式來保證兩邊都能高產出的工作?可能第一直覺就是讓他們相互分離地工作。例如,完全分開代碼庫,並讓數據科學家獨立工作,產出需求文檔,再由程序員團隊實現。這種方法也行得通,但流程通常會非常得慢,且容易出錯。因為重新開發實現一遍就可能會引入錯誤,尤其是在程序員並不熟悉數據分析算法的情況下。同時能否進行外部迭代來改進係統的表現也依賴於程序員是否有足夠的能力來實現數據科學家的需求。
圖9:圖片來自Mikio Braun的演講頁
幸運的是,很多數據科學家實際上是希望能成為好的程序員,或是反過來。所以我們已經開始試驗一些更直接和更能幫助加快流程的合作模式,
例如,數據科學家和程序員的代碼庫依然是分離的,但部分生產係統會提供清晰定義的接口來方便數據科學家把他們的方法嵌入進係統。與這些生產係統的接口進行溝通的代碼必須嚴格地依據軟件開發實踐流程,但這是數據科學家的工作。用這種方式,數據科學團隊可以在自己的代碼快速地迭代,同時也就是完成了對生產係統的迭代。
圖10:圖片來自Mikio Braun的演講頁
這種架構模式的一個具體實現是采用“微服務”方法。即讓生產係統去調用數據科學家團隊開發的微服務來獲取推薦。用這個方式,整個數據科學家使用的離線分析管道還可以被調整用來做A/B測試,甚至是加入生產係統而不用程序員團隊重新開發實現。這種模式會要求數據科學家具有更多的軟件工程技能,但我們看到越來越多的數據科學家已經具有這樣的技能集。事實上,後來我們修改了Zalando的數據科學家的職銜為“研究工程師(數據科學)”來反應這種實際情況。
采用類似這樣的方法,數據科學家可以快速實踐,對離線數據做迭代研究,並在生產係統環境裏迭代開發。整個團隊可以持續地把穩定的數據分析方法遷移進生產係統。
◆ ◆ ◆
持續適應並改進
至此,我概述了一個能把數據科學引入生產係統的架構的典型模式。需要理解的一個關鍵概念就是這樣的係統需要持續地適應並改進(這和幾乎所有的針對實際數據的數據驅動項目類似)。能夠快速迭代,實驗新的方法,使用A/B測試驗證結果,這一切都非常重要。
依據我的經驗,保持數據科學家團隊和程序員團隊的分離是不可能達成這些目標的。與此同時,很重要的是我們也要承認他們兩個團隊的工作方式確實是不同的,因為他們的目標不一樣(數據科學家的工作更加具有探索性,而程序員更關注於開發軟件和係統)。通過允許各自團隊能工作在更適合他們的目標的方式,並定義一些清晰的接口,是有可能集成兩個團隊,並保證新的方法可以被快速地試錯的。這會要求數據科學家團隊具有更多的軟件工程技能,或是至少能有軟件工程師來橋接起兩個世界。
原文發布時間為:2016-12-02
本文來自雲棲社區合作夥伴“大數據文摘”,了解相關信息可以關注“BigDataDigest”微信公眾號
最後更新:2017-05-31 11:04:14