從工具選擇到團隊溝通,看ML工程師一步步打造生產(chǎn)級機器學(xué)習(xí)
為了讓機器學(xué)習(xí)為用戶帶來真正的價值,我們需要將其部署到生產(chǎn)系統(tǒng)中。人工智能銷售軟件開發(fā)公司 Toucan AI 的 ML 工程師 Marifel 介紹了他們在打造生成級機器學(xué)習(xí)時所考慮的一些問題,希望這些經(jīng)驗?zāi)転槟愕墓ぷ鲙韼椭?/p>
這些年,隨著數(shù)據(jù)和計算技術(shù)的發(fā)展,「機器學(xué)習(xí)」和「深度學(xué)習(xí)」已經(jīng)變成了熱門研究領(lǐng)域。對公司來說,雖然使用機器學(xué)習(xí)很時髦,但首先還是需要評估一下自己的業(yè)務(wù)能否從中受益。如果你的公司已經(jīng)認(rèn)定機器學(xué)習(xí)對公司的下一步發(fā)展來說是必需的,那么作為機器學(xué)習(xí)工程師的你就該思考如何為生產(chǎn)環(huán)境構(gòu)建機器學(xué)習(xí)過程了。希望本文能幫你明晰你需要考慮的一些東西。
注:本文所提到的「創(chuàng)業(yè)公司」都是指有軟件「產(chǎn)品」的公司;對于提供軟件「服務(wù)」的公司,則會專門指明。軟件產(chǎn)品公司的業(yè)務(wù)重心是開發(fā)自己的軟件產(chǎn)品,而軟件服務(wù)公司(如代理商或咨詢公司)則是為客戶開發(fā)軟件。盡管這篇文章是根據(jù)作者在早期階段的軟件產(chǎn)品創(chuàng)業(yè)公司擔(dān)任機器學(xué)習(xí)工程師的經(jīng)歷寫的,但其中某些思考也適用于其它階段的公司或其它公司類型。
本文作者、Toucan AI 公司 ML 工程師 Marifel。
尋找對你有用的工具
機器學(xué)習(xí)軟件的選擇有很多,有開源的工具,比如 PyTorch、TensorFlow 和 scikit-learn;也有企業(yè)提供的機器學(xué)習(xí)服務(wù),比如 Google AI Platform、Amazon SageMaker 和 Azure Machine Learning。光是 PyTorch 和 TensorFlow,就有很多開源的軟件庫可用,這些直接可用的模型可用作開發(fā)產(chǎn)品的起點。
此外,每年還有大量不同領(lǐng)域的機器學(xué)習(xí)研究論文發(fā)表,有的研究者還會以開源形式提供代碼。https://paperswithcode.com/ 這個網(wǎng)站可用來尋找?guī)в写a的論文資源。
選擇合適工具所要考慮的關(guān)鍵因素包括:
- 文檔的質(zhì)量;
- 工具的開發(fā)情況(有的工具仍有人維護,有的則已經(jīng)中止開發(fā)或已被啟用,或者有嚴(yán)重的問題等等);
- 圍繞該工具的其它工具所構(gòu)成的生態(tài)系統(tǒng);
- 參與該工具開發(fā)的開發(fā)者社區(qū);
- 團隊成員對該工具的熟悉程度;
- 將會使用該工具的團隊的規(guī)模;
- 該工具所涉及的資金成本。
在作者個人看來,如果你在一家處于早期階段的創(chuàng)業(yè)公司,則不必搞清楚所有這些因素。你可以先選擇一種強大的工具,然后就此出發(fā)。另外,在開始的時候使用企業(yè)提供的機器學(xué)習(xí)服務(wù)也是完全可以的,只要你覺得這樣做所帶來的收益能超過你的投入。
何時做機器學(xué)習(xí)以及圍繞機器學(xué)習(xí)的發(fā)展過程
開發(fā)伊始,使用簡單的基準(zhǔn)模型是很好的做法。從更簡單的模型開始操作能幫助你找出工作流程中的問題,還能幫你了解是否值得采用更耗時間的解決方案。那么,你該如何選用簡單的基準(zhǔn)模型呢?
首先,「簡單」是相對的。在某些案例中,簡單的意思是模型簡單,比如硬編碼一些直觀理解的結(jié)果。而在另一些案例中,模型本身可能很復(fù)雜,但是很容易應(yīng)用。某些被廣泛應(yīng)用的數(shù)據(jù)集有一些開源的當(dāng)前最佳模型,你能在研究論文或排行榜等地方找到它們;比如斯坦福問答數(shù)據(jù)集(SQuAD)就有這樣一個排行榜。你可以尋找一些當(dāng)前最佳的解決方案,然后尋找與該研究論文相關(guān)的代碼。這能為你提供很好的起點。
在早期階段的創(chuàng)業(yè)公司,你可能沒有時間馬上動手開發(fā)機器學(xué)習(xí)過程。通常而言,你的工作重心是早點做出一些有效的東西展示給你的投資者或客戶。他們通常不是很關(guān)心過程的優(yōu)化。所以不要在意你的初始部署完美與否;它們只需能得到有效的結(jié)果就行,即真實可見的最終產(chǎn)品。你可以在做好基礎(chǔ)產(chǎn)品之后再去考慮機器學(xué)習(xí)過程的相關(guān)事項,這時候你會有更多的空閑時間,可以為你的機器學(xué)習(xí)過程應(yīng)用小型的增量改進。
相反,如果你是一家代理商,因為你已經(jīng)將成品提供給了不同的客戶,并已經(jīng)事先修復(fù)了所有漏洞,因此出錯的空間更小。在向客戶發(fā)貨了產(chǎn)品之后,你會轉(zhuǎn)向下一個客戶合同,因此通常不會有資源來進行進一步的改進。盡管如此,作為一家代理商,你仍然必須快速行動。為了做到更快,擁有一個更細化的機器學(xué)習(xí)工作過程會大有裨益。因此對于代理商的模型而言,如果事先花更多時間來進行細化和自動化,也許能為更長遠業(yè)務(wù)節(jié)省時間。
實驗管理中所要考慮的事項
在機器學(xué)習(xí)工作中,實驗管理并不輕松。當(dāng)你正盡可能多地運行實驗時,很容易就會把你的項目工作區(qū)搞得一團糟。但是,在早期階段的創(chuàng)業(yè)公司,你沒有辦法投入幾個月的時間來運行數(shù)百場實驗。你只得必須關(guān)注更好的東西,然后盡可能快地進行更新。無論如何,在實驗管理方面,有肯定比沒有好。下面是在管理機器學(xué)習(xí)實驗時需要考慮的一些地方。
模型版本控制
我們 Toucan AI 使用 GitHub 來存儲不同版本的代碼。GitHub 很不錯,但不適合對大型數(shù)據(jù)文件進行版本控制。盡管一個代碼庫可以高達 100GB,但 GitHub 建議將代碼庫的規(guī)模保持在 1GB 以下;此外,單個文件的大小也不能超過 100MB。
你可以使用其它云存儲服務(wù),比如 Google Cloud Storage 或 Amazon S3。使用云提供商的命令行工具或網(wǎng)絡(luò)用戶接口,只需創(chuàng)建一個存儲空間(文件夾),就能實現(xiàn)對目標(biāo)(文件或文件夾)的版本控制。但是,如果你希望同步你的云存儲和你的 GitHub 項目代碼庫,還需要進行一些額外的人工操作。
因此,我們選擇了最自然的集成方案,其中組合了 Git 平臺的最佳特性以及其它云存儲選擇的優(yōu)勢:數(shù)據(jù)版本控制(DVC,https://dvc.org/。該項目的宣傳語是「用于機器學(xué)習(xí)項目的開源版本控制系統(tǒng)」。
DVC 是一款命令行工具,其帶有的子命令與 Git 子命令非常類似。設(shè)置好 Git 平臺與云存儲之后,你可以運行 DVC 的 add 和 push 命令,在云存儲中以文件或文件夾的形式保存不同的版本。同時,你還可以通過 DVC 文件的引用功能在你的 Git 項目代碼庫中跟蹤較大的數(shù)據(jù)文件。DVC 的一大優(yōu)勢是僅需要少量類 Git 的命令,讓你不至于與已有的 Git 工作流程脫節(jié)。
為實驗編寫文檔
如果你在調(diào)節(jié)超參數(shù),可能很容易就會忘記你在特定時間運行過的某個模型的某種設(shè)置。為了為這個模型準(zhǔn)備或預(yù)處理數(shù)據(jù)集,你可能還必須回顧一下你之前的工作。你的 Jupyter Notebook 可能具有大致了描述了其中內(nèi)容的文件名,但你仍然需要些時間才知道當(dāng)時做了什么——先做了 A 還 B?
針對這個問題,一種解決方案是在你的筆記文件名中加入排序號(我喜歡使用 step 01_),而且你之后也可以重新調(diào)整順序。為筆記文件使用清晰明了的命名規(guī)則和排序方式能為你的團隊(以及未來的你)提供很大的幫助,讓他們能快速了解你究竟是如何做實驗的。除了在實踐中為筆記文件排序,我們也可使用開源平臺 MLflow(https://mlflow.org (https://mlflow.org/)),其提供了可用于查看實驗超參數(shù)和度量結(jié)果的網(wǎng)絡(luò)接口。
此外,在為實驗編寫文檔時,你還應(yīng)關(guān)注邏輯結(jié)構(gòu)和簡潔性。對于一個又一個模型的筆記和訓(xùn)練腳本,你需要充分利用文件夾結(jié)構(gòu)的命令規(guī)則來進行組織管理。假設(shè)有讀者在閱讀你的筆記本,他們通常會從上到下閱讀,所以你要移除那些臨時倉促添加的部分。根據(jù)過往經(jīng)驗,你應(yīng)該為一個模型和一個數(shù)據(jù)集寫一個筆記,如果當(dāng)前的筆記過長,也要創(chuàng)建一個新筆記。你的最終版筆記不應(yīng)該包含訓(xùn)練和推理過程的代碼;這些應(yīng)被放在另外的腳本中,然后你可以在筆記中調(diào)用它們。最后,當(dāng)你在使用 MLflow 等軟件來生成實驗記錄時,可以試試將運行實驗的筆記自動引用到所生成的實驗輸出文件中。
測試框架
在某個指標(biāo)上得到更好的分?jǐn)?shù)并不意味著你的模型能在真實世界樣例上取得更好推理結(jié)果。此外,在生產(chǎn)級機器學(xué)習(xí)系統(tǒng)中,機器學(xué)習(xí)模型通常并不單獨工作。舉個例子,你的工作流程中可能包含探索方法、預(yù)處理和緩存的結(jié)果。因此,當(dāng)你嘗試改進你已有的機器學(xué)習(xí)模型時,你要意識到打造出適用于真實世界的推理樣例需要大量時間。
你需要深入理解更大規(guī)模的生產(chǎn)代碼,了解你想要改進的模型在實際情況中被調(diào)用的時機。你不能只是檢查一下輸入和輸出,僅了解模型本身的情況,而要檢查整個機器學(xué)習(xí)系統(tǒng)工作過程。你改進的模型將如何影響整個系統(tǒng)?效果更好還是更差?
為了真正實現(xiàn)模型提升,而不只是想出一些新的推理樣例或改變生產(chǎn)流程中的某些東西,我們需要配置一個自動化系統(tǒng)或端到端的測試框架。
我們 Toucan AI 的主要產(chǎn)品是一款 AI 銷售智能體,因此測試覆蓋主要邏輯分支的示例對話就足夠了,并且我們還提供了一種形式的回歸測試。我們目前正在開發(fā)一款命令行工具(command-line interface,CLI),該工具可以基于一系列示例對話運行 pytest 審定: https://docs.pytest.org/en/latest/。只需一行命令就可以測試所有對話,如果有任何測試不過關(guān),我們就會以人工方式更新該測試或評估我們的「更好」模型是否真的能更好地應(yīng)對生產(chǎn)環(huán)境。
簡而言之,為了了解你當(dāng)前的實驗?zāi)P驮谏a(chǎn)機器學(xué)習(xí)系統(tǒng)中的表現(xiàn),配備一個測試框架是非常重要的。有了好用的測試框架,你的模型改進工作流程能更高效地運行,讓你可以比之前運行更多實驗。
使用還在快速演進的工具
在我們的生產(chǎn)系統(tǒng)中,我們往往使用的是更老版本代碼庫的修改版;如果這個代碼庫正在快速演進,我們可能很難將新的改進整合到生產(chǎn)系統(tǒng)中。因此,對于正在快速演進的代碼庫,你該如何對其進行修改以滿足自己的需求以及盡可能高效地應(yīng)用其最新的更新呢?
我認(rèn)為這個問題不存在唯一的正確答案,而是有很多不同的路徑可走。其中一條路是將他們的一部分代碼與你的一部分代碼組合起來,做成可用的系統(tǒng);另一條路是取用他們的代碼;并且完全升級你的舊版本,但這種做法需要更長的時間。
簡而言之,你要仔細考慮重新開發(fā)需要多少時間,以及什么是優(yōu)先事項。把重心放在優(yōu)先事項上,之后再考慮要不要完全重構(gòu);你可以在你自己的代碼庫和這個快速演進的工具更加穩(wěn)定之后再做這件事。
實驗清理
當(dāng)你關(guān)注的重點是獲得結(jié)果時,你很容易就會忽視整潔性。你會思考要運行的下一組實驗及其超參數(shù)設(shè)置。出現(xiàn)了一個錯誤?沒有問題,修改輸出文件夾上的時間戳,然后再次運行實驗。但是,你最后得到的不過是另一些由不完整實驗生成的文件或文件夾。之后,查看實驗記錄的人會深感頭痛,他們被迫在 MLflow 中查看長長的列表,搜尋那些完整運行了的實驗。
解決方案很簡單,自動刪除那些你不想保存的試驗性運行。舉個例子,最好刪除那些在第一輪訓(xùn)練迭代之前就已經(jīng)失敗的實驗。為了團隊的未來,我們應(yīng)當(dāng)盡己所能地保持實驗記錄的整潔干凈。
隔離問題
為了改善你的模型,你會研究和嘗試各種不同的機器學(xué)習(xí)項目,你會遇到一些互相沖突的 Python 軟件包需求。一開始,你可能會使用在兩個開發(fā)者之間共享的云服務(wù)器,但很快你就會發(fā)現(xiàn)這樣很不方便,因為你的安裝可能會覆蓋己方團隊的安裝。
使用 Docker 吧!這是一種輕量級的容器化軟件平臺,可用于管理你的項目環(huán)境和依賴。你應(yīng)該為你的每個機器學(xué)習(xí)模型和應(yīng)用服務(wù)使用不同的 Docker 容器,這樣可以主動地減少「這只在我的機器上有效」的問題,防止項目之間出現(xiàn)依賴沖突。你和你的團隊無需設(shè)置更多開發(fā)服務(wù)器,而是可以每個人都在同一個共享服務(wù)器上設(shè)置自己的 Docker 容器,這樣做一般也更具成本效益。
此外,你可能會疑惑為什么選 Docker 而不是 Conda,畢竟 Conda 讓你能用不同的軟件版本創(chuàng)建不同的環(huán)境?我們選擇 Docker 的原因是其提供的工具更適合生產(chǎn)以及在云上操作。如果你要在一臺遠程機器上使用 Conda,就必須首先連接到該機器,然后處理文件傳輸問題。而在使用 Docker 時,只需要幾行命令,就能將本地文件修改同步到遠程機器的 Docker 容器中。
此外,運行項目所需的一切都會在 Dockerfile 或 Docker Compose 文件中說明。而在使用 Conda 時,如果不參考一下 README,我們不知道是否還需要額外的步驟。
最后,在 Docker Compose 的幫助下,如果一個機器學(xué)習(xí)項目需要其它服務(wù)才能運行,那么就可以將這些額外服務(wù)運行在其它 Docker 容器中,然后讓這些容器根據(jù) Docker Compose 文件設(shè)置進行通信。就我所知,使用 Conda 不能實現(xiàn)跨環(huán)境通信。
做好在有需要時擴展規(guī)模的準(zhǔn)備
當(dāng)創(chuàng)業(yè)公司還處于早期階段時,還不需要擴展規(guī)模,但還是有必要思考一下用于實現(xiàn)擴展的技術(shù)。其中之一是 Celery:http://www.celeryproject.org/。這是一個異步任務(wù)隊列系統(tǒng),可以將任務(wù)分發(fā)給多個工作器處理。我們目前是為每種類型的服務(wù)(服務(wù)器、客戶端、嵌入式模型)使用一個工作器,但如無必要,不應(yīng)該花太多精力來為同一服務(wù)設(shè)置更多工作器。
此處有一個疑問,通過嵌入進行緩存是你的擴展瓶頸嗎?沒有問題,我們可以再做另一個嵌入式 Celery 工作器或增加當(dāng)前工作器的并發(fā)數(shù)量,這能讓你并行運行多個子進程。我們 Toucan AI 的配置是在一個 Docker 容器中運行單個 Celery 工作器,這同時也考慮到了隔離問題。
Celery 不僅能擴展你的生產(chǎn)系統(tǒng),還非常適合用于執(zhí)行那些需要長時間運行的任務(wù),比如機器學(xué)習(xí)模型推理任務(wù)。除了允許服務(wù)器響應(yīng)掛起,服務(wù)器響應(yīng)(智能體的回復(fù))可以立即返回給與 Toucan AI 智能體對話的終端用戶,同時還可以在后臺安靜地運行異步任務(wù)(比如緩存機制)。
此外,我們還使用 Celery beat 來運行我們?nèi)粘0才诺姆治龉ぷ髌魅蝿?wù)。Celery beat 有助于使用 cron 來安排工作器任務(wù)。
與團隊和未來的自己合作
機器學(xué)習(xí)研究論文正在大量發(fā)表,作為一位機器學(xué)習(xí)工程師,你需要知道你的團隊正在開發(fā)以及嘗試過哪些模型和技術(shù)。那么你該怎么做呢?你沒有任何捷徑可以獲得他們的知識、經(jīng)驗和見解,但你可以與他們溝通,并且要多多溝通。
無論什么時候,都要保持溝通,尤其是通過書面溝通。很多時候,你做著自己的項目,而你當(dāng)前所做的事情可能與你的團隊所做的事情完全無關(guān)。盡管如此,也許未來某個時間他們需要審查或擴展你已經(jīng)實現(xiàn)的東西。可能在你完成那項任務(wù)的幾個月后,你需要對你自己的項目進行一些修改,而這時你可能已經(jīng)忘記了你做過了什么。所以記得做文檔,做文檔,做文檔!重復(fù)三篇,現(xiàn)在你知道做文檔的重要性了吧?
另外要注意,有時候光有筆記是不夠的。你需要讓你的團隊也了解你做的事情。如果你有些不確定的地方,當(dāng)你需要他們的誠實意見時,或你感覺口語是更有效率的溝通媒介時,你都可以與他們談?wù)勀愕捻椖康陌l(fā)展方向。注意從一開始就要保持溝通清楚,這是非常重要的,可以防止誤解、徒勞、擔(dān)憂和悔恨。
機器學(xué)習(xí)工程師的內(nèi)心掙扎
作為一位機器學(xué)習(xí)工程師,你必須學(xué)會調(diào)整自己的思想,不要老想著查漏補缺,把事情做得比實際所需的更好。你必須學(xué)會接受不完美,把重要的時間放在完成最緊迫的任務(wù)上。舉個例子,我喜歡花時間改進第三方的訓(xùn)練/評估代碼,但這個時候我也許只需要盡快知道推理結(jié)果是否有所改善。
我有做網(wǎng)站開發(fā)的背景,那時候我基本必須完全自己寫代碼,但在機器學(xué)習(xí)工程開發(fā)中,我必須學(xué)會如何應(yīng)用其他人的代碼。當(dāng)你總是使用別人的代碼時(這些代碼往往是學(xué)生和研究者花費幾個月乃至幾年的時間研究出來的),有時候難免覺得失落,覺得自己的工作不完整,尤其是當(dāng)你過于在意地想要理解那些代碼的方方面面時。但是,這是不必要的,你要做的只是將他們的模型成功地部署到你的生產(chǎn)系統(tǒng)中。
不管怎么說,我們本質(zhì)上都是好奇的生物,很自然會想要理解超過實際所需的東西。如果你想要做些探索,最好讓你的團隊也知道這一點。如果你能足夠及時地完成你的目標(biāo)工作,互相理解的工作環(huán)境能為你提供學(xué)習(xí)更多的機會。只要你知道什么是優(yōu)先事項,那就不要太擔(dān)憂,開心去探索吧。
總結(jié)
為生產(chǎn)系統(tǒng)打造機器學(xué)習(xí)過程并非易事。盡管文中列出了這么多所要考慮的東西,但有時候,你要做的僅僅是一個決定。如果這條路不同,那就走另一條。雖說如此,但還是希望這篇文章能幫你了解這些需要考慮的東西。






