data-science · Vietnamese · 9 min
🇺🇸 Read in EnglishSHAP Không Chỉ Để Giải Thích — Mà Để Tìm Lỗi Mô Hình
April 16, 2026
Trong dự án dự báo doanh số này, SHAP không chỉ là công cụ thuyết trình cho stakeholder — nó là kính hiển vi để thấy mô hình đang sai ở đâu. Weather features đóng góp 0.4%. Store-level factors đôi khi overpredict. SHAP tìm ra cả hai.
Bạn đã bao giờ thêm một nhóm features vào mô hình, chạy xong thấy accuracy cải thiện nhẹ, và tự nhủ "ổn rồi" chưa? Ví dụ: tích hợp dữ liệu thời tiết vào bài toán dự báo doanh số — trực giác bảo rằng mưa nắng ảnh hưởng đến lượng khách, vậy thêm vào hẳn sẽ giúp ích. Nhiều người dùng XAI (eXplainable AI) như SHAP chủ yếu để làm slide cho sếp: "nhìn xem, mô hình đang dùng feature A nhiều hơn feature B." Nhưng thực ra SHAP còn làm được điều khác hẳn — nó chỉ ra chính xác nơi mà mô hình đang hiểu sai dữ liệu. Trong dự án sales_forecasting_xai của tôi, SHAP đã phơi bày hai vấn đề cụ thể mà metric dự đoán đơn thuần không thể thấy được.
Bức Tranh Toàn Cảnh: Dự Án Làm Gì
Trước khi đi vào SHAP, cần có ngữ cảnh. Đây là một proof-of-concept (PoC) dự báo doanh số hàng ngày ở cấp độ cửa hàng — mặt hàng cụ thể, sử dụng dữ liệu bán lẻ hai năm (2016–2017) bao gồm nhiều tỉnh thành và cửa hàng, được bổ sung thêm tín hiệu thời tiết.
Stack kỹ thuật: LightGBM làm mô hình chính, Optuna cho hyperparameter tuning, SHAP TreeExplainer cho phần giải thích, và Streamlit để tạo giao diện cho stakeholder không chuyên về kỹ thuật có thể tương tác với kết quả dự báo.
Điều tôi muốn nhấn mạnh là cấu trúc dự án này không dừng ở notebook. Có thư mục docs/ chứa hai báo cáo có cấu trúc — một mô tả mục tiêu và phạm vi PoC, một là báo cáo phân tích SHAP với các con số cụ thể. Đây là thiết kế có chủ đích: interpretability không phải là phần thêm vào sau, mà là deliverable song song với accuracy.
Feature Engineering: Nhiều Tầng Thời Gian
Trước khi hiểu được kết quả SHAP, cần nhìn vào cách features được xây dựng.
Tôi thiết kế lag features theo nhiều độ phân giải thời gian: 1, 7, 14, 21, và 28 ngày. Mỗi khoảng này bắt sóng một tín hiệu khác nhau:
| Lag window | Tín hiệu bắt được |
|---|---|
| 1 ngày | Biến động ngắn hạn, outlier đột xuất |
| 7 ngày | Chu kỳ tuần (thứ 7 vs thứ 2) |
| 14–21 ngày | Xu hướng mid-term |
| 28 ngày | Chu kỳ tháng, tín hiệu trend dài hơn |
Thiết kế này không phải ngẫu nhiên — nó được ghi lại trong tài liệu PoC như một quyết định có chủ ý. Rolling averages trên các cửa sổ này, kết hợp với các đặc trưng cấp item và store, tạo thành không gian feature chính. Weather features (nhiệt độ, lượng mưa, v.v.) được thêm vào như một nhóm riêng để kiểm tra giả thuyết về tác động thời tiết.
Metric đánh giá chính là WAPE (Weighted Absolute Percentage Error), cùng với MAE và RMSE. WAPE robust hơn MAPE trong bộ dữ liệu bán lẻ vì không bị vỡ khi doanh số bằng 0 hoặc gần 0 — một lựa chọn domain-aware.
SHAP Như Kính Hiển Vi, Không Phải Kính Trình Chiếu
Đây là nơi dự án trở nên thú vị.
Phát Hiện 1: Weather Đóng Góp 0.4%
Sau khi chạy SHAP TreeExplainer và nhìn vào global feature importance, con số hiện ra: weather features chỉ đóng góp khoảng 0.4% tổng predictive power. Trong khi đó, rolling averages cấp item — tức là lịch sử doanh số trung bình theo từng mặt hàng — chiếm khoảng 50% tổng feature importance.
Nếu chỉ nhìn vào WAPE tổng, bạn sẽ không thấy điều này. Mô hình vẫn chạy tốt. Weather features không làm hỏng accuracy, nhưng SHAP chỉ ra rằng chúng về cơ bản không được mô hình học. Đây là sự khác biệt giữa "feature có trong dataset" và "feature mang thông tin mà mô hình có thể sử dụng."
Hệ quả thực tế: pipeline tích hợp dữ liệu thời tiết — API call, join, imputation — đang tạo ra chi phí kỹ thuật không tương xứng với giá trị đem lại. Nếu không có SHAP, sự thật này có thể nằm im trong pipeline mãi mãi vì không có metric nào "bị hỏng."
import shap
explainer = shap.TreeExplainer(lgb_model)
shap_values = explainer.shap_values(X_test)
# Global summary — nhìn ngay được feature nào đang làm việc
shap.summary_plot(shap_values, X_test, plot_type="bar")Summary plot bar chart sẽ xếp hạng toàn bộ features theo mean absolute SHAP value. Weather features sẽ nằm gần đáy — đây là lúc bạn bắt đầu đặt câu hỏi về chi phí pipeline.
Phát Hiện 2: Strong-Item / Weak-Store Misalignment
SHAP còn hé lộ một vấn đề tinh tế hơn ở cấp độ local explanations: store-level factors đôi khi overpredict, đặc biệt trong trường hợp mà một mặt hàng bán chạy (strong item) nhưng lại đặt tại một cửa hàng hiệu suất thấp (weak store).
Khi nhìn vào SHAP waterfall plot cho các dự đoán cụ thể trong nhóm này, mô hình bị kéo về phía dự đoán cao bởi item-level features, nhưng store-level features không kéo ngược đủ mạnh để bù lại. Kết quả là overprediction có hệ thống cho một phân khúc cụ thể.
Đây là loại lỗi mà không một aggregate metric nào có thể phát hiện trừ khi bạn chủ động slice dữ liệu theo phân khúc đó. SHAP local explanations làm điều này tự nhiên — bạn nhìn vào một prediction cụ thể, thấy contribution của từng feature, và nhận ra pattern.
# Local explanation cho một prediction cụ thể
shap.waterfall_plot(shap.Explanation(
values=shap_values[i],
base_values=explainer.expected_value,
data=X_test.iloc[i],
feature_names=X_test.columns.tolist()
))Waterfall plot hiển thị từng feature đang push prediction lên hay kéo xuống, từ base value đến final prediction. Trong strong-item/weak-store cases, bạn sẽ thấy item rolling average features đang push mạnh lên phía dương trong khi store features lại quá yếu để counteract.
Kết Quả SHAP Trong Bức Tranh Lớn Hơn
Hai phát hiện trên không phải điểm yếu của dự án — chúng là điểm mạnh. Một PoC tốt không chỉ cần chứng minh rằng bài toán có thể giải được, mà còn phải chỉ ra rõ ràng đâu là rủi ro và đâu là câu hỏi cần Phase 2 trả lời.
Báo cáo SHAP trong docs/ của dự án làm đúng điều này: ghi lại các con số cụ thể (0.4% weather importance, ~50% item rolling features), chỉ ra feature-weight imbalances như một vấn đề mở, và đặt câu hỏi về sự phức tạp của weather pipeline. Đây là loại tài liệu mà một engineering team cần để quyết định có đi tiếp sang Phase 2 hay không — và nếu đi tiếp, cần sửa gì trước.
Streamlit app đóng vai trò là deliverable cho phía business: stakeholder có thể chọn store, chọn item, và xem dự báo cùng với SHAP explanation tương ứng. Điều này cho phép người không làm kỹ thuật đặt câu hỏi về các trường hợp cụ thể — một cơ chế validation quan trọng trong retail forecasting.
Sai Lầm Thường Gặp Khi Dùng SHAP
1. Dùng SHAP chỉ để làm slide thuyết trình, không để debug
SHAP global summary đẹp để trình bày, nhưng giá trị thực nằm ở việc dùng local explanations và dependency plots để tìm failure modes. Nếu bạn chỉ print summary bar chart rồi thôi, bạn đang bỏ qua phần quan trọng nhất.
2. Nhầm "feature có SHAP value thấp" với "feature vô dụng"
Weather features có SHAP value thấp không nhất thiết có nghĩa là thời tiết không ảnh hưởng đến doanh số trong thực tế. Nó có nghĩa là mô hình hiện tại, với feature engineering hiện tại, không học được tín hiệu đó. Cần phân biệt hai điều này — đôi khi vấn đề là feature representation, không phải feature relevance.
3. Chỉ nhìn aggregate metrics, bỏ qua phân tích theo phân khúc
Strong-item/weak-store misalignment sẽ không thấy trong WAPE tổng. Luôn slice error analysis theo các categorical dimensions quan trọng (store tier, item category, season) trước khi kết luận mô hình đã hoạt động đúng.
4. Để SHAP analysis nằm trong notebook, không đưa vào docs
SHAP findings là business-critical information. Nếu chỉ sống trong .ipynb, nó sẽ bị lãng quên. Cấu trúc docs/ của dự án này — với báo cáo SHAP riêng biệt có con số cụ thể — là pattern đáng học.
5. Chạy SHAP trên toàn bộ test set rồi kết luận ngay
SHAP values có thể bị dominated bởi high-frequency samples. Cân nhắc lấy mẫu có chiến lược — ưu tiên các edge cases, outliers, và phân khúc mà bạn đang quan tâm nhất — thay vì chạy trên random sample.
6. Bỏ qua SHAP interaction values
Trong retail forecasting, item và store features thường interact với nhau (một mặt hàng bán chạy tại một cửa hàng cụ thể, không phải toàn bộ). shap.dependence_plot với interaction_index có thể hé lộ những interaction này mà summary plot không thấy.
Tóm tắt:
- SHAP TreeExplainer dùng được cho cả global rankings lẫn local per-prediction explanations — cả hai đều cần thiết, không phải chọn một
- Trong dự án này, item-level rolling averages chiếm ~50% feature importance; weather features chỉ đóng góp 0.4% — SHAP biến con số này thành evidence để ra quyết định về pipeline
- Local SHAP explanations phát hiện strong-item/weak-store misalignment mà aggregate WAPE không thể thấy
- Một PoC tốt không chỉ là "mô hình chạy được" — mà là tài liệu hóa rõ ràng đâu là điểm yếu và câu hỏi nào cần Phase 2 trả lời
- Cấu trúc
docs/với SHAP report riêng biệt — không phải chỉ là notebook output — là pattern giúp findings tồn tại được sau khi dự án kết thúc
Nguồn tham khảo