16

如何处理 sk-learn 中标签编码的未知值?标签编码器只会在检测到新标签的情况下爆炸。

我想要的是通过one-hot -encoder对分类变量进行编码。但是,sk-learn 不支持字符串。所以我在每一列上都使用了一个标签编码器。

我的问题是在管道的交叉验证步骤中出现了未知标签。基本的 one-hot-encoder 可以选择忽略这种情况。先验pandas.getDummies /cat.codes是不够的,因为管道应该与现实生活中的新传入数据一起工作,这些数据也可能包含未知标签。

是否可以CountVectorizer为此目的使用 a ?

4

1 回答 1

18

编辑:

用 scikit-learn 处理这个问题的更简单/更好的方法是使用该类sklearn.preprocessing.OneHotEncoder

from sklearn.preprocessing import OneHotEncoder

enc = OneHotEncoder(handle_unknown='ignore')
enc.fit(train)

enc.transform(train).toarray()

老答案:

有几个答案提到pandas.get_dummies了这种方法,但我觉得这种labelEncoder方法对于实现模型来说更干净。其他类似的答案提到了使用DictVectorizer这个,但再次将整个转换DataFrame为 dict 可能不是一个好主意。

让我们假设以下有问题的列:

from sklearn import preprocessing
import numpy as np
import pandas as pd

train = {'city': ['Buenos Aires', 'New York', 'Istambul', 'Buenos Aires', 'Paris', 'Paris'],
        'letters': ['a', 'b', 'c', 'd', 'a', 'b']}
train = pd.DataFrame(train)

test = {'city': ['Buenos Aires', 'New York', 'Istambul', 'Buenos Aires', 'Paris', 'Utila'],
        'letters': ['a', 'b', 'c', 'a', 'b', 'b']}
test = pd.DataFrame(test)

Utila 是一个比较少见的城市,它不在训练数据中,而是在测试集中,我们可以在推理时考虑新数据。

诀窍是将此值转换为“其他”并将其包含在 labelEncoder 对象中。然后我们可以在生产中重用它。

c = 'city'
le = preprocessing.LabelEncoder()
train[c] = le.fit_transform(train[c])
test[c] = test[c].map(lambda s: 'other' if s not in le.classes_ else s)
le_classes = le.classes_.tolist()
bisect.insort_left(le_classes, 'other')
le.classes_ = le_classes
test[c] = le.transform(test[c])
test

  city  letters
0   1   a
1   3   b
2   2   c
3   1   a
4   4   b
5   0   b

要将其应用于新数据,我们只需le为每一列保存一个对象,这可以使用 Pickle 轻松完成。

这个答案是基于这个我觉得我并不完全清楚的问题,因此添加了这个例子。

于 2016-12-14T06:07:19.260 回答