一种在提高精度的同时保持分类器召回率的方法

机器算法验证 机器学习 深度学习 精确召回
2022-03-25 03:16:15

我构建了一个 ML 分类器,它实现了很好的召回率(0.8),但精度很低(0.3)。有没有办法在提高精度的同时保持这种召回率?

4个回答

准确率和召回率是一种权衡。通常,提高给定模型的精度意味着降低召回率,但这取决于模型的精度-召回曲线,所以你可能会很幸运。

通常,如果您想要更高的精度,您需要将阳性预测限制为模型中具有最高确定性的预测,这意味着总体预测更少的阳性(反过来,这通常会导致较低的召回率)。

如果您想在提高精度的同时保持相同的召回水平,您将需要一个更好的分类器。

(对于此类问题,请始终牢记二乘二列联表;有关详细信息,请参阅维基百科的召回/精度灵敏度/特异性

召回率(或灵敏度)与 P(测试/分类器为正 | 现实为真)或 True Positives/(True Positives + False Negatives)或 True positives/ True items相同

精度(或阳性预测值)与 P(现实为真 | 测试/分类器为阳性)或 True Positives/(True Positives + False Positives)或 True positives/ Positive items相同

更好的召回意味着更多的现实命中(真实的事物更可能包含在正面),更好的精确度意味着更多的正面命中(如果你分类为正面,更有可能是真实的)。

可以通过使您的分类器包含更多内容来任意增加召回率(如果它们不正确,则无需关心)。只要说一切都是积极的,你就可以有完美的回忆。这样就不会有假阴性了。当然,你会有很多误报。在列联表中,这就像将正负之间的水平线向下移动。它显然会增加召回率(并且可能会或可能不会影响精度)。

由于这里的一切都是双重的,我们可以说:

人们可以通过在考虑您的黄金标准以拥有越来越多的真实性时增加宽容度来任意提高精确度。只要说一切都是真的,你就可以获得完美的精确度。这样就不会出现误报。当然,你会有很多假阴性。它显然会提高精度(并且可能会或可能不会影响精度)。(是的,这似乎是一个奇怪的解释,但请耐心等待)

但这似乎有点武断(对于两者)。

当您增加一个(通过更改某些截止值)时,您将倾向于减少另一个。你要求的是避免减少。那肯定更好。模糊的方法是包含应该找到的东西(将 FN 转换为 TP),但不包含不应该包含的东西(不要将 TN 转换为 FP)。

你能控制什么?分类器本身?还是特征空间(数据点本身)?如果分类器是算法设计的一部分,那么我假设他是特征空间本身。

为了做一个过于简单的例子,让我们考虑一个搜索引擎。假设您要查找涉及概念 X 的网页。如果您从 X 开始,您将丢失提及 X 同义词的网页。如果您将同义词 Y 添加到搜索中,您会将一些 False Negatives 变成 True positives (你会收集到更多你之前丢失的东西)。但是这个新词 Y 可能是模棱两可的,它的替代含义可能包括更多你不想要的东西(增加误报,降低精度)。为了防止这种情况,您需要排除 Y 具有意外替代含义的上下文。

我不知道您正在使用的每个库。但是大多数 ML 库都内置了模型优化器来帮助您完成这项任务。

例如,如果您使用 sklearn,则可以使用RandomizedSearchCV为您寻找超参数的良好组合。例如,如果你训练一个随机森林分类器”:

#model
MOD = RandomForestClassifier() 
#Implemente RandomSearchCV
m_params = { 
            "RF": {
                    "n_estimators" : np.linspace(2, 500, 500, dtype = "int"),  
                    "max_depth": [5, 20, 30, None], 
                    "min_samples_split": np.linspace(2, 50, 50, dtype = "int"),  
                    "max_features": ["sqrt", "log2",10, 20, None],
                    "oob_score": [True],
                    "bootstrap": [True]
                    },
            }
    scoreFunction = {"recall": "recall", "precision": "precision"}
    random_search = RandomizedSearchCV(MOD,
                                       param_distributions = m_params[model], 
                                       n_iter = 20,
                                       scoring = scoreFunction,               
                                       refit = "recall",
                                       return_train_score = True,
                                       random_state = 42,
                                       cv = 5,
                                        verbose = 1 + int(log)) 

    #trains and optimizes the model
    random_search.fit(x_train, y_train)

    #recover the best model
    MOD = random_search.best_estimator_

请注意,参数 score 和 refit 将告诉 RandomizedSerachCV 您对最大化哪些指标最感兴趣。此方法还将节省您手动调整的时间(并可能使您的模型过度拟合您的测试数据)。

祝你好运!

此处未说明的另一种替代方法是对与训练数据集中不同标签对应的数据点进行过采样和欠采样。通过这种方式,您可以确保您的模型具有训练数据的平衡表示。这称为类平衡,可以显着提高召回率,从而使精度保持在相当可控的范围内。