Почему я не могу сравниться с рейтингом ЛГБМ? - PullRequest
0 голосов
/ 15 февраля 2019

Я не могу сопоставить cv балл LGBM вручную.

Вот MCVE:

from sklearn.datasets import load_breast_cancer
import pandas as pd
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import roc_auc_score
import lightgbm as lgb
import numpy as np

data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.Series(data.target)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

folds = KFold(5, random_state=42)

params = {'random_state': 42}

results = lgb.cv(params, lgb.Dataset(X_train, y_train), folds=folds, num_boost_round=1000, early_stopping_rounds=100, metrics=['auc'])
print('LGBM\'s cv score: ', results['auc-mean'][-1])

clf = lgb.LGBMClassifier(**params, n_estimators=len(results['auc-mean']))

val_scores = []
for train_idx, val_idx in folds.split(X_train):
    clf.fit(X_train.iloc[train_idx], y_train.iloc[train_idx])
    val_scores.append(roc_auc_score(y_train.iloc[val_idx], clf.predict_proba(X_train.iloc[val_idx])[:,1]))
print('Manual score: ', np.mean(np.array(val_scores)))

Я ожидал, что две оценки CV будут идентичны - я установил случайные семенаи сделал то же самое.Все же они отличаются.

Вот вывод, который я получаю:

LGBM's cv score:  0.9851513530737058
Manual score:  0.9903622177441328

Почему?Я неправильно использую модуль LGMB cv?

1 Ответ

0 голосов
/ 15 февраля 2019

Вы разделяете X на X_train и X_test.Для cv вы делите X_train на 5 сгибов, а вручную - на 5 сгибов.то есть вы используете больше очков вручную, чем с помощью cv.

, измените results = lgb.cv(params, lgb.Dataset(X_train, y_train) на results = lgb.cv(params, lgb.Dataset(X, y)

Более того, могут быть разные параметры.Например, количество потоков, используемых lightgbm, меняет результат.Во время резюме модели устанавливаются параллельно.Следовательно, количество используемых потоков может отличаться от вашего последовательного обучения.

РЕДАКТИРОВАТЬ после 1-й коррекции:

Вы можете достичь тех же результатов, используя ручное расщепление / cv, используя этокод:

from sklearn.datasets import load_breast_cancer
import pandas as pd
from sklearn.model_selection import train_test_split, KFold
from sklearn.metrics import roc_auc_score
import lightgbm as lgb
import numpy as np

data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names)
y = pd.Series(data.target)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

folds = KFold(5, random_state=42)


params = {
        'task': 'train',
        'boosting_type': 'gbdt',
        'objective':'binary',
        'metric':'auc',
        }

data_all = lgb.Dataset(X_train, y_train)

results = lgb.cv(params, data_all, 
                 folds=folds.split(X_train), 
                 num_boost_round=1000, 
                 early_stopping_rounds=100)

print('LGBM\'s cv score: ', results['auc-mean'][-1])

val_scores = []
for train_idx, val_idx in folds.split(X_train):

    data_trd = lgb.Dataset(X_train.iloc[train_idx], 
                           y_train.iloc[train_idx], 
                           reference=data_all)

    gbm = lgb.train(params,
                    data_trd,
                    num_boost_round=len(results['auc-mean']),
                    verbose_eval=100)

    val_scores.append(roc_auc_score(y_train.iloc[val_idx], gbm.predict(X_train.iloc[val_idx])))
print('Manual score: ', np.mean(np.array(val_scores)))

выход

LGBM's cv score:  0.9914524426410262
Manual score:  0.9914524426410262

Что отличает эту строку reference=data_all.Во время cv объединение переменных (относится к lightgbm doc ) создается с использованием всего набора данных (X_train), в то время как в вашем руководстве для цикла оно было построено на обучающем подмножестве (X_train.iloc [train_idx]),Передав ссылку на набор данных, связывающий все данные, lightGBM будет использовать то же самое объединение, давая те же результаты.

...