淺談 Machine Learning 實驗管理技巧與可重現性 (Reproducibility)
近年來,隨著機器學習 (Machine Learning) 技術的迅速發展,除了追求更好的模型、資料、訓練技法外,其實 ML 實驗管理更是在開發過程中,確保成果可持續推進的重要基石。ML 實驗往往牽扯大量的數據、模型設計、訓練演算法以及超參數配置。在這樣的背景下,如何有效管理這些實驗,確保結果的可重現性與透明度,不只是研究與開發人員的重要課題,也是管理 ML 團隊的重要基礎。
與網路上大部分討論實驗追蹤的文章不同,這篇文章並不會直接大力推廣或介紹某個框架或工具。而是聚焦在可重現性 (Reproducibility) 這個基礎,以概述的角度、實務的角度解釋ML實驗管理的關鍵要素,並提供一些概念、實做建議和工具提點。
文章難度:★★★★☆
閱讀建議: 本篇是相當偏向 ML 務實工程的部分,也稍微偏向提高團隊合作角度的文章。文章中討論怎麼讓 ML 實驗可以最大化地達到在不同個體間都具備一定的規則、公平與透明性。文章從 reproducibility 在科研的重要性開始,依序介紹在 ML 上達成 reproducibility 的關鍵元素,包含資料版本控制 (data versioning)、程式碼版本控制 (code versioning)、隨機因子控制 (random seed)、虛擬環境 (virtual environments)、與實驗數據追蹤 (experimental tracking) 等。
推薦背景知識:Code Versioning, Data Versioning, CI/CD, MLOps, Docker.
Reproducibility
在科學研究中,實驗的可重現性是重要的核心概念之一。而隨著機器學習領域的發展,
我們在意的往往已經不只是訓練好的模型與程式碼,而是還包含了資料、資料流水線與訓練環境等因子的完整 ML 生命週期。
因為,當實驗結果可以被他人或自己再次重現時,這些結果才具有可信度和學術價值,實現站在巨人肩膀上持續精進。
Real Examples
許多團隊,時常會因為實驗可重現性問題絆住腳步,導致研究工作進展停滯,影響團隊整體的工作效率與成果質量。以下舉幾個常見的例子來說明:
- 上線模型來自未提交的程式碼變更:某位同仁在進行實驗時,針對模型的超參數或演算法進行了微調,也得到了表現最佳的模型,並順利的整合到產品或服務中。但這些訓練程式的調整並未完整地提交到版本控制系統中,導致後續團隊無法重現這一成果,進而無法基於這個結果繼續優化模型。
- 不可逆的資料改動或擴充:在 data preprocess 過程中,某些不經意的操作可能對資料進行了不可逆的改動。例如,直接在原始數據上進行 filtering 或是在無資料版本控制的情況下持續增加資料,導致即使後續使用相同的程式碼,也無法再現之前的結果。這樣的情況會讓實驗結果失去重現性,並且難以確保模型在未來數據上的穩定性。
- 依賴特定環境設定:在一些不熟悉雲端基礎設施 (IaaS) 的團隊中,常見的情況是模型的訓練和調試只能在某些特定的電腦或server上完成。如果沒有容器化與虛擬化的計算資源,往往可能因為一些瑣碎的小地方產生重現性的問題。如某些 libraries 版本需求寫的不夠嚴格,或甚至是使用非正式 release 的套件版本 (如自行 checkout 到某個 branch 後安裝);又或是資料讀取採用 auto threading 開啟多個檔案,產生在不同環境下因 thread 數量不同導致資料處理順序不同。這些都可能導致無法再現之前的實驗結果。
有時無法復現特定成果時,模型的進一步優化就失去了穩固的基礎,這往往會導致整個個人甚至團隊的實驗進程陷入瓶頸。因此,確保實驗的可重現性,不僅是提高團隊效率的關鍵,更是長期開發機器學習模型的基本要求。
General Concept
讓實驗具備良好的重現性,是達到 ML 團隊效率最大化不可或缺的一環。適當的開發觀念、規範與工具可以協助團隊有效地達到重現性。比如:
- 易於復現與取得的資料。
- 易於復現與取得的實驗程式碼、超參數與隨機因子 (random seed)。
- 易於復現與取得的實驗環境。
- 易於取得的實驗數據與分析報告。
這部分同時也會跟透明度高度相關。當每位團隊成員都能輕鬆獲取所需的資料、程式碼、環境與數據時,實驗過程就能保持高度透明,這相當有助於知識的轉移,同時也能避免溝通障礙與重工。
在接下來的章節中會針對這些項目,進行分別的討論。
Data Versioning
在機器學習的任務中,只管理程式碼版本並不足以保證機器學習實驗的可重現性。因為即使程式碼版本固定,數據集的變更仍可能導致模型結果上的差異。
數據集是機器學習實驗的基礎,其變更會直接影響模型的訓練和測試結果。因此,資料版本控制在機器學習實驗管理中重要的核心觀念。
常見工具
在進行數據版本管理時,有幾個基本的策略和工具可以使用,以確保數據的版本控制和管理更為高效。
- DVC (Data Version Control):與 Git 深度集成來追蹤數據的 metadata ,並將實際數據存儲於遠端存儲,有效地解決了數據版本管理的需求,也讓開發者能像管理程式碼一樣,方便地對數據進行版本控制。因此, DVC 非常適合在處理整理好的訓練數據集進行版本控制。
- LakeFS:是為大規模數據湖 (data lake) 設計的版本控制系統。與 DVC 不同的是,LakeFS 不依賴於 Git 的 metadata,而是直接在數據湖的物理存儲層進行操作。這種設計讓 LakeFS 在處理海量數據、支持多分支並行工作以及與大數據處理框架 (如 Apache Spark 或 Presto) 集成時更具優勢。因此, LakeFS 非常適合需要處理龐大數據湖的團隊。
Data Versioning 的實踐建議
- 記錄數據與程式碼的對應關係:在每次實驗中,記錄所使用的數據版本、數據處理流程和程式碼版本,以便完全重現實驗,並方便團隊成員之間的協作。
- 使用適合的工具:根據團隊規模、數據量和項目需求,選擇合適的數據版本控制工具。如以整理好的訓練資料可選擇 DVC;大型數據湖項目則可考慮 LakeFS;若僅需管理大型文件,可使用 Git LFS。
- 版本化數據處理流程:不僅要對原始數據進行版本控制,還應該對data processing scripts 和 data pipeline 進行版本管理,確保從原始數據到最終模型輸出的全流程可重現。
實務上,使用資料版本控制是比較嚴禁的作法。在開發前期也可以使用權限控管良好的資料夾,搭配不同批資料打版號或日期的方式,實現簡易的資料版本控制。
Code Versioning
隨著實驗的進行,程式碼可能會經歷多次變更與多個分支。因此,使用 Git 等版本控制系統,可以方便地管理和追蹤程式碼的歷史變更,為實驗結果的解釋和重現提供可靠的依據。
雖然程式碼版本控制是整個軟體工程領域非常基本的觀念,不過實際在工作上時常發現,部分完全是機器學系背景出身的人,對於這塊的觀念其實相對模糊。不過為了避免過於冗長,這邊不會介紹 Git 的觀念,而是著重在跟ML相關的部分,應該特別注意的操作。
配置和超參數管理
與一般的程式碼不同,ML 通常會有更多的超參數需要紀錄,因此建議將超參數設置從主要程式碼中拆分出來,存儲在獨立的配置文件中 (例如 config.yaml
或 params.json
)。這樣可以減少程式碼變更的頻率,使 Git 的版本記錄更加清晰和易於管理,這也讓merge或rebase的時候處理衝突會相對簡潔。
管理未提交的變更 (Uncommitted Changes)
在 ML 開發中,由於時常會有頻繁的實驗,在存在許多手動訓練操作的情況,就很容易發生放版模型來自包含 uncommitted changes 的資料處理或訓練程式。
雖然說 ML 基礎建設不是一朝一夕可成,在這之前這些改動都仍然需要被記錄起來。這個時期,將每次訓練時透過將未提交變更作為為 Artifact 儲存起來是一個簡單且有效的作法。
Code Versioning的實踐建議
- 建立標準化的程式碼管理策略:如將不同類型的 commit 打上不一樣的註記,並使用清晰的 branch 命名規則 (如
feat/<功能名稱>
或exp/<實驗名稱>
) 等。 - 建立實驗性程式碼管理規則:如果有頻繁的實驗產生,應確定這些改動是透過 CI/CD 流程自動建立程式碼版本或是透過有管理與規則的機制將的uncommitted stash 作為 Artifact 起來管理。
- 記錄程式碼與實驗數據的對應關係:在每次實驗結果中記錄對應的 Git commit hash,確保實驗數據與程式碼版本的唯一對應性。並使用實驗數據管理工具自動同步程式碼版本資訊。這部分同樣最好利用自動化工具完成,減少人為疏失的機率。
Random Seeds
在機器學習實驗中,隨機性無處不在。比如說:模型參數初始化 (model weight initialization)、資料增強 (data augmentation)、資料重新排列 (dataset shuffling) 等。
雖然說如果一個模型的性能對隨機性極為敏感,某種程度上反映了該模型的不穩定性,我們應該避免開發出這樣的模型。但實務上還是會
盡量鎖定跟紀錄過程中的 random seeds 。
實驗中的隨機性挑戰
在學術研究中,為了證明有效性和穩定性,研究者常見的作法之一是:
- 多次訓練模型:例如訓練模型 k 次。
- 報告平均結果:計算多次實驗結果的平均值和標準差,以量化模型的性能和穩定性。
Random Seed的實踐建議
然而在工程開發中,反覆訓練多次模型以取平均過於耗時。為了在效率和可重現性之間取得平衡,一個合理的做法是:
- 初始探索:首先隨機選擇多個隨機種子進行訓練,觀察結果的變異性。
- 選擇代表性的 random seed:從中選擇一個性能接近平均水平的隨機種子,避免極端情況 (過高或過低都不好)。
- 固定 random seed:在後續的實驗中,使用選定的隨機種子,確保每次實驗的隨機過程一致,增強結果分析的一治性。
以下是一些常用 libraries 的設定方法:
# python general (not limited)
random.seed(42)
np.random.seed(42)
# if using tensorflow
tf.random.set_seed(42)
# if using pytorch
torch.manual_seed(42)
torch.cuda.manual_seed_all(42)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
為了完全控制隨機性,其實還有很多細節要去鎖定,如控制 Python hash 隨機性的
PYTHONHASHSEED
以及如果其他第三方套件也包含隨機性,通常也盡量都要查閱如何固定。
Virtual Environments
當我們固定了資料版本、程式碼版本與隨機因子後,程式執行環境是接下來影響實驗結果的環節。
硬體、作業系統與套件的版本差異,都可能對實驗結果產生影響。
因為目前 ML 主流仍然以 Python 為主,以下介紹將環境管理分為 Python 環境和作業系統環境兩個部分,但其實觀念在不同語言間都是通用的。
Python環境
Python 作為機器學習領域的主流程式語言,其環境管理直接關係到模型訓練與推理的可重現性。為了確保每次實驗使用相同的依賴套件和版本,記錄並管理Python環境雖然是基本中的基本,實際上在檢查上卻時常被忽視。
- requirements.txt:這是最基本也最常用的方式之一。在進行實驗之前,可以使用
pip freeze > requirements.txt
命令將當前環境中的所有依賴套件及其版本記錄下來,確保後續實驗在相同的環境中進行。 - Poetry:是較新的 Python 套件管理工具,不僅可以管理依賴套件,還能同時管理專案的 virtual environment 。 Poetry 的管理主要是通過
pyproject.toml
文件來記錄專案的所有依賴。 - Conda:Conda 也是一個廣泛使用的套件和環境管理工具,不僅可以管理 Python 套件,也能管理部份其他語言的套件,甚至 CUDA 。
執行時將當前環境中的所有套件都記錄下來,這其實會導致依賴列表過於冗長,不容易閱讀。在我的經驗上,手動編寫
requirements.txt
或使用pipreqs
等工具,只列出直接依賴的重要套件,作為易於開發閱讀的部分。但在執行時仍然自動備份一份完整依賴,是一個可行的折衷作法。
無論選擇哪種工具,目標都是確保 Python 環境的一致性,從而減少因依賴套件版本差異導致的實驗結果變異。實務上,基於上述方法再進一步建立虛擬環境(如使用venv
、virtualenv
、Conda等),也是推薦的。
OS系統與硬體配置
作業系統 (OS) 環境在機器學習實驗的可重現性中也是要注意的部分,特別是在涉及底層計算資源或 GPU 加速的實驗中,作業系統和硬體配置可能會直接影響到模型的訓練效果和效率,如最大可執行的 batch size 或是 thread 數量不同導致自動讀取資料順序可能會不同等。
dataset = Dataset.range(1, 6) # ==> [ 1, 2, 3, 4, 5 ]
dataset = dataset.map(
lambda x: x + 1,
num_parallel_calls=tf.data.AUTOTUNE
) # not deterministic
要真的管理所有 OS 與硬體配置一致,其實是很不容易的事情。因此,通常都是先使用容器化 (Containerization) ,製造出一致的虛擬作業系統與硬體配置,比如說 Docker 。
通過使用 Docker ,開發者可以將應用程式及其所有相依套件打包成一個容器,確保程式可以在任何 Docker 支持的平台上執行,並獲得軟體上一致的結果。而硬體的部分,容器化的程式可以輕易地在 Infrastructure as Code 的平台上指定執行的硬體。這讓實驗的重現性變得更加簡單,而且相當利於部屬大規模實驗。
通常,在將Python專案包成Docker時,也會預先將Python的依賴套件寫入requirements.txt
或pyproject.toml
中,並在Docker映像的構建過程中自動安裝這些依賴。這樣可以確保每個Docker容器在執行時,都擁有一致的Python環境和OS設定,大幅減少環境變異對實驗結果的影響。同時將OS的依賴與Python的依賴分開紀錄,更易於管理。
除了軟體和硬體環境,環境變數和配置文件也是常紀錄的項目。使用如
dotenv
或配置管理工具,可以將敏感資訊和環境特定的配置從代碼中分離,增強應用的安全性和可移植性。
Virtual Environment的實踐建議
- Python 環境管理:使用任何一種 Python 套件管理工具,並且區分出不同的 requirements 檔案,如 base 、 deploy 或 development 。
- 習慣使用 container :針對專案維護 Dockerfile ,並使用 Docker 管理非 Python 的其他環境。除非程式碼中有自行處理硬體的控制,否則在部屬實驗時,沒有特殊原因指定一致的硬體規格。
實驗數據追蹤
在前述的項目中,整體上已經完成了 ML 程式本身的可重現性。然而,實驗單純具備可重現性其實是不太夠的,通常還是需要一個實驗數據追蹤的機制,讓自己或同事方便找到想要重現或分析對比的實驗。
管理實驗數據的核心目的是讓團隊的實驗數據取得更有效率與透明,同時保持資訊安全。
當所有的實驗數據,包括參數設定、模型結果以及環境資訊都易於團隊成員取得時,可以大幅提升團隊的合作效率。另一方面,易於取得也利於彼此協助對方檢查實驗與數據,可以有效減少因個人失誤導致的錯誤實驗與分析。
所謂的資訊安全指的是讓經過授權的人才可以獲取這些資料。這部分有的時候與透明是有些衝突,需要權衡的。但這篇文章不會特別深入這部分,以免模糊焦點。
Experimental Data
在機器學習實驗中,實驗數據是指實驗過程中產生的各類輸出結果,包括但不限於以下幾種內容:
- 訓練 logs:記錄訓練過程中的關鍵資訊,例如各項 loss 與 weight sum 的數值等。
- 評估結果:包含模型在 validation set 或 testing set 上的性能數據,例如 accuracy 或 mAP 等。
- 超參數組合:例如學習率 (learning rate)、批次大小 (batch size) 和優化器等超參數的設定。
- 其他 artifacts:包括圖片預測、語音、模型權重檔案以及中間產物等。
實驗數據追蹤工具
以下介紹三個常用的實驗數據管理工具:TensorBoard、MLflow 和 Weights & Biases (W&B)。
TensorBoard
TensorBoard 是由 TensorFlow 原生提供的一個可視化工具,主要用於記錄和可視化訓練過程中的數據,同時也支援其他框架使用。它提供了實時查看訓練曲線的能力,並支持模型結構和參數分布的可視化。TensorBoard 是一個輕量級的解決方案,適合初學者和小型實驗使用。
- 優點:操作簡單;可提供實時查看訓練指標;可地端運行。
- 缺點:雖然可以設計擴充機制,但 TensorBoard 本質不算數據中心,更像是個人的 log viewer。
MLflow
MLflow 是一個開源的實驗追蹤與管理工具,提供完整的實驗追蹤功能,能記錄每次實驗的超參數、指標和 artifacts,也能夠管理產出的模型。
優點:具備 TensorBoard 大部分功能,且可以直觀地比較多個實驗的結果;支持超參數管理、Artifact管理、模型管理與部署,從實驗到生產環境的過渡非常流暢;開源且擴展性強,可根據需求自定義功能。
缺點:初次配置較複雜,功能完全的部屬需要搭建後端儲存來配合;視覺化功能個人覺得相較比較缺乏。
Weights & Biases (W&B)
Weights & Biases 是一個專注於實時監控和實驗可視化的工具,由商業化的公司支持,基本上可以說是這個領域中最好用的工具。由於他有提供雲端版免費給學術圈使用,相信許多人對這個工具應該不陌生。
優點:具備 TensorBoard 與 MLFlow 的大部分功能;視覺化與實驗比較功能極為強大,整體介面也是效率最好的。
缺點:Self-managed或雲端版免費版功能有限,大部分團隊功能都需訂閱付費版本。
其他還有一些實驗數據管理工具如 Comet 或 Neptune.ai 其實都是不錯的選項,但不再此多贅述。
Virtual Environment的實踐建議
- 願意付費可優先評估 W&B:整體上在使用效果上 W&B 可以說是最全面的工具,但其免費版不論在雲端或地端都相當受限,甚至存在一些已知的瑕疵。
- 願意花時間修改優先評估 MLFlow :因 MLFlow 才是真正以開源為本的工具,而且已經具備基本的管理功能,其他不支援的功能也有機會透過其他工具整合或擴充完成。
ML 的工作流程相較於以往的軟體工程流程更多,且有許多中間產物與實驗數據,因此在管理上單純具備軟體工程概念多半是不夠的。在這篇文章中接紹了可重現性的基本概念,並帶過一些工具的關鍵字與介紹,協助個人或團隊建立起可靠的 ML pipeline 與實驗追蹤,以提高整體開發效率。
實際上,這些流程與細節未來估計會逐步被某些公司與工具一統江湖,就像 git 一樣融入每個 ML 開發人員的流程中。不過在那之前恐怕還有很長的一段時間,
希望這篇文章可以協助到有需要的人,渡過這段 MLOps 邁向更成熟與普及的過程。
好了~這篇文章就先到這邊。老話一句,ML 領域每年都會有大量高質量的進展,說真的要跟緊不是一件容易的事。所以我的觀點可能也會存在瑕疵,若有發現什麼錯誤或值得討論的地方,歡迎回覆文章或來信一起討論 :)