Chuỗi thời gian 8 — Triển khai dự báo production
Chuỗi thời gian 8 — Triển khai dự báo production
Bảy bài trước đã đi từ tổng quan (Chuỗi thời gian 1), phân rã và EDA (Chuỗi thời gian 2), mô hình cổ điển (Chuỗi thời gian 3), feature + ML (Chuỗi thời gian 4), Prophet/deep learning (Chuỗi thời gian 5), đánh giá (Chuỗi thời gian 6) đến phát hiện bất thường (Chuỗi thời gian 7). Tất cả đều dừng ở một mô hình chạy tốt trên máy của bạn. Bài này bàn về phần khó nhất và ít được dạy nhất: làm cho dự báo chạy đều mỗi ngày, không cần bạn ngồi bấm, và biết khi nào nó bắt đầu sai.
Nguyên tắc bao trùm: một mô hình dự báo trong production không phải là một file .pkl, mà là một hệ thống sống gồm dữ liệu chảy vào, mô hình được huấn luyện lại, dự báo được sinh ra, và một vòng giám sát liên tục soi xem nó còn đúng không. Đây chính là time-series MLOps — nối tiếp các nguyên lý MLOps chung ở ML 8 — Triển khai & MLOps và quy trình ML ở ML 1 — Workflow, nhưng có những cạm bẫy riêng của dữ liệu theo thời gian.
1. Pipeline dự báo end-to-end
Một pipeline dự báo production gồm năm giai đoạn nối tiếp, chạy theo lịch:
1.1. Thu thập & cập nhật dữ liệu
Mỗi ngày (hoặc mỗi giờ), pipeline kéo dữ liệu mới nhất vào một bảng chuẩn hoá dạng "long": (entity_id, ds, y, [biến ngoại sinh]). Với ngân hàng, entity_id có thể là mã ATM, mã chi nhánh, mã sản phẩm; y là lượng tiền rút, số dư, doanh số. Việc quan trọng ở đây không phải là kéo dữ liệu, mà là đánh dấu thời điểm dữ liệu thực sự có mặt — vì dữ liệu ngân hàng thường về trễ (xem mục 6).
-- ▶ Chạy được
SELECT date_trunc('day', created_at) AS ds,
COUNT(*) AS so_giao_dich,
SUM(CASE WHEN kind = 'withdrawal' THEN amount ELSE 0 END) AS tong_rut
FROM transactions
GROUP BY 1
ORDER BY 1;
Câu trên là ví dụ bước "vật liệu hoá chuỗi ngày" từ bảng giao dịch thô — chính là đầu vào y của pipeline dự báo lượng tiền rút.
1.2. Feature engineering as-of (tránh rò rỉ)
Đây là điểm chết người nhất của dự báo. Rò rỉ dữ liệu (data leakage) xảy ra khi feature cho ngày t vô tình chứa thông tin chỉ biết được sau t. Trong training offline thì dễ vô tình dùng cả tương lai; trong production thì tại thời điểm dự báo cho ngày mai, bạn chưa có giá trị hôm nay đã chốt sổ.
Nguyên tắc as-of: mọi feature phải được tính chỉ từ dữ liệu có mặt tính đến (as of) thời điểm cắt. Feature điển hình của chuỗi thời gian:
- Lag (
y[t-1],y[t-7],y[t-28]) — luôn hợp lệ vì thuộc quá khứ. - Rolling (trung bình/độ lệch chuẩn 7/28 ngày) — phải tính trên cửa sổ kết thúc trước
t, không bao gồmt. - Lịch: ngày trong tuần, ngày lễ/Tết, ngày lương, cuối tháng — biết trước nên hợp lệ.
Mấu chốt: dùng chung một hàm feature cho cả training lẫn serving. Nếu training tính theo cách A còn serving tính theo cách B, bạn có training-serving skew — mô hình nhìn thấy feature khác lúc suy luận so với lúc học.
# Minh hoa - KHONG danh dau chay duoc (Python)
def make_features(df, cutoff):
# chi giu du lieu co mat TINH DEN cutoff (as-of)
hist = df[df["ds"] <= cutoff].sort_values("ds")
feats = {}
feats["lag_1"] = hist["y"].iloc[-1]
feats["lag_7"] = hist["y"].iloc[-7]
feats["ma_28"] = hist["y"].iloc[-28:].mean() # cua so ket thuc TRUOC hom du bao
feats["dow"] = (cutoff + pd.Timedelta(days=1)).dayofweek
feats["is_payday"] = int(is_payday(cutoff + pd.Timedelta(days=1)))
return feats
# Dung DUNG ham nay o ca train va serve => tranh training-serving skew
Xem thêm nền tảng feature ở AI 2 — Dữ liệu & Feature.
1.3. Train / retrain
Huấn luyện (hoặc huấn luyện lại) mô hình trên toàn bộ lịch sử as-of, dùng backtesting theo thời gian (rolling-origin) để chọn siêu tham số — tuyệt đối không dùng k-fold ngẫu nhiên như bài toán tabular thường, vì nó phá vỡ thứ tự thời gian (chi tiết ở Chuỗi thời gian 6 — Đánh giá). Kết quả train được đóng gói thành một artifact có phiên bản (mục 5).
1.4. Sinh dự báo
Nạp mô hình đã chọn, tính feature as-of tại thời điểm hiện tại, sinh dự báo cho horizon cần (ví dụ 14 ngày tới). Với dự báo nhiều bước, có hai chiến lược: recursive (dùng dự báo bước trước làm lag cho bước sau — dễ tích luỹ sai số) và direct (huấn luyện riêng một mô hình cho mỗi horizon). Nên xuất cả điểm dự báo lẫn khoảng dự báo (prediction interval), vì nghiệp vụ ngân hàng cần biên an toàn (ví dụ tiếp quỹ ATM theo P90 chứ không theo trung bình).
1.5. Phục vụ (serving): batch vs real-time
| Tiêu chí | Batch | API real-time |
|---|---|---|
| Cách hoạt động | Sinh dự báo định kỳ, ghi bảng/warehouse | Nhận request, tính & trả ngay |
| Độ trễ | Cao (phút–giờ), chấp nhận được | Thấp (ms–giây) |
| Phù hợp | Dự báo hằng ngày cho hàng trăm ATM, báo cáo | Dự báo theo yêu cầu, tham số động |
| Tiêu thụ | BI/dashboard đọc bảng đã tính | App gọi endpoint |
| Chi phí vận hành | Thấp, dễ giám sát | Cao hơn (service luôn chạy) |
Với dự báo ngân hàng, batch là mặc định: horizon dài (ngày/tuần), không cần trả tức thời, và ghi sẵn kết quả vào một bảng để dashboard đọc là đủ. API chỉ cần khi có kịch bản "what-if" tương tác. Kỹ thuật dựng API dự báo có thể tham khảo Python 8 — SQL, API & Async và ingestion phía nguồn ở PyDE 6 — API & Ingestion.
2. Lịch retraining
Mô hình dự báo xuống cấp theo thời gian vì hành vi thực tế đổi (lạm phát, thói quen dùng tiền mặt giảm, chi nhánh mới mở). Có hai triết lý:
- Định kỳ (scheduled): retrain theo lịch cố định — ví dụ mỗi tuần một lần, hoặc mỗi đêm với chuỗi biến động nhanh. Đơn giản, dễ đoán, dễ vận hành. Rủi ro: retrain thừa (tốn tài nguyên) hoặc thiếu (mô hình đã hỏng giữa hai kỳ).
- Theo trigger drift: chỉ retrain khi giám sát phát hiện sai số vượt ngưỡng hoặc phân phối dữ liệu lệch (mục 3). Tiết kiệm và phản ứng đúng lúc, nhưng cần hạ tầng giám sát tin cậy.
Thực tế tốt nhất là kết hợp: một lịch định kỳ làm nền (ví dụ hằng tuần) cộng một trigger drift để retrain khẩn khi có biến cố (Tết, thay đổi chính sách rút tiền). Luôn ghi lại: dữ liệu nào, code version nào, kết quả backtest ra sao — để so sánh mô hình mới với mô hình đang chạy trước khi thay thế (đừng "deploy mù").
3. Giám sát: phần quan trọng nhất
Không có giám sát thì bạn không biết mô hình đang sai cho tới khi nghiệp vụ than phiền. Cần theo dõi ba tầng:
3.1. Theo dõi sai số thực tế theo thời gian
Khi giá trị thật của ngày t về, ghép nó với dự báo đã sinh trước đó và tính sai số (MAE, MAPE, WAPE, pinball loss cho khoảng dự báo). Vẽ sai số theo thời gian cho từng entity. Dấu hiệu xấu: MAPE trượt dốc dần, hoặc sai số có thiên lệch (bias) — mô hình dự báo thấp/cao có hệ thống. Nên đặt ngưỡng cảnh báo so với baseline seasonal-naive: nếu mô hình chính thua baseline nhiều kỳ liên tiếp thì nó không còn đáng dùng.
3.2. Phát hiện data drift
Data drift là phân phối đầu vào đổi so với lúc train (ví dụ trung bình lượng rút hằng ngày tăng vọt, hoặc biến ngoại sinh có giá trị chưa từng thấy). Đo bằng so sánh phân phối tham chiếu (train) với gần đây: PSI (Population Stability Index), KS-test, hoặc đơn giản là theo dõi mean/std trượt. Drift đầu vào chưa chắc làm hỏng dự báo, nhưng là cảnh báo sớm.
3.3. Phát hiện concept drift
Concept drift là quan hệ giữa feature và mục tiêu đổi — cùng một feature nhưng y phản ứng khác trước. Đây là loại nguy hiểm hơn, thường chỉ lộ ra qua sai số dự báo tăng dù đầu vào trông bình thường. Vì thế 3.1 (theo dõi sai số) là tuyến phòng thủ chính, còn 3.2 chỉ là bổ trợ.
data drift = P(X) doi -> phat hien som, chua chac hong
concept drift = P(y|X) doi -> chi lo qua sai so tang, nguy hiem hon
Khi sai số vượt ngưỡng hoặc drift báo động, hệ thống cảnh báo (Slack/email) và có thể tự kích hoạt retrain. Nguyên lý drift/monitoring chung xem ML 8 — Triển khai & MLOps.
4. Nhiều chuỗi: hàng trăm ATM/chi nhánh
Ngân hàng không dự báo một chuỗi, mà hàng trăm đến hàng nghìn (mỗi ATM, mỗi chi nhánh, mỗi cặp sản phẩm×vùng). Huấn luyện một mô hình riêng cho mỗi chuỗi (local model) sớm trở nên bất khả thi về vận hành và kém với chuỗi ít dữ liệu (ATM mới).
Giải pháp là global model: một mô hình (thường là gradient boosting hoặc mạng như DeepAR) học chung trên tất cả các chuỗi, với entity_id và thuộc tính (vùng, loại máy, cỡ chi nhánh) là feature. Ưu điểm:
- Học chéo (cross-learning): chuỗi nhiều dữ liệu "cho mượn" hình mẫu cho chuỗi ít dữ liệu → xử lý tốt cold-start (ATM mới) và chuỗi ngắn.
- Chỉ một artifact để deploy, giám sát, versioning thay vì hàng trăm.
- Rẻ và mở rộng được theo số chuỗi.
Nhược: khó diễn giải hơn và có thể lấn át chuỗi "cá tính". Thực dụng: dùng global model làm nền, đặt cạnh baseline per-series, và cho phép override vài chuỗi đặc biệt.
5. Versioning & reproducibility
Để có thể trả lời "vì sao ngày đó dự báo ra con số này", bạn phải tái tạo được. Cần version hoá cả ba:
- Dữ liệu: snapshot/hash của bảng đầu vào tại thời điểm train (data version). Không thể chỉ trỏ vào bảng "hiện tại" vì nó đã đổi.
- Code/feature: commit git của pipeline và định nghĩa feature.
- Mô hình: artifact + siêu tham số + kết quả backtest, lưu trong model registry (mục 7), gắn nhãn
staging/production.
Reproducibility = cùng data version + cùng code version → ra cùng mô hình. Đây là điều kiện để audit — cực kỳ quan trọng với ngân hàng, nơi thanh tra có thể hỏi lại quyết định tiếp quỹ của sáu tháng trước.
6. Backfill & dữ liệu trễ/điều chỉnh
Dữ liệu ngân hàng hiếm khi "chốt ngay". Ba tình huống thường gặp:
- Dữ liệu trễ (late-arriving): giao dịch cuối ngày, đối soát liên ngân hàng về sau 1–2 ngày. Nếu pipeline dự báo lúc 6h sáng, con số hôm qua có thể chưa đủ.
- Điều chỉnh (restatement): số liệu đã chốt bị sửa (huỷ giao dịch, điều chỉnh kế toán). Giá trị lịch sử thay đổi sau khi bạn đã dự báo.
- Backfill: khi thêm feature mới hoặc sửa lỗi, cần tính lại lịch sử feature/dự báo cho quá khứ để so sánh công bằng.
Cách xử lý an toàn:
- Ghi nhận theo "vintage"/
event_timelẫningestion_time— biết mỗi điểm được biết vào lúc nào, để feature as-of của quá khứ phản ánh đúng thông tin có tại thời điểm đó (tránh rò rỉ ngược khi backtest). - Cửa sổ chờ chốt (settlement window): không dùng ngày chưa đủ chín; hoặc dự báo lại khi số liệu chốt về.
- Backfill idempotent: chạy lại pipeline cho một khoảng ngày phải cho kết quả nhất quán, ghi đè an toàn (chèn theo partition ngày).
Chất lượng đầu vào là điều kiện tiên quyết — liên hệ Gov 3 — Chất lượng dữ liệu.
7. Con người trong vòng lặp & công cụ
Con người trong vòng lặp (human-in-the-loop): dự báo tự động không thay thế chuyên gia. Cán bộ kho quỹ biết trước sự kiện mô hình không thấy trong dữ liệu (một lễ hội địa phương, một doanh nghiệp lớn trả lương bằng tiền mặt vào ngày X). Nên cho phép override có kiểm soát: chuyên gia điều chỉnh dự báo, hệ thống ghi log giá trị gốc và giá trị đã sửa, rồi so sánh về sau xem override đúng hay sai — đây là dữ liệu quý để cải thiện mô hình.
Công cụ (khái quát):
- Airflow (hoặc scheduler tương đương) điều phối DAG các bước 1.1→1.5 theo lịch, quản lý phụ thuộc, retry, cảnh báo khi task fail.
- Feature store lưu định nghĩa feature dùng chung giữa train và serve, đảm bảo tính as-of và chống skew.
- Model registry quản lý phiên bản mô hình, nhãn môi trường, lineage.
Chi tiết MLOps/công cụ xem ML 8 — Triển khai & MLOps.
8. Sơ đồ pipeline production (có vòng retrain/monitor)
Use case thực tế
Bài toán: NCB vận hành một mạng lưới 420 máy ATM. Tiếp quỹ (nạp tiền mặt) tốn chi phí và rủi ro: nạp thừa → ứ đọng vốn không sinh lời + rủi ro an ninh; nạp thiếu → ATM hết tiền, khách bức xúc, mất uy tín. Mục tiêu: dự báo lượng rút mỗi ATM cho 14 ngày tới để lập lịch tiếp quỹ theo P90.
Kiến trúc triển khai:
- Thu thập (Airflow, 5h sáng mỗi ngày): DAG kéo giao dịch rút tiền D-1 từ core banking vào bảng chuỗi long
(atm_id, ds, y_rut), gắningestion_time. Có cửa sổ chốt 1 ngày vì đối soát về trễ. - Feature as-of: với mỗi ATM, tính lag 1/7/14, MA-7/MA-28 (cửa sổ kết thúc trước ngày dự báo), cờ ngày lương/lễ/Tết, thuộc tính máy (khu dân cư/khu công nghiệp/trung tâm TM). Dùng chung một hàm cho train và serve qua feature store.
- Mô hình: một global model (gradient boosting, dự báo trực tiếp theo từng horizon) học trên cả 420 chuỗi — ATM mới mở cạnh khu công nghiệp được hưởng lợi từ hình mẫu các ATM tương tự (cold-start).
- Sinh dự báo & phục vụ (batch): xuất điểm dự báo và P90 cho 14 ngày, ghi vào bảng warehouse; dashboard kho quỹ đọc bảng này. Cán bộ kho quỹ được phép override (ví dụ biết sắp có lễ hội địa phương), hệ thống log lại.
- Retraining: lịch hằng tuần (Chủ nhật đêm) + trigger drift: nếu WAPE 7 ngày gần nhất của một cụm ATM vượt 1.5× baseline seasonal-naive, kích retrain khẩn.
- Giám sát: mỗi sáng ghép y thực D-1 với dự báo cũ, tính WAPE per-ATM và toàn mạng, vẽ theo thời gian; PSI trên phân phối lượng rút để bắt data drift. Cảnh báo Slack khi có ATM xuống cấp.
Kết quả (minh hoạ, không phải số đo thật): sau 3 tháng, tỷ lệ ATM hết tiền giảm rõ, số lần tiếp quỹ khẩn giảm nhờ đặt lịch theo P90, và tồn quỹ trung bình giảm đáng kể — vừa bớt rủi ro an ninh vừa giải phóng vốn. Điểm mấu chốt giúp hệ thống bền: giám sát sai số theo thời gian phát hiện sớm hai ATM bị lệch do khu vực có nhà máy đóng cửa (concept drift), trigger retrain kịp trước khi gây sự cố.
Ghi nhớ
- Dự báo production là một hệ thống sống, không phải một file model: dữ liệu → feature → retrain → dự báo → phục vụ → giám sát → quay lại.
- Feature as-of và dùng chung hàm feature giữa train và serve là tuyến phòng thủ chính chống rò rỉ dữ liệu và training-serving skew.
- Batch (ghi bảng) là mặc định cho dự báo ngân hàng horizon dài; API real-time chỉ khi cần tương tác what-if.
- Retraining: định kỳ làm nền + trigger drift để phản ứng biến cố; luôn so mô hình mới với mô hình cũ và với baseline trước khi thay.
- Giám sát ba tầng: sai số thực tế theo thời gian (quan trọng nhất), data drift (P(X) đổi, cảnh báo sớm), concept drift (P(y|X) đổi, nguy hiểm, chỉ lộ qua sai số tăng).
- Hàng trăm chuỗi → dùng global model (một artifact, học chéo, xử lý cold-start) thay vì mô hình riêng từng chuỗi.
- Versioning cả dữ liệu + code + mô hình để reproducibility và audit — bắt buộc trong môi trường ngân hàng.
- Xử lý dữ liệu trễ/điều chỉnh bằng event_time vs ingestion_time, cửa sổ chốt, và backfill idempotent.
- Giữ con người trong vòng lặp: cho override có log; công cụ nền là Airflow (điều phối), feature store, model registry.
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ế.