Yo también estoy interesado en esta cuestión y quería añadir algunos experimentos para entender mejor el CalibratedClassifierCV (CCCV).
Como ya se ha dicho, hay dos formas de utilizarlo.
#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)
Alternativamente, podríamos probar el segundo método, pero calibrándolo sobre los mismos datos que hemos ajustado.
#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)
Aunque los documentos advierten que hay que utilizar un conjunto disjunto, esto podría ser útil porque permite inspeccionar my_clf
(por ejemplo, para ver el coef_
que no están disponibles en el objeto CalibratedClassifierCV). (¿Alguien sabe cómo obtener esto de los clasificadores calibrados--por ejemplo, hay tres de ellos por lo que se promedian los coeficientes).
Decidí comparar estos 3 métodos en cuanto a su calibración en un conjunto de pruebas completamente retenido.
Aquí hay un conjunto de datos:
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])
He añadido un poco de desequilibrio de clases y sólo he proporcionado 500 muestras para hacer de éste un problema difícil.
Hago 100 ensayos, cada vez probando cada método y trazando su curva de calibración.
Boxplots de las puntuaciones Brier en todas las pruebas:
Aumentar el número de muestras a 10.000:
Si cambiamos el clasificador a Naive Bayes, volviendo a las 500 muestras:
Parece que no hay suficientes muestras para calibrar. Aumentando las muestras a 10.000
Código completo
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')
Por lo tanto, los resultados de la puntuación Brier no son concluyentes, pero según las curvas parece ser mejor utilizar el segundo método.