SMOTE 与 SMOTE-NC 用于具有分类和数字数据的二元分类器

数据挖掘 机器学习 分类 阶级失衡 打击 smotenc
2021-10-01 06:00:35

我正在使用 Xgboost 进行分类。y是 0 或 1(真或假)。我有分类和数字特征,所以理论上,我需要使用 SMOTE-NC 而不是 SMOTE。但是,我使用 SMOTE 获得了更好的结果。

谁能解释为什么会这样?

另外,如果我对分类数据使用一些编码器(BinaryEncoder、one hot 等),我需要在编码之后还是之前使用 SMOTE-NC?

我复制了我的示例代码(x并且y在清理之后,包括 BinaryEncoder)。

_train, X_val, y_train, y_val = train_test_split(x, y, test_size=0.2, random_state=1)

smt = SMOTE()
X_resampled, y_resampled = smt.fit_resample(X_train, y_train)


params_model1 = {
    'booster': ['dart', 'gbtree', 'gblinear'],
    'learning_rate': [0.001, 0.01, 0.05, 0.1],
    'min_child_weight': [1, 5, 10, 15, 20],
    'gamma': [0, 0.5, 1, 1.5, 2, 5],
    'subsample': [0.6, 0.8, 1.0],
    'colsample_bytree': [0.6, 0.8, 1.0],
    'max_depth': [3, 4, 5, 6, 7, 8],
    'max_delta_step': [0, 1, 2, 3, 5, 10],
    'base_score': [0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65],
    'reg_alpha': [0, 0.5, 1, 1.5, 2],
    'reg_lambda': [0, 0.5, 1, 1.5, 2],
    'n_estimators': [100, 200, 500]
}

skf = StratifiedKFold(n_splits=3, shuffle=True, random_state=1001)

xgb = XGBClassifier(base_score=0.5, booster='gbtree', colsample_bylevel=1,
                    colsample_bynode=1, colsample_bytree=0.3, gamma=1,
                    learning_rate=0.1, max_delta_step=0, max_depth=10,
                    min_child_weight=5, missing=None, n_estimators=1000, n_jobs=1,
                    nthread=None, objective='binary:logistic', random_state=0,
                    reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=None,
                    silent=None, subsample=0.8, verbosity=1)

scoring = 'f1'
rs_xgb = RandomizedSearchCV(xgb, param_distributions=params_model1, n_iter=1,
                            scoring=scoring,  n_jobs=4, cv=skf.split(X_resampled, y_resampled), verbose=3,
                            random_state=1001)

rs_xgb.fit(X_resampled, y_resampled)

refit = rs_xgb.best_estimator_

joblib.dump(refit, 'validator1.pkl')

loaded_xgb = joblib.load('validator1.pkl')

y_predict = loaded_xgb.predict(X_val.as_matrix())

print(confusion_matrix(y_val, y_predict))

print("Final result " + str(f1_score(y_val, y_predict)))
1个回答

你必须记住,机器学习在很大程度上仍然是一个经验领域,充满了临时的方法,虽然它们在大多数情况下运行良好,但缺乏关于它们为什么这样做的理论解释

SMOTE 可以说属于这一类;与 SMOTE 相比,绝对不能保证(理论上或其他方面)SMOTE-NC 对您的数据更有效,甚至无法保证 SMOTE 与更简单的方法(如过采样/欠采样)相比表现更好。引用原始 SMOTE 论文的 SMOTE-NC 的第 6.1 节(强调添加):

使用成人数据集的 SMOTE-NC 与我们的典型结果不同:它的性能基于 AUC 的普通欠采样差。[...] 即使是仅将连续特征应用于成人数据集的 SMOTE,也无法获得比普通欠采样更好的性能。

作者继续提供一些可能的解释,说明为什么他们在上述数据集上看到 SMOTE/SMOTE-NC 的这种非典型性能,但正如您将看到的,这与对数据集本身及其特征的深入关注有关,它本身在本质上是相当经验的,几乎不是“理论的”。

底线:关于您的问题,这里没有太多要解释的;任何进一步的细节都需要深入了解数据集的具体特征,这在此处当然是不可能的。但我建议不要打扰并继续以您的实验结果为指导,而不是由任何(实际上不存在的)关于该主题的理论...