機器學習下的持續交付

文/Danilo Sato、Arif Wider、Christoph Windheuser

譯/白髮川、沈建軍、王登宇

機器學習在行業中的應用變得越來越流行,然而相對於傳統軟件開發,例如Web服務或者Mobile應用來說,這類程序的開發、部署和持續改進也變得更加的複雜。它們的功能改變通常由以下三個維度驅動:

  • 代碼本身的修改
  • 模型的修改
  • 數據的改變

這類程序的表現行爲通常是非常複雜、難以預測、難以測試、不具備可解釋性、很難去改進的。機器學習下的持續交付(CD4ML)是開發機器學習應用時可以遵循、參照的原則和最佳實踐。

前言簡介

在 Google 2015年發出的著名論文《機器學習系統中隱藏的技術債》中,重點突出了在實際的機器學習系統中,機器學習的代碼在系統中只佔了很小的比重,周邊有非常多的基礎設施和流程來支持系統的演進,同時也提到了這種不斷被積累下來的技術債的多種來源,其中有些技術債的來源與數據的依賴關係、模型的複雜度、可再現性、測試、監控和外部響應變化有着非常大的聯繫。

傳統軟件開發系統流程也存在許多人們同樣關心的問題,而持續交付一直以來用自動化、高質量和規律性的方法,在生產環境中實踐這種可靠且可復現的軟件開發方式。在他們的創造性著作中,Jez Humble 和 David Farley 強調:

“持續交付具有改變一切的可能性——包括新的特性,可控制的改變,各種BUG的修復以及實驗項目——爲了生產環境,或者說是爲了用戶,能夠以一種可持續的軟件開發方式快速安全的構建項目。”

除了代碼外,對ML模型的改變以及訓練它們使用的數據是另一種需要我們去管理和融入軟件交付流程的改變(圖1)。

(圖1:三個維度的改變對ML應用的影響——數據、模型和代碼——以及一些它們影響改變的原因)

順着這個思路,我們可以擴展持續交付的定義,以此來包含存在於現實世界ML系統中的新元素和挑戰,一種我們稱之爲“機器學習下的持續交付(CD4ML)的方法”。

機器學習下的持續交付(CD4ML)是一種可以在短期適應週期中隨時再現和可靠地發佈的軟件工程方法,其中由跨職能團隊以小而安全的增量生成基於代碼、數據和模型的機器學習應用程序。

這個定義包含了以下這些基本原則:

  • **軟件工程的方法:**它使得團隊能夠高效高質量的完成軟件開發。
  • **具有跨職能的團隊:**在數據工程、數據科學、機器學習工程開發、運營和其他知識領域擁有不同技能和工作流程的專家們在一起協同工作,這裏強調每個團隊成員的技能和優勢。
  • **基於代碼、數據和機器學習模型的軟件開發:**ML軟件生產過程的所有組件都需要不同的工具和工作流程,我們必須對其進行版本控制和管理。
  • **微小且安全的增量:**對軟件每個組件的發行都分爲微小的小步增量,使得在每個不同的輸出環節都可視可控,這樣做在整個流程上增加了安全性。
  • **可復現的且可靠的軟件版本發行:**發行ML軟件的整個流程是可再現且可靠的,這需要我們儘可能的利用自動化。
  • **軟件隨時發佈:**ML軟件能夠隨時被投入生產環境是非常重要的。即使組織沒有想要隨時發佈軟件,但是它也應該一直保持一種可發佈的狀態。這使得發行的決定更容易首商業的影響而不是技術上的影響。
  • **短暫的適應週期:**短暫的週期意味着開發時間只有天或者小時,而並不是周或者年爲單位。所以自動化的流程和高質量的構建是達成這些的關鍵。這樣也將創建一個反饋循環,允許你通過學習其在生產環境的行爲來調整你自己的模型。

這篇文章將講述在實現CD4ML時我們發現的重要技術組件,我們使用一個ML樣例應用來解釋概念,同時演示怎樣把不同的工具放在一起來使用進而實現一個完整的端到端的流程。在合適的情景下,我們將會突出我們所選擇的可代替的工具。也將使用我們在行業上的成熟實踐經驗來討論未來的開發和研究的領域。

一個對銷售進行預測的機器學習應用

自從2016年以來,我們就已經開始思考如何將持續集成帶到機器學習領域。之前我們已經發布和介紹過了我們的一個客戶項目,一個使用了AutoScout構建的用來預測在他們自己平臺上發佈汽車價格的項目。

由於我們無法使用真實的客戶項目上的代碼作爲示例,所以我們決定構建一個基於公共問題和數據的樣例ML應用來說明CD4ML的實現過程。這個應用解決了一個許多零售商都會遇見的共同問題:試圖使用歷史銷售數據來預測未來某種商品的銷售量。我們爲一家大型的厄瓜多爾雜貨零售商Favorita公司在Kaggle上創建的問題構建了一個簡單的解決方案。爲了我們的目的,我們已經組合和簡化了他們的數據,因爲我們的目標不是找到最佳的預測————這種工作最好交給你的數據科學家————而是演示怎樣實現CD4ML。

用一種監督學習算法和Python流行的scikit-learn庫,我們使用標註好的數據訓練了預測模型,並且將這個模型整合到一個已經被部署到雲端的簡單web應用中。圖2展示了整個大致的流程。

(圖2:訓練我們的ML模型的初始化過程,整合它到一個web應用,最後將它部署到生產環境中。)

一旦我們部署了,我們的web應用(圖3)會允許用戶去選擇一個想要預測的產品和日期,然後這個模型將會預測輸出在那天將會賣出多少產品。

(圖3:演示我們的模型的工作的web UI)

共同的挑戰

實現這個端到端的流程已經能夠遇見兩個挑戰了,不過同時對於我們的討論來說也是一個好的起點。第一個挑戰來自於我們的組織架構:不同的團隊或許擁有不同部分的工作流程,這就會存在一個工作交接的問題————通常來說,“扔過牆(打破障礙)”——並沒有明切的目標去指導它們如何直接跨越這個界限(圖4)。數據工程師或許正在搭建pipelines來使得他人可以獲取數據,與此同時,數據科學家正在關心ML模型的構建和改進。然後機器學習工程師或者開發者在關注怎樣去把模型整合併發布到生產環境中。

(圖4:大型組織中常見的功能性孤島將會產生一些障礙,這扼殺了使用自動化去進行端到端的流程部署ML應用的能力。)

這導致了項目延期和不同團隊間的摩擦。一種常見的問題就是隻擁有可以在實驗室工作的模型,但是從來沒有離開概念驗證階段。又或者他們只用一種特定的方式部署到生產環境,使模型變得落後,也難以更新。

第二個挑戰是技術方面的:怎樣使得一個流程是可以復現和審計的。因爲這些團隊使用不同的工具且有着不同的工作流程,這會使得復現它端到端的整個流程非常困難。這裏有太多的代碼以外的組件需要我們去管理,同時對它們進行版本的管理也並不簡單。其中的一些可能非常大,需要用更復雜的工具來有效地存儲和檢索它們。

解決組織上的挑戰已經超過了本文的範圍,但是我們能帶來我們從Agile、DevOps所學到的思想,創建由各種不同領域的專家組成的跨職能和結果導向的團隊來構建一個端到端的ML系統。如果不能在你的組織裏這樣做的話,請至少鼓勵大家去打破這些障礙,在工作流程中讓他們儘早的,頻繁的協作起來。

本文剩餘部分將會探討我們對於技術挑戰方面的解決方案。我們將會深入研究每個技術組件,伴隨着慢慢改進和拓展到端到端的流程,使其更加的強大。

CD4ML 的技術組件

當我們思考如何使用機器學習解決預測問題時,第一步是瞭解數據集。在這種情況下,它可以是一組包含以下信息的CSV文件:

  • **產品:**如分類,是否易腐爛 (產品是否是耐久貨品)
  • **商店:**例如他們的位置以及他們如何聚集在一起
  • **特殊活動 (事件):**如公衆假期,季節性活動或2016年襲擊厄瓜多爾的7.8級地震
  • **銷售交易:**包括給定產品的銷售單位數,日期和地點

在此階段,數據分析師和數據科學家通常會通過執行某種探索性數據分析(EDA),以得到數據分析圖,從而確定更多的模式和離羣值。例如,我們發現銷售單位數量爲負數的產品,我們用它來代表產品退貨,因此我們會將其從訓練集中刪除。

但是在許多組織中,訓練有效ML模型所需的數據可能不會完全按照數據科學家的需要進行構建,那麼CD4ML的第一個技術組件也因此誕生了:可探索和可訪問的數據。

可探索和可訪問的數據

最常見的數據來源是你的核心交易系統。但是,從組織外部引入的其他數據源也很有價值。我們已經找到了一些用於收集和提供數據的常用模式,例如使用Data Lake架構,更傳統的數據倉庫,以及實時數據流,或者我們最近正在嘗試的(分佈式)去中心化Data Mesh架構。

無論你擁有哪種架構,重要的是使數據易於探索和訪問。當數據科學家越難找到他們需要的數據時,他們建立有效模型所需的時間就越長。我們還應該考慮到他們會想要在輸入數據之上設計新的特徵,這可能有助於提高他們模型的性能。

在我們的示例中,在進行初始探索性​​數據分析之後,我們決定將多個文件反規範化爲單個CSV文件,並清理不相關的或者可能會將不必要的噪聲引入模型的數據點 (如負面銷售等)。然後,我們將輸出存儲在Amazon S3,Google Cloud Storage或Azure等雲存儲系統中。

使用此文件來作爲輸入訓練集的快照,我們能夠根據文件夾結構和文件命名約定,設計一種簡單的方法來對數據集進行版本控制。數據版本控制是一個廣泛的話題,因爲它可以在兩個不同的維度上進行更改:對其架構的結構更改以及隨時間推移的實際數據採樣。我們的數據科學家Emily Gorcenski在博文《Data Versioning》中更詳細地介紹了這一主題,但本文將討論的是隨着時間推移,我們對數據集進行版本化的其他方法。

值得注意的是,在現實生活中,你可能會有更復雜的數據pipelines將數據從多個來源轉移到數據科學家可以訪問和使用的地方。

可復現的模型訓練

一旦數據可用,我們就會進入模型構建中的迭代數據科學工作流程。 這通常涉及將數據拆分爲訓練集和驗證集,嘗試不同的算法組合,並調整其參數和超參數。 這樣就創建了一個模型,它可以針對驗證集進行評估,進而評估其預測的質量。而一步一步的這個模型訓練的過程就構成了機器學習 pipeline。

在圖5中,我們突出了不同的源代碼,數據和模型組件,展示瞭如何爲銷售預測問題構建ML pipeline。 數據的輸入,中間訓練和驗證數據集以及輸出模型可能是大文件,我們不希望將其存儲在源控制存儲庫中。 此外,由於pipeline的各個階段通常會不斷變化,除了在數據科學家的本地環境,我們很難再重現它們。

(圖5:針對我們的銷售預測問題的機器學習pipeline,以及使用DVC實現自動化的3個步驟)

爲了在代碼中標準化模型訓練過程,我們使用了一個名爲DVC(數據科學版本控制)的開源工具。 它爲Git提供了類似的語義,也解決了一些特定於ML的問題:

  • 它有多個後端插件,用於在源控件存儲庫之外的外部存儲上獲取和存儲大文件;
  • 它可以跟蹤這些文件的版本,允許我們在數據更改時重新訓練我們的模型;
  • 它跟蹤用於執行ML pipeline的依賴圖和命令,允許在其他環境中重現該過程;
  • 它可以與Git分支集成,允許多個實驗共存;

例如,我們可以使用三個dvc運行命令來配置圖5中ML pipeline的初始化(-d指定依賴項,-o指定輸出,-f是記錄該步驟的文件名,-M是結果指標):

dvc run -f input.dvc \ ➊
  -d src/download_data.py -o data/raw/store47-2016.csv python src/download_data.py
dvc run -f split.dvc \ ➋
  -d data/raw/store47-2016.csv -d src/splitter.py \
  -o data/splitter/train.csv -o data/splitter/validation.csv python src/splitter.py
dvc run ➌
  -d data/splitter/train.csv -d data/splitter/validation.csv -d src/decision_tree.py \
  -o data/decision_tree/model.pkl -M results/metrics.json python src/decision_tree.py

每次運行都將創建一個相應的文件,該文件可以提交給版本控制,並允許其他人通過執行dvc repro命令重現整個ML pipeline。

一旦找到合適的模型,我們就會將其視爲需要進行版本化並部署到生產中的組件。我們可以通過使用DVC的dvc push和dvc pull命令從外部存儲器發佈和獲取它。

你也可以使用其他開源工具來解決這些問題:Pachyderm使用容器來執行pipeline的不同步驟,通過跟蹤數據提交併基於此優化流水線的執行,來解決數據版本控制和數據源問題。 MLflow Projects定義了一種文件格式來指定環境和管道的步驟,並提供API和CLI工具在本地或遠程運行項目。 我們之所以選擇DVC,是因爲它雖然只是一個簡單的CLI工具,但是卻能很好地解決這部分問題。

模型服務和部署

一旦我們找到一個合適的模型,我們需要去決定怎樣部署它到生產環境。我們已經看到一些模式可以做到這樣:

  • **可嵌入的模型:**這是一個更簡化的方法,你可以將模型的組件視爲打包和構建應用的依賴項。從現在開始,你可以將這個應用的組件和版本視爲應用代碼和選擇模型的一種組合。
  • **將模型部署爲一個單獨的服務:**在這個方法裏,模型被包含在一個可以獨立於消費應用程序的能被單獨部署的服務裏。這使得更新模型可以獨立發佈,但也可能造成一些在模型推斷上的延時,因爲每個預測結果都需要進行遠程調用。
  • **將模型作爲數據發佈:**在這個方法中,模型也被獨立處理和發佈,但是消費應用將在運行時將其作爲數據獲取。我們已經看到這樣被使用在流/實時的場景進行應用程序已發佈的事件訂閱。無論何時一個新的模型版本發佈了,就將它們獲取到內存中,與此同時,繼續使用舊版本的模型進行預測。軟件發佈模式比如Blue Green Deployment 或者Canary Releases 也能被應用於這些場景中。

在我們的示例中,鑑於我們的消費應用程序也是用Pyhton編寫的,我們已經決定使用更簡便的方法去嵌入這個模型。我們的模型被以一種序列化對象(pickle文件)的方式導入,由DVC進行推送到儲存。當構建我們的應用程序的時候,我們將它拉下來並嵌入到同一個Docker容器之中。從那時起,這個Docker鏡像成爲了我們獲得版本和部署到生產環境的應用程序+模型的一個組件。

除了使用pickle序列化模型對象之外,這裏也有其他的工具選擇可以來實現這個嵌入模型的方式。MLeap提供了一種常用的序列格式來導出/導入 Spark,scikit-learn和Tensorflow 模型。也有和語言無關的交換格式來共享模型,比如說PMML,PFA和ONNX。其中一些序列化選項也是可以應用到實現“模型作爲數據”的這一模式上的。

另一種方法是使用比如像H2O的工具來導出在JAR的java庫裏的模型作爲POJO,這樣你就可以在應用程序中增加它們作爲依賴。這個方法的好處在於你能使用數據科學家熟悉的語言訓練模型,比如說Python或者R,導出編譯好可以在不同目標環境(JVM)中運行的二進制模型,這樣做可以使推斷更快耗時更少。

爲了實現這個“把模型作爲服務”的模式,很多雲服務提供者都有工具和SDK來包裝你的模型然後部署至他們的MLaaS(把機器學習作爲一種服務),比如說 Azure Machine Learning,AWS Sagemaker或者Google AI 平臺。其他的選項是使用工具像kubeflow,這是一個被設計用來部署ML工作流到Kubernetes上的項目,即使它嘗試去解決更多的不止模型服務這部分的問題。

MLflow Models 正在試圖提供一種基礎的方法來根據不同的喜好打包模型,以供不同的下游工具使用,一些是“把模型作爲服務”的模式,一些是“讓模型可嵌入”的模式。我們只想說,現今領域開發的各種工具和供應商都在努力工作簡化這項任務。但是這也意味着那裏還沒有明確的基準(開放或者私有)可以被認爲一定是贏家,因此你需要根據你的需求來改進正確的選擇。

值得注意的是,不論你決定使用哪種模式,模型與其消費者總是存在着隱式的關聯。模型將會經常性的期望輸入數據是一種確定的形狀,如果數據科學家改變了關聯關係以要求新的輸入或者添加新的特徵,你就會遇到集成的問題並打斷使用它的應用程序。這又將會把我們引入到測試的話題上。

集成測試

這裏有一些不同類型的測試————自動化的或者是手動的————這些都能在ML工作流中提供。第一點是去驗證模型和消費應用程序的關聯。我們能夠使用相似的方法來測試服務或者應用程序的集成性,在模型改變時使用關聯測試來驗證預期的接口是適合消費應用程序的。這樣可以用來阻止在生產環境的集成問題,同時可以給出應用程序需要改變去使用新模型的早期反饋。

另一種測試類型是當你的模型以不同的格式生產出的時候,確保你的導出模型依然產生同樣的結果。這樣可以通過運行原來的和生產的模型輸入同樣的驗證數據集,然後比較兩者的結果應該是相同的來做到。

因爲ML模型的性能是不確定的,數據科學家經常收集和監控許多許多指標來確定一個模型的性能,比如錯誤率、準確率、AUC、ROC、混淆矩陣、精度、回調等等。這些指標在參數和超參數優化期間也是相當有用的。我們可以使用這些指標來引入Threshold Tests或者ratcheting 到我們的pipeline中,這樣可以確認新模型不會在已知性能指標基礎上降低。

在我們的樣例應用程序中,評估指標是Favorita指定的錯誤率所確定的。我們寫來一個簡單的如果錯誤率超過80%就會停止的PyUnit threshold test,並且可以在發佈新模型版本之前將此測試添加到部署pipeline中,從而防止錯誤模型進入生產階段。

我們也考慮過其他類型的測試,但是其中很多的難以全自動化。因此,我們認爲添加一些手動階段到部署的pipeline中是很重要的,這是爲了顯示關於模型的信息進而使得人們決定他們是否進行到部署的pipeline這一步驟。這樣允許你爲機器學習治理的流程建模並引入模型權重檢查,模型的公平性以及收集可被人類解釋的信息用來幫助人們理解模型的行爲。

實驗跟蹤

爲了支持這種治理流程,獲取並展示信息是非常重要的,這使得人們能夠決定是否或者哪一個模型投入到生產環境中。由於數據科學的流程幾乎全部以研究爲中心,所以在通常的情況下同時會進行多次實驗,然而大部分的實驗結果最終不會進入到生產環境中。

在研究階段這些實驗方法與傳統軟件的開發流程是截然不同的,因爲我們知道很多實驗的代碼最終將被丟棄,最後只留下小部分被認爲是值得投入生產環境中的。因爲這個原因,我們需要一個明確的方法去追蹤它們。

在我們的例子中,我們決定採取DVC建議的方法,在代碼管理中使用不同的Git分支去追蹤不同的實驗。即使這違背了我們的在一個主幹上實踐持續集成的理論。DVC能夠獲取和展示從不同分支或標籤運行的實驗的指標數據,有了這些數據的導航可以讓人們更容易作出選擇。

在傳統的特徵分支的軟件開發中,如果這些分支長期存在的話容易引起合併時痛苦。這將降低團隊重構代碼的積極性,因爲這些改變能影響到更大範圍的代碼庫。並且它也阻止了持續集成的實踐,因爲它迫使你在多個分支間來回作業導致正確的集成被拖延,直到代碼被合併回到主線。

對於ML的實驗,我們希望大多數分支永遠不會被集成,這些在實驗間改變的代碼通常不顯著。從CI的自動化角度來看,我們確實想爲每個實驗訓練多個模型,再收集那些會提醒我們哪個模型能夠進行到下一階段的部署到pipeline的指標。

除了DVC之外還有另一個我們使用的工具叫做MLflow Tracking來幫助我們追蹤實驗。它能夠以主機服務的方式被部署,然後提供一個API或者是一個web接口來可視化多個實驗的運行,並一起展示出來它們的參數和性能指標。就像下面的圖6。

(圖6:MLflow Tracking 的web UI 來展示實驗的運行,參數以及指標。)

爲了支持這個實驗的流程,突出強調這個擁有彈性基礎的好處也很重要,因爲你或許需要能夠使用多個實驗的環境————有時候也會在特殊的硬件設備上————去訓練。基於雲服務的架構天生非常適合這種情況,同時許多的公共雲服務提供商正在構建服務和解決方案來支持這個多方面的流程。

可持續交付業務流程設置

所有的主要部件都已到位,然後我們需要將所有的事都緊繫在一起,這就是我們的持續交付的業務流程設置工具起作用的地方。這個地方有許多可以選擇的工具,其中大多數提供了設置方法和執行部署pipline去構建和發行軟件到生產環境。在CD4ML中,我們有額外的編排要求:提供基礎設施和執行機器學習訓練的pipeline,同時從多個模型實驗中收集指標;構建,測試和我們的數據pipline的部署流程;以及集成測試和部署我們的模型到生產環境中。

我們使用GoCD作爲我們的持續集成工具,因爲它是由pipline作爲首要關心部分的概念來構建的。不止這些,它也允許我們組合不同的pipeline來設置複雜的工作流和依賴。觸發它們,之後在pipline之間確定手動或者自動升級的步驟。

在我們簡單的模型中,我們並沒有構建任何負載的數據pipeline或者基礎設施配置,但是我們演示來怎樣組合兩個GoCD的piplines。

  • **機器學習pipeline:**在GoCD代理下執行模型訓練和評測,同樣執行基礎的threshold test來決定這個模型是否能夠被推送至下一階段。如果這個模型很好,我們進行dvc push的命令來把它作爲一個組件公佈。
  • **應用程序部署的pipeline:**構建和測試應用程序的代碼,使用dvc pull獲取從上游pipeline推送的模型,打包成一個新的包含來模型和應用程序的混合組件來作爲Docker鏡像,最後部署它們到Kubernetes 集羣的生產環境上。

隨着時間的推移,這個ML的pipeline能夠擴展去同時執行多個實驗(一種由GoCD的扇出/扇入對模型支持的特徵),檢查權重、公平性、正確率以及其他類型的大門來確定你的模型治理流程以便人們來決定哪個模型被推送和部署到生產環境中。

最後,另一方面你的持續交付的流程設置上需要確定回滾的方案,以防萬一部署在生產環境下的模型在事實的證明下表現的不好或者不正確。這樣爲以上的流程增添了另一張安全網。

模型的檢測以及可觀測性

既然模型存在,我們就需要去理解它是怎樣在生產環境中表現的,同時使數據的反饋形成一個閉環。這裏我們可以複用所有的,可能在你的應用程序和服務中,進行監控和可見的基礎設施。

爲日誌集合和指標收集的工具通常用於從一個實時系統捕獲數據,比如商業的KPIs,軟件可靠性和性能指標,解決問題的調試的信息,以及其他的能夠在一些組件運行不正常時觸發警告的的指標。我們也可以利用這些相同的工具來捕獲數據,以此來理解我們的模型是怎樣運作的,比如說:

  • **模型輸入:**瞭解什麼數據被送進來模型,這樣可以看到任何訓練服務的出現的偏差。模型輸出:模型用這些輸入來產生什麼樣的預測以及推薦,方便理解模型在真實數據下表現的如何。
  • **可解釋的模型輸出:**一些指標比如說模型的係數、ELI5或者LIME輸出使得我們能夠進行更深入的調查去理解模型如何作出預測,以及確定潛在的過擬合或者在訓練期間沒有找到的的權重。
  • **模型的公平性:**分析輸入的數據和輸出的預測結果和已有的特徵做對比,這可以包括權重,比如說比賽、性別、年齡、收入羣體等等。

在我們的樣例中,我們使用EFK棧來監控並使過程可見,主要由三個工具組成

  • **Elasticsearch:**一個開源的搜索引擎。
  • **FluentD:**一個開源的對統一日誌源的收集程序
  • **Kibana:**一個開源的web UI 讓使用者能夠更簡單的探索和可視化Elasticsearch的數據索引。

我們可以使用我們的應用程序代碼,將模型輸入和預測記錄爲FluentD中的事件:

predict_with_logging.py…
 df = pd.DataFrame(data=data, index=['row1'])
  df = decision_tree.encode_categorical_columns(df)
  pred = model.predict(df)
  logger = sender.FluentSender(TENANT, host=FLUENTD_HOST, port=int(FLUENTD_PORT))
  log_payload = {'prediction': pred[0], **data}
  logger.emit('prediction', log_payload)

這個事件之後就被轉發,並且被ElasticSearch索引,我們可以使用Kibana的web接口去查詢和分析它,就像下面圖7所示。

(圖7:在Kibana分析我們的模型對實際輸入數據的預測)

這裏有一些其他的監控和可視化的工具,比如說ELK stack(另一種方法是使用Logstash代替FluentD來收集日誌和轉發),Splunk等等。

收集監控和可見的數據甚至比你部署了多個模型在生產環境中更重要。比如說,你可能對多個模型進行分開的測試————或者簡單的並排部署一個影子模型在你的正常的模型中來對同樣的生產環境下的數據作出預測並比較它們。

如果你正在訓練或者運行聯合模型在邊緣設備上也與這是有關係的————比如說在一個移動設備上————或者如果你部署一個隨着時間推移,用生產環境中的新數據學習的在線學習的模型。

通過捕獲這些數據,你能夠使這些數據的反饋閉環。要做到這些,我們可以通過收集更多的真實數據(例如,在一個價格引擎或者推薦系統裏)或者增加人類到這個環中去分析從生產環境中捕獲的新數據,幫助它爲新的和改進的模型創建新的訓練數據集來使之閉環。能使這個反饋閉環就是CD4ML的主要優點之一,因爲它允許我們調整從真實生產環境中的數據所學習的模型,進而開創了一個可持續改進的流程。

端到端的CD4ML流程

通過慢慢解決每個技術挑戰,並使用各種工具和技術,我們成功的創建瞭如圖8所示的端到端流程。該流程管理橫跨三個維度的組件的推廣:代碼,模型和數據。

(圖8:機器學習端到端流程的持續交付)

首先,我們需要有一種簡單的方法來管理、發現、訪問和版本化我們的數據。 然後,我們將模型構建和訓練的過程自動化,使其可重現。 這使我們能夠實驗和訓練多個模型,此時我們就需要管理和跟蹤這些實驗。 一旦我們找到合適的模型,我們就可以決定如何生產和服務。 由於模型正在發展,我們必須確保它不會破壞與消費者的任何關聯,因此我們需要在部署到生產之前對其進行測試。 一旦投入生產,我們就可以使用監控和可觀察性基礎設施來收集新數據,這些新數據可以分析和創建新訓練集,從而使持續改進的反饋循環閉環。

一個可持續交付業務流程設置工具可以協調端到端CD4ML流程,按需提供所需的基礎架構,並管理模型和應用程序如何部署到生產環境。

當下,我們如何起步?

我們在本文中使用的示例應用程序和代碼可以在我們的Github存儲庫中找到,並作爲我們在各種會議與客戶在爲期半天的研討中展示的基本樣例。我們將繼續發展關於如何實現CD4ML的想法。在本節結束時,我們強調了研討材料中沒有反映的一些改進領域,以及需要進一步探討的一些開放領域。

數據版本控制

在持續交付中,我們將每個代碼提交作爲一個發佈候選,這將觸發部署pipeline的新的執行動作。假設提交的代碼通過了所有pipeline階段,它就可以部署到生產環境中。而當談到CD4ML時,我們經常遇到的一個問題是“當數據發生變化時,我如何觸發pipeline?”

在我們的示例中,圖5中的機器學習pipeline從download data.py文件開始,該文件負責從共享的地方下載訓練集。如果我們在共享的地方更改數據集的內容,它並不會立即觸發pipeline,因爲代碼沒有更改,DVC也無法檢測它。要對數據進行版本控制,我們必須創建一個新文件或更改文件名,這反過來要求我們使用新的路徑更新download data.py腳本,並因此創建一個新的代碼提交。

這種方法的一個改進是允許DVC跟蹤我們的文件內容,其改進是在機器學習pipeline的第一步替換我們手寫的下載腳本,如圖9所示:

dvc add data/raw/store47-2016.csv ➊

(圖9:更新第一步來允許DVC跟蹤數據版本,同時簡化ML的pipeline)

這將創建一個元數據文件,該文件跟蹤文件內容的校驗和,我們可以將校驗和提交給Git。現在,當文件內容更改時,校驗和將更改,DVC將更新該元數據文件,這將是觸發pipeline執行時所需的提交。

雖然這允許我們在數據更改時重新訓練模型,但它並沒有說明數據版本控制的全部內容。一個方面是歷史數據:理想情況下你會想要保持所有數據的整個歷史變化,但這並不是總是可行的,具體取決於數據變化的頻率。另一個方面是數據來源:瞭解是什麼處理步驟導致了數據發生更改,以及如何跨越不同的數據集進行傳播。還有一個問題是隨着時間的推移來跟蹤和演進數據的模式,我們需要知道這些更改是否向後和向前兼容。

如果你在一個流媒體世界中,那麼數據版本控制的這些方面將變得更加複雜,因此我們希望在這個領域中有更多的實踐、工具和技術得到發展。

數據Pipelines

到目前爲止我們還沒有討論的另一個方面是如何對數據pipelines本身進行版本、測試、部署和監視。在現實世界中,一些工具選項比其他工具更好地支持CD4ML。例如,許多ETL工具需要通過GUI定義轉換和處理步驟,這些工具通常不容易進行版本控制,也不易於測試或部署到混合環境中。

我們傾向於使用開放源碼工具,這些工具允許我們在代碼中定義數據pipeline,這樣更容易進行版本控制、測試和部署。例如,如果你正在使用Spark,你的數據pipeline可能是用Scala編寫的,你可以使用ScalaTest或Spark -test -base對其進行測試,然後將該作業打包爲JAR構件,該構件就可以在GoCD中的部署pipeline上進行版本控制和部署。

作爲數據Pipelines通常作爲批處理作業運行或作爲一個長時間運行的流媒體應用程序,在圖8中,我們沒有包括他們在端到端的CD4ML流程圖,但如果他們改變了你的模型或應用程序的需要的輸出,就會造成另一個潛在來源的集成問題。因此,我們所追求的是將集成和數據Contract Tests作爲部署Pipelines的一部分來捕獲這些錯誤。

與數據Pipelines相關的另一種測試類型是數據質量檢查,但這可能成爲另一個廣泛討論的主題,最好在單獨的文章中討論。

平臺思維

你可能已經注意到,我們使用了各種工具和技術來實現CD4ML。如果您有多個團隊嘗試這樣做,他們可能最終可能會可能重塑事物或重複工作。這就是平臺思維的用武之地。不是通過將所有的工作集中到一個團隊中,導致他們成爲瓶頸,而是將平臺工程的工作集中到與領域無關的構建工具中,既隱藏了潛在的複雜性,也加快了團隊的上手速度。我們的同事Zhamak Dehghani在她的Data Mesh文章中對此進行了更詳細的討論。

將平臺思維應用於CD4ML是我們看到機器學習平臺和其他產品越來越受關注的原因,這些產品試圖提供一個單一的解決方案來管理端到端機器學習生命週期。許多主要的技術巨頭都開發了自己的內部工具,但我們相信這是一個活躍的研究和開發領域,並期望出現新的工具和供應商,提供可以被更廣泛採用的解決方案。

總結

隨着機器學習技術的不斷髮展和執行越來越複雜的任務,如何管理和交付此類應用程序到生產中的知識也在不斷髮展。通過從持續交付中引入和擴展的原則和實踐,我們可以更好地管理,以安全可靠的方式發佈對機器學習應用程序的更改的風險。

通過一個示例的銷售預測應用程序,我們在本文中展示了CD4ML的技術組件,並討論了實現這些組件的幾種方法。我們相信這種技術將會繼續發展,新的工具將會不斷出現和消失,但是持續交付的核心原則仍然是保持不變的,你應該爲自己的機器學習應用程序做更多的思考。

原文:Continuous Delivery for Machine Learning


跟多精彩洞見,請關注微信公號:ThoughtWorks洞見

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