API phân loại ticket thường trả cả nhãn và xác suất. Nếu chỉ lưu nhãn sau ngưỡng, bạn khó phân biệt một dự đoán sai với độ tự tin 0,51 và một dự đoán sai với độ tự tin 0,99. Bài này dùng dữ liệu tự tạo để kiểm tra phép tính Brier score nhị phân, trước khi đưa metric vào báo cáo đánh giá.
Nội dung đối chiếu tài liệu scikit-learn 1.9.1 ngày 02/11/2026. Ví dụ chạy bằng Python 3.9.6 và thư viện chuẩn, không cài hay chạy scikit-learn, không huấn luyện model. Các con số bên dưới chỉ thuộc fixture, không đại diện chất lượng sản phẩm AI nào.
Chốt nhãn dương trước khi tính
Giả sử 1 nghĩa là ticket cần chuyển cho người xử lý, 0 nghĩa là không. Mỗi p phải là xác suất của đúng nhãn 1, không phải xác suất của nhãn mà model vừa chọn. Nếu API trả hai cột, hãy ghi lại thứ tự nhãn và lấy đúng cột.
Trong bài, Brier là trung bình của (p - y) ** 2, nằm trong khoảng 0 đến 1; thấp hơn là tốt hơn theo metric này. Đây là quy ước nhị phân đã chia đôi so với công thức cộng lỗi trên cả hai lớp. Tài liệu API có tham số scale_by_half từ phiên bản 1.7; khi đối chiếu báo cáo từ thư viện khác, cần kiểm tra quy ước thay vì so trực tiếp hai số khác thang.
Một ví dụ có cùng nhãn nhưng khác mức tự tin
Lưu đoạn sau thành demo_brier.py, rồi chạy python3 demo_brier.py:
from math import isfinite, isclose
def brier_binary(labels, probabilities):
if not labels or len(labels) != len(probabilities):
raise ValueError("Can hai day cung do dai va khong rong")
if any(y not in (0, 1) for y in labels):
raise ValueError("Nhan phai la 0 hoac 1")
if any(not isfinite(p) or not 0 <= p <= 1 for p in probabilities):
raise ValueError("Xac suat phai huu han trong [0, 1]")
return sum((p - y) ** 2 for y, p in zip(labels, probabilities)) / len(labels)
labels = [1, 0, 1, 0]
model_a = [0.6, 0.4, 0.6, 0.6]
model_b = [0.9, 0.1, 0.9, 0.9]
def decisions(probabilities):
return [int(p >= 0.5) for p in probabilities]
assert decisions(model_a) == decisions(model_b) == [1, 0, 1, 1]
assert isclose(brier_binary(labels, model_a), 0.21)
assert isclose(brier_binary(labels, model_b), 0.21)
model_c = [0.99, 0.01, 0.99, 0.99]
assert decisions(model_c) == decisions(model_a)
assert isclose(brier_binary(labels, model_c), 0.2451)
print([round(brier_binary(labels, p), 4) for p in (model_a, model_b, model_c)])
Kết quả đã kiểm tra là [0.21, 0.21, 0.2451]. Cả ba đều đúng 3 trong 4 nhãn ở ngưỡng 0,5. A và B thậm chí có Brier bằng nhau: cải thiện ở ba mẫu đúng bù đúng phần tăng lỗi ở mẫu cuối. C tự tin hơn nữa nhưng có Brier cao hơn trên fixture này.
Điểm đáng chú ý là phải tính toàn bộ tập, không suy từ một mẫu sai rằng model nào chắc chắn có tổng điểm tệ hơn. Bạn có thể đổi riêng xác suất cuối của A từ 0,6 xuống 0,4, tính lại và giải thích vì sao cả quyết định lẫn lỗi bình phương thay đổi.
Thêm vào báo cáo đánh giá thế nào?
Lưu ID mẫu, nhãn thật, xác suất nhãn dương và phiên bản model trước khi tính. Giữ cùng tập kiểm tra và cùng quy ước trọng số khi so hai phiên bản. Đừng làm tròn xác suất thành 0 hoặc 1 trước phép tính: khi đó bạn đã bỏ mất thông tin cần đánh giá.
Trong báo cáo, đặt Brier cạnh metric quyết định ở ngưỡng nghiệp vụ. Một model có điểm xác suất tốt vẫn có thể bỏ sót ticket quan trọng tại ngưỡng đang dùng. Với tập nhỏ, thêm việc xem từng mẫu và phân bố nhãn; vài quan sát không đủ để kết luận triển khai.
Điểm thấp chưa chứng minh calibration tốt
Tài liệu calibration của scikit-learn giải thích Brier phản ánh nhiều thành phần, gồm khả năng phân biệt và độ tin cậy xác suất. Vì vậy, chỉ nhìn tổng điểm thấp hơn không đủ kết luận model được calibration tốt hơn. Có thể xem thêm reliability diagram và số mẫu trong mỗi nhóm xác suất, với tập đánh giá phù hợp.
Không đưa trực tiếp một câu tự nhận “tôi chắc 90%” của chatbot vào công thức rồi coi đó là xác suất đã được kiểm chứng. Trước hết cần định nghĩa sự kiện nhị phân, cách thu xác suất và nhãn thật nhất quán. Hàm minh họa cũng chỉ nhận dãy số trong bộ nhớ; xử lý dữ liệu thiếu, ID trùng và định dạng API thuộc bước chuẩn hóa riêng.


