磚的筆記本+ MLflow自動化部署和測試
今天許多數據科學(DS)組織正在加速使用磚筆記本的敏捷開發過程分析。充分利用Apache火花™的分布式計算能力,這些組織能夠輕易與數據交互中的規模,從探索快速原型和productionize複雜的機器學習(ML)模型。快速迭代實現在高速度,越來越明顯的是,它是簡單的DS生命周期管理效率、再現性和高質量。挑戰繁殖在大型企業數據量呈指數級增長,投資回報率高的期望從數據中獲得商業價值,和跨職能協作是常見的。
在這個博客中,我們引入一個聯合工作IterableDS變硬的過程與軟件開發最佳實踐。這種方法的自動化構建、測試和部署的DS工作流內部磚筆記本和集成完全MLflow和磚CLI。它使適當的版本控製和綜合錄井的重要指標,包括功能測試和集成測試,模型性能指標和數據沿襲。這些都是實現不需要維護一個單獨的構建服務器。
概述
在典型的軟件開發工作流程(例如Github流),一個特性分支創建基於主分支功能開發。筆記本可以同步特性分支通過Github集成。從Databrick工作區或筆記本可以導出你的筆記本電腦和代碼更改提交到git命令的特性分支。開發準備評審時,把請求(PR)設置和功能部門會被部署到集成測試的登台環境。一旦測試和批準,特性分支將被合並到主分支。主分支總是樂於被部署到生產環境中。
在我們的方法中,部署和測試流程的司機是一個筆記本。司機筆記本可以運行在自己的集群或集群與其他部署共享筆記本專用的高並發性。筆記本可以手動觸發或他們可以集成構建服務器對於一個成熟的CI / CD的實現。輸入參數包括部署環境(測試、分期、刺激等),一個實驗id, MLflow日誌消息和工件,和源代碼的版本。
如下描述的工作流,司機筆記本從初始化開始訪問令牌磚工作區和源代碼回購(例如github)。構建和部署過程的司機節點集群上運行,並構建工件將被部署到dbfs目錄。部署狀態和消息可以記錄當前MLflow運行的一部分。
部署後,功能測試和集成測試可以由司機筆記本。測試結果被記錄的一部分運行在一個MLflow實驗。從不同的運行測試結果相比MLflow可跟蹤。在這個博客中,python和scala代碼提供的例子如何利用MLflow跟蹤能力在你的測試。
筆記本電腦自動化部署過程
首先,創建一個uuid和專門的工作目錄的並發部署部署,以便相互隔絕。下麵的代碼片段顯示了如何部署uuid分配從活動的運行id的MLflow實驗,以及如何創建工作目錄。
進口mlflowactive_run = mlflow.start_run (experiment_id = experiment_id)deploy_uuid = active_run.info.run_id工作區=“/ tmp / {}”。格式(deploy_uuid)打印(“工作區:{}”。格式(工作區))如果不os.path.exists(工作區):os.mkdir(工作區)
進行身份驗證和訪問數據磚CLI和Github,您可以設置個人訪問令牌。設置CLI認證的細節可以發現:磚CLI >設置身份驗證。訪問令牌應小心使用。明確包括筆記本的令牌可以是危險的。令牌不小心可以暴露當筆記本出口和與其他用戶共享。
保護你的令牌的方法之一是把令牌存儲在磚的秘密。首先需要創建一個範圍:
磚秘密創建範圍——cicd-test範圍
一個令牌存儲在一個範圍:
磚的秘密——範圍cicd-test關鍵牌
訪問令牌存儲在秘密,dbutils.secrets.get
可以利用。獲取令牌顯示在筆記本(修訂)。允許訪問令牌可以使用定義ACL的秘密。關於秘密的API的更多細節,請參閱磚秘密的API。
下麵的代碼片段顯示了如何從一個檢索範圍:秘密
db_token=dbutils.secrets.get (範圍=pipeline_config (“secrets_scope”)鍵=pipeline_config [" databricks_access_token "])git_username=dbutils.secrets.get (範圍=pipeline_config (“secrets_scope”)鍵=pipeline_config [" github_user "])git_token=dbutils.secrets.get (範圍=pipeline_config (“secrets_scope”)鍵=pipeline_config [" github_access_token "])
磚可以設置通過訪問.databrickscfg
文件,如下所示。請注意,每個都有自己的工作目錄.databrickscfg
文件支持的並發部署。
dbcfg_path = os.path.join(工作區,“.databrickscfg”)與開放(dbcfg_path“w +”)作為f:f.write (“(默認)\ n”)f.write (“主機= {}\ n”。格式(db_host_url))f.write (“令牌= {}\ n”。格式(db_token))
下麵的代碼片段顯示了如何查看源代碼從Github代碼版本。不包括建設過程但結帳後可以添加的步驟。在那之後,工件部署到dbfs位置,筆記本可以導入到磚的工作空間中。
行=“‘# ! / bin / bash出口DATABRICKS_CONFIG_FILE = {dbcfg}回聲“cd{工作區}/ {repo_name} /筆記本電腦/”cd{工作區}/ {repo_name} /筆記本電腦/回聲“target_ver_dir = {target_ver_dir}”磚的工作區中刪除- r {target_ver_dir}磚工作區mkdir {target_ver_dir}如果[[$ ?! = 0]];然後退出1;fi磚工作區import_dir {source_dir} {target_ver_dir}“‘。格式(target_base_dir = target_base_dir git_hash = git_hash deploy_env = deploy_env repo_name = repo_name target_ver_dir = target_ver_dir git_url = git_url pipeline_id = pipeline_id工作區=工作區,dbcfg = dbcfg_path)與開放(“{}/ deploy_notebooks.sh”。格式(工作區),“w +”)作為f:f.writelines(線)過程= subprocess.Popen ([“bash”,“{}/ deploy_notebooks.sh”。格式(工作區)],stdout =子流程。管,stderr = subprocess.PIPE)sys.stdout.write (process.communicate () (0])
部署跟蹤
為可見性狀態的部署,我們通常可能存儲在數據庫或使用某種管理部署服務的UI。在我們的例子中,我們可以使用MLflow用於這些目的。
等元數據部署環境中,應用程序的名字,筆記可以記錄MLflow跟蹤API:
試一試:mlflow.log_param (“run_id”active_run.info.run_uuid)mlflow.log_param (“env”deploy_env)mlflow.log_param (“githash”git_hash)mlflow.log_param (“pipeline_id”,pipeline_config [“pipeline-id”])mlflow.log_param (“deploy_note”deploy_note)除了:clean_up (active_run.info.run_uuid)提高
觸發筆記本
現在我們已經部署我們的筆記本電腦在我們工作區路徑,我們需要能夠觸發的正確版本的筆記本電腦環境。我們可能筆記本版本在珠江三角洲環境同時登台環境測試版本B。
每個部署係統都需要一個真理的來源“部署”的映射githash為每一個環境。對我們來說,我們利用磚δ,因為它為我們提供了事務擔保。
對我們來說,我們隻是在部署三角洲表中查找githash對於一個給定的環境和運行筆記本這條道路。
dbutils.notebook.run (PATH_PREFIX + s“$ {git_hash} /筆記本”,…)
在生產中
在Iterable,我們需要迅速采取行動,避免設置重基礎設施部署和觸發係統如果可能的話。因此我們開發了這種方法與李磚,這樣我們可以進行我們的大多數工作流磚內部,利用三角洲作為數據庫,並使用MLflow部署視圖狀態的真理。
因為我們的數據科學家磚內工作,現在可以部署在磚他們最新的變化,利用MLflow和磚筆記本提供的界麵,我們能夠快速迭代,而擁有一個健壯的部署和觸發係統部署之間的零停機。
實現測試
測試和驗證可以通過調用斷言語句添加到您的筆記本電腦。然而從斷言錯誤消息分散在筆記本,沒有可用的測試結果的概述。在本節中,我們將向您展示如何使用MLflow自動化測試從筆記本電腦和跟蹤結果跟蹤api。
在我們的例子中,一個司機筆記本作為的主要入口點所有的測試。司機筆記本源控製,可以調用從部署筆記本。司機筆記本,測試/測試筆記本的列表定義出發,經由運行並生成測試結果。測試可以一組特定於當前分支的回歸測試和測試。司機筆記本處理創建MLflow範圍和記錄測試結果的正確運行實驗。
deflog_message(test_name:str味精:str):如果experiment_id:mlflow.log_param (test_name, msg)打印(“{}{}”。格式(msg) test_name)deftest_notebook(notebook_path):進口時間test_name = get_notebook_name (notebook_path)試一試:start_time = time.time ()結果= dbutils.notebook.run (notebook_path,120年,{“egg_file”:egg_file})elapsed_time = time.time () - start_timelog_message (test_name,結果)mlflow.log_metric (“{}_dur”。格式(elapsed_time test_name))除了異常作為艾凡:log_message (test_name“失敗”)打印(e)為t在test_notebooks:test_notebook (t)
下圖顯示了一個屏幕截圖MLflow的一個實驗,其中包含從不同的運行測試結果。每個運行基於代碼版本(git提交),這也是記錄的參數運行。
MLflow UI為終端用戶提供了強大的功能,探索和分析他們的實驗結果。結果表可以通過特定的過濾參數和指標。指標從不同的運行可以比較和生成一個趨勢的指標如下:
單元測試的功能也由MLflow跟蹤。一個常見的測試夾具可以實現日誌記錄元數據的測試。測試類將繼承這常見的夾具包括MLflow跟蹤能力測試。我們當前的實現是基於——scalate雖然類似的實現可以用其他測試框架。
下麵的代碼示例顯示了如何固定(testTracker
)可以被定義為覆蓋withFixture
方法TestSuiteMixin
。一個測試函數傳遞withFixture
和執行內部withFixture
。這種方式,withFixture
服務器作為測試的包裝器函數。前和後處理的代碼可以實現內部withFixture
。在我們的例子中,預處理是記錄測試的開始時間,和後處理是記錄元數據的一個測試函數。任何測試套件也繼承了這個裝置會自動運行這個夾具之前和之後的每個測試記錄元數據的測試。
進口org.scalatest._進口scala.collection.mutable._特質TestTracker擴展TestSuiteMixin {這:TestSuite= >vartestRuns = scala.collection.mutable.Map [字符串MetricsTrackData] ()varenvVariables:字符串=”“/ /與實際的測試套件名稱被覆蓋vartestSuiteName:字符串.toString = randomUUID ()
摘要覆蓋def withFixture(測試:NoArgTest) = {val ts = System.currentTimeMillis ()val t0 = system . nanotime ()vartestRes:布爾=假var例:字符串=”“試一試超級.withFixture(測試)匹配{情況下結果:結果= >如果(結果。isFailed | | result.isCanceled) {val = result.asInstanceOf失敗(失敗)= failed.exception.toString交貨}其他的如果(result.isCanceled) {val取消= result.asInstanceOf[取消]= canceled.exception.toString交貨}其他的如果(結果。isSucceeded) {testRes =真正的}結果情況下其他= >其他}最後{/ /待辦事項:記錄你的指標}}def AllTestsPassed ():布爾= {如果(testRuns。大小= =0)真正的其他的{testRuns.values。原則,{t= >t.status}}}}
一個測試套件需要擴展TestTracker
將日誌記錄自己的測試能力。下麵的代碼示例顯示了如何繼承測試夾具上麵定義的元數據日誌記錄功能:
類TestClass擴展FlatSpec與TestTracker{“addCountColumns”應該“添加正確計數”在{/ /待辦事項:測試你的函數/ /維護(…)}}/ /運行測試val測試=新TestClasstest.execute ()
討論
在這個博客中,我們回顧了如何構建一個CI / CD管道結合磚CLI和MLflow的能力。這種方法的主要優點是:
- 部署筆記本生產而無需建立和維持一個構建服務器。
- 自動記錄指標的測試。
- 提供查詢功能的測試。
- 概述的部署狀態和測試結果。
- ML算法性能跟蹤,可以分析(例如漂移檢測模型、性能下降)。
使用這種方法,您可以快速建立一個生產管道磚環境。你也可以擴展方法通過添加更多的約束為自己的隨筆過程和步驟。
學分
我們要感謝下列因素:丹尼李,克裏斯托弗•Hoshino-Fish Ankur Mathur安德烈Mesarovic,克萊門斯Mewald