MLOps 6 — Giám sát & phát hiện trôi (drift)
MLOps 6 — Giám sát & phát hiện trôi (drift)
Ở bài pipelines ta đã tự động hoá việc train và ở bài model registry & deploy mô hình đã ra prod phục vụ thật. Nhưng một sự thật khắc nghiệt: mô hình bắt đầu xuống cấp ngay từ khoảnh khắc nó lên prod. Không phải vì code hỏng — code đứng yên. Mà vì thế giới thay đổi còn mô hình thì không. Bài này nói về mắt xích giữ cho hệ thống ML sống được lâu dài: giám sát (monitoring) và phát hiện trôi (drift detection).
Vì sao mô hình xuống cấp theo thời gian
Một mô hình học được quan hệ từ dữ liệu tại thời điểm train. Sau đó thực tế trôi đi:
- Hành vi khách thay đổi. Đại dịch, mùa lễ Tết, khủng hoảng kinh tế, một sản phẩm mới ra mắt — chi tiêu, vay mượn, gửi tiết kiệm của khách dịch chuyển.
- Thủ đoạn gian lận biến hoá. Kẻ gian liên tục thử cách mới để né mô hình cũ; cái mô hình từng bắt được, giờ chúng tránh.
- Dữ liệu đầu vào đổi. Đổi hệ thống core banking, thêm kênh giao dịch (ví điện tử, QR), đổi cách mã hoá mã ngành nghề merchant → phân phối feature lệch so với lúc train.
- Quan hệ nhân quả đổi. Chính sách lãi suất, quy định tín dụng mới làm quan hệ giữa đặc điểm khách và khả năng vỡ nợ thay đổi.
Kết quả: mô hình vẫn chạy (không có exception, latency vẫn ổn) nhưng dự đoán ngày càng sai. Đây là kiểu hỏng nguy hiểm nhất — hỏng âm thầm. Không có log lỗi nào báo "AUC vừa rơi từ 0.91 xuống 0.78". Nếu không chủ động giám sát, ta chỉ phát hiện khi thiệt hại nghiệp vụ đã lớn (tỷ lệ bắt gian lận tụt, nợ xấu tăng).
Năm tầng giám sát
Giám sát một hệ thống ML không chỉ là "xem AUC". Có năm tầng, từ hạ tầng lên tới ý nghĩa mô hình:
Càng xuống dưới càng khó phát hiện nhưng càng gần "ý nghĩa thật". Tầng trên phát hiện nhanh nhưng chỉ là dấu hiệu gián tiếp; tầng dưới cho biết mô hình có còn đúng không nhưng thường phải chờ nhãn.
1. Operational monitoring
Đây là giám sát hạ tầng — giống hệt bất kỳ dịch vụ phần mềm nào, dùng chung công cụ observability:
- Latency — p50/p95/p99 thời gian phản hồi của endpoint scoring. Mô hình chấm điểm giao dịch cần trả trong vài chục ms.
- Throughput — số request/giây, để biết khi nào cần scale.
- Error rate — tỷ lệ request lỗi (timeout, exception, model load fail).
- Tài nguyên — CPU/RAM/GPU, đặc biệt khi model nặng.
Tầng này KHÔNG cho biết mô hình dự đoán đúng hay sai — chỉ cho biết nó có phục vụ được không. Nhưng nó phát hiện nhanh nhất và không cần chờ nhãn.
2. Data quality monitoring
Kiểm tra chính dữ liệu đầu vào mà mô hình nhận lúc serve. Đây là nối tiếp bước validate data của pipeline (bài 4) nhưng áp vào lúc inference thời gian thực:
- Schema — đúng cột, đúng kiểu. Upstream đổi cấu trúc mà không báo là chuyện thường.
- Missing / null — tỷ lệ null của từng feature.
merchant_categorybỗng null 30%? Đứt nguồn dữ liệu. - Giá trị bất thường — ngoài miền hợp lệ (amount âm, tuổi khách 200), giá trị lạ (mã currency chưa từng thấy), hoặc feature bị "đóng băng" (mọi request đều cùng một giá trị mặc định — dấu hiệu upstream trả rác).
Data quality kém là nguyên nhân số một khiến mô hình đột ngột sai. Feature vào bị hỏng thì model dù tốt đến mấy cũng ra rác.
3. Data / feature drift
Drift dữ liệu (còn gọi feature drift hay covariate shift): phân phối của feature đầu vào P(X) thay đổi so với lúc train — dù mỗi giá trị vẫn "hợp lệ". Ví dụ: lúc train, giao dịch trung bình 2 triệu VND; ba tháng sau trung bình 3.5 triệu. Không có giá trị nào sai schema, nhưng mô hình đang thấy một thế giới khác. Đây là loại drift đo được mà không cần nhãn — chỉ cần so phân phối feature hôm nay với phân phối tham chiếu (baseline lúc train).
Các thước đo phổ biến:
| Thước đo | Dùng cho | Ý tưởng | Ngưỡng cảnh báo tham khảo |
|---|---|---|---|
| PSI (Population Stability Index) | Feature số & hạng mục (chia bucket) | Tổng (a% − e%) × ln(a%/e%) qua các bucket, đo lệch phân phối hiện tại vs tham chiếu | < 0.1 ổn định; 0.1–0.25 cần chú ý; > 0.25 drift đáng kể |
| KS test (Kolmogorov–Smirnov) | Feature số liên tục | Khoảng cách lớn nhất giữa 2 hàm phân phối tích luỹ (CDF) | p-value < 0.05 → phân phối khác nhau |
| Chi-square | Feature hạng mục | So tần suất quan sát vs kỳ vọng theo từng nhóm | p-value < 0.05 → khác biệt |
| KL divergence | So 2 phân phối xác suất | Đo "khoảng cách" thông tin từ phân phối tham chiếu tới hiện tại (bất đối xứng) | không có ngưỡng cố định; theo dõi xu hướng tăng |
PSI là "ngựa thồ" trong ngân hàng — quen thuộc từ thời scorecard tín dụng (xem credit scoring), dễ diễn giải, dễ báo cáo. Quy tắc kinh nghiệm PSI (< 0.1 / 0.1–0.25 / > 0.25) đã thành chuẩn ngành. Cần lưu ý: các ngưỡng này là kinh nghiệm, không phải chân lý — hãy hiệu chỉnh theo từng feature và mức nhạy nghiệp vụ.
Một lưu ý kỹ thuật với PSI/KL: tránh bucket có 0% (log của 0 phân kỳ) bằng cách gộp bucket hoặc thêm epsilon nhỏ.
4. Prediction drift
Phân phối đầu ra của mô hình P(ŷ) thay đổi. Ví dụ: mô hình gian lận trước đây gắn cờ 0.8% giao dịch, tuần này gắn cờ 2.5%. Điểm hay: prediction drift đo được ngay, không cần nhãn — chỉ cần lưu lại điểm số mô hình xuất ra. Nó thường là tín hiệu sớm của rắc rối: hoặc đầu vào đã drift (kéo đầu ra lệch theo), hoặc có gì đó bất thường. Nhưng prediction drift không tự nó nói mô hình sai — có thể thế giới thật đúng là đang có nhiều gian lận hơn. Nó là cờ để đi điều tra.
5. Concept drift
Loại khó nhất: quan hệ X → y thay đổi. Cùng một đầu vào X, nhưng nhãn thật y giờ khác. Ví dụ: một nhóm khách trước đây có hồ sơ "an toàn" giờ lại vỡ nợ nhiều do suy thoái ngành nghề của họ — đặc điểm không đổi nhưng ý nghĩa của đặc điểm đổi. Concept drift không phát hiện được chỉ bằng nhìn phân phối đầu vào (P(X) có thể y nguyên). Nó chỉ lộ ra qua sụt chất lượng mô hình — mà chất lượng thì cần nhãn thật. Đây chính là lý do bài toán nhãn trễ dưới đây trở nên nan giải.
Phân biệt nhanh:
| Loại | Cái gì đổi | Cần nhãn? | Phát hiện qua |
|---|---|---|---|
| Data/feature drift | P(X) — đầu vào | Không | PSI, KS, chi-square, KL |
| Prediction drift | P(ŷ) — đầu ra | Không | So phân phối điểm số theo thời gian |
| Concept drift | P(y|X) — quan hệ | Có | Sụt AUC/KS/precision khi có nhãn |
Vấn đề nhãn trễ (label lag)
Đây là nút thắt lớn nhất khi giám sát mô hình tín dụng/rủi ro. Ground truth (nhãn thật) đến rất muộn. Với mô hình dự báo nợ xấu, nhãn "khách này có vỡ nợ không" chỉ biết chắc sau nhiều tháng (thường định nghĩa quá hạn 90+ ngày, tức DPD90). Vậy suốt nhiều tháng chờ nhãn, ta không thể tính AUC thật để bắt concept drift trực tiếp.
Cách xử lý trong lúc chờ nhãn:
- Proxy / leading indicator (chỉ báo sớm). Dùng các tín hiệu đến sớm hơn thay cho nhãn cuối cùng: tỷ lệ quá hạn 30 ngày (DPD30) thay cho DPD90, tỷ lệ trả trễ kỳ đầu, tỷ lệ liên hệ nhắc nợ. Chúng tương quan với nhãn thật và cho tín hiệu sớm hơn.
- Giám sát input & prediction drift. Vì hai loại này không cần nhãn, chúng là "hệ thống cảnh báo sớm" trong khi nhãn thật chưa về. PSI feature tăng vọt + prediction drift lớn = cờ đỏ dù chưa có AUC mới.
- Đánh giá theo cohort khi nhãn chín. Khi nhãn của một đợt (vintage) khách đủ chín, đo hiệu năng của model trên đúng đợt đó — chấp nhận độ trễ để có sự thật.
Nguyên tắc: input/prediction drift cho tín hiệu nhanh nhưng gián tiếp; sụt chất lượng thật cho tín hiệu chắc nhưng chậm. Hệ thống tốt kết hợp cả hai.
Theo dõi hiệu năng theo thời gian & phân khúc
Đo AUC/KS/precision tổng thể theo thời gian là bước đầu, nhưng trung bình che giấu vấn đề. Một mô hình có AUC tổng ổn định vẫn có thể đã hỏng nặng ở một phân khúc:
- Theo phân khúc khách — theo thành phố/vùng, độ tuổi, phân khúc thu nhập, kênh (ATM/mobile/quầy). Drift thường bắt đầu ở một nhóm.
- Theo sản phẩm — thẻ tín dụng vs vay tiêu dùng vs vay mua nhà.
- Theo thời gian — theo tuần/tháng, phát hiện xu hướng dốc xuống.
Ví dụ thực tế: mô hình chấm gian lận AUC tổng 0.90 ổn định, nhưng tách theo kênh thì AUC nhóm giao dịch QR đã rơi xuống 0.71 vì kênh này mới, thủ đoạn mới — cái mà con số tổng che mất. Luôn slice theo phân khúc.
Nối tín hiệu vào trigger retrain
Giám sát chỉ có giá trị khi nó dẫn tới hành động. Tín hiệu drift/sụt chất lượng là đầu vào cho trigger retrain — nối thẳng vào ML pipeline ở bài 4. Ba loại trigger:
- Theo drift — PSI feature quan trọng vượt 0.25, hoặc prediction drift lớn, hoặc AUC (khi có nhãn) rơi dưới ngưỡng → phát tín hiệu retrain. Tiết kiệm vì chỉ train khi thật sự cần.
- Theo lịch — retrain định kỳ (tuần/tháng) như một tấm lưới an toàn, kể cả khi chưa thấy drift rõ.
- Theo ngưỡng chất lượng — khi chỉ số nghiệp vụ (precision@k, tỷ lệ bắt gian lận) rơi dưới ngưỡng cam kết.
Nhắc lại điểm cốt lõi từ bài 4: trigger tạo ra ứng viên, còn model gate mới quyết định model mới có lên prod không. Drift kích hoạt retrain ≠ tự động deploy — model mới vẫn phải vượt cổng kiểm định.
Công cụ
Không nên tự viết mọi thứ từ đầu. Vài công cụ chuyên giám sát ML đáng nhắc:
- Evidently (mã nguồn mở) — tính PSI/KS/chi-square, sinh report drift dữ liệu & chất lượng, tích hợp vào pipeline dễ; phổ biến để bắt đầu.
- NannyML (mã nguồn mở) — mạnh ở ước lượng hiệu năng khi chưa có nhãn (đúng bài toán nhãn trễ), phát hiện concept drift gián tiếp.
- WhyLabs — nền tảng giám sát ML/dữ liệu, profiling & alerting quy mô lớn.
Trong ngân hàng, nhiều nơi vẫn tính PSI bằng SQL/warehouse trực tiếp (như minh hoạ dưới) vì đội rủi ro đã quen PSI và cần kiểm soát chặt trong môi trường on-prem.
Alerting & dashboard
- Dashboard mô hình — một trang gom: latency/throughput/error (operational), tỷ lệ null từng feature, PSI từng feature theo tháng, phân phối điểm số, và AUC/KS theo cohort khi nhãn chín. Tách theo phân khúc.
- Alerting — cảnh báo theo ngưỡng (PSI > 0.25, null > 5%, prediction rate lệch > X%) gửi tới kênh trực (Slack/email/PagerDuty). Đặt ngưỡng vừa đủ nhạy nhưng tránh alert fatigue (báo động giả nhiều tới mức bị bỏ qua).
- Runbook — mỗi cảnh báo đi kèm hành động: điều tra nguồn dữ liệu, kiểm phân khúc, quyết định có kích hoạt retrain không.
Minh hoạ SQL: phát hiện dịch chuyển phân phối đầu vào
Một cách bắt data drift đơn giản mà đội rủi ro hay dùng: so trung bình, độ lệch chuẩn và phân vị của một feature (ở đây là amount của giao dịch) theo từng tháng. Nếu trung bình hay độ phân tán dịch chuyển rõ giữa các tháng, đó là dấu hiệu phân phối đầu vào đang trôi — cần soi PSI kỹ hơn. Truy vấn dưới đây chạy được trên sandbox PostgreSQL read-only:
-- ▶ Chạy được
SELECT date_trunc('month', created_at)::date AS thang,
COUNT(*) AS so_gd,
ROUND(AVG(amount)::numeric, 0) AS trung_binh,
ROUND(STDDEV_POP(amount)::numeric, 0) AS do_lech_chuan,
ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY amount)::numeric, 0) AS trung_vi,
ROUND(PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY amount)::numeric, 0) AS p90
FROM transactions
GROUP BY date_trunc('month', created_at)
ORDER BY thang;
Đọc kết quả: nếu trung_binh và p90 tăng đều qua các tháng trong khi trung_vi ít đổi, có thể xuất hiện đuôi giao dịch giá trị lớn mới (drift ở đuôi phân phối). Bước tiếp theo là chia amount thành các bucket cố định và tính PSI giữa tháng hiện tại và tháng tham chiếu.
Cũng có thể phân bố amount theo bucket để nhìn hình dạng phân phối trực tiếp — cũng chạy được:
-- ▶ Chạy được
SELECT width_bucket(amount, 0, 10000000, 10) AS bucket,
COUNT(*) AS so_gd,
ROUND(100.0 * COUNT(*) / SUM(COUNT(*)) OVER ()::numeric, 2) AS ty_le_pct
FROM transactions
GROUP BY width_bucket(amount, 0, 10000000, 10)
ORDER BY bucket;
So ty_le_pct từng bucket giữa hai kỳ chính là nguyên liệu để tính PSI: PSI = Σ (a% − e%) × ln(a%/e%).
Use case thực tế
Bối cảnh. NCB vận hành hai mô hình quan trọng: mô hình chấm điểm rủi ro tín dụng (dùng khi duyệt vay) và mô hình phát hiện gian lận giao dịch thẻ. Cả hai đã lên prod (bài 5). Đội MLOps + rủi ro thiết lập giám sát nhiều tầng.
Thiết lập giám sát.
- Operational — dashboard latency/throughput/error của endpoint scoring gian lận (yêu cầu p99 < 80ms), dùng chung stack observability.
- Data quality — job hằng ngày kiểm null/schema của feature đầu vào; một lần bắt được
merchant_categorynull nhảy từ 1% lên 34% do đứt nguồn upstream → cảnh báo, chặn dùng feature hỏng. - PSI hàng tháng — với mô hình tín dụng, đội rủi ro tính PSI cho từng feature scorecard (thu nhập, số dư, lịch sử giao dịch...) giữa tháng hiện tại và tập tham chiếu lúc train. Báo cáo tự động mỗi đầu tháng.
- Prediction drift — theo dõi tỷ lệ giao dịch bị gắn cờ gian lận theo tuần; ngưỡng cảnh báo nếu lệch > 50% so với baseline.
Một tháng có drift. Tháng 5, PSI của feature "số giao dịch QR 30 ngày" của mô hình gian lận nhảy lên 0.31 (> 0.25) — do khách chuyển mạnh sang thanh toán QR sau một chiến dịch khuyến mãi. Đồng thời prediction drift cho thấy tỷ lệ gắn cờ tăng từ 0.8% lên 1.9%. Nhãn thật còn trễ (cán bộ xác nhận gian lận mất vài tuần), nên đội dùng proxy: tỷ lệ khiếu nại giao dịch bị chặn nhầm tăng — dấu hiệu precision đang giảm.
Hành động. Cảnh báo drift kích hoạt điều tra → slice theo kênh xác nhận AUC nhóm QR rơi xuống 0.71 (tổng vẫn 0.89, bị che). Đội trigger retrain sớm (không chờ lịch cuối quý), pipeline train fraud_model bản mới có thêm dữ liệu QR gần đây. Model mới qua model gate (AUC nhóm QR phục hồi lên 0.86, tổng 0.92) và được promote. Nhờ giám sát PSI + prediction drift + slice phân khúc, đội bắt được vấn đề trước khi nhãn gian lận thật về, tránh được nhiều tuần bỏ lọt/chặn nhầm.
Với mô hình tín dụng (nhãn trễ nặng). Vì nhãn vỡ nợ chỉ chắc sau ~6 tháng (DPD90), đội dựa vào PSI hàng tháng + DPD30 làm leading indicator. Khi PSI của feature thu nhập vượt 0.25 kèm DPD30 của vintage mới nhích lên, đội đánh giá theo cohort ngay khi nhãn đủ chín và lên kế hoạch retrain — thay vì đợi tới lúc nợ xấu đã hiện rõ trên báo cáo.
Ghi nhớ
- Mô hình xuống cấp âm thầm vì thế giới đổi (hành vi khách, thủ đoạn gian lận, dữ liệu, chính sách) trong khi mô hình đứng yên — không có log lỗi nào báo. Phải chủ động giám sát.
- Năm tầng: operational (latency/throughput/lỗi) → data quality (schema/null/bất thường) → data/feature drift → prediction drift → concept drift. Tầng trên phát hiện nhanh nhưng gián tiếp; tầng dưới chắc nhưng cần nhãn.
- Data/feature drift đo bằng PSI (< 0.1 ổn / 0.1–0.25 chú ý / > 0.25 drift), KS, chi-square, KL — không cần nhãn. PSI là chuẩn ngành ngân hàng.
- Concept drift (quan hệ X→y đổi) không thấy qua phân phối đầu vào; chỉ lộ qua sụt chất lượng → cần nhãn.
- Nhãn trễ: nợ xấu biết sau nhiều tháng → dùng proxy/leading indicator (DPD30, khiếu nại) + input/prediction drift làm cảnh báo sớm; đánh giá theo cohort khi nhãn chín.
- Luôn slice theo phân khúc — trung bình tổng che giấu drift ở một nhóm.
- Nối tín hiệu vào trigger retrain (drift / lịch / ngưỡng chất lượng) → chạy pipeline; nhưng trigger chỉ tạo ứng viên, model gate mới cho lên prod.
- Công cụ: Evidently, NannyML (ước lượng hiệu năng khi chưa có nhãn), WhyLabs; kèm dashboard + alerting có runbook, tránh alert fatigue.
Bài viết liên quan
Phân biệt AI/ML/DL, các kiểu học máy, quy trình ML end-to-end và thuật ngữ nền tảng.
Chất lượng dữ liệu, xử lý thiếu/ngoại lai, mã hoá, chuẩn hoá, tạo đặc trưng và tránh data leakage.
Mô hình ngôn ngữ lớn hoạt động ra sao, token, context window, tham số sinh, và kỹ thuật viết prompt.
Retrieval-Augmented Generation, vector database, tool calling, agent và MCP để xây ứng dụng LLM thực tế.