Mô hình Classifier Chain cho dự báo rủi ro tín dụng với các mức DPD
Bối cảnh:
- Dữ liệu đặc trưng:
- Nhân khẩu học: Tuổi, thu nhập, tình trạng việc làm
- Lịch sử tín dụng: Dư nợ hiện tại, số lần trễ hạn trước đây, tỷ lệ sử dụng tín dụng
- Đặc trưng khoản vay: Số tiền vay, lãi suất, kỳ hạn, tỷ lệ nợ trên giá trị tài sản
Nhãn (Labels) đa nhãn:
DPD30+: Trễ ≥30 ngày
DPD60+: Trễ ≥60 ngày
DPD90+: Trễ ≥90 ngày
Các nhãn này không loại trừ lẫn nhau. Ví dụ, nếu khách hàng trễ 90 ngày, họ chắc chắn đã trễ 30 và 60 ngày trước đó. Điều này tạo ra mối liên hệ chặt chẽ giữa các nhãn.
Ý tưởng chính của Classifier Chain:
Thay vì dự đoán từng nhãn một cách độc lập, mô hình sẽ dự đoán tuần tự và sử dụng kết quả dự đoán trước đó như một phần đầu vào cho bước tiếp theo. Điều này giúp mô hình tận dụng quan hệ giữa các nhãn.
┌────────────────┐
│ Đặc trưng │
│ (Features) │
└───────┬────────┘
│
v
┌────────────────┐
│ Classifier A │
│ Dự đoán DPD30+ │
└───────┬────────┘
│
(Xác suất DPD30+)
│
v
┌────────────────┐
│ Classifier B │
│ Dự đoán DPD60+ │
│ (dựa trên │
│ đặc trưng + │
│ kết quả A) │
└───────┬────────┘
│
(Xác suất DPD60+)
│
v
┌────────────────┐
│ Classifier C │
│ Dự đoán DPD90+ │
│ (dựa trên │
│ đặc trưng + │
│ kết quả A, B) │
└───────┬────────┘
│
(Xác suất DPD90+)
│
v
(Kết quả)
Classifier A: Dự đoán DPD30+ dựa trên đặc trưng ban đầu.
Classifier B: Dự đoán DPD60+, nhưng đầu vào gồm cả đặc trưng ban đầu và dự đoán từ A (DPD30+).
Classifier C: Dự đoán DPD90+, đầu vào gồm đặc trưng ban đầu và dự đoán từ A, B.
Trong sơ đồ trên, mỗi mũi tên thể hiện việc truyền thông tin: Dự đoán ở bước trước hỗ trợ bước sau.
Quy trình dự đoán:
1. Bước 1:
- Đầu vào: Đặc trưng khách hàng (nhân khẩu học, lịch sử tín dụng, khoản vay)
- Đầu ra A: Xác suất khách trễ ≥30 ngày (ví dụ: 0.7)
Bước 2:
Đầu vào: Đặc trưng ban đầu + kết quả dự đoán DPD30+ (0.7)
Đầu ra B: Xác suất trễ ≥60 ngày (ví dụ: 0.4)
Bước 3:
Đầu vào: Đặc trưng ban đầu + kết quả DPD30+ (0.7) + kết quả DPD60+ (0.4)
Đầu ra C: Xác suất trễ ≥90 ngày (ví dụ: 0.1)
Điểm nổi bật:
- Khai thác quan hệ giữa các nhãn:
Các mức trễ hạn cao (DPD90+) phụ thuộc logic vào khả năng trễ hạn ở mức thấp hơn (DPD30+, DPD60+).
Dự đoán thực tế hơn:
Nếu khả năng trễ 30 ngày và 60 ngày thấp, thì khả năng trễ 90 ngày cũng sẽ thấp. Ngược lại, nếu hệ thống dự đoán 30 và 60 ngày trễ hạn cao, mô hình sẽ phản ánh điều đó vào dự đoán 90 ngày.
Dễ mở rộng:
Có thể thử nhiều thứ tự nhãn khác nhau hoặc sử dụng các mô hình mạnh mẽ (như XGBoost, Deep Learning) bên trong mỗi bước phân loại.
import numpy as npfrom sklearn.linear_model import LogisticRegressionfrom sklearn.multioutput import ClassifierChainfrom sklearn.model_selection import train_test_split# Giả lập dữ liệu:# - X: ma trận đặc trưng, giả sử có 1000 khách hàng, mỗi khách có 10 đặc trưng.# - Y: ma trận nhãn, giả sử có 3 nhãn: DPD30+, DPD60+, DPD90+.# Dữ liệu giả lập mang tính minh họa, trong thực tế bạn dùng dữ liệu thật.np.random.seed(42)X = np.random.rand(1000, 10) # 1000 khách, 10 đặc trưngY = np.zeros((1000, 3)) # 3 nhãn: DPD30+, DPD60+, DPD90+# Tạo nhãn giả lập dựa trên X. Ví dụ:# - Nếu tổng một số đặc trưng > 5 thì khách có khả năng DPD30+,# - DPD60+ và DPD90+ sẽ phụ thuộc vào DPD30+ (giả lập quan hệ nhãn).threshold_30 =5.0threshold_60 =5.5threshold_90 =6.0sum_feats = X.sum(axis=1)Y[:, 0] = (sum_feats > threshold_30).astype(int) # DPD30+Y[:, 1] = ((sum_feats > threshold_60) & (Y[:,0] ==1)).astype(int) # DPD60+ (phụ thuộc vào DPD30+)Y[:, 2] = ((sum_feats > threshold_90) & (Y[:,1] ==1)).astype(int) # DPD90+ (phụ thuộc vào DPD60+)# Chia tập dữ liệuX_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=42)# Khởi tạo mô hình LogisticRegressionbase_lr = LogisticRegression()# Tạo Classifier Chain# Thứ tự nhãn: [DPD30+, DPD60+, DPD90+] tương ứng các cột Y[:,0], Y[:,1], Y[:,2]chain = ClassifierChain(base_lr, order=[0, 1, 2], cv=None)# Huấn luyện mô hìnhchain.fit(X_train, Y_train)# Dự đoán trên dữ liệu testY_pred = chain.predict(X_test)# Đánh giáfrom sklearn.metrics import accuracy_score, hamming_loss# accuracy_score với multi-label sẽ tính số mẫu mà tất cả các nhãn dự đoán đúngacc = accuracy_score(Y_test, Y_pred)h_loss = hamming_loss(Y_test, Y_pred) # Tỷ lệ nhãn sai trên tổng số nhãnprint("Accuracy (multi-label exact match):", acc)print("Hamming Loss:", h_loss)# In ra vài kết quả dự đoánprint("Dự đoán một vài khách hàng (DPD30+, DPD60+, DPD90+):")for i inrange(5):print("Thực tế:", Y_test[i], "Dự đoán:", Y_pred[i])
Accuracy (multi-label exact match): 0.925
Hamming Loss: 0.025
Dự đoán một vài khách hàng (DPD30+, DPD60+, DPD90+):
Thực tế: [0. 0. 0.] Dự đoán: [0. 0. 0.]
Thực tế: [0. 0. 0.] Dự đoán: [0. 0. 0.]
Thực tế: [0. 0. 0.] Dự đoán: [0. 0. 0.]
Thực tế: [0. 0. 0.] Dự đoán: [0. 0. 0.]
Thực tế: [0. 0. 0.] Dự đoán: [0. 0. 0.]