有没有办法确定scikit-learn的LabelEncoder中标签的顺序?

3 投票
2 回答
6540 浏览
提问于 2025-04-18 17:31

假设我有一个分类任务,我想把文本分为“垃圾邮件”(Spam)和“正常邮件”(Ham)。在这个情况下,“精准度”分数(计算公式是“真正例 / (真正例 + 假正例)”)可以帮助我了解有多少“正常邮件”被错误地标记为“垃圾邮件”。我们可以用一个混淆矩阵来表示这个情况:

enter image description here

据我所知,scikit-learn会根据下面的方式计算混淆矩阵:

enter image description here

现在,如果我使用标签编码器(见下面的代码),它会把“垃圾邮件”标记为1,把“正常邮件”标记为0,这样就会反转混淆矩阵(假正例会变成真正例等等),导致精准度的含义发生变化。所以,我想知道有没有办法告诉标签编码器应该把哪个标签分配给哪个类别?(在这个情况下其实很简单,我可以用一个简单的列表推导来解决这个问题,但我想知道scikit-learn里有没有现成的解决方案。)

所以,我的目标是使用标签编码器,把“垃圾邮件”标记为0,把“正常邮件”标记为1。

from sklearn.preprocessing import LabelEncoder

X = df['text'].values 
y = df['class'].values

print('before: %s ...' %y[:5])

le = LabelEncoder()
y = le.fit_transform(y)

print('after: %s ...' %y[:5])


before: ['spam' 'ham' 'ham' 'ham' 'ham'] ...
after: [1 0 0 0 0] ...

2 个回答

0

LabelEncoder 是一个工具,它使用 Python 内置的排序方式,也就是你用 sorted 函数排序时,不加任何特别的比较规则或关键字时的结果。不过,有些评估指标在处理标签时是不对称的,它们需要一个叫 pos_label 的参数,来明确指定哪个类别是“正类”。

>>> a = np.random.randint(0, 2, 10)
>>> a
array([0, 0, 0, 0, 1, 0, 0, 0, 1, 0])
>>> precision_recall_fscore_support(a, np.ones(10), pos_label=1, average='micro')
(0.20000000000000001, 1.0, 0.33333333333333337, None)
>>> precision_recall_fscore_support(a, np.ones(10), pos_label=0, average='micro')
/home/larsmans/src/scikit-learn/sklearn/metrics/classification.py:920: UndefinedMetricWarning: Precision and F-score are ill-defined and being set to 0.0 due to no predicted samples.
(0.0, 0.0, 0.0, None)
1

当然,如果你使用 precision_score(... pos_label=1, ...),你可以手动指定哪个类是“正类”,这对于计算“正确”的分数非常重要,因为精确度的计算公式依赖于你定义的“正类”(精确度 = 真正例 / (真正例 + 假正例))。

但是,有一个情况是标签可能会导致问题的,那就是我在做交叉验证的时候,比如想计算精确度,因为 cross_validation 函数没有提供“正类”这个参数。

cross_val_score(clf, X_train, y_train, cv=cv, scoring='precision')

不过,正如在GitHub上建议的那样,有一个解决办法,就是创建一个“自定义评分器”,你可以在交叉验证中使用它来解决标签的问题:

from functools import partial
from sklearn.metrics import precision_score, make_scorer
custom_scorer = make_scorer(partial(precision_score, pos_label="1"))

撰写回答