Model Evaluation & Selection
Đánh giá và chọn mô hình
Năm model candidate cùng dự đoán gian lận thẻ. Model A đạt độ chính xác 98,4%, Model B đạt 97,9%. A thắng?
Hình minh họa
Bốn model đã huấn luyện. Bạn chọn cái nào?
Bốn model dưới đây đã chạy xong trên cùng tập dữ liệu phát hiện gian lận. Con số của chúng được thiết kế để không model nào thống trị, mỗi model mạnh ở một trục khác nhau. Bạn kéo trọng số cho từng metric, dashboard sẽ sắp xếp lại thứ hạng ngay tức khắc. Hãy thử:
- Chỉ quan tâm độ chính xác. Ai lên đầu?
- Tăng weight recall (sợ bỏ sót gian lận). Thứ tự đổi ra sao?
- Cần latency thấp cho thanh toán realtime. Ai rơi xuống?
Tỉ lệ dự đoán đúng trên toàn bộ tập test
Trong các ca báo gian lận, bao nhiêu đúng là gian lận?
Trong các ca gian lận thật, model bắt được bao nhiêu?
Trung bình điều hòa của precision và recall
Thời gian chấm 1000 giao dịch (ms). Càng thấp càng tốt.
Thời gian huấn luyện một lần (phút). Càng thấp càng tốt.
F1 cao nhất, inference nhanh, nhưng huấn luyện lâu và cần tuning nhiều tham số. Ứng viên hàng đầu cho production.
Cân bằng tốt giữa precision và recall. Huấn luyện nhanh, nhưng inference chậm hơn logistic vì phải hỏi cả trăm cây.
Recall tốt nhất, bắt được nhiều ca gian lận nhất. Bù lại huấn luyện lâu nhất và inference chậm nhất. Chọn nó khi chi phí bỏ sót cao.
Siêu nhanh, dễ giải thích, độ chính xác cao ngất. Nhưng chính độ chính xác cao đang đánh lừa bạn vì nó bỏ sót hơn nửa số ca gian lận.
Metrics không phải một loại. Mỗi bài toán có nhóm metrics riêng. Bấm qua 4 tab dưới để thấy visual + một đoạn code sklearn nhỏ cho mỗi nhóm.
Kéo ngưỡng (threshold) để thấy confusion matrix đổi ra sao. Threshold thấp thì bắt nhiều gian lận (recall cao) nhưng báo động giả nhiều (precision thấp). Threshold cao thì ngược lại.
from sklearn.metrics import (
precision_score, recall_score, f1_score, roc_auc_score,
)
# y_true: nhãn thật, y_pred: dự đoán (0/1), y_proba: xác suất
print("Precision:", precision_score(y_true, y_pred))
print("Recall: ", recall_score(y_true, y_pred))
print("F1: ", f1_score(y_true, y_pred))
print("ROC AUC: ", roc_auc_score(y_true, y_proba))Chọn model không phải đi tìm “model tốt nhất”. Việc của bạn là biên soạn một bộ yêu cầu rồi tìm model thoả mãn bộ đó.
Bộ yêu cầu thường gồm: metric chính (tuỳ bài toán), ràng buộc thời gian (huấn luyện, inference), khả năng giải thích (cho khách hàng, cho cơ quan quản lý), và chi phí (tính toán, bảo trì). Khi bộ yêu cầu đã viết xong, câu trả lời về model gần như tự hiện ra.
Model X được quảng cáo ROC AUC = 0,95. Bạn triển khai thử thì accuracy chỉ 55%. Chuyện gì xảy ra?
Giải thích
Đánh giá và chọn mô hình đi theo vòng lặp 4 bước: huấn luyện → dự đoán → đo lường → so sánh. Mỗi vòng lặp cho bạn thêm hiểu biết để tinh chỉnh: đổi hyperparameter, thêm feature, hoặc chuyển hẳn sang model khác.
Quy trình 5 bước so sánh model một cách khoa học
Trước khi mở editor, hãy viết ra giấy: bài toán là classification hay regression? Dữ liệu cân bằng không? Latency giới hạn bao nhiêu? Chi phí sai âm (bỏ sót) so với sai dương (báo giả) lệch nhau ra sao? Bộ yêu cầu này là la bàn. Mọi quyết định sau đó đều phải nhìn lại nó.
ROC AUC: một dòng công thức, một đời dùng được
ROC AUC là xác suất model đưa ra score cao hơn cho một mẫu dương ngẫu nhiên so với một mẫu âm ngẫu nhiên:
Nói ngắn gọn: đưa cho model hai giao dịch, một là gian lận thật, một là giao dịch bình thường. AUC = 0,95 có nghĩa là 95% số lần model xếp giao dịch gian lận với score cao hơn. AUC 0,50 nghĩa là đoán mò. AUC 1,0 là hoàn hảo. Biểu đồ dưới đây so ba mức AUC:
Average Precision (AP): bạn đồng hành của AUC khi dữ liệu mất cân bằng
AP là diện tích dưới precision-recall curve. Khi gian lận chỉ chiếm 1% dữ liệu, AUC có thể cao một cách giả tạo do TN rất nhiều. Trong khi đó, AP nhìn trực tiếp vào đường precision-recall nên phản ánh thực chất hơn. Quy tắc: dữ liệu mất cân bằng trên 1:20 thì ưu tiên AP hơn AUC.
Code: cross_val_score + GridSearchCV trong 13 dòng
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import cross_val_score
models = {
"LogReg": LogisticRegression(max_iter=1000, random_state=42),
"RandomForest": RandomForestClassifier(n_estimators=100, random_state=42),
}
for name, m in models.items():
scores = cross_val_score(m, X, y, cv=5, scoring="f1_weighted")
print(f"{name}: F1 = {scores.mean():.3f} +/- {scores.std():.3f}")from sklearn.model_selection import GridSearchCV
from sklearn.ensemble import RandomForestClassifier
param_grid = {
"n_estimators": [100, 300],
"max_depth": [None, 8, 16],
"min_samples_leaf": [1, 4],
}
grid = GridSearchCV(RandomForestClassifier(random_state=42),
param_grid, cv=5, scoring="f1", n_jobs=-1)
grid.fit(X_train, y_train)
print("Best:", grid.best_params_, "score:", grid.best_score_)sklearn.metrics.classification_report(y_true, y_pred) in ra precision, recall, F1 cho từng lớp, macro-avg, weighted-avg. Luôn in báo cáo này song song với accuracy để phát hiện bất cân bằng sớm.
Sơ đồ quyết định: chọn metric theo bài toán
- Không có model 'tốt nhất' chung. Chỉ có model phù hợp nhất với bộ yêu cầu cụ thể của bài toán.
- Accuracy bị đánh lừa khi dữ liệu mất cân bằng. Luôn kèm precision, recall, F1 hoặc AP.
- ROC AUC đo khả năng xếp hạng, còn accuracy đo trên một threshold cụ thể. Hai câu chuyện khác nhau.
- Cross-validation 5-fold rồi báo cáo cả mean và std, không chỉ một con số.
- Latency, thời gian huấn luyện, khả năng giải thích luôn nằm cùng bàn cân với F1. Đừng chỉ nhìn một trục.
Kiểm tra hiểu biết
Bạn có 4 model dự đoán gian lận. Tất cả đều đạt độ chính xác 98%. Nên nhìn vào đâu tiếp theo?