Я также заинтересован в этом вопросе и хотел бы добавить несколько экспериментов, чтобы лучше понять CalibratedClassifierCV (CCCV).
Как уже было сказано, есть два способа его использования.
#Method 1, train classifier within CCCV
model = CalibratedClassifierCV(my_clf)
model.fit(X_train_val, y_train_val)
#Method 2, train classifier and then use CCCV on DISJOINT set
my_clf.fit(X_train, y_train)
model = CalibratedClassifierCV(my_clf, cv='prefit')
model.fit(X_val, y_val)
В качестве альтернативы, мы могли бы попробовать второй метод, но просто выполнить калибровку по тем же данным, которые мы использовали.
#Method 2 Non disjoint, train classifier on set, then use CCCV on SAME set used for training
my_clf.fit(X_train_val, y_train_val)
model = CalibratedClassifierCV(my_clf, cv='prefit')
model.fit(X_train_val, y_train_val)
Хотя документы предупреждают об использовании непересекающегося набора, это может быть полезно, потому что оно позволяет вам затем проверить my_clf
(например, увидетьcoef_
, которые недоступны из объекта CalibratedClassifierCV). (Кто-нибудь знает, как получить это из калиброванных классификаторов - для одного, их три, так что вы бы усреднили коэффициенты?).
Я решил сравнить эти 3 метода с точки зрения их калибровки на полностью проведенном тестовом наборе.
Вот набор данных:
X, y = datasets.make_classification(n_samples=500, n_features=200,
n_informative=10, n_redundant=10,
#random_state=42,
n_clusters_per_class=1, weights = [0.8,0.2])
Я добавил некоторый дисбаланс классов и предоставил только 500 образцов, чтобы сделать эту проблему сложной.
Я провожу 100 испытаний, каждый раз пробуя каждый метод и составляя его калибровочную кривую.
Бокплоты Бриера набирают очки во всех испытаниях:
Увеличение количества образцов до 10000:
Если мы изменим классификатор наивный Байес, возвращаясь к 500 выборкам:
Похоже на то, что образцов недостаточно для калибровки. Увеличение образцов до 10000
Полный код
print(__doc__)
# Based on code by Alexandre Gramfort <alexandre.gramfort@telecom-paristech.fr>
# Jan Hendrik Metzen <jhm@informatik.uni-bremen.de>
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.naive_bayes import GaussianNB
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import brier_score_loss
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.model_selection import train_test_split
def plot_calibration_curve(clf, name, ax, X_test, y_test, title):
y_pred = clf.predict(X_test)
if hasattr(clf, "predict_proba"):
prob_pos = clf.predict_proba(X_test)[:, 1]
else: # use decision function
prob_pos = clf.decision_function(X_test)
prob_pos = \
(prob_pos - prob_pos.min()) / (prob_pos.max() - prob_pos.min())
clf_score = brier_score_loss(y_test, prob_pos, pos_label=y.max())
fraction_of_positives, mean_predicted_value = \
calibration_curve(y_test, prob_pos, n_bins=10, normalize=False)
ax.plot(mean_predicted_value, fraction_of_positives, "s-",
label="%s (%1.3f)" % (name, clf_score), alpha=0.5, color='k', marker=None)
ax.set_ylabel("Fraction of positives")
ax.set_ylim([-0.05, 1.05])
ax.set_title(title)
ax.set_xlabel("Mean predicted value")
plt.tight_layout()
return clf_score
fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, figsize=(6,12))
ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated",)
ax2.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")
ax3.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")
scores = {'Method 1':[],'Method 2':[],'Method 3':[]}
fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, figsize=(6,12))
ax1.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated",)
ax2.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")
ax3.plot([0, 1], [0, 1], "k:", label="Perfectly calibrated")
scores = {'Method 1':[],'Method 2':[],'Method 3':[]}
for i in range(0,100):
X, y = datasets.make_classification(n_samples=10000, n_features=200,
n_informative=10, n_redundant=10,
#random_state=42,
n_clusters_per_class=1, weights = [0.8,0.2])
X_train_val, X_test, y_train_val, y_test = train_test_split(X, y, test_size=0.80,
#random_state=42
)
X_train, X_val, y_train, y_val = train_test_split(X_train_val, y_train_val, test_size=0.80,
#random_state=42
)
#my_clf = GaussianNB()
my_clf = LogisticRegression()
#Method 1, train classifier within CCCV
model = CalibratedClassifierCV(my_clf)
model.fit(X_train_val, y_train_val)
r = plot_calibration_curve(model, "all_cal", ax1, X_test, y_test, "Method 1")
scores['Method 1'].append(r)
#Method 2, train classifier and then use CCCV on DISJOINT set
my_clf.fit(X_train, y_train)
model = CalibratedClassifierCV(my_clf, cv='prefit')
model.fit(X_val, y_val)
r = plot_calibration_curve(model, "all_cal", ax2, X_test, y_test, "Method 2")
scores['Method 2'].append(r)
#Method 3, train classifier on set, then use CCCV on SAME set used for training
my_clf.fit(X_train_val, y_train_val)
model = CalibratedClassifierCV(my_clf, cv='prefit')
model.fit(X_train_val, y_train_val)
r = plot_calibration_curve(model, "all_cal", ax3, X_test, y_test, "Method 2 non Dis")
scores['Method 3'].append(r)
import pandas
b = pandas.DataFrame(scores).boxplot()
plt.suptitle('Brier score')
Таким образом, результаты оценки Бриера неубедительны, но в соответствии с кривыми лучше всего использовать второй метод.