modelselection.Kfold дает другие результаты, чем kf.split

Я работаю над набором данных TelcoSigtel, который содержит 5 тыс. цель с 86% не оттока и 16% оттока.

Извините, я хотел дать выдержку из фрейма данных, но он слишком велик или когда я пытаюсь взять небольшую группу, не хватает отбойников.

Моя проблема заключается в том, что следующие два метода, приведенные ниже, должны давать одинаковые результаты, но на некоторых алгоритмах они сильно различаются, а на некоторых других они дают точно такие же результаты.

Информация о наборе данных:

models = [('logit',
  LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
                     intercept_scaling=1, l1_ratio=None, max_iter=600,
                     multi_class='ovr', n_jobs=1, penalty='l2', random_state=None,
                     solver='liblinear', tol=0.0001, verbose=0, warm_start=False)), ....]
# Method 1:

from sklearn import model_selection
from sklearn.model_selection import KFold


X = telcom.drop("churn", axis=1)
Y = telcom["churn"]

results = []
names = []

seed = 0
scoring = "roc_auc"
for name, model in models:
    kfold = model_selection.KFold(n_splits = 5, random_state = seed)

    cv_results = model_selection.cross_val_score(model, X, Y, cv=kfold, scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)

# boxplot algorithm comparison
fig = plt.figure()
fig.suptitle('Algorithm Comparison-AUC')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.grid()

plt.show()

введите здесь описание изображения

# Method 2:


from sklearn.model_selection import KFold
from imblearn.over_sampling import SMOTE
from sklearn.metrics import roc_auc_score

kf = KFold(n_splits=5, random_state=0)

X = telcom.drop("churn", axis=1)
Y = telcom["churn"]

results = []
names = []

to_store1 = list()

seed = 0
scoring = "roc_auc"

cv_results = np.array([])

for name, model in models:
    for train_index, test_index in kf.split(X):
        # split the data
        X_train, X_test = X.loc[train_index,:].values, X.loc[test_index,:].values
        y_train, y_test = np.ravel(Y[train_index]), np.ravel(Y[test_index])  

        model = model  # Choose a model here
        model.fit(X_train, y_train )  
        y_pred = model.predict(X_test)

        to_store1.append(train_index)

        # store fold results
        result = roc_auc_score(y_test, y_pred)
        cv_results = np.append(cv_results, result)

    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)
    cv_results = np.array([])   

# boxplot algorithm comparison
fig = plt.figure()
fig.suptitle('Algorithm Comparison-AUC')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.grid()

plt.show()

введите здесь описание изображения


person glouis    schedule 20.11.2019    source источник
comment
Вы пытались поставить random_state во все свои модели?   -  person Shihab Shahriar Khan    schedule 20.11.2019
comment
да у них обоих есть random_state=0   -  person glouis    schedule 20.11.2019


Ответы (1)


Короткий ответ заключается в том, что вы должны использовать model.predict_proba(X_test)[:, 1] или model.decision_function(X_test) для получения идентичных результатов, так как roc auc scorer нуждается в вероятностях класса. Длинный ответ заключается в том, что вы можете воспроизвести такое же поведение на игрушечном примере:

import numpy as np
from sklearn.model_selection import KFold, cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.metrics import roc_auc_score, make_scorer

def assert_equal_scores(rnd_seed, needs_threshold):
    """Assert two different scorings, return equal results."""
    X, y, *_ = load_breast_cancer().values()
    kfold = KFold(random_state=rnd_seed)
    lr = LogisticRegression(random_state=rnd_seed + 10)
    roc_auc_scorer = make_scorer(roc_auc_score, needs_threshold=needs_threshold)
    cv_scores1 = cross_val_score(lr, X, y, cv=kfold, scoring=roc_auc_scorer)
    cv_scores2 = cross_val_score(lr, X, y, cv=kfold, scoring='roc_auc')
    np.testing.assert_equal(cv_scores1, cv_scores2)

Попробуйте assert_equal_scores(10, False) и assert_equal_scores(10, True) (или любое другое случайное семя). Первый поднимает AssertionError. Разница в том, что roc auc scorer требует, чтобы параметр needs_threshold был равен True.

person Georgios Douzas    schedule 21.11.2019