還在用Github管理機器學習項目?你早該了解這些更專業的新工具!
大數據文摘出品
編譯:錢天培、胡笳
“太復雜了!機器學習(ML)項目實在太復雜了!”
聽到這種抱怨,熟悉軟件開發的小伙伴們往往是嗤之以鼻的。
機器學習,不過是和數據和軟件打交道。那就應該是是運行代碼、迭代算法的簡單問題呀?一段時間后,我們就能擁有一個***的訓練有素的ML模型。
有什么復雜的?
然而,當真正著手起機器學習項目,你就會發現:事情可沒有那么簡單!
在項目進行了一段時間后,你的訓練數據或許已經被更改或刪除,而你對訓練腳本的理解可能也已經十分模糊。
回過頭看你訓練好的模型,你可能也記不得每一個模型是怎么訓練出來的了;再或者,你想要查看先前訓練好的模型,卻發現模型早已被覆蓋。
更可怕的是團隊協作,你想要把你的工作分享給你的同事們,他們卻怎么也無法復現你的結果,更別提參與協作了。
別慌!今天,文摘菌就來帶大家系統地學習一下,如何正確地管理機器學習(ML)項目。
正如一般的軟件開發項目一樣,你需要更好地管理代碼版本和項目資產。在軟件開發項目中,人們可能需要重新審視項目先前的狀態。在機器學習項目中,我們該如何實現類似的審查呢?與Pull Request相對應的又是什么呢?
就我個人而言,我才剛剛開始接觸機器學習工具。在學習過程中,我觀看了一些教程視頻。老師們提到的一些問題會讓我想起我在軟件工程職業生涯早期碰到的難題。例如,在1993到1994年,我是一個開發電子郵件用戶代理的團隊***工程師。我們沒有任何源代碼管理(SCM)系統。每天我都會咨詢其他團隊成員,看看他們那天做了哪些改變,也就是在他們的源樹和主源樹之間運行一個diff操作,然后手動更改代碼。稍后,團隊成員從主源樹手動更新他們的源樹。
在我們發現早期的SCM系統(CVS)之前,這真是一團糟。SCM工具使項目運行得更加順利。
當我了解到機器學習和數據科學項目中使用的工具時,我發現機器學習過程就如上邊所說的那樣。即使在今天,機器學習研究人員有時會將實驗(數據,代碼等)存儲在并行目錄結構中,以便于進行diff審查,就像我在1993年所做的那樣。
那么,理想中的機器學習項目管理應該是怎么樣的呢?
ML項目管理原則
讓我們從一些簡要的ML項目管理原則說起。
在任何ML項目中,程序員們都會進行許多實驗,為目標場景開發***的訓練模型。實驗一般包含:
- 代碼和配置:實驗中使用的軟件,以及配置參數
- 數據集:任何輸入數據的使用——這可以是千兆級別大小的數據,比如語音識別、圖像識別項目中所用到的數據
- 輸出:訓練后的ML模型和實驗的任何其他輸出
機器學習項目本質也就是軟件運行。但是,與同事共享文件或復制結果,并及時回顧以評估項目通常十分困難。我們需要更全面的管理工具。
解決方案需要涵蓋以下幾點(從Patrick Ball的題為《原則性數據處理》的演講中摘錄):
(1) 透明性:方便檢查ML項目的方方面面
- 使用什么代碼、配置和數據文件
- 工程項目采用什么工序,工序的次序是什么
(2) 可審核性:方便檢查pipeline的中間結果
(3) 可復現性:在開發的任何階段精確地重新執行項目的能力,以及同事精確地重新執行項目的能力
- 記錄處理步驟,以便任何人都可以自動重新運行這些步驟
- 在項目進行過程中記錄項目的狀態。“狀態”表示代碼、配置和數據集
- 能夠在項目歷史的任何時候重新創建可用的精確數據集
(4) 可擴展性:支持多個同事同時處理一個項目的能力,以及同時處理多個項目的能力。
為什么不在機器學習項目中使用常規的軟件工程工具?
誠然,在常規軟件工程項目中使用的許多工具可能對機器學習研究人員有用。
在常規的源代碼管理系統(如Git)中可以輕松地管理代碼和實驗配置,并且可以使用pull request之類的技術來管理對這些文件的更新。CI/CD(Jenkins等)系統甚至可以用于自動化項目運行。
但是,ML項目另有不同之處,使得普通的軟件開發工具無法滿足所有的需求。下面是幾個重要的不同點:
- 度量標準驅動(metrics-driven)的開發與特性驅動(feature-driven)的開發:在常規軟件工程中,“是否發布”這一決策基于團隊是否達完成了一些特征。相比之下,機器學習研究人員研究的是一種完全不同的測量方法——生成的機器學習模型的預測值。研究人員將迭代地生成幾十個(或更多)模型,測量每個模型的準確性。由于目標是找到最精確的模型,因此項目由每個實驗中實現的度量指標來指導。
- 機器學習模型需要大量的資源來訓練:一個常規的軟件項目將文件組織在一起編譯一個軟件產品,而機器學習項目則訓練一個描述AI算法的“模型”。在大多數情況下,編譯一個軟件產品只需要幾分鐘,非常快速,因此許多團隊遵循持續集成(continuous integration)的策略。訓練一個機器學習模型則需要很長時間。除非必要,***避免持續集成。
- 龐大的數據集和訓練好的模型:機器學習開發階段幾乎總是需要龐大的數據集,此外,訓練過的模型也可能是巨大的。普通的源代碼管理工具(Git等)不能很好地處理大型文件,而且Git- lfs之類的附加組件也不適合ML項目。
- 工作流(pipelines):機器學習項目是一系列步驟——如下載數據、準備數據、將數據分離到培訓/驗證集、培訓模型和驗證模型。許多人使用pipelines這個詞來描述整個過程,意思是用每個步驟的離散命令來構造機器學習項目,而不是把所有東西都塞進一個程序中。
- 專用硬件:軟件開發商可以將其軟件基礎設施托管在任何類型的服務器設備上。如果他們想要一個云部署,他們可以從他們喜歡的云計算提供商那里租用VPS。然而,機器學習研究人員有巨大的計算需求。高性能GPU不僅可以加速視頻編輯,還可以讓ML算法加速“飛”起來,大大縮短了訓練ML模型所需的時間。
現在,我們已經有了一個機器學習項目開發的原則列表,并了解了ML項目和普通軟件開發項目的不同之處。
接下來,讓我們看看有哪些開源軟件可以幫助我們實現這些原則。
我們將特別討論兩個工具,MLFlow和DVC。當然,還有很多其他軟件可以取得類似的效果。
機器學習項目中的數據與模型存儲
我們的討論可以歸結為:
- 跟蹤每一輪訓練機器學習模型使用的數據文件
- 跟蹤訓練后的模型和評估指標
- 通過任何形式的文件共享系統與同事共享數據文件的簡單方法
總的來說,我們需要一個數據跟蹤系統來透明地審計、或者復現結果。我們也需要一個數據共享系統來將項目團隊擴展到多個同事。
就如我們先前討論的一樣,使用Git或其他SCM(源代碼管理系統)來存儲機器學習項目中使用的數據文件是不切實際的。
一些庫提供了API來簡化遠程存儲上的文件處理,并管理向遠程存儲上傳或獲取文件。雖然這有利于遠程數據集的共享訪問,但卻對我們面對的問題沒有幫助。
首先,它是嵌入式配置的一種形式,因為文件名被嵌入到軟件中。在源代碼中嵌入配置設置的任何程序在其他情況下都更難以被重新使用。其次,它沒有將腳本版本和其使用的數據文件關聯起來。
下面,然后我們看一下MLFlow的示例代碼:
- mlflow.pytorch.load_model("runs:/<mlflow_run_id>/run-relative/path/to/model")
這支持多種文件訪問“方案”,包括S3這樣的云存儲系統。這里的示例從“run”區域加載一個文件,在本例中是一個經過訓練的模型。每次執行一段代碼時,MLFlow都會生成一個“run”。你需要配置一個存儲“run”數據的位置,并且顯然會為每個用于索引到數據存儲區域的運行生成一個“run ID”。
這種方式有效地將數據與對應SCM源碼管理庫中的代碼和配置文件的commit提交版本關聯起來。此外,MLFLow API有多種實現語言,并不局限于 Python語言。
DVC采用的則是另一種方式。對比上面將文件API集成到ML腳本中,你的腳本可以簡單地使用普通文件系統的API實現輸入和輸出文件。例如:
- model=torch.load(‘path/to/model.pkl’)
通過上述代碼,路徑名稱將通過這條命令傳入。你無需特別修改代碼,因為DVC可以通過外部傳遞訓練代碼或驗證模型代碼需要的值。
DVC讓這一切變得透明——數據文件版本與代碼的Git版本是相匹配的。
通過下述命令,你可將文件或文件夾加入DVC的版本管理:
- $ dvc add path/to/model.pkl
數據存儲在你的工作目錄中。瀏覽各項運行的結果也很簡單,只需要瀏覽你的Git歷史即可。查看特定結果就像git checkout一樣簡單,DVC將被調用,并確保將正確的數據文件連接到workspace。
一個”DVC文件”將被創建,用于追蹤每個文件及目錄,并將被添加到workspace中。這樣做有兩個目的,一是可以追蹤數據和模型文件,另一個則是記錄工作流程中的命令。我們將在下一節中介紹這部分。
這些DVC文件記錄文件和目錄的MD5總和校驗碼(MD5 checksum)。他們被提交到git workspace上,因此DVC文件記錄了每次git提交的每個文件的總和校驗碼。DVC使用了“DVC緩存目錄”來存儲每個文件的多個實例。文件實例通過總和校驗碼進行索引,并使用reflinks或symlinks鏈接到workspace。當DVC響應git checkout命令時,它能夠根據DVC文件中的總和校驗碼快速地重排鏈接文件。
DVC支持遠程緩存目錄,用于共享文件和模型。
- $ dvc remote add remote1 ssh://user@host.name/path/to/dir$ dvc push$ dvc pull
DVC remote是一個存儲池,可以進行數據共享。它支持許多存儲服務,包括S3、HTTP和FTP等。創建一個DVC remote非常簡單。dvc push和dvc pull命令高度模擬了git push 和git pull命令。dvc push用于將數據發送到遠程DVC的緩存中,dvc pull用于從遠程DVC緩存中拉取數據。
機器學習項目中的工作流描述
接下來,我們將討論如何更好地描述機器學習項目的工作流。我們應該一股腦將所有東西堆成一個程序嗎?還是應該使用多種工具?
為了盡可能地創造靈活性,我們可以將工作流通過pipeline或有向無環圖(DAG),并采用命令行參數作為配置選項的方式來實現。這有點類似Unix哲學中的小而精巧的工具——小巧但可以很好地協同工作。其行為可由命令行選項或環境變量指定,并且可以根據需要任意搭配使用。
相比之下,很多ML框架采用不同的方式。他們編寫單獨的程序來驅動特定項目的工作流。程序***步先將數據拆分為訓練集和驗證集,然后訓練模型并驗證模型。這種整套的單獨程序可帶來重用代碼的機會有限。
將ML項目構建pipeline可帶來如下好處
- 管理復雜性:將這些步驟作為單獨命令實現可以提高透明度,并幫助你更加集中精力。
- 優化執行:可以跳過那些沒有修改且不需要返回值的步驟。
- 可重用性:在多個項目中可重用相同的工具。
- 可擴展性:不同的工具可由不同的團隊成員獨立開發。
在MLFlow中,你需要編寫一個“驅動程序”。這個程序包含了所需的執行邏輯,例如處理及生成機器學習模型。在程序背后,MLFlow API發送請求給MLFlow 服務器,通過該服務器生成指定的命令。
下面這個多步驟工作流的MLFlow例子清晰的展示了這一切。
- ...load_raw_data_run = _get_or_run("load_raw_data", {}, git_commit)ratings_csv_uri = os.path.join(load_raw_data_run.info.artifact_uri, "ratings-csv-dir")etl_data_run = _get_or_run("etl_data", {"ratings_csv": ratings_csv_uri, "max_row_limit": max_row_limit}, git_commit)…als_run = _get_or_run("als", {"ratings_data": ratings_parquet_uri, "max_iter": str(als_max_iter)}, git_commit)…_get_or_run("train_keras", keras_params, git_commit, use_cache=False)...
_get_or_run函數是mlflow.run的一個wrapper。每個調用函數中的***個參數為在MLproject文件中定義的entrypoint。每個entrypoint包含環境變量,要運行的命令,以及傳遞給該命令的參數。例如:
- etl_data: parameters: ratings_csv: path max_row_limit: {type: int, default: 100000} command: "python etl_data.py --ratings-csv {ratings_csv} --max-row-limit {max_row_limit}"
乍一看感覺非常不錯。但是這里有幾個問題值得思考:
- 如果你的工作流是比直線流程更復雜的情況怎么辦?你可以將傳給mlflow.run的同步參數設為false,然后等待SubmittedRun對象標記任務已完成。也就是說,可以在MLFlow API上構建流程管道系統。
- 為什么需要服務器?為什么不直接通過命令行執行命令?增加服務器及其配置使得MLFlow項目的設置更加復雜。
- 如何避免執行那些不需要的任務?在許多ML項目中,訓練模型通常需要數天時間。資源應該只有在需要時才應該被使用,例如更換數據,修改參數或算法。
DVC可以使用常規命令行工具,并且既不需要設置服務器也不需要編寫驅動程序。DVC支持使用前面提到的,通過一組DVC文件將工作流定義為有向無環圖(DAG)。
我們之前提到了,DVC文件會與添加到workspace中的文件相關聯。DVC文件同時還描述了要執行的命令:
- $ dvc run -d matrix-train.p -d train_model.py \ -o model.p \ python train_model.py matrix-train.p 20180226 model.p$ dvc run -d parsingxml.R -d Posts.xml \ -o Posts.csv \ Rscript parsingxml.R Posts.xml Posts.csv
dvc run命令定義了一個DVC文件,其中包含了需要執行的命令。-d參數記錄了對文件的依賴性,DVC將根據校驗總和碼來檢測文件的更改。-o參數表示命令輸出設置。一個命令的輸出同樣可以用于另一個命令的輸入。通過查看依賴關系和輸出,DVC可以計算出執行命令的順序。
AI輸出(包含訓練模型)將被自動的記錄在DVC的緩存中,workspace中的其他數據文件也如此。
因為它計算校驗和,DVC可以檢測到更改的文件。當用戶請求DVC重新執行管道時,它只執行有變化的那部分。輸入文件沒有變化的情況,DVC可以節省大量模型訓練任務所需要的時間。
所有的執行都使用常規命令行,不需要設置服務器。如果你希望在云計算環境,或在附加GPU的服務器上執行,只需要將代碼和數據部署到該服務器上,并通過命令行執行DVC命令即可。
總結
我們在提高機器學習實踐原則的探索上已經走了很長一段路。如我們所知,機器學習領域需要更好的管理工具,以便機器學習團隊能夠更有效、更可靠地工作。
結果可復現意味著他人可以評估你已完成的工作,或者協作進行更深層的開發。可重復性具有很多先決條件,包括能夠檢查系統的每個部分,以及能夠精確地重新運行軟件及輸入數據。
機器學習項目中,一些GUI工具有非常漂亮的用戶界面,例如Jupyter Notebook。這些工具在機器學習的工作中占有一席之地。但是,GUI工具不太適合本文討論的原則。命令行工具非常適合處理在后臺運行的任務,并且可以輕松地滿足我們上述的所有原則。而一般的GUI則會妨礙這些原則。
正如本文中描述的一樣,我們可以從常規軟件工程中借用很多工具和實踐方式。但是,機器學習項目的特殊性決定了我們需要用到更適合其目標的工具。這些有價值的工具包括:MLFlow,DVC,ModelDb,Git-LFS等等。
相關報道:https://dev.to/robogeek/principled-machine-learning-4eho
【本文是51CTO專欄機構大數據文摘的原創文章,微信公眾號“大數據文摘( id: BigDataDigest)”】