《機器學習工業復現的 12 個要素》

原文鏈接:https://blog.maiot.io/12-factors-of-ml-in-production/
譯文轉自:機器之心 公衆號

過去二十年來,我們對軟件開發的理解有了大幅提升。其中一大部分原因是 DevOps 概念的出現及其在軟件開發行業的廣泛應用。

領先的軟件公司都遵循着同樣的模式:首先是在軟件開發過程中快速迭代,然後進行持續集成、持續交付、持續部署。每個特性都要經過測試,看其提供價值的能力如何,而且軟件始終要處於就緒的狀態,並且通過自動化方法進行部署。

機器學習這個領域雖不同於傳統的軟件開發,但我們也能從軟件開發行業汲取很多實用的經驗教訓。過去幾年裏,我們一直在開發生產型機器學習項目。我們的目標並不只是概念驗證,而是與軟件開發一樣的可復現能力(reproducibility)。因此,我們構建了一套流程協調器、強大的自動化能力並建立了一套用於實現該目標的工作流程。

爲什麼不直接使用 Jupyter Notebook?從頭開始構建一組包含所有處理步驟的筆記需要多長時間?爲團隊納入新成員的難易程度如何?你現在可以復現兩個月前的結果嗎?能以多快的速度復現?你能將今天的結果和歷史結果進行對比嗎?你能在訓練過程中關注到數據的出處嗎?如果你的模型過時了又會發生什麼?

我們遇到過所有這些問題。現在,我們將這些經驗進行了歸納總結,得到了成功構建生產型機器學習的 12 個要素(類似於軟件開發中的十二要素應用/12 factor app)。

  1. 版本控制
    對軟件工程師來說,版本控制基本上是理所當然需要做的,但是這一方法論還尚未被數據科學家廣泛接受。讓我引述一下 Gitlab 上一些人的說法:

版本控制可促進整個軟件開發團隊之間的協調、共享和協作。版本控制軟件讓團隊可以在分佈式和異步環境中工作、管理代碼和文件的修改和版本以及解決合併衝突和相關異常。

簡單來說,版本控制能讓你安全地管理軟件開發中會變化的部分。

機器學習其實是一種特殊的軟件開發,有着自己特定的要求。首先,機器學習中會變化的部分不止一種,而是兩種:代碼和數據。其次,模型訓練的方式是(快速)迭代,並且代碼中的差異會很大(比如拆分、預處理、模型)。

只要數據發生更改,就需要保存一個版本,這樣才能保證能復現結果以及重複執行實驗和訓練模型。簡單粗暴的版本控制(硬拷貝)具有很大的改進空間,不過尤其是在團隊共享的情況下,能夠保持不變的版本控制是至關重要的。

代碼的版本控制還要更加重要。除了上面引述的內容,預處理代碼不僅在訓練階段很重要,而且在服務階段也很重要,需要與模型有保持不變的相關性。爲了在數據科學家的工作流程和投入生產的要求之間建立一種中臺,一種方便的方法是提供無服務器的功能。

總結:你需要對代碼進行版本控制,也需要對數據進行版本控制。

  1. 明確的特徵依賴關係

在理想世界中,產生你的輸入數據的東西應該總是會產生同樣的數據,至少結構上是這樣。但這個世界並不是完美的,你從上游服務獲取的數據也是由人類構建的,因此可能會發生變化。最終,特徵也可能發生改變。最好的情況是你的模型會直接故障報錯,但還有最壞的情況:你的模型悄悄繼續工作,但得到的結果都是垃圾。

明確定義的特徵依賴關係能夠儘快揭示出失敗案例。如果系統設計得好,還能在服務時進行持續訓練,然後調整依賴關係並加以適應。

總結:明確代碼中的特徵依賴關係。

  1. 描述性的訓練和預處理
    優良的軟件都有優良的描述和註釋——讓人無需閱讀每一行代碼就能輕鬆閱讀和理解代碼功能。

儘管機器學習是一類特殊的軟件開發,但它並不鼓勵實踐者背離已有的代碼書寫準則。在代碼書寫標準中,最基本的一條是能讓人在短時間內不費力地閱讀。

預處理和模型的代碼都應該遵循 PEP8 規範。代碼中應當使用有意義的對象名幷包含有助於理解的註釋。遵循 PEP8 規範可提升代碼的可讀性,降低複雜度並加快調試速度。SOLID 之類的編程範式提供了經過深思熟慮的框架,可讓代碼在未來用例中的可維護性、可理解性和靈活性都得到改善。

配置應該與代碼分離。不要將數據分配比例硬編碼到代碼之中,而是通過配置方式提供,以便在運行時修改。人們在超參數調節方面已經熟知這一點了:使用分離的配置文件可以顯著加快迭代速度,並且讓代碼庫可以重複使用。

總結:提升代碼可讀性並且將代碼和配置分開。

  1. 訓練結果的可復現性
    如果你不能復現訓練結果,那麼這個結果就是不可信的。儘管這是本文的主題,但在可復現性方面有一些細節需要說明。不僅是你自己需要能復現訓練結果,你的整個團隊都要能做到這一點。不管是在 PC 還是在 AWS 虛擬機上,模糊處理 Jupyter Notebook 中的訓練結果都與可復現性背道而馳。

通過設定訓練的工作流程,整個團隊都可以透明地訪問已執行的實驗和已運行的訓練。通過綁定可複用的代碼庫以及分離的配置文件,每個人都可在任何時間成功重新訓練。

總結:使用管道式工作流程和自動化。

  1. 測試
    測試的形式有很多。舉兩個例子:

1)單元測試是原子層面上的測試——基於各自的標準單獨測試每個函數和功能。

2)集成測試則相反,是將代碼庫的所有元素都放到一起進行測試,同時還會測試上下游服務的克隆版本或模擬版本。

這兩種範式都適應於機器學習。預處理代碼是預先確定的,直到測試階段——這樣的轉換能在不同的輸入下都得到正確結果嗎?模型是集成測試的一個絕佳案例——在生產環境中提供服務時,你的模型的表現是否與評估時相當?

總結:測試你的代碼,測試你的模型。

  1. 偏移與持續訓練
    在生產場景中,任務發生偏移是合理存在的問題。只要數據存在變化的可能性,你就需要考慮偏移的可能性。對於此問題的風險,有兩種可以採取的措施:

1)監控生產系統中的數據。建立自動化報告機制,在數據發生變化時通知團隊,這種變化甚至可能超過明確定義的特徵依賴關係。

2)基於新輸入的數據持續訓練。良好自動化的管道化流程可以基於新數據重複運行,然後與歷史訓練結果進行比較,展示性能變化情況以及將訓練得到的模型快速投放到生產中,從而讓模型表現更好。

總結:如果你的數據會發生變化,那就採用一種持續訓練的管道化流程。

  1. 跟蹤結果
    Excel 並非一種跟蹤實驗結果的好方法。而且還不只是 Excel,任何分散的人工跟蹤方法得到的信息都是不夠權威的,也因此是不可信的。

正確的做法是以一種中心化的數據存儲方式自動記錄訓練結果。自動化能夠保證可靠地跟蹤每次訓練,從而方便之後比較每次訓練的結果。對結果進行中心化存儲,能爲團隊提供透明,實現持續性分析。

總結:通過自動化方法跟蹤結果。

  1. 實驗模型與生產模型
    我們需要努力才能理解數據集。通常來說,我們會通過實驗來實現理解,尤其是當我們關注的領域具備大量隱含領域知識時。創建一個 Jupyter Notebook,將部分/全部數據導入 Pandas Dataframe,進行幾個小時無序研究,訓練第一個模型,評估結果——任務完成。但幸運的是,現實並不如此。

在機器學習的生命週期中,實驗有自己的目的。這些目的並不是模型,而是理解。基於探索性 Jupyter Notebook 的模型是爲了理解,而不是爲生產開發的成品。理解之後,還需要進一步開發和適應,才能開始打造用於生產的訓練流程。

不過,所有與領域特定的知識無關的理解都可以自動化。你可以基於你使用的每個數據版本生成統計信息,從而可以跳過那些你在 Jupyter Notebook 中做過的一次性的臨時探索工作,然後直達第一個管道式流程。你在流程中實驗進行得越早,你就能越早地在中間結果上進行協作,也就能更早地實現可投入生產的模型。

總結:筆記不能投入生產,因此要在流程中儘早實驗。

  1. 訓練和服務之間的方法差異
    訓練和實際服務之間往往存在方法差異,爲了正確地將所有數據預處理過程都納入到模型服務環境中,需要減少這些差異。這當然是正確的,你也需要堅持這一原則。但是,這只是對這一問題的部分解讀。

先來簡單看一段古老的 DevOps 歷史:2006 年,亞馬遜的 CTO Werner Vogels 創造了一個說法「You build it, you run it(你構建的東西你要運行)」。這是一個描述性的短語,意思是開發者的責任不只是寫程序,還需要運行它們。

機器學習項目也需要類似的機制——理解上游的數據生成以及下游的模型使用都在數據科學家的職責範圍內。你訓練用的數據是通過什麼體系生成的?它會出問題嗎?該體系的服務級目標(SLO)是什麼?這與實際服務的目標一致嗎?你的模型的服務方式是怎樣的?運行時環境是怎樣的?怎樣在服務時對函數進行預處理?這些都是數據科學家需要理解和解答的問題。

總結:正確地將預處理嵌入到服務之中,確保你理解數據的上下游。

  1. 可比較性
    從爲項目引入第二個訓練腳本開始,可比較性就成了未來工作的重要組成部分。如果第二個模型的結果無法與第一個模型的結果進行比較,則整個過程就浪費了,其中至少有一個是多餘的,甚至可能兩個都多餘。

根據定義,所有試圖解決同一問題的模型訓練都需要可以比較,否則它們就不是在解決同一問題。儘管迭代過程可能導致所要比較的東西發生變化,但是在技術上實現模型訓練的可比較性需要一開始就作爲首要功能內置於訓練架構之中。

總結:構建你自己的管道式流程,以便輕鬆比較各個流程的訓練結果。

  1. 監控
    粗略地說,機器學習的目標應該是通過學習數據來解決問題。爲了解決這個問題,需要分配計算資源。首先是分配給模型的訓練,然後是分配給模型的服務。負責在訓練期間提供資源的不管是人還是部門,都需要負責將這些資源轉移給服務。模型在使用過程中可能出現很多性能下降問題。數據可以偏移,模型可能成爲整體性能的瓶頸,偏差也是一個真實存在的問題。

效果:數據科學家和團隊負責監控他們創建的模型。他們並不一定要負責實施監控,尤其是當組織結構很大時,但他們肯定需要負責監控數據的理解和解釋。最低限度上,需要監控的內容包括輸入數據、推理次數、資源使用情況(CPU、RAM)和輸出數據。

總結:同樣,「You build it, you run it(你構建的東西你要運行)」。監控生產過程中的模型是數據科學的部分工作。

  1. 模型的可部署性
    從技術層面講,每個模型訓練流程都需要得到可部署到生產環境中的成品。毫無疑問,這些模型結果可能很糟糕,但它需要做成可以部署到生產環境的形態。

這是軟件開發中的常見模式,也叫做持續交付(Continuous Delivery)。團隊需要能夠隨時部署他們的軟件,爲了滿足這個目標,迭代週期需要足夠快。

機器學習也需要採用類似的方法。這樣才能迫使團隊首先考慮現實與期望之間的平衡。所有利益相關者都應當清楚,在模型結果方面,哪些結果是理論上可能的。所有利益相關者都應當在模型的部署方式以及如何與更大的軟件架構整合上達成一致。但是,這也可能需要自動化,也需要前文提到的一些要素。

總結:每個訓練流程都需要得到可部署的成品,而不「只是」模型。

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