Python 字符串分类特征的一种热编码

Python 字符串分类特征的一种热编码,python,encoding,scikit-learn,one-hot-encoding,Python,Encoding,Scikit Learn,One Hot Encoding,我正在尝试对一个微不足道的数据集执行一次热编码 data = [['a', 'dog', 'red'] ['b', 'cat', 'green']] 使用Scikit Learn预处理这些数据的最佳方法是什么 本能地,你会看向Scikit的Learn。但是one hot编码器不支持字符串作为特性;它只离散整数 然后,您将使用,它将字符串编码为整数。但是,您必须将标签编码器应用到每个列中,并存储每个标签编码器(以及应用它们的列)。这感觉非常笨重 那么,在Scikit Learn中

我正在尝试对一个微不足道的数据集执行一次热编码

data = [['a', 'dog', 'red']
        ['b', 'cat', 'green']]
使用Scikit Learn预处理这些数据的最佳方法是什么

本能地,你会看向Scikit的Learn。但是one hot编码器不支持字符串作为特性;它只离散整数

然后,您将使用,它将字符串编码为整数。但是,您必须将标签编码器应用到每个列中,并存储每个标签编码器(以及应用它们的列)。这感觉非常笨重

那么,在Scikit Learn中,最好的方法是什么

请不要建议。这就是我现在常用的一种热编码。然而,它的局限性在于您不能单独编码您的训练/测试集。

这是一个很好的问题

然而,在某种意义上,这是一个私人案例(至少对我来说)经常出现-给定
sklearn
阶段适用于
X
矩阵的子集,我想应用(可能几个)给定整个矩阵。例如,在这里,您有一个知道在单个列上运行的stage,您希望应用它三次—每列一次

这是使用的经典案例

下面是一个可重用阶段的(草图),它接受一个字典,将列索引映射到要应用于它的转换中:

class ColumnApplier(object):
    def __init__(self, column_stages):
        self._column_stages = column_stages

    def fit(self, X, y):
        for i, k in self._column_stages.items():
            k.fit(X[:, i])

        return self

    def transform(self, X):
        X = X.copy()
        for i, k in self._column_stages.items():
            X[:, i] = k.transform(X[:, i])

        return X
现在,在这个上下文中使用它,从

X = np.array([['a', 'dog', 'red'], ['b', 'cat', 'green']])
y = np.array([1, 2])
X
您可以使用它将每个列索引映射到所需的转换:

multi_encoder = \
    ColumnApplier(dict([(i, preprocessing.LabelEncoder()) for i in range(3)]))
multi_encoder.fit(X, None).transform(X)

一旦你开发了这样一个阶段(我不能发布我使用的阶段),你可以反复使用它进行各种设置。

我已经多次面对这个问题,我在他的第100页的书中找到了解决方案:

我们可以应用这两种转换(从文本类别到整数类别,然后从整数类别) 使用LabelBinarizer类一次性将类别设置为一个热向量:

示例代码如下:

from sklearn.preprocessing import LabelBinarizer
encoder = LabelBinarizer()
housing_cat_1hot = encoder.fit_transform(data)
housing_cat_1hot
因此: 请注意,默认情况下,这将返回密集的NumPy数组。您可以通过传递来获得稀疏矩阵 稀疏_输出=LabelBinarizer构造函数的True


如果您使用的是sklearn>0.20.dev0,您可以在sklearn官方文档中找到关于LabelBinarizer的更多信息

In [11]: from sklearn.preprocessing import OneHotEncoder
    ...: cat = OneHotEncoder()
    ...: X = np.array([['a', 'b', 'a', 'c'], [0, 1, 0, 1]], dtype=object).T
    ...: cat.fit_transform(X).toarray()
    ...: 
Out[11]: array([[1., 0., 0., 1., 0.],
           [0., 1., 0., 0., 1.],
           [1., 0., 0., 1., 0.],
           [0., 0., 1., 0., 1.]])
In [30]: cat = CategoricalEncoder()

In [31]: X = np.array([['a', 'b', 'a', 'c'], [0, 1, 0, 1]], dtype=object).T

In [32]: cat.fit_transform(X).toarray()
Out[32]:
array([[ 1.,  0., 0.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  1.,  0.,  1.]])
如果您在sklearn==0.20.dev0上

In [11]: from sklearn.preprocessing import OneHotEncoder
    ...: cat = OneHotEncoder()
    ...: X = np.array([['a', 'b', 'a', 'c'], [0, 1, 0, 1]], dtype=object).T
    ...: cat.fit_transform(X).toarray()
    ...: 
Out[11]: array([[1., 0., 0., 1., 0.],
           [0., 1., 0., 0., 1.],
           [1., 0., 0., 1., 0.],
           [0., 0., 1., 0., 1.]])
In [30]: cat = CategoricalEncoder()

In [31]: X = np.array([['a', 'b', 'a', 'c'], [0, 1, 0, 1]], dtype=object).T

In [32]: cat.fit_transform(X).toarray()
Out[32]:
array([[ 1.,  0., 0.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  1.,  0.],
       [ 0.,  0.,  1.,  0.,  1.]])
另一种方法是使用category_编码器

以下是一个例子:

% pip install category_encoders
import category_encoders as ce
le =  ce.OneHotEncoder(return_df=False, impute_missing=False, handle_unknown="ignore")
X = np.array([['a', 'dog', 'red'], ['b', 'cat', 'green']])
le.fit_transform(X)
array([[1, 0, 1, 0, 1, 0],
       [0, 1, 0, 1, 0, 1]])

老实说,我以前也创造过类似的东西。而且感觉很笨重。Scikit Learn应该有一个在幕后对其进行抽象的类,因为这是一种常见的设计模式。如果没有,那么我认为这方面的PR是合适的。你的解决方案给出了这个数据的问题:X=np.数组([['cat'],['dog'],'cat'],['pet'],'man'],['cat']])y=[1,2,3,4]我通常也做类似的事情,但是一个已知的缺点是
LabelEncoder#transform
在看到训练中没有出现的字符串时崩溃。难道
fit#u transform
不应该纠正这个问题吗?这在Windows 10上的Python 3.6中失败了。>>外壳\u cat\u 1hot=encoder.fit\u transform(数据)-----回溯(最近一次调用):文件“”,第1行,在,,,,,,,这不是一个热编码,而是虚拟编码。此外,pandas.get_虚拟二进制编码被决策树分类器视为连续编码,因此不适用于该场景。CategorialEncoder已与OneHotEncoder合并,因此该功能包含在当前版本的sklearn==0.20.dev0中