XGBoost để phân loại nhị phân: chọn đúng ngưỡng


8

Tôi đang làm việc trên một bộ dữ liệu nhị phân có nhãn rất mất cân bằng, trong đó số lượng nhãn thực sự chỉ là 7% từ toàn bộ dữ liệu. Nhưng một số kết hợp các tính năng có thể mang lại số lượng cao hơn số lượng trung bình trong một tập hợp con.

Ví dụ: chúng tôi có bộ dữ liệu sau với một tính năng (màu):

180 mẫu đỏ - 0

20 mẫu đỏ - 1

300 mẫu xanh - 0

100 mẫu xanh - 1

Chúng ta có thể xây dựng một cây quyết định đơn giản:

                      (color)

                red /       \ green

 P(1 | red) = 0.1              P(1 | green) = 0.25

P (1) = 0,2 cho tổng số liệu

Nếu tôi chạy XGBoost trên tập dữ liệu này, nó có thể dự đoán xác suất không lớn hơn 0,25. Điều đó có nghĩa là, nếu tôi đưa ra quyết định ở ngưỡng 0,5:

  • 0 - P <0,5
  • 1 - P> = 0,5

Sau đó, tôi sẽ luôn nhận được tất cả các mẫu được dán nhãn là số không . Hy vọng rằng tôi mô tả rõ ràng vấn đề.

Bây giờ, trên tập dữ liệu ban đầu tôi đang nhận được biểu đồ sau (ngưỡng tại trục x):

nhập mô tả hình ảnh ở đây

Có tối đa F1_score ở ngưỡng = 0,1. Bây giờ tôi có hai câu hỏi:

  • Tôi thậm chí có nên sử dụng F1_score cho một tập dữ liệu có cấu trúc như vậy không?
  • Có hợp lý không khi sử dụng ngưỡng 0,5 để ánh xạ xác suất thành nhãn khi sử dụng XGBoost để phân loại nhị phân?

Cập nhật. Tôi thấy chủ đề đó thu hút một số quan tâm. Dưới đây là mã Python để tái tạo thử nghiệm đỏ / xanh bằng XGBoost. Nó thực sự đưa ra các xác suất dự kiến:

from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split
import numpy as np

X0_0 = np.zeros(180) # red - 0
Y0_0 = np.zeros(180)

X0_1 = np.zeros(20) # red - 1
Y0_1 = np.ones(20)

X1_0 = np.ones(300) # green - 0
Y1_0 = np.zeros(300)

X1_1 = np.ones(100) # green  - 1
Y1_1 = np.ones(100)

X = np.concatenate((X0_0, X0_1, X1_0, Y1_1))
Y = np.concatenate((Y0_0, Y0_1, Y1_0, Y1_1))

# reshaping into 2-dim array
X = X.reshape(-1, 1)

import xgboost as xgb

xgb_dmat = xgb.DMatrix(X_train, label=y_train)

param = {'max_depth': 1,
         'eta': 0.01,
         'objective': 'binary:logistic',
         'eval_metric': 'error',
         'nthread': 4}

model = xgb.train(param, xg_mat, 400)

X0_sample = np.array([[0]])
X1_sample = np.array([[1]])

print('P(1 | red), predicted: ' + str(model.predict(xgb.DMatrix(X0_sample))))
print('P(1 | green), predicted: ' + str(model.predict(xgb.DMatrix(X1_sample))))

Đầu ra:

P(1 | red), predicted: [ 0.1073855]
P(1 | green), predicted: [ 0.24398108]

Câu trả lời:


5

Bạn phải quyết định những gì bạn muốn tối đa hóa.

Phân loại bằng cách so sánh xác suất với 0,5 là phù hợp nếu bạn muốn tối đa hóa độ chính xác. Không phù hợp nếu bạn muốn tối đa hóa số liệu F1.

Nếu bạn muốn tối đa hóa độ chính xác, luôn dự đoán số 0 phân loại tối ưu.

pp

Nếu bạn muốn tối đa hóa số liệu F1, một cách tiếp cận là huấn luyện bộ phân loại của bạn để dự đoán xác suất, sau đó chọn ngưỡng tối đa hóa điểm số F1. Ngưỡng có thể sẽ không là 0,5.

Một lựa chọn khác là hiểu chi phí của lỗi loại I so với lỗi loại II và sau đó gán trọng số cho phù hợp.


1
Tôi chỉ muốn đề cập đến hai điều nữa: (a) thay vì điểm F1, OP cũng có thể sử dụng độ chính xác có trọng số hoặc thậm chí tối đa hóa một số liệu xếp hạng như AUC ROC (b) xgboosthỗ trợ trọng số lớp, OP nên chơi với những người đó nếu anh ta không hài lòng với bất kỳ số liệu nào anh ta muốn tối đa hóa.
Ricardo Cruz

@RicardoCruz, cảm ơn - đề xuất tốt! (Tôi đã đề cập ngắn gọn về trọng lượng của lớp - đoạn cuối của câu trả lời - nhưng tôi rất vui vì bạn đã nhấn mạnh nó.)
DW

Btw, một class_weights phổ biến được sử dụng là tần số nghịch đảo : n_samples / (n_classes * np.bincount(y)). Điều này tránh việc phân loại tạo thêm trọng lượng cho các lớp đông dân hơn.
Ricardo Cruz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.