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