提高类别不平衡的精度/召回率?

机器算法验证 分类 Python 随机森林 scikit-学习 不平衡类
2022-03-27 22:53:29

试图为这两个类获得更好的精度/召回率......有什么建议吗?

  • 我有异构特征 [一些 num vars、一些 cat vars 和 2 个 text vars]
  • 目标是具有类不平衡的二元分类 [大约 85% 的 1 类和 15% 的 0 类]
  • 没有太多的训练数据[只有大约 17K 行]

这是我的管道:

cat_transformer = Pipeline(steps=[
    ('cat_imputer', SimpleImputer(strategy='constant', fill_value='missing')),
    ('cat_ohe', OneHotEncoder(handle_unknown='ignore'))])

num_transformer = Pipeline(steps=[
    ('num_imputer', SimpleImputer(strategy='constant', fill_value=0)),
    ('num_scaler', StandardScaler())])

text_transformer_0 = Pipeline(steps=[
    ('text_bow', CountVectorizer(lowercase=True,\
                                 token_pattern=SPLIT_PATTERN,\
                                 stop_words=stopwords))])
# SelectKBest()
# TruncatedSVD()

text_transformer_1 = Pipeline(steps=[
    ('text_bow', CountVectorizer(lowercase=True,\
                                 token_pattern=SPLIT_PATTERN,\
                                 stop_words=stopwords))])
# SelectKBest()
# TruncatedSVD()

FE = ColumnTransformer(
    transformers=[
        ('cat', cat_transformer, CAT_FEATURES),
        ('num', num_transformer, NUM_FEATURES),
        ('text0', text_transformer_0, TEXT_FEATURES[0]),
        ('text1', text_transformer_1, TEXT_FEATURES[1])])

pipe = Pipeline(steps=[('feature_engineer', FE),
                     ("scales", MaxAbsScaler()),
                     ('rand_forest', RandomForestClassifier(n_jobs=-1, class_weight='balanced'))])

random_grid = {"rand_forest__max_depth": [3, 10, 100, None],\
              "rand_forest__n_estimators": sp_randint(10, 100),\
              "rand_forest__max_features": ["auto", "sqrt", "log2", None],\
              "rand_forest__bootstrap": [True, False],\
              "rand_forest__criterion": ["gini", "entropy"]}

strat_shuffle_fold = StratifiedKFold(n_splits=5,\
  random_state=123,\
  shuffle=True)

cv_train = RandomizedSearchCV(pipe, param_distributions=random_grid, cv=strat_shuffle_fold)
cv_train.fit(X_train, y_train)

from sklearn.metrics import classification_report, confusion_matrix
preds = cv_train.predict(X_test)
print(confusion_matrix(y_test, preds))
print(classification_report(y_test, preds))

平均而言,我通过分类报告进行了许多不同的尝试组合:

  • 1级=>大约。95% 精度;98% 召回
  • 0级=>大约。80-85% 精度;57-66% 召回

当我执行分层 k-fold shuffle 并添加 class_weight='balanced" 时,我可以达到 66% 的召回率,但希望达到 75%-80% 左右

问题:

  1. 我可以做任何其他特征工程技术来改进预测类 0?[在所有功能上尝试了 TFIDF、Hashing Trick、selectKBest、SVD() 和 maxAbsScaler() 等文本的不同方法]
  2. 我应该尝试任何其他算法吗?【只试过随机森林分类器】
  3. 召回率低有什么大不了的吗?
  4. 大多数情况下只是“即插即用”......我错过了什么明显的东西吗?
  5. 应用过采样有帮助吗?如果是这样,如何在 python / sklearn 中完成?

任何帮助将非常感激!

1个回答

很明显,您的模型正遭受数据不平衡的困扰,这是您需要解决的问题。现在,关于你的问题:

我可以做任何其他特征工程技术来改进预测类 0?[在所有功能上尝试了 TFIDF、Hashing Trick、selectKBest、SVD() 和 maxAbsScaler() 等文本的不同方法]

这些都是有效的预处理步骤,但没有特征工程步骤可以帮助您解决真正的问题(即类不平衡)。它们有助于处理其他问题,例如高维、过度拟合等。

我应该尝试任何其他算法吗?【只试过随机森林分类器】

基于树的算法通常最适合处理不平衡的数据。您可以尝试一些现在非常流行的流行树增强算法(例如 XGBoost、LightGBM、Catboost)

召回率低有什么大不了的吗?

取决于你的目标......让我印象深刻的不是召回值低,而是它与 0 级的差异。从 98% 下降到 66% 是一个巨大的差异,应该是处理。

大多数情况下只是“即插即用”......我错过了什么明显的东西吗?应用过采样有帮助吗?如果是这样,如何在 python / sklearn 中完成?

是的,过采样是您应该做的第一件事!这可以通过 Python 中的不平衡学习来完成,它提供了大量的欠采样和过采样。只要您将sklearn.pipeline.Pipelineimblearn.pipeline.Pipeline交换,这将发挥得很好。请注意,必须在将文本转换为向量之后(即在 CountVectorizer 或 TFIDF 之后)完成此步骤。