Ошибка ранней остановки Lightgbm внезапно возрастает при перекрестной проверке kfolds (из-за объединения индексов pandas) - в чем может быть причина? - PullRequest
0 голосов
/ 11 февраля 2019

При выполнении n-кратной перекрестной проверки на регрессоре LightGBM с некоторыми сохраненными индексами ошибка сначала уменьшается, но затем внезапно возрастает.Это происходит только для самого первого фолда и только когда я использую то, что я называю train_dev_kfolds, а не когда я использую kfolds.Вот результат: Изображение ошибки

Я проверил kfolds по индексам информационного кадра, хотя все вроде бы в порядке: индексы взаимоисключающие и в совокупности исчерпывающие (с точки зрениядатафрейм).Регенерация kfolds все еще вызывает ту же проблему.Наиболее странно, что это хорошо для других сгибов и других разбиений на подмножестве кадра данных (то есть kfolds).Использование LGBRegressor (API в стиле sklearn) не вызывает этой проблемы, например, при model = LGBMRegressor(n_estimators=500 ).fit(X_train, y_train,eval_set=[(X_dev, y_dev)],eval_metric='rmse',early_stopping_rounds=200,verbose=True) вывод в порядке.

Что может быть причиной этой довольно загадочной ошибки?train_idx.union (dev_idx) из импорта lightgbm LGBMRegressor

train_idx = folds[0][0]
dev_idx = folds[0][1]

inc_cols, key_col = pp.get_cols(settings,'model1',df)
X_train = df.loc[train_idx,inc_cols]
X_dev = df.loc[dev_idx,inc_cols]
y_train = df.loc[train_idx,key_col]
y_dev = df.loc[dev_idx,key_col]
lgb_train = lgb.Dataset(X_train,
                        label=y_train,
                        free_raw_data=False)
lgb_test = lgb.Dataset(X_dev,
                       label=y_dev,
                       free_raw_data=False)

model = lgb.train(
                params,
                lgb_train,
                valid_sets=[lgb_train, lgb_test],
                valid_names=['train', 'test'],
                num_boost_round=200,
                early_stopping_rounds= 200,
                verbose_eval=10
                )
preds = model.predict(X_dev)
display(mean_squared_error(y_dev, preds)**.5)

Эта функция используется для сохранения индексов:

def set_kf(root_train_df, root_test_df, settings):
    n_folds = settings['N_FOLDS']
    train_idx, dev_idx, test_idx = get_train_dev_test_idx(root_train_df, root_test_df, settings)
    kf = KFold(n_splits=n_folds,shuffle=True,random_state=42)
    kfolds, train_dev_kfolds = [],[] #get n_splits may be better for fine control

    #split on train only
    for kf_train_idx, kf_test_idx in kf.split(train_idx):
        kfolds.append((train_idx[kf_train_idx], train_idx[kf_test_idx]))

    #split on union of train and dev
    if dev_idx is not None:
        train_dev_idx = train_idx.union(dev_idx)
        for kf_train_idx, kf_test_idx in kf.split(train_dev_idx):
            train_dev_kfolds.append((train_dev_idx[kf_train_idx], train_dev_idx[kf_test_idx]))
    else:
        train_dev_kfolds = None

    data = {
        'train_idx': train_idx
        ,'dev_idx': dev_idx
        ,'test_idx': test_idx
        ,'kfolds': kfolds
        ,'train_dev_kfolds': train_dev_kfolds
        ,'kf': kf
    }

    with open(settings['cvs'], 'wb') as f:
        #pickle the 'data' dictionary using the highest protocol available.
        pickle.dump(data, f, pickle.HIGHEST_PROTOCOL)        

    del kfolds, train_dev_kfolds, data
    gc.collect()

Вот параметры, используемые для регрессии:

params ={
        'task': 'train',
        'boosting': 'goss',
        'objective': 'regression',
        'metric': 'rmse',
        'learning_rate': 0.01,
        'subsample': 0.9855232997390695,
        'max_depth': 7,
        'top_rate': 0.9064148448434349,
        'num_leaves': 63,
        'min_child_weight': 41.9612869171337,
        'other_rate': 0.0721768246018207,
        'reg_alpha': 9.677537745007898,
        'colsample_bytree': 0.5665320670155495,
        'min_split_gain': 9.820197773625843,
        'reg_lambda': 8.2532317400459,
        'min_data_in_leaf': 21,
        'verbose': 10,
        'seed':42,
        'bagging_seed':42,
        'drop_seed':42,
        'device':'gpu'
        }

РЕДАКТИРОВАТЬ: Создание разделений в том же сценарии, кажется, хорошо и не создает этой проблемы - это тогда проблема с рассолом?

РЕДАКТИРОВАТЬ 2: еще более странно, когда я загружаюtrain_idx и dev_idx от объекта pickle и выполнения разбиений на их объединении (с train_dev_idx = train_idx.union(dev_idx)), возникает та же проблема.Однако, если я получу индекс объединения из существующего фрейма данных train_dev_idx2 = train_dev_df.index, это нормально.Более того, когда я сравниваю эти два с train_dev_idx.equals(train_dev_idx2), то получается False, но когда я беру разницу, это пустой индекс.

EDIT 3: я сузил проблему до train_idx.union(dev_idx).Когда я заменяю эту строку на train_dev_idx=root_train_df.index, тогда все кажется в порядке.Однако, может ли кто-нибудь помочь мне понять, почему это может иметь место?Все элементы в индексах кажутся одинаковыми.Кроме того, почему это может привести к появлению ошибки для LightGBM?

...