【问题标题】:F1 score reduced after using class weight使用班级权重后 F1 分数降低
【发布时间】:2020-08-26 19:41:49
【问题描述】:

我正在研究一个多类分类用例,并且数据高度不平衡。通过高度不平衡的数据,我的意思是频率最高的类别和频率最低的类别之间存在巨大差异。因此,如果我继续使用SMOTE oversampling,那么数据量会大大增加(数据量从 280k 行增加到超过 250 亿行,因为不平衡性太高了)并且实际上不可能将 ML 模型拟合到如此庞大的数据集.同样,我不能使用欠采样,因为这会导致信息丢失。

所以我想在创建 ML 模型时使用来自 sklearn 的 compute_class_weight

代码:

from sklearn.utils.class_weight import compute_class_weight

class_weight = compute_class_weight(class_weight='balanced',
                                    classes=np.unique(train_df['Label_id']),
                                    y=train_df['Label_id'])

dict_weights = dict(zip(np.unique(train_df['Label_id']), class_weight))

svc_model = LinearSVC(class_weight=dict_weights)

我对测试数据进行了预测,并注意到了accuracyf1_scorerecall 等指标的结果。 我尝试复制相同但不传递class_weight,如下所示:

svc_model = LinearSVC()

但是我得到的结果很奇怪。通过class_weight 后的指标比没有class_weight 的指标差一些。

我希望得到完全相反的结果,因为我正在使用 class_weight 来改进模型,从而改进指标。

两种模型的指标差异很小,但与没有class_weight 的模型相比,f1_score 的模型与class_weight 的模型相比较小。

我也试过下面的sn-p:

svc_model = LinearSVC(class_weight='balanced')

但与没有class_weight 的模型相比,f1_score 仍然更少。

以下是我获得的指标:

LinearSVC w/o class_weight

Accuracy: 89.02, F1 score: 88.92, Precision: 89.17, Recall: 89.02, Misclassification error: 10.98

LinearSVC with class_weight=’balanced’

Accuracy: 87.98, F1 score: 87.89, Precision: 88.3, Recall: 87.98, Misclassification error: 12.02

LinearSVC with class_weight=dict_weights

Accuracy: 87.97, F1 score: 87.87, Precision: 88.34, Recall: 87.97, Misclassification error: 12.03

我认为使用class_weight 会改善指标,但反而会恶化指标。为什么会发生这种情况,我该怎么办?如果我不处理不平衡数据可以吗?

【问题讨论】:

    标签: python machine-learning scikit-learn classification imbalanced-data


    【解决方案1】:

    我如何看待问题

    我对您的问题的理解是,您的 类权重 方法实际上正在改进您的模型,但您没有看到它(可能)。原因如下:

    假设您有 10 个 POS 和 1k NEG 样本,并且您有两个模型:M-1 正确预测了所有 NEG 样本(假阴性率 = 0),但仅正确预测了 10 个 POS 样本中的 2 个。 M-2 正确预测了 700 个 NEG 和 8 个 POS 样本。从异常检测的角度来看,第二个模型可能是首选,而第一个模型(显然陷入了不平衡问题)具有更高的 f1 分数。

    类权重将尝试解决您的不平衡问题,将您的模型从 M-1 转移到 M-2。因此,您的 f1 分数可能会略有下降。但您可能有质量更好的模型。

    如何验证我的意见

    您可以通过查看混淆矩阵来检查我的观点,看看 f1 分数是否由于您的主要课程的更多错误分类而降低,以及您的次要课程现在是否有更多的真阳性。此外,您可以专门针对不平衡类测试其他指标。我知道Cohen's Kappa 可能你看到班级权重实际上增加了 Kappa 分数。

    还有一件事:做一些引导或交叉验证,f1 分数的变化可能是由于数据的可变性而没有任何意义

    【讨论】:

    • 我确实尝试过StratifiedKfold CV,但得到了类似的结果。此外,我有 600 多个课程,因此在我的情况下几乎不可能阅读 confusion_matrix。此外,我使用f1_scoreaverage='weighted' 来惩罚高频率的类,并通过考虑类权重来获得f1_score。因此,在我的情况下,您的 POS 和 NEG 示例将不成立,因为 f1_scoreaverage='weighted' 将惩罚 NEG 类
    【解决方案2】:

    并不总是保证如果您使用 class_weight 性能会一直提高。当我们使用随机系统时,总是存在一些不确定性。

    你可以试试class_weight = 'auto'。这里有一个讨论:https://github.com/scikit-learn/scikit-learn/issues/4324

    最后,您似乎使用了线性 SVM 的默认超参数,即 C=1 和;我建议尝试使用超参数,如果可能的话甚至进行网格搜索进行测试,如果 class_weight 仍然降低性能,请尝试数据归一化。

    【讨论】:

    • 我正在处理的数据是文本数据。数据规范化是什么意思。能详细点吗?
    • 对于文本数据,svc 似乎是一个非常不理想的选择。您是否尝试过 mlp,或者如果您对 DL 感兴趣,那么请使用 lstm/gru。如果是文本数据,您可以尝试删除停用词。
    • 同意,但它不是带有段落或长句的实际文本数据。该功能最多包含 4 个单词,因此不能将其视为我们将使用 NLP 或任何 DL 模型的实际文本数据。我希望你明白我的意思。使用 tfidf 和 ML 模型可以轻松解决此用例。你也可以看到我们得到的f1_score 还不错。
    猜你喜欢
    • 1970-01-01
    • 2016-01-24
    • 2018-10-08
    • 1970-01-01
    • 2020-02-05
    • 1970-01-01
    • 2018-07-16
    • 2019-09-01
    • 1970-01-01
    相关资源
    最近更新 更多