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.
我想对数据集中 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.