[ad_1]
Các trường hợp sử dụng và mã để khám phá lớp mới giúp điều chỉnh ngưỡng quyết định trong scikit-learn
Bản phát hành 1.5 của scikit-learn bao gồm một lớp mới, TunedThresholdClassifierCV, giúp việc tối ưu hóa ngưỡng quyết định từ bộ phân loại scikit-learn trở nên dễ dàng hơn. Ngưỡng quyết định là điểm giới hạn chuyển đổi đầu ra xác suất dự đoán bằng mô hình học máy thành các lớp riêng biệt. Ngưỡng quyết định mặc định của .predict()
phương pháp từ bộ phân loại scikit-learn trong cài đặt phân loại nhị phân là 0,5. Mặc dù đây là một mặc định hợp lý nhưng hiếm khi nó là lựa chọn tốt nhất cho các nhiệm vụ phân loại.
Bài đăng này giới thiệu lớp TunedThresholdClassifierCV và trình bày cách nó có thể tối ưu hóa các ngưỡng quyết định cho các tác vụ phân loại nhị phân khác nhau. Lớp mới này sẽ giúp thu hẹp khoảng cách giữa các nhà khoa học dữ liệu xây dựng mô hình và các bên liên quan trong kinh doanh, những người đưa ra quyết định dựa trên đầu ra của mô hình. Bằng cách tinh chỉnh các ngưỡng quyết định, các nhà khoa học dữ liệu có thể nâng cao hiệu suất của mô hình và phù hợp hơn với các mục tiêu kinh doanh.
Bài đăng này sẽ đề cập đến các tình huống sau trong đó việc điều chỉnh ngưỡng quyết định có lợi:
- Tối đa hóa số liệu: Sử dụng tùy chọn này khi chọn ngưỡng tối đa hóa chỉ số ghi điểm, chẳng hạn như điểm F1.
- Học tập nhạy cảm với chi phí: Điều chỉnh ngưỡng khi chi phí của việc phân loại sai một kết quả dương tính giả không bằng chi phí của việc phân loại sai một kết quả âm tính giả và bạn có ước tính chi phí.
- Điều chỉnh dưới những ràng buộc: Tối ưu hóa điểm vận hành trên ROC hoặc đường cong thu hồi chính xác để đáp ứng các hạn chế về hiệu suất cụ thể.
Mã được sử dụng trong bài đăng này và các liên kết đến bộ dữ liệu có sẵn trên GitHub.
Bắt đầu nào! Đầu tiên, nhập các thư viện cần thiết, đọc dữ liệu và phân chia dữ liệu huấn luyện và kiểm tra.
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.compose import make_column_selector as selector
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import (
RocCurveDisplay,
f1_score,
make_scorer,
recall_score,
roc_curve,
confusion_matrix,
)
from sklearn.model_selection import TunedThresholdClassifierCV, train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScalerRANDOM_STATE = 26120
Tối đa hóa số liệu
Trước khi bắt đầu quá trình xây dựng mô hình trong bất kỳ dự án học máy nào, điều quan trọng là phải làm việc với các bên liên quan để xác định (các) số liệu nào cần tối ưu hóa. Việc đưa ra quyết định này sớm đảm bảo rằng dự án phù hợp với các mục tiêu đã định.
Việc sử dụng thước đo độ chính xác trong các trường hợp sử dụng phát hiện gian lận để đánh giá hiệu suất của mô hình là không lý tưởng vì dữ liệu thường mất cân bằng và hầu hết các giao dịch đều không có tính gian lận. Điểm F1 là giá trị trung bình hài hòa của độ chính xác và khả năng thu hồi, đồng thời là thước đo tốt hơn cho các tập dữ liệu mất cân bằng như phát hiện gian lận. Hãy sử dụng TunedThresholdClassifierCV
lớp để tối ưu hóa ngưỡng quyết định của mô hình hồi quy logistic nhằm tối đa hóa điểm F1.
Chúng tôi sẽ sử dụng Bộ dữ liệu phát hiện gian lận thẻ tín dụng Kaggle để giới thiệu tình huống đầu tiên mà chúng ta cần điều chỉnh ngưỡng quyết định. Đầu tiên, chia dữ liệu thành các tập huấn luyện và tập kiểm tra, sau đó tạo quy trình scikit-learn để chia tỷ lệ dữ liệu và huấn luyện mô hình hồi quy logistic. Điều chỉnh đường dẫn trên dữ liệu huấn luyện để chúng tôi có thể so sánh hiệu suất của mô hình ban đầu với hiệu suất của mô hình đã điều chỉnh.
creditcard = pd.read_csv("information/creditcard.csv")
y = creditcard("Class")
X = creditcard.drop(columns=("Class"))X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=RANDOM_STATE, stratify=y
)
# Solely Time and Quantity should be scaled
original_fraud_model = make_pipeline(
ColumnTransformer(
(("scaler", StandardScaler(), ("Time", "Quantity"))),
the rest="passthrough",
force_int_remainder_cols=False,
),
LogisticRegression(),
)
original_fraud_model.match(X_train, y_train)
Chưa có sự điều chỉnh nào xảy ra nhưng nó sẽ xuất hiện trong khối mã tiếp theo. Những lý lẽ cho TunedThresholdClassifierCV
tương tự như khác CV
các lớp học trong scikit-learn, chẳng hạn như LướiTìm kiếmCV. Ở mức tối thiểu, người dùng chỉ cần chuyển công cụ ước tính ban đầu và TunedThresholdClassifierCV
sẽ lưu trữ ngưỡng quyết định giúp tối đa hóa độ chính xác cân bằng (mặc định) bằng cách sử dụng xác thực chéo Ok-fold phân tầng 5 lần (mặc định). Nó cũng sử dụng ngưỡng này khi gọi .predict()
. Tuy nhiên, mọi số liệu scikit-learn (hoặc có thể gọi được) đều có thể được sử dụng làm scoring
Hệ mét. Ngoài ra, người dùng có thể vượt qua quen thuộc cv
đối số để tùy chỉnh chiến lược xác thực chéo.
Tạo TunedThresholdClassifierCV
occasion và phù hợp với mô hình trên dữ liệu huấn luyện. Vượt qua mô hình ban đầu và đặt điểm là “f1”. Chúng tôi cũng sẽ muốn thiết lập store_cv_results=True
để truy cập các ngưỡng được đánh giá trong quá trình xác thực chéo để trực quan hóa.
tuned_fraud_model = TunedThresholdClassifierCV(
original_fraud_model,
scoring="f1",
store_cv_results=True,
)tuned_fraud_model.match(X_train, y_train)
# common F1 throughout folds
avg_f1_train = tuned_fraud_model.best_score_
# Examine F1 within the take a look at set for the tuned mannequin and the unique mannequin
f1_test = f1_score(y_test, tuned_fraud_model.predict(X_test))
f1_test_original = f1_score(y_test, original_fraud_model.predict(X_test))
print(f"Common F1 on the coaching set: {avg_f1_train:.3f}")
print(f"F1 on the take a look at set: {f1_test:.3f}")
print(f"F1 on the take a look at set (unique mannequin): {f1_test_original:.3f}")
print(f"Threshold: {tuned_fraud_model.best_threshold_: .3f}")
Common F1 on the coaching set: 0.784
F1 on the take a look at set: 0.796
F1 on the take a look at set (unique mannequin): 0.733
Threshold: 0.071
Bây giờ chúng tôi đã tìm thấy ngưỡng tối đa hóa việc kiểm tra điểm F1 tuned_fraud_model.best_score_
để tìm hiểu xem điểm F1 trung bình tốt nhất là bao nhiêu trong quá trình xác thực chéo. Chúng tôi cũng có thể xem ngưỡng nào tạo ra những kết quả đó bằng cách sử dụng tuned_fraud_model.best_threshold_
. Bạn có thể hình dung điểm số của các ngưỡng quyết định trong quá trình xác thực chéo bằng cách sử dụng objective_scores_
Và decision_thresholds_
thuộc tính:
fig, ax = plt.subplots(figsize=(5, 5))
ax.plot(
tuned_fraud_model.cv_results_("thresholds"),
tuned_fraud_model.cv_results_("scores"),
marker="o",
linewidth=1e-3,
markersize=4,
coloration="#c0c0c0",
)
ax.plot(
tuned_fraud_model.best_threshold_,
tuned_fraud_model.best_score_,
"^",
markersize=10,
coloration="#ff6700",
label=f"Optimum cut-off level = {tuned_fraud_model.best_threshold_:.2f}",
)
ax.plot(
0.5,
f1_test_original,
label="Default threshold: 0.5",
coloration="#004e98",
linestyle="--",
marker="X",
markersize=10,
)
ax.legend(fontsize=8, loc="decrease middle")
ax.set_xlabel("Determination threshold", fontsize=10)
ax.set_ylabel("F1 rating", fontsize=10)
ax.set_title("F1 rating vs. Determination threshold -- Cross-validation", fontsize=12)
# Test that the coefficients from the unique mannequin and the tuned mannequin are the identical
assert (tuned_fraud_model.estimator_(-1).coef_ ==
original_fraud_model(-1).coef_).all()
Chúng tôi đã sử dụng cùng một mô hình hồi quy logistic cơ bản để đánh giá hai ngưỡng quyết định khác nhau. Các mô hình cơ bản đều giống nhau, được chứng minh bằng hệ số bằng nhau trong tuyên bố khẳng định ở trên. Tối ưu hóa trong TunedThresholdClassifierCV
đạt được bằng cách sử dụng các kỹ thuật xử lý hậu kỳ, được áp dụng trực tiếp vào đầu ra xác suất dự đoán của mô hình. Tuy nhiên, điều quan trọng cần lưu ý là TunedThresholdClassifierCV
theo mặc định sử dụng xác thực chéo để tìm ngưỡng quyết định nhằm tránh trang bị quá mức cho dữ liệu huấn luyện.
Học tập nhạy cảm với chi phí
Học tập nhạy cảm với chi phí là một loại học máy ấn định chi phí cho từng loại phân loại sai. Điều này chuyển hiệu suất của mô hình thành các đơn vị mà các bên liên quan hiểu được, chẳng hạn như số tiền tiết kiệm được.
Chúng tôi sẽ sử dụng Tập dữ liệu về khách hàng rời bỏ của TELCO, một tập dữ liệu phân loại nhị phân, để chứng minh giá trị của việc học tập nhạy cảm với chi phí. Mục tiêu là dự đoán liệu khách hàng có rời bỏ hay không, dựa trên các đặc điểm về nhân khẩu học, chi tiết hợp đồng và thông tin kỹ thuật khác về tài khoản của khách hàng. Động lực để sử dụng tập dữ liệu này (và một số mã) là từ Khóa học của Dan Becker về tối ưu hóa ngưỡng quyết định.
information = pd.read_excel("information/Telco_customer_churn.xlsx")
drop_cols = (
"Depend", "Nation", "State", "Lat Lengthy", "Latitude", "Longitude",
"Zip Code", "Churn Worth", "Churn Rating", "CLTV", "Churn Cause"
)
information.drop(columns=drop_cols, inplace=True)# Preprocess the information
information("Churn Label") = information("Churn Label").map({"Sure": 1, "No": 0})
information.drop(columns=("Whole Prices"), inplace=True)
X_train, X_test, y_train, y_test = train_test_split(
information.drop(columns=("Churn Label")),
information("Churn Label"),
test_size=0.2,
random_state=RANDOM_STATE,
stratify=information("Churn Label"),
)
Thiết lập quy trình cơ bản để xử lý dữ liệu và tạo ra các xác suất dự đoán bằng mô hình rừng ngẫu nhiên. Đây sẽ là cơ sở để so sánh với TunedThresholdClassifierCV
.
preprocessor = ColumnTransformer(
transformers=(("one_hot", OneHotEncoder(),
selector(dtype_include="object"))),
the rest="passthrough",
)original_churn_model = make_pipeline(
preprocessor, RandomForestClassifier(random_state=RANDOM_STATE)
)
original_churn_model.match(X_train.drop(columns=("customerID")), y_train);
Việc lựa chọn tiền xử lý và loại mô hình không quan trọng đối với hướng dẫn này. Công ty muốn giảm giá cho những khách hàng được dự đoán sẽ rời bỏ. Trong quá trình cộng tác với các bên liên quan, bạn biết rằng việc giảm giá cho những khách hàng không rời bỏ (dương tính giả) sẽ tốn 80 USD. Bạn cũng biết rằng việc giảm giá cho những khách hàng lẽ ra sẽ rời bỏ sẽ đáng giá 200 USD. Bạn có thể biểu diễn mối quan hệ này trong ma trận chi phí:
def cost_function(y, y_pred, neg_label, pos_label):
cm = confusion_matrix(y, y_pred, labels=(neg_label, pos_label))
cost_matrix = np.array(((0, -80), (0, 200)))
return np.sum(cm * cost_matrix)cost_scorer = make_scorer(cost_function, neg_label=0, pos_label=1)
Chúng tôi cũng bao gồm chức năng chi phí trong một công cụ ghi điểm tùy chỉnh scikit-learn. Cầu thủ ghi bàn này sẽ được sử dụng làm scoring
đối số trong TunedThresholdClassifierCV và để đánh giá lợi nhuận trên tập kiểm tra.
tuned_churn_model = TunedThresholdClassifierCV(
original_churn_model,
scoring=cost_scorer,
store_cv_results=True,
)tuned_churn_model.match(X_train.drop(columns=("CustomerID")), y_train)
# Calculate the revenue on the take a look at set
original_model_profit = cost_scorer(
original_churn_model, X_test.drop(columns=("CustomerID")), y_test
)
tuned_model_profit = cost_scorer(
tuned_churn_model, X_test.drop(columns=("CustomerID")), y_test
)
print(f"Unique mannequin revenue: {original_model_profit}")
print(f"Tuned mannequin revenue: {tuned_model_profit}")
Unique mannequin revenue: 29640
Tuned mannequin revenue: 35600
Lợi nhuận của mô hình điều chỉnh cao hơn so với mô hình ban đầu. Một lần nữa, chúng ta có thể vẽ biểu đồ số liệu khách quan theo các ngưỡng quyết định để trực quan hóa việc lựa chọn ngưỡng quyết định trên dữ liệu huấn luyện trong quá trình xác thực chéo:
fig, ax = plt.subplots(figsize=(5, 5))
ax.plot(
tuned_churn_model.cv_results_("thresholds"),
tuned_churn_model.cv_results_("scores"),
marker="o",
markersize=3,
linewidth=1e-3,
coloration="#c0c0c0",
label="Goal rating (utilizing cost-matrix)",
)
ax.plot(
tuned_churn_model.best_threshold_,
tuned_churn_model.best_score_,
"^",
markersize=10,
coloration="#ff6700",
label="Optimum cut-off level for the enterprise metric",
)
ax.legend()
ax.set_xlabel("Determination threshold (likelihood)")
ax.set_ylabel("Goal rating (utilizing cost-matrix)")
ax.set_title("Goal rating as a perform of the choice threshold")
Trên thực tế, việc ấn định chi phí tĩnh cho tất cả các trường hợp bị phân loại sai theo cùng một cách là không thực tế từ góc độ kinh doanh. Có nhiều phương pháp nâng cao hơn để điều chỉnh ngưỡng bằng cách gán trọng số cho từng phiên bản trong tập dữ liệu. Điều này được bao phủ trong ví dụ học tập nhạy cảm với chi phí của scikit-learn.
Điều chỉnh dưới những ràng buộc
Phương pháp này hiện không được đề cập trong tài liệu scikit-learn nhưng là trường hợp kinh doanh phổ biến cho các trường hợp sử dụng phân loại nhị phân. Phương pháp điều chỉnh theo ràng buộc tìm ra ngưỡng quyết định bằng cách xác định một điểm trên đường cong ROC hoặc đường cong thu hồi chính xác. Điểm trên đường cong là giá trị lớn nhất của một trục trong khi ràng buộc trục kia. Đối với hướng dẫn này, chúng tôi sẽ sử dụng bộ dữ liệu về bệnh tiểu đường của người da đỏ Pima. Đây là nhiệm vụ phân loại nhị phân để dự đoán xem một cá nhân có mắc bệnh tiểu đường hay không.
Hãy tưởng tượng rằng mô hình của bạn sẽ được sử dụng làm thử nghiệm sàng lọc cho nhóm dân số có nguy cơ trung bình áp dụng cho hàng triệu người. Ước tính có khoảng 38 triệu người mắc bệnh tiểu đường ở Mỹ. Đây là khoảng 11,6% dân số, do đó, độ đặc hiệu của mô hình phải cao để không chẩn đoán sai hàng triệu người mắc bệnh tiểu đường và chuyển họ đến các xét nghiệm xác nhận không cần thiết. Giả sử CEO tưởng tượng của bạn đã thông báo rằng họ sẽ không chấp nhận tỷ lệ dương tính giả cao hơn 2%. Hãy xây dựng một mô hình đạt được điều này bằng cách sử dụng TunedThresholdClassifierCV
.
Đối với phần hướng dẫn này, chúng ta sẽ xác định một hàm ràng buộc sẽ được sử dụng để tìm tỷ lệ dương tính thực sự tối đa ở tỷ lệ dương tính giả 2%.
def max_tpr_at_tnr_constraint_score(y_true, y_pred, max_tnr=0.5):
fpr, tpr, thresholds = roc_curve(y_true, y_pred, drop_intermediate=False)
tnr = 1 - fpr
tpr_at_tnr_constraint = tpr(tnr >= max_tnr).max()
return tpr_at_tnr_constraintmax_tpr_at_tnr_scorer = make_scorer(
max_tpr_at_tnr_constraint_score, max_tnr=0.98)
information = pd.read_csv("information/diabetes.csv")
X_train, X_test, y_train, y_test = train_test_split(
information.drop(columns=("Final result")),
information("Final result"),
stratify=information("Final result"),
test_size=0.2,
random_state=RANDOM_STATE,
)
Xây dựng hai mô hình, một mô hình hồi quy logistic để làm mô hình cơ sở và mô hình còn lại, TunedThresholdClassifierCV
sẽ bao bọc mô hình hồi quy logistic cơ bản để đạt được mục tiêu mà Giám đốc điều hành đã vạch ra. Trong mô hình đã điều chỉnh, đặt scoring=max_tpr_at_tnr_scorer
. Một lần nữa, việc lựa chọn mô hình và tiền xử lý không quan trọng đối với hướng dẫn này.
# A baseline mannequin
original_model = make_pipeline(
StandardScaler(), LogisticRegression(random_state=RANDOM_STATE)
)
original_model.match(X_train, y_train)# A tuned mannequin
tuned_model = TunedThresholdClassifierCV(
original_model,
thresholds=np.linspace(0, 1, 150),
scoring=max_tpr_at_tnr_scorer,
store_cv_results=True,
cv=8,
random_state=RANDOM_STATE,
)
tuned_model.match(X_train, y_train)
So sánh sự khác biệt giữa ngưỡng quyết định mặc định từ các công cụ ước tính scikit-learn, 0,5 và ngưỡng được tìm thấy bằng cách sử dụng phương pháp điều chỉnh theo ràng buộc trên đường cong ROC.
# Get the fpr and tpr of the unique mannequin
original_model_proba = original_model.predict_proba(X_test)(:, 1)
fpr, tpr, thresholds = roc_curve(y_test, original_model_proba)
closest_threshold_to_05 = (np.abs(thresholds - 0.5)).argmin()
fpr_orig = fpr(closest_threshold_to_05)
tpr_orig = tpr(closest_threshold_to_05)# Get the tnr and tpr of the tuned mannequin
max_tpr = tuned_model.best_score_
constrained_tnr = 0.98
# Plot the ROC curve and evaluate the default threshold to the tuned threshold
fig, ax = plt.subplots(figsize=(5, 5))
# Observe that this would be the identical for each fashions
disp = RocCurveDisplay.from_estimator(
original_model,
X_test,
y_test,
title="Logistic Regression",
coloration="#c0c0c0",
linewidth=2,
ax=ax,
)
disp.ax_.plot(
1 - constrained_tnr,
max_tpr,
label=f"Tuned threshold: {tuned_model.best_threshold_:.2f}",
coloration="#ff6700",
linestyle="--",
marker="o",
markersize=11,
)
disp.ax_.plot(
fpr_orig,
tpr_orig,
label="Default threshold: 0.5",
coloration="#004e98",
linestyle="--",
marker="X",
markersize=11,
)
disp.ax_.set_ylabel("True Optimistic Price", fontsize=8)
disp.ax_.set_xlabel("False Optimistic Price", fontsize=8)
disp.ax_.tick_params(labelsize=8)
disp.ax_.legend(fontsize=7)
Phương pháp điều chỉnh theo ràng buộc đã tìm thấy ngưỡng 0,80, dẫn đến độ nhạy trung bình là 19,2% trong quá trình xác thực chéo dữ liệu huấn luyện. So sánh độ nhạy và độ đặc hiệu để xem mức ngưỡng được giữ trong bộ kiểm tra như thế nào. Mô hình có đáp ứng yêu cầu cụ thể của CEO trong bộ thử nghiệm không?
# Common sensitivity and specificity on the coaching set
avg_sensitivity_train = tuned_model.best_score_# Name predict from tuned_model to calculate sensitivity and specificity on the take a look at set
specificity_test = recall_score(
y_test, tuned_model.predict(X_test), pos_label=0)
sensitivity_test = recall_score(y_test, tuned_model.predict(X_test))
print(f"Common sensitivity on the coaching set: {avg_sensitivity_train:.3f}")
print(f"Sensitivity on the take a look at set: {sensitivity_test:.3f}")
print(f"Specificity on the take a look at set: {specificity_test:.3f}")
Common sensitivity on the coaching set: 0.192
Sensitivity on the take a look at set: 0.148
Specificity on the take a look at set: 0.990
Phần kết luận
Cái mới TunedThresholdClassifierCV
class là một công cụ mạnh mẽ có thể giúp bạn trở thành nhà khoa học dữ liệu giỏi hơn bằng cách chia sẻ với các nhà lãnh đạo doanh nghiệp về cách bạn đạt đến ngưỡng quyết định. Bạn đã học cách sử dụng scikit-learn mới TunedThresholdClassifierCV
lớp để tối đa hóa số liệu, thực hiện việc học theo chi phí và điều chỉnh số liệu theo ràng buộc. Hướng dẫn này không nhằm mục đích toàn diện hoặc nâng cao. Tôi muốn giới thiệu tính năng mới và nêu bật sức mạnh cũng như tính linh hoạt của nó trong việc giải quyết các vấn đề phân loại nhị phân. Vui lòng xem tài liệu scikit-learn, hướng dẫn sử dụng và các ví dụ để biết các ví dụ sử dụng kỹ lưỡng.
Một lời cảm ơn lớn tới Guillaume Lemaitre cho công việc của mình về tính năng này.
Cảm ơn vì đã đọc. Chúc mừng điều chỉnh.
Giấy phép dữ liệu:
Gian lận thẻ tín dụng: DbCL
Bệnh tiểu đường của người da đỏ Pima: CC0
TELCO ngừng hoạt động: sử dụng thương mại được
[ad_2]
Source link