OneHotEncoder 的分类特征问题

Issue with OneHotEncoder for categorical features

我想对数据集中 10 个特征中的 3 个分类特征进行编码。我使用 sklearn.preprocessing 中的 preprocessing 来执行以下操作:

from sklearn import preprocessing
cat_features = ['color', 'director_name', 'actor_2_name']
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

但是,我无法继续,因为我收到此错误:

    array = np.array(array, dtype=dtype, order=order, copy=copy)
ValueError: could not convert string to float: PG

我很惊讶为什么它抱怨字符串,因为它应该转换它!我在这里遗漏了什么吗?

来自文档:

categorical_features : “all” or array of indices or mask
Specify what features are treated as categorical.
‘all’ (default): All features are treated as categorical.
array of indices: Array of categorical feature indices.
mask: Array of length n_features and with dtype=bool.

pandas 数据框的列名将不起作用。如果您的分类特征是列号 0、2 和 6,请使用 :

from sklearn import preprocessing
cat_features = [0, 2, 6]
enc = preprocessing.OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

还必须注意,如果这些分类特征没有进行标签编码,则需要在使用OneHotEncoder

之前对这些特征使用LabelEncoder

如果您阅读 OneHotEncoder 的文档,您会看到 fit 的输入是 "Input array of type int"。所以你需要为你的一个热编码数据做两个步骤

from sklearn import preprocessing
cat_features = ['color', 'director_name', 'actor_2_name']
enc = preprocessing.LabelEncoder()
enc.fit(cat_features)
new_cat_features = enc.transform(cat_features)
print new_cat_features # [1 2 0]
new_cat_features = new_cat_features.reshape(-1, 1) # Needs to be the correct shape
ohe = preprocessing.OneHotEncoder(sparse=False) #Easier to read
print ohe.fit_transform(new_cat_features)

输出:

[[ 0.  1.  0.]
 [ 0.  0.  1.]
 [ 1.  0.  0.]]

编辑

0.20 开始,这变得更容易了,不仅因为 OneHotEncoder 现在可以很好地处理字符串,还因为我们可以使用 ColumnTransformer 轻松转换多个列,请参见下文一个例子

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import LabelEncoder, OneHotEncoder
import numpy as np

X = np.array([['apple', 'red', 1, 'round', 0],
              ['orange', 'orange', 2, 'round', 0.1],
              ['bannana', 'yellow', 2, 'long', 0],
              ['apple', 'green', 1, 'round', 0.2]])
ct = ColumnTransformer(
    [('oh_enc', OneHotEncoder(sparse=False), [0, 1, 3]),],  # the column numbers I want to apply this to
    remainder='passthrough'  # This leaves the rest of my columns in place
)
print(ct2.fit_transform(X)) # Notice the output is a string

输出:

[['1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '0.0' '0.0' '1.0' '1' '0']
 ['0.0' '0.0' '1.0' '0.0' '1.0' '0.0' '0.0' '0.0' '1.0' '2' '0.1']
 ['0.0' '1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '1.0' '0.0' '2' '0']
 ['1.0' '0.0' '0.0' '1.0' '0.0' '0.0' '0.0' '0.0' '1.0' '1' '0.2']]

您可以应用两种转换(从文本类别到整数类别,然后从整数类别 使用 LabelBinarizer class:

cat_features = ['color', 'director_name', 'actor_2_name']
encoder = LabelBinarizer()
new_cat_features = encoder.fit_transform(cat_features)
new_cat_features

请注意,此 returns 默认情况下是一个密集的 NumPy 数组。您可以通过传递来获得稀疏矩阵 sparse_output=符合 LabelBinarizer 构造函数。

来源Hands-On Machine Learning with Scikit-Learn and TensorFlow

如果数据集在pandas数据框中,使用

pandas.get_dummies

会更直接。

*从 pandas.get_getdummies 更正为 pandas.get_dummies

@Medo,

我遇到了同样的行为,觉得很沮丧。正如其他人指出的那样,Scikit-Learn 在考虑选择 categorical_features 参数中提供的列之前,要求 所有 数据都是数字。

具体来说,列选择由 /sklearn/preprocessing/data.py 中的 _transform_selected() 方法处理,该方法的第一行是

X = check_array(X, accept_sparse='csc', copy=copy, dtype=FLOAT_DTYPES).

如果提供的数据帧 X 中的 any 数据无法成功转换为浮点数,则此检查失败。

我同意 sklearn.preprocessing.OneHotEncoder 的文档在这方面具有误导性。

如果您像我一样对此感到沮丧,有一个简单的解决方法。只需使用 Category Encoders' OneHotEncoder。这是一个 Sklearn Contrib 包,因此与 scikit-learn 配合得非常好 API.

这可以作为直接替代品并为您完成无聊的标签编码。

from category_encoders import OneHotEncoder
cat_features = ['color', 'director_name', 'actor_2_name']
enc = OneHotEncoder(categorical_features=cat_features)
enc.fit(dataset.values)

对@piman314 的回答的评论(没有足够的声誉来发表评论)

这个问题只发生在 sklearn 版本 <= 0.19。 Documentation of 0.19 fit 方法只允许整数输入:

fit(X, y = None)

X: Input array of type int.

更高版本(documentation of 0.20)自动处理输入数据类型并允许字符串输入

fit(X, y = None)

X: The data to determine the categories of each feature.