如何在多类分类中最大化特定标签的召回分数?

数据挖掘 机器学习
2022-03-06 14:06:57

以为我已经解决了这个问题,但我遇到了不一致的问题,所以在这里联系。

我有一个带有四个标签 ['--','-','+','++'] 的多标签分类问题,并且对于一个基本的随机森林模型,我在一个标签“-”上存在显着的性能问题,而其他三个标签的表现相当不错。

model = RandomForestClassifier(random_state=42)
model_name = 'RFC_base'

grid_params={}

pipe = GridSearchCV(make_pipeline(model),scoring='recall_weighted',cv=5,param_grid=grid_params,n_jobs=-1)

          recall avg    recall (++) recall (+)  recall (-)  recall (--) 
RFC_base    0.848485    0.840909    0.871795    0.771429    0.893617

我很清楚 GridSearchCV 过于工程化,但我喜欢在优化时保持修补程序之间的代码一致。

我想提高“-”的召回分数,因此创建了一个自定义评分函数,我认为该函数可以最大化“-”的召回分数。

recall_neg_scorer = make_scorer(recall_score,average=None,labels=['-'],greater_is_better=True)

我一直在修补它以优化它,因此试图定义“greater_is_better”参数。所以我现在做了一个实际的 GridSearchCV 来改变一些参数。

model = RandomForestClassifier(random_state=42)
scaler = StandardScaler()

grid_params = {
    'randomforestclassifier__n_estimators': [81], #np.arange(start=60,stop=90,step=1),
    'randomforestclassifier__max_depth': np.arange(1,10,step=1),
    'randomforestclassifier__criterion': ['gini'], #,'entropy'],
    'randomforestclassifier__max_features': [7], #np.arange(1,X.shape[1]+1,step=1),
    'standardscaler': [StandardScaler(),MinMaxScaler(),None]
}

model_name = 'RFC_gscv_recall_neg'

pipe = GridSearchCV(make_pipeline(scaler,model),scoring=recall_neg_scorer,param_grid=grid_params,cv=5,n_jobs=-1)

我发现当“greater_is_better = True”时,我的评分函数实际上并没有优化“-”

例如,当 GSCV 在 'max_depth' 上运行时,它选择 9 给出:

          recall avg    recall (++) recall (+)  recall (-)  recall (--) 
RFC_gscv_9  0.836364    0.818182    0.871795    0.742857    0.893617

在“-”上的表现甚至比基本情况还要差。当我强制 max_depth = 8 它给出:

          recall avg    recall (++) recall (+)  recall (-)  recall (--) 
RFC_force_8 0.842424    0.818182    0.871795    0.8        0.87234  

当我选择“greater_is_better = False”时,它会主动尝试最小化分数。有什么我在这里搞砸了,还是有一个我错过的已知问题?

另外,我对堆栈有点陌生,所以如果有什么我遗漏的,请告诉我。

2个回答

我强烈建议对为什么会预测 ("-") 类进行更深入的分析。意思是当没有正确的班级时,您对班级(“-”)的预测是什么。分析这一点,您可以看到您将类(“-”)订购为类“++”。您可以查看区分这两类的输入数据和特征工程师特征。强迫您的模型间接执行此操作是一种公平的尝试,但模型无法了解数据中找不到的内容。使用特征工程,您可以增强数据以便更好地区分。

所以我刚刚想通了这一点,我觉得自己有点像个白痴。我没有在问题中发布这个 - 这就是为什么我需要在堆栈上做得更好的部分原因。

所以所有的评分数据都是基于“测试”分数。GSCV 的优化评分数据显然仅基于 TRAINING 数据。

因此,我想在基于测试分数数据而不是火车分数数据进行优化时,我的模型出现了一些数据泄漏。