從煉金術到工程學:數據科學項目持續成功10條規則(最佳實踐)
出自16世紀荷蘭畫家彼得·勃魯蓋爾(Pieter Bruegel the Elder)的《煉金術士的實驗室/Alchemist's Laboratory》
在數據科學項目中,我們經常遇到各種腳本、notebook、Python代碼、Java代碼、SQL等大雜燴式組合在一起的工程項目。這些項目從各種來源提取數據,代碼被復制并在各個地方經過微小調整后重新使用。有些項目有版本控制和自動化的打包腳本,而有些項目根本沒有測試、持續集成和部署(CI/CD)。所有這些問題導致無法確保項目質量和可重復性,為項目失敗埋下隱患。大部分數據科學項目都是無序堆積的大雜燴,在工程化管理方面存在明顯不足。
隨著數據科學(包括人工智能應用)的復雜性和重要性在當今企業中不斷增加,許多數據科學項目在實際應用中遇到各種問題,導致項目失敗或結果不可靠。為了保障數據項目的成功,DrivenData Lab團隊在其電子書《The 10 Rules of Reliable Data Science》中總結了數據科學項目持續成功的十條規則(最佳實踐)。這些規則為確保數據項目的成功提供了寶貴的指導,能夠幫助數據科學家和團隊提高工作效率,確保項目質量和可重復性。
規則1:有序開始,有序進行(Start Organized, Stay Organized)
“在數據準備過程中,經常出現‘管道叢林’的現象。這些管道可能隨著新信號的識別和新信息源的添加而自然發展。如果不加以注意,最終為機器學習準備數據的系統可能會變成由抓取、連接和采樣步驟組成的叢林,常常伴隨著中間文件的輸出。管理這些管道、檢測錯誤和從失敗中恢復都是困難且昂貴的……所有這些都會增加系統的技術債務,使得進一步的創新變得更加昂貴。” —— Sculley 等人, “Machine Learning: The High Interest Credit Card of Technical Debt” (2014)
以干凈和邏輯清晰的結構開始數據科學項目,并保持這種有序性,有助于數據科學家理解、擴展和重現分析。
- 為什么要遵循這條規則?
- 防止混亂:如果沒有明確的結構,項目中的代碼和數據很快就會變得混亂,導致結果難以重現。
- 促進協作:一個組織良好的項目使他人更容易理解和貢獻,促進更好的協作。
- 自我文檔化:有序的代碼本身就是一種文檔,減少了大量文檔的需求,使得以后返回項目時更容易上手。
- 如何實現這條規則:
- 使用模板:從像Cookiecutter Data Science這樣的項目模板開始,它提供了合理且自我文檔化的結構。
以下是Cookiecutter的項目結構:
├── LICENSE <- Open-source license if one is chosen├── Makefile <- Makefile with convenience commands like `make data` or `make train`├── README.md <- The top-level README for developers using this project.├── data│ ├── external <- Data from third party sources.│ ├── interim <- Intermediate data that has been transformed.│ ├── processed <- The final, canonical data sets for modeling.│ └── raw <- The original, immutable data dump.│├── docs <- A default mkdocs project; see www.mkdocs.org for details│├── models <- Trained and serialized models, model predictions, or model summaries│├── notebooks <- Jupyter notebooks. Naming convention is a number (for ordering),│ the creator's initials, and a short `-` delimited description, e.g.│ `1.0-jqp-initial-data-exploration`.│├── pyproject.toml <- Project configuration file with package metadata for │ {{ cookiecutter.module_name }} and configuration for tools like black│├── references <- Data dictionaries, manuals, and all other explanatory materials.│├── reports <- Generated analysis as HTML, PDF, LaTeX, etc.│ └── figures <- Generated graphics and figures to be used in reporting│├── requirements.txt <- The requirements file for reproducing the analysis environment, e.g.│ generated with `pip freeze > requirements.txt`│├── setup.cfg <- Configuration file for flake8│└── {{ cookiecutter.module_name }} <- Source code for use in this project. │ ├── __init__.py <- Makes {{ cookiecutter.module_name }} a Python module │ ├── config.py <- Store useful variables and configuration │ ├── dataset.py <- Scripts to download or generate data │ ├── features.py <- Code to create features for modeling │ ├── modeling │ ├── __init__.py │ ├── predict.py <- Code to run model inference with trained models │ └── train.py <- Code to train models │ └── plots.py <- Code to create visualizationste
這種標準化的項目結構有助于保持項目的有序性和可維護性,確保數據科學項目的成功。
規則2:所有數據都有來源,原始數據不可變(Everything Comes from Somewhere, and the Raw Data is Immutable)
“每一條知識都必須在系統內有一個唯一的、明確的、權威的表示。” —— Andy Hunt 和 Dave Thomas, 《The Pragmatic Programmer》
這條規則強調確保項目中的所有數據都可以追溯到其來源的重要性。原始數據應保持不變,任何轉換或分析都應能從這一原始數據集中再現。
- 為什么要遵循這條規則?
- 可重現性:確保每一個結論或結果都可以通過一個清晰、不間斷的轉換鏈條追溯到最初的原始數據。
- 問責性:有助于驗證數據的有效性及其衍生結果的可靠性。
- 清晰性:通過澄清每個數據的來源,減少模糊性。
- 如何實現這條規則?
- 追蹤數據血緣:使用有向無環圖(DAG)來追蹤數據的依賴關系和所應用的轉換。
- 保持原始數據不可變:將原始數據存儲為只讀格式,絕不修改它。任何清洗或轉換應生成一個新的數據集。
- 記錄數據獲取過程:在README或其他可訪問文件中記錄數據的獲取方式,包括任何預處理步驟。
- 使用依賴管理工具:使用像Apache Airflow或Prefect這樣的工具來管理和可視化數據管道,確保可追溯性。
- 工具和軟件包:
- Apache Airflow:用于創建和管理數據管道。
- Prefect:另一個數據管道管理工具,注重簡潔和靈活性。
- DAGsHub:用于數據和機器學習模型的版本控制,以及代碼管理。
通過確保所有數據都可以追溯到其來源并保持原始數據的不可變性,數據科學家可以提高分析的可重現性和可靠性,使他們的工作更值得信賴且更易于審計。
規則3:版本控制是基本的專業素養(Version Control is Basic Professionalism)
“如果你沒有源代碼控制,你會在讓程序員協同工作時感到壓力重重。程序員無法知道其他人做了什么。錯誤也無法輕易回滾。” —— Joel Spolsky, “The Joel Test: 12 Steps to Better Code”
這條規則強調使用像Git這樣的版本控制系統(VCS)來管理代碼和數據的變更。它確保所有修改都被追蹤、可逆且可審查。
- 為什么要遵循這條規則?
- 協作:通過允許多個人在同一個項目上工作而不產生沖突,促進團隊合作。
- 問責:追蹤變更并識別是誰做了哪些修改,增強透明度。
- 可逆性:當出現問題時,可以輕松回滾到以前的版本。
- 審查和質量控制:使代碼審查和審計成為可能,幫助維持高質量標準。
- 如何實現這條規則?
- 使用Git進行代碼管理:定期將代碼更改提交到Git倉庫。使用分支來管理不同的功能或開發階段。
- 避免在VCS中存儲大數據:僅存儲小型、很少更改的數據集。對于較大的數據集,使用DVC(數據版本控制)或Git LFS(大文件存儲)等工具。
- 自動化版本控制:使用腳本或工具自動對數據集和模型進行版本控制,確保每次更改都被追蹤。
- 代碼審查實踐:實施一個通過拉取請求進行代碼審查的流程,確保所有更改都由至少一個團隊成員審查。
- 記錄變更:維護一個變更日志,記錄項目中的重大變化和更新。
- 工具和軟件包:
- Git:最廣泛使用的版本控制系統,用于追蹤代碼更改。
- Git LFS:用于在Git中管理大文件。
- DVC:用于對數據、模型和管道進行版本控制,與代碼一起管理。
- GitHub/GitLab/Bitbucket:提供倉庫、代碼審查工具和CI/CD集成的平臺。
使用版本控制是任何專業數據科學項目的基本要求。它增強了協作、問責和質量控制,使代碼和數據的管理和維護隨著時間的推移變得更加容易。
規則4:Notebooks用于探索,源文件用于重復(Notebooks are for Exploration, Source Files are for Repetition)
“大多數我聽到的關于Notebooks的抱怨,我認為是對它們用途的誤解……Notebooks絕對不是讓你像在編輯器里那樣輸入所有代碼并弄得一團糟。” —— Mali Akmanalp
這條規則強調了Notebooks和源文件在數據科學項目中不同的用途。Notebooks適合進行探索性分析和可視化,而源文件則更適合可重現和自動化的任務。
- 為什么要遵循這條規則?
- 探索:Notebooks提供了一個交互環境,非常適合實驗和可視化。
- 可重現性:當源文件經過良好組織和管理時,確保過程可以可靠地重復。
- 協作和審查:源文件更容易在版本控制系統中管理,促進代碼審查和協作。
- 如何實現這條規則?
- 在Notebooks中進行探索性分析:使用Jupyter或R Notebooks進行初步數據探索、可視化和迭代分析。
- 提取常用函數:在開發可重用的函數和流程時,將它們從Notebooks中提取到源文件(如Python腳本)。
- 組織源代碼:將這些腳本放在一個組織良好的目錄結構中,如/src或/scripts。
- 版本控制:將這些源文件提交到版本控制系統,啟用協作開發和代碼審查。
- 測試:為源文件中的函數編寫測試,確保它們在Notebooks環境外也能正常工作。
- 工具和軟件包:
- Jupyter Notebooks:用于交互式數據分析和可視化。
- VS Code或PyCharm:用于開發和管理源文件。
- nbconvert:將JupyterNotebooks轉換為腳本。
- pytest:用于測試從Notebooks中提取的Python代碼。
- Git:用于管理Notebooks和源文件的版本控制。
Notebooks非常適合探索性和迭代分析,但關鍵函數應提取到源文件中以確保可重現性和可維護性。這種方法利用了兩種環境的優勢,促進了更清晰和更有條理的工作流程。
規則5:測試和健全性檢查預防災難(Tests and Sanity Checks Prevent Catastrophes)
“沒有測試的代碼是糟糕的代碼。它無論寫得多么好,無論多么漂亮、面向對象或者封裝良好。有了測試,我們可以快速而可靠地改變代碼的行為。沒有測試,我們真的不知道我們的代碼是變得更好還是更糟。” —— Michael Feathers, 《Working Effectively with Legacy Code》
這條規則強調在數據科學代碼中編寫測試和進行健全性檢查的重要性,以確保正確性和可靠性。測試有助于及早發現錯誤,并確保代碼按預期工作。
- 為什么要遵循這條規則?
- 錯誤預防:測試有助于在問題變得更嚴重之前捕捉錯誤。
- 信心:確保代碼在各種條件下都能正確執行。
- 維護:通過測試能夠捕捉到回歸,使得修改和擴展代碼庫更加容易。
- 可重現性:確保結果能夠長期可靠地重現。
- 如何實現這條規則?
- 編寫單元測試:專注于為單個函數和組件編寫測試,驗證它們在隔離環境中的行為。
- 使用健全性檢查:實施健全性檢查和冒煙測試,驗證數據和基本功能的有效性。
- 使用樣本數據進行測試:使用小型、具有代表性的數據集創建測試,驗證代碼處理典型情景和邊緣情況的能力。
- 自動化測試:使用持續集成工具將測試集成到開發工作流中,實現自動化運行測試。
- 文檔化測試:清晰地記錄每個測試驗證的內容,便于他人理解和維護。
- 工具和軟件包:
- pytest:用于在Python中編寫和運行測試的框架。
- unittest:Python內置的測試模塊。
- Hypothesis:用于Python中的基于屬性的測試。
- tox:用于跨多個環境自動化測試。
- 持續集成(CI)工具:如GitHub Actions、Travis CI或Jenkins,用于自動化運行測試。
測試和健全性檢查對于確保數據科學代碼的正確性和可靠性至關重要。它們有助于及早發現錯誤,提升對代碼行為的信心,并使代碼庫更易于維護和擴展。
規則6:大聲失敗,快速失敗(Fail Loudly, Fail Quickly)
“這個問題在機器學習系統中比其他類型的系統更常見。假設正在進行聯接的特定表不再更新。機器學習系統將進行調整,其行為將繼續保持相當良好,逐漸衰減。有時會發現表格已經過時數月,簡單的刷新比季度內的任何其他發布都提高了性能!” — Martin Zinkevich, 《Rules of Machine Learning/機器學習規則》
這條規則強調設計系統以在遇到意外情況時能夠及時且顯眼地失敗的重要性。它倡導防御性編程實踐,使錯誤變得顯而易見且可以迅速采取措施。
- 為什么要遵循這條規則?
- 錯誤檢測:幫助及時捕捉錯誤,防止錯誤擴散并導致更大的問題。
- 調試:便于識別和修復問題的根本原因。
- 可靠性:確保系統表現可預測,并以受控方式失敗。
- 責任:提供清晰的錯誤消息,幫助開發人員理解問題的原因及如何修復。
- 如何實現這條規則?
- 驗證假設:實施檢查確保輸入和中間結果符合預期條件。
- 使用斷言:添加斷言來強制執行關于數據和代碼行為的假設。
- 記錄錯誤:實施全面的日志記錄,捕獲關于錯誤及其上下文的詳細信息。
- 引發異常:使用異常處理未預期的情況,并確保適當處理。
- 快速失敗:設計系統立即檢測和響應錯誤,必要時停止進一步執行。
- 工具和軟件包:
- 日志記錄庫:如Python的內置日志記錄模塊,用于捕獲詳細的錯誤信息。
- assert:Python中的assert語句,用于強制執行條件。
- 錯誤處理庫:如Python中的bulwark,用于執行數據驗證和假設。
- 測試庫:像pytest這樣的工具,編寫測試確保系統在無效條件下正確失敗。
設計系統以大聲失敗和快速失敗有助于及時捕捉和解決錯誤,提高可靠性和可維護性。通過強制執行假設并提供清晰的錯誤消息,開發人員可以確保問題能夠有效檢測和解決。
規則7:從原始數據到最終輸出,項目運行完全自動化(Project Runs are Fully Automated from Raw Data to Final Outputs)
“即使人們記得這些步驟,他們也可能會自我安慰而跳過某些步驟。在復雜的過程中,畢竟,并不是所有的步驟總是很重要。……‘這以前從未成為問題,’人們會說。直到有一天它變成了問題。” — Atul Gawande, 《The Checklist Manifesto/清單宣言》
這條規則強調了自動化整個數據流水線的重要性,從原始數據到最終輸出,確保流程可重復、可靠,并能夠以最小的努力被任何人執行。
- 為什么要遵循這條規則?
- 可重復性:確保整個過程可以重復執行并得到相同的結果。
- 效率:通過自動化重復性任務節省時間。
- 減少錯誤:通過減少手動步驟降低人為錯誤的發生概率。
- 一致性:確保每次執行都遵循相同的步驟,產生一致的結果。
- 如何實現這條規則?
- 使用構建工具:實施類似GNU Make或Apache Airflow的工具來管理和自動化數據流水線。
- 為每個步驟編寫腳本:創建用于數據提取、清洗、轉換、建模和報告的腳本。
- 自動化環境設置:使用Docker或虛擬環境等工具確保可以重現分析環境。
- 文檔化過程:在README或類似文件中清晰記錄運行流水線所需的步驟和命令。
- 持續集成:集成CI/CD工具,以便在代碼庫進行更改時自動運行流水線。
- 工具和軟件包:
- Apache Airflow:用于編排復雜的數據流水線。
- GNU Make:管理構建過程的簡單而強大的工具。
- Docker:用于容器化環境,確保在不同設置中的一致性。
- Vagrant:創建和配置輕量級、可重現和便攜式工作環境。
- Jenkins/CircleCI/GitHub Actions:CI/CD工具,用于自動化運行流水線。
自動化從原始數據到最終輸出的整個數據流水線,確保了可重復性、效率和一致性。它減少了人為錯誤的可能性,并使任何人都能輕松執行流程,從而產生更可靠和可信的結果。
規則8:重要參數提取和集中管理(Important Parameters are Extracted and Centralized)
“明確優于隱晦。” — Tim Peters, 《The Zen of Python/Python之禪》
這條規則側重于在項目中集中和清晰定義重要參數,而不是將它們分散到代碼中各處。這種做法提升了項目的清晰度、可重復性和修改的便捷性。
- 為什么要遵循這條規則?
- 清晰度:集中參數使得更容易理解項目的配置方式。
- 易于修改:在一個地方修改參數減少了不一致性和錯誤的風險。
- 文檔化:集中的配置作為項目設置和參數的文檔。
- 可重復性:確保所有參數都被明確設置和跟蹤,使得結果更易重現。
- 如何實現這條規則?
- 使用配置文件:將參數存儲在一個中心化的配置文件中(例如 config.yml、settings.json)。
- 環境變量:對于敏感信息或在不同環境中可能變化的參數,使用環境變量。
- 參數管理工具:使用能夠管理參數并強制保持一致性的工具。
- 文檔化參數:在配置文件或單獨的文檔文件中清晰地記錄每個參數的作用和可能的取值。
- 集中訪問:確保所有需要訪問參數的代碼部分從集中化的配置中讀取參數。
- 工具和軟件包:
- YAML/JSON/TOML:配置文件的格式。
- ConfigParser:Python模塊,用于處理配置文件。
- dotenv:用于在 .env 文件中管理環境變量。
- Hydra:Python項目中管理配置文件的框架。
- Cerberus:Python中一個輕量級且可擴展的數據驗證庫。
集中和明確定義重要參數,提升了數據科學項目的清晰度、可維護性和可重復性。將所有配置集中在一處使得修改更易管理,項目也更加易于理解和可靠。
規則9:項目運行默認詳細,并生成實質性產物(Project Runs are Verbose by Default and Result in Tangible Artifacts)
“在數據流水線運行期間捕獲有用的輸出,使得很容易找出結果的來源,便于回顧和繼續上次的工作。” — DrivenData
這條規則強調了使數據流水線運行詳細化,并確保其產生實質性的產物,記錄了整個過程和結果。
- 為什么要遵循這條規則?
- 透明度:詳細的日志和產物清晰地展示了結果如何獲得。
- 調試:詳細的輸出幫助識別問題出現的位置。
- 文檔化:自動生成的產物作為記錄,有助于未來的重現和理解。
- 責任追溯:確保流水線的每一步都有記錄,便于審查和審計。
- 如何實現這條規則?
- 啟用詳細日志記錄:使用日志庫捕獲數據流水線每個步驟的詳細信息。
- 生成產物:確保每次運行都生成產物,如日志、配置文件、中間數據集和最終結果。
- 時間戳和版本信息:在日志和產物中包含時間戳和版本信息,跟蹤隨時間的變化。
- 存儲產物:將產物保存在結構化且易訪問的位置,如版本控制的目錄或云存儲桶中。
- 文檔化運行:為每次運行創建摘要報告,詳細描述采取的步驟、使用的配置和獲得的結果。
- 工具和軟件包:
- logging:Python的內置日志模塊,用于捕獲詳細日志。
- MLflow:用于管理機器學習生命周期的工具,包括實驗跟蹤、模型注冊和產物存儲。
- WandB:Weights & Biases,用于跟蹤實驗和可視化結果。
- TensorBoard:用于可視化TensorFlow日志。
- 結構化存儲:如S3、Google Cloud Storage或Azure Blob Storage,用于存儲產物。
通過使項目運行詳細化并確保產生實質性的產物,可以提升透明度,便于調試,并提供全面的文檔記錄。這種做法使得理解、重現和建立在以前工作基礎上更加容易,從而提升數據科學項目的整體可靠性和效率。
規則10:從最簡單的端到端流水線開始(Start with the Simplest Possible End-to-End Pipeline)
“一個復雜系統的工作通常是從一個簡單工作的系統演變而來的。從頭設計的復雜系統從來都不會工作,并且不能通過補丁來使其工作。你必須從一個能工作的簡單系統開始。” — Brian Kernighan 和 John Gall, Systemantics
這條規則強調了在逐步增加復雜性之前,從一個簡單且功能完整的端到端流水線開始的重要性。首先建立一個最小可行產品(MVP),能夠從原始數據處理到最終輸出,然后逐步增強和優化。
- 為什么要遵循這條規則?
- 基礎建設:建立一個工作的基準線,確保流程的各個部分都能連接和正常工作。
- 迭代改進:允許逐步完善和優化,減少引入錯誤的風險。
- 專注:在深陷細節和優化之前,幫助保持對主要目標的關注。
- 靈活性:提供一個靈活的框架,可以根據需要進行調整和擴展。
- 如何實現這條規則?
- 定義最小流水線:確定從原始數據處理到最終輸出所需的基本步驟,并實施它們。
- 迭代開發:從最簡單的實現開始,逐步添加功能、優化和復雜性。
- 早期驗證:確保每個流水線階段在進入下一階段之前都能正常工作。
- 先用簡單工具:最初使用簡單且易理解的工具和方法,只有在必要時才引入更高級的技術。
- 文檔化過程:隨著每次迭代更新文檔,確保不斷演變的流水線仍然易于理解。
- 工具和軟件包:
- Make:用于簡單的構建自動化。
- Pandas:用于數據操作和初始數據處理。
- Scikit-learn:用于基本建模和機器學習任務。
- Jupyter Notebooks:用于原型設計和探索初始實現。
- Docker:用于創建可復現的環境。
從最簡單的端到端流水線開始,確保了一個堅實的基礎進行構建。這種方法允許逐步開發和完善,確保每個新增功能都建立在一個經過驗證和功能完整的基礎上,從而降低復雜性并提高可維護性。
數據科學項目的成功不僅依賴于技術和算法,更依賴于良好的工作實踐和組織管理。通過遵循上述 10 個規則(最佳實踐),數據科學家和團隊可以提高工作效率,確保項目結果的可靠性和可重復性,為企業創造更大的價值。這些規則不僅適用于數據科學項目,也適用于任何需要高質量數據分析和處理的領域。希望這些最佳實踐能對您的工作有所幫助,并期待與您共同探討和改進數據科學工作流程。
《The 10 Rules of Reliable Data Science》 下載地址:https://drivendata.co/insights