Dựng CI/CD cho model ML với CML: đăng so sánh metric vào mỗi pull request
Một file workflow và ba script Python là đủ để reviewer biết thay đổi của bạn làm model tốt lên hay tệ đi, trước khi bấm merge.
- 1Mở pull requestEvent pull_request kích hoạt workflow GitHub Actions
- 2Cài CMLAction setup-cml, token truyền qua REPO_TOKEN từ secrets.GITHUB_TOKEN
- 3Kiểm tra dữ liệucheck_data.py soát cột và giá trị rỗng, sai thì dừng workflow
- 4Huấn luyện lạitrain.py ghi metric ra metrics.json
- 5So với baselinecompare.py in bảng Markdown, gắn cờ khi metric giảm quá ngưỡng
- 6Đăng vào PRcml comment create đưa báo cáo thành comment
Dữ liệu sai thì dừng sớm; model tệ đi thì bị gắn cờ ngay trong comment của PR.
Đồ hoạ: FDE Times
Tóm tắt nhanh
- CI cho ML phải kiểm tra cả dữ liệu, schema và model, không chỉ code.
- CML chạy trên GitHub Actions, huấn luyện lại model trong mỗi PR và đăng báo cáo metric thành comment.
- CML không kèm DVC; nếu dữ liệu nằm trong DVC, bạn cần thêm action Setup DVC.
Trong nhiều đội ML, câu hỏi khó nhất lúc review không nằm ở code. Nó là chuyện model sau thay đổi này tốt lên hay tệ đi. Reviewer nhìn diff thấy ba dòng sửa feature, nhưng không ai biết accuracy đã rơi từ 0,91 xuống 0,89 cho đến khi model lên production.
CML, viết tắt của Continuous Machine Learning, tự giới thiệu là CI/CD dành cho dự án machine learning. Lời hứa của nó rất cụ thể: mỗi pull request tự sinh một báo cáo có metric và biểu đồ. Bài này dựng đúng pipeline đó từ đầu đến cuối trên GitHub.
Với người muốn làm FDE, đây là kỹ năng dùng được ngay. Ở site khách hàng, thay vì đề xuất ngay một hạ tầng MLOps lớn, bạn nên bắt đầu bằng một cơ chế nhỏ chạy trong repo của khách, để mọi người cùng thấy model thay đổi ra sao sau mỗi lần sửa.
CI cho ML khác CI cho web ở điểm nào?
GitLab định nghĩa CI là kiểm chứng thay đổi code sớm và thường xuyên bằng build và test tự động, còn CD là tự động chuẩn bị code đã test để luôn sẵn sàng deploy. Với hệ thống ML, tài liệu MLOps của Google Cloud mở rộng phạm vi đó: CI phải kiểm tra cả dữ liệu, schema dữ liệu và model.
Google còn tách riêng continuous training (CT), tức tự động huấn luyện lại và phục vụ model, và gọi đó là thuộc tính chỉ hệ thống ML mới có. Pipeline trong bài vì thế có ba nhịp: kiểm tra dữ liệu, huấn luyện lại, rồi so sánh metric. Code chạy qua test vẫn có thể cho ra một model tệ hơn.
Bạn sẽ dựng gì, cần chuẩn bị gì?
Kết quả cuối cùng: mỗi khi ai đó mở pull request, GitHub Actions chạy một workflow. Theo tài liệu GitHub, workflow là một quy trình tự động chạy một hoặc nhiều job, và nó được kích hoạt bởi event, tức một hoạt động cụ thể trong repo như việc mở pull request.
Job của bạn sẽ kiểm tra dữ liệu, huấn luyện, so sánh với baseline và để CML đăng bảng kết quả vào PR.
Bạn cần một repo GitHub, Python, một file dữ liệu CSV nhỏ để trong repo và một model huấn luyện được trong vài phút. Ví dụ dưới đây đã được giản lược để dễ theo dõi; tên cột, thư viện và ngưỡng là giả định, bạn thay theo dự án của mình.
Bước 1: Chặn dữ liệu lỗi trước khi huấn luyện
Huấn luyện tốn thời gian, nên lỗi dữ liệu phải bị chặn trước. Script dưới đây kiểm tra đủ cột và không có giá trị rỗng. Nếu sai, nó thoát với mã lỗi khác 0 và workflow dừng luôn.
# check_data.py (ví dụ giản lược)
import sys
import pandas as pd
EXPECTED = ["tenure", "monthly_spend", "churned"]
df = pd.read_csv("data/train.csv")
missing = [c for c in EXPECTED if c not in df.columns]
if missing:
sys.exit(f"Thiếu cột: {missing}")
if df[EXPECTED].isnull().any().any():
sys.exit("Có giá trị rỗng trong cột bắt buộc")
print(f"OK: {len(df)} dòng")
Kiểm tra: chạy python check_data.py trên máy. Sau đó xóa thử một cột trong CSV và chạy lại, script phải báo lỗi. Một bước kiểm tra chưa từng báo lỗi là bước chưa được thử.
Bước 2: Huấn luyện và ghi metric ra file
Điều kiện duy nhất cho train.py là ghi metric ra một file máy đọc được. Mã huấn luyện là của bạn; phần cần giữ là đoạn cuối.
# cuối train.py (giản lược)
import json
metrics = {"accuracy": round(acc, 4), "recall": round(rec, 4)}
with open("metrics.json", "w") as f:
json.dump(metrics, f)
Chạy một lần trên nhánh chính, rồi copy kết quả thành baseline.json và commit. Đây là mốc để mọi PR so vào. Cách này đơn giản hơn việc so trực tiếp với nhánh main trên CI, đổi lại bạn phải nhớ cập nhật baseline khi chấp nhận model mới.
Bước 3: Sinh báo cáo so sánh dạng Markdown
Comment của CML là Markdown, nên script so sánh chỉ cần in ra một bảng.
# compare.py (giản lược)
import json
base = json.load(open("baseline.json"))
new = json.load(open("metrics.json"))
print("| Metric | Baseline | PR | Chênh lệch |")
print("|---|---|---|---|")
for k in base:
d = new[k] - base[k]
flag = "⚠️" if d < -0.01 else ""
print(f"| {k} | {base[k]} | {new[k]} | {d:+.4f} {flag} |")
Thử với số giả định: baseline accuracy 0,91, PR cho ra 0,89. Chênh lệch là -0,02, vượt ngưỡng -0,01, nên dòng đó gắn cờ cảnh báo. Reviewer thấy ngay, không cần chạy lại notebook của ai.
Bước 4: Nối mọi thứ vào workflow
Tạo file .github/workflows/cml.yaml. Các chi tiết lấy từ tài liệu CML: dùng action setup-cml để cài CML, không cần Docker container; truyền token qua biến REPO_TOKEN lấy từ secrets.GITHUB_TOKEN; bước cuối gọi cml comment create. Phần khung còn lại là cấu trúc GitHub Actions tối giản, bạn nên đối chiếu tag phiên bản action với trang Get Started của CML.
name: model-check
on: pull_request
jobs:
train-and-report:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: iterative/setup-cml@v2 # đối chiếu tag trong tài liệu CML
- name: Kiểm tra dữ liệu, huấn luyện, báo cáo
env:
REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
pip install -r requirements.txt
python check_data.py
python train.py
python compare.py > report.md
cml comment create report.md
Thứ tự lệnh trong run chính là logic của bài: dữ liệu sai thì dừng ở dòng thứ hai, không tốn thời gian train.
Bước 5: Mở PR và đọc comment
Tạo một nhánh, đổi một tham số của model, push và mở pull request. Tài liệu CML mô tả kết quả rất ngắn: một lúc sau, comment chứa báo cáo CML sẽ xuất hiện trong PR. Bạn sẽ thấy bảng metric từ Bước 3 ngay dưới phần mô tả PR.
Kiểm tra thêm hai trường hợp: một PR làm hỏng CSV (workflow phải đỏ ở bước kiểm tra dữ liệu) và một PR làm giảm metric (workflow xanh nhưng comment có cờ cảnh báo). Hai kiểu thất bại này khác nhau, và đội của bạn cần thấy rõ sự khác biệt.
Những lỗi hay gặp nhất
Lỗi đầu tiên là dữ liệu không có trên runner. Nếu dữ liệu được quản lý bằng DVC, cần biết CML không kèm DVC và các dependency của nó; tài liệu chỉ rõ bạn phải thêm action Setup DVC riêng trước bước kiểm tra dữ liệu.
Lỗi thứ hai là comment không hiện dù workflow xanh. Hãy xem lại biến REPO_TOKEN có nằm trong env của đúng bước gọi cml comment create không, rồi kiểm tra quyền của token trong cài đặt repo.
Lỗi thứ ba khó thấy hơn: baseline cũ. Merge một model mới tốt hơn mà quên cập nhật baseline.json thì mọi PR sau sẽ được so với mốc đã lỗi thời và trông đẹp giả tạo.
Kỹ năng này xuất hiện ở site khách hàng thế nào?
Theo trang chủ CML, công cụ này dùng chính GitLab, GitHub hoặc Bitbucket để quản lý thí nghiệm ML, và truy vết ai đã huấn luyện model hay sửa dữ liệu, vào lúc nào. Khi model chạy sai, đó chính là câu hỏi cần trả lời: ai đổi gì, khi nào.
Nếu trả lời được bằng lịch sử PR, bạn đỡ phải lục lại notebook của từng người.
Lời khuyên thực tế: tuần đầu ở khách hàng, đừng vội đề xuất nền tảng MLOps mới. Hãy hỏi họ đang dùng Git hosting nào, rồi dựng đúng một workflow như trên cho model quan trọng nhất.
Khi đọc JD FDE hay ML engineer, nếu thấy các cụm như “CI/CD for ML”, “model validation” hay “reproducible training”, bạn nên chuẩn bị sẵn để kể lại một pipeline như thế này, kèm ảnh chụp comment metric trong PR.
Mục tiêu cuối cùng là để đội của khách nhìn bảng metric trước khi nhìn diff. Khi đó, mỗi pull request tự trả lời câu hỏi khó nhất lúc review: model tốt lên hay tệ đi.