
Một mô hình học máy dự đoán gian lận thẻ tín dụng báo cáo độ chính xác 99.9%. Đội ngũ điều hành rất vui mừng - cho đến khi họ phát hiện ra rằng 0.1% giao dịch là gian lận, và mô hình chỉ đơn giản dự đoán is_fraud = False cho mọi yêu cầu. Nó không phát hiện được 0% gian lận trong khi tự hào về độ chính xác gần như hoàn hảo.
Đây chính là Nghịch lý Độ chính xác. Trong học máy thực tế - nơi các tập dữ liệu không cân bằng và chi phí của sai sót dương tính khác biệt rất lớn so với sai sót âm tính - độ chính xác thô là vô nghĩa.
Hướng dẫn này cung cấp một khung làm việc cấp độ sản xuất để đánh giá các mô hình phân loại, chọn số liệu phù hợp cho vấn đề kinh doanh của bạn và điều chỉnh ngưỡng quyết định trong Python.
┌─────────────────────────────────────────┐
│ Actual Reality │
│ Positive (1) │ Negative (0) │
┌─────────┬──────────┼───────────────────┼─────────────────────┤
│ Model │ Pos (1) │ True Pos (TP) │ False Pos (FP) │
│ Predict ├──────────┼───────────────────┼─────────────────────┤
│ │ Neg (0) │ False Neg (FN) │ True Neg (TN) │
└─────────┴──────────┴───────────────────┴─────────────────────┘
Từ bốn giá trị này, tất cả các chỉ số đánh giá chính đều được suy ra:
\text{Precision} = \frac{\text{TP}}{\text{TP} + \text{FP}} \quad \text{(Khi mô hình dự đoán dương tính, nó đúng bao nhiêu lần?)}
\text{Recall (Sensitivity)} = \frac{\text{TP}}{\text{TP} + \text{FN}} \quad \text{(Trong số tất cả các trường hợp dương tính thực sự, chúng ta đã phát hiện được bao nhiêu phần trăm?)}
\text{Specificity} = \frac{\text{TN}}{\text{TN} + \text{FP}} \quad \text{(Trong số tất cả các trường hợp âm tính thực sự, chúng ta đã loại bỏ được bao nhiêu phần trăm?)}
Mỗi mô hình phân loại đều xuất ra một xác suất liên tục p \in [0, 1]. Việc dịch chuyển ngưỡng quyết định (ví dụ từ 0.5 xuống 0.2) sẽ tăng Recall nhưng phải đánh đổi bằng Precision.
Low Threshold (e.g. 0.1) ───────────► High Recall, Low Precision (Catches everything, high noise)
High Threshold (e.g. 0.8) ──────────► High Precision, Low Recall (Only fires on sure things)
F_1 so với F_\betaĐiểm F_1 tiêu chuẩn là trung bình điều hòa của Precision và Recall, cân bằng cả hai một cách đồng đều:
F_1 = 2 \cdot \frac{\text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}}
Khi doanh nghiệp của bạn ưu tiên một yếu tố hơn yếu tố kia, hãy sử dụng Điểm F_\beta:
F_\beta = (1 + \beta^2) \cdot \frac{\text{Precision} \cdot \text{Recall}}{(\beta^2 \cdot \text{Precision}) + \text{Recall}}
\beta = 2.0 (Điểm F_2): Trọng số Recall cao gấp 2 lần Precision (lý tưởng cho phát hiện gian lận / chẩn đoán y tế).\beta = 0.5 (Điểm F_{0.5}): Trọng số Precision cao gấp 2 lần Recall (lý tưởng cho tìm kiếm & lọc thư rác).Cả hai chỉ số đều đánh giá mô hình trên tất cả các ngưỡng quyết định có thể (từ 0.0 đến 1.0), nhưng chúng hoạt động rất khác nhau trên dữ liệu không cân bằng:
ROC Curve: Plot of True Positive Rate (Recall) vs False Positive Rate (FPR)
PR Curve: Plot of Precision vs Recall
from sklearn.metrics import roc_auc_score, average_precision_score
# ROC-AUC is misleadingly high on imbalanced datasets!
roc = roc_auc_score(y_true, y_pred_prob) # e.g., 0.985 (looks amazing)
# PR-AUC (Average Precision) reflects real-world rare class performance
pr_auc = average_precision_score(y_true, y_pred_prob) # e.g., 0.620 (reveals true difficulty)
Quy tắc chung:
Nhiều bộ phân loại hiện đại (đặc biệt là XGBoost, LightGBM và Mạng nơ-ron sâu) xuất ra các xác suất không được hiệu chuẩn. Nếu một mô hình gán xác suất 0.80 cho 100 người dùng, chính xác 80 trong số họ phải là dương tính. Nếu chỉ có 40 người là dương tính, mô hình đang quá tự tin.
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.metrics import brier_score_loss
import lightgbm as lgb
# Train raw classifier
base_model = lgb.LGBMClassifier()
base_model.fit(X_train, y_train)
# Calculate Brier Score (lower is better; 0 = perfect calibration)
raw_brier = brier_score_loss(y_test, base_model.predict_proba(X_test)[:, 1])
# Calibrate using Isotonic Regression or Platt Scaling (Sigmoid)
calibrated_model = CalibratedClassifierCV(
estimator=base_model,
method='isotonic', # or 'sigmoid' for smaller datasets (< 1000 samples)
cv='prefit'
)
calibrated_model.fit(X_val, y_val)
calibrated_brier = brier_score_loss(y_test, calibrated_model.predict_proba(X_test)[:, 1])
print(f"Brier score improved from {raw_brier:.4f} to {calibrated_brier:.4f}")
Đây là cách huấn luyện một bộ phân loại trên dữ liệu không cân bằng và tìm ngưỡng quyết định tối ưu dựa trên chi phí kinh doanh (Cost(FN) = $100, Cost(FP) = $5):
import numpy as np
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.metrics import precision_recall_curve
# Generate synthetic imbalanced dataset (1% positive class)
X, y = make_classification(
n_samples=50_000, n_features=20, weights=[0.99, 0.01], random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y)
# Fit model
clf = HistGradientBoostingClassifier(class_weight='balanced', random_state=42)
clf.fit(X_train, y_train)
# Predict continuous probabilities
y_probs = clf.predict_proba(X_test)[:, 1]
# Calculate Precision-Recall curve
precisions, recalls, thresholds = precision_recall_curve(y_test, y_probs)
# Define Business Cost Function
COST_FALSE_NEGATIVE = 100.0 # Missed fraud cost
COST_FALSE_POSITIVE = 5.0 # User friction cost
total_costs = []
for t in thresholds:
y_pred = (y_probs >= t).astype(int)
fn = np.sum((y_test == 1) & (y_pred == 0))
fp = np.sum((y_test == 0) & (y_pred == 1))
cost = (fn * COST_FALSE_NEGATIVE) + (fp * COST_FALSE_POSITIVE)
total_costs.append(cost)
# Find optimal threshold minimizing business loss
best_idx = np.argmin(total_costs)
optimal_threshold = thresholds[best_idx]
print(f"Default 0.5 Threshold Cost: ${total_costs[np.abs(thresholds - 0.5).argmin()]:,.2f}")
print(f"Optimized Threshold ({optimal_threshold:.3f}) Cost: ${total_costs[best_idx]:,.2f}")
| Kịch bản | Chỉ số chính | Chỉ số phụ |
|---|---|---|
| Phân loại nhị phân cân bằng | ROC-AUC | Độ chính xác / F_1 |
| Phát hiện gian lận / bất thường (< 2% dương tính) | PR-AUC (Độ chính xác trung bình) | Điểm F_2 & Đường cong chi phí |
| Tìm kiếm & Truy xuất nội dung | Precision@K / Độ chính xác trung bình (MAP) | NDCG@K |
| Hệ thống nhạy cảm với xác suất (Đấu thầu / Rủi ro) | Điểm Brier & Lỗi hiệu chuẩn dự kiến (ECE) | Log-Loss |
Một mô hình machine learning đang được phát triển để xác định các lỗ hổng bảo mật nghiêm trọng trong một codebase lớn. Một false negative (bỏ sót một lỗ hổng nghiêm trọng) có thể dẫn đến vi phạm dữ liệu lớn, trong khi một false positive (đánh dấu một lỗ hổng không tồn tại) sẽ yêu cầu nhà phát triển dành thời gian điều tra một vấn đề không có thật. Với những rủi ro này, chỉ số đánh giá nào nên được ưu tiên trong quá trình phát triển mô hình và điều chỉnh ngưỡng?
Làm sạch log AI CLI, tạo biểu thức cron, giải mã JWT và tính quyền chmod offline.

So sánh toàn diện Polars và Pandas về mức sử dụng bộ nhớ, tích hợp Apache Arrow, tối ưu hóa truy vấn lazy và khả năng mở rộng CPU đa nhân.
Đọc tiếp
Tự động hoá không phải để xây hệ thống hoành tráng, mà để bỏ phần việc nhàm chán và quay lại làm việc thật - bằng các bước nhỏ, đúng công cụ và có kiểm soát.
Đọc tiếp
Tài liệu tham khảo tiêu chuẩn cho môi trường production về lập trình bất đồng bộ trong Python: cơ chế nội bộ của event loop, structured concurrency với TaskGroup, free-threaded CPython 3.13, connection pooling, và profiling event loop starvation.
Đọc tiếp