如何在Sklearn Pipeline中进行Onehotencoding

13

我正在尝试对Pandas数据框中的分类变量进行One-Hot编码。该数据框包括分类和连续变量。我意识到可以使用Pandas的.get_dummies()函数轻松完成此操作,但我需要使用管道以便稍后生成PMML文件。

以下是创建映射器的代码。我想要编码的分类变量存储在名为“dummies”的列表中。

from sklearn_pandas import DataFrameMapper
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder

mapper = DataFrameMapper(
    [(d, LabelEncoder()) for d in dummies] +
    [(d, OneHotEncoder()) for d in dummies]
)

这是创建管道的代码,包括映射器和线性回归。

from sklearn2pmml import PMMLPipeline
from sklearn.linear_model import LinearRegression

lm = PMMLPipeline([("mapper", mapper),
                   ("regressor", LinearRegression())])

现在当我尝试拟合(使用“features”作为数据框和“targets”作为序列),它会报错“无法将字符串转换为浮点数”。

lm.fit(features, targets)
2个回答

9

OneHotEncoder 不支持字符串类型的特征,并且使用 [(d, OneHotEncoder()) for d in dummies] 会将其应用于所有虚拟列。请使用 LabelBinarizer 替代:

mapper = DataFrameMapper(
    [(d, LabelBinarizer()) for d in dummies]
)

另一个选择是使用LabelEncoder与第二个OneHotEncoder步骤。
mapper = DataFrameMapper(
    [(d, LabelEncoder()) for d in dummies]
)

lm = PMMLPipeline([("mapper", mapper),
                   ("onehot", OneHotEncoder()),
                   ("regressor", LinearRegression())])

非常感谢,LabelBinarizer 对我很有用。但我认为现在我只保留了经过 OneHot 编码的分类特征。是否有办法将原始连续特征也包括进来? - Desiré De Waele
是的,在DataFrameMapper中用None作为转换器将它们列出来。 - dukebody

2

LabelEncoderLabelBinarizer旨在对数据的目标(标签)进行编码/二值化,即y向量。当然,它们与OneHotEncoder做的事情大体相同,主要区别在于Label预处理步骤不接受矩阵,仅接受1-D向量。

example = pd.DataFrame({'x':np.arange(2,14,2),
                        'cat1':['A','B','A','B','C','A'],
                        'cat2':['p','q','w','p','q','w']})
dummies = ['cat1', 'cat2']

    x cat1 cat2
0   2    A    p
1   4    B    q
2   6    A    w
3   8    B    p
4  10    C    q
5  12    A    w

作为一个例子,LabelEncoder().fit_transform(example['cat1']) 是可行的,但是 LabelEncoder().fit_transform(example[dummies]) 会抛出一个 ValueError 异常。
相比之下,OneHotEncoder 可以接受多列:
from sklearn.preprocessing import OneHotEncoder

OneHotEncoder().fit_transform(example[dummies])

<6x6 sparse matrix of type '<class 'numpy.float64'>'
        with 12 stored elements in Compressed Sparse Row format>

可以通过使用ColumnTransformer将其纳入管道中,将其他列传递(或者替代地应用不同的转换):
from sklearn.compose import ColumnTransformer

ct = ColumnTransformer([('encode_cats', OneHotEncoder(), dummies),],
                       remainder='passthrough')      
pd.DataFrame(ct.fit_transform(example), columns = ct.get_feature_names_out())

   encode_cats__cat1_A  encode_cats__cat1_B  ...  encode_cats__cat2_w  remainder__x
0                  1.0                  0.0  ...                  0.0           2.0
1                  0.0                  1.0  ...                  0.0           4.0
2                  1.0                  0.0  ...                  1.0           6.0
3                  0.0                  1.0  ...                  0.0           8.0
4                  0.0                  0.0  ...                  0.0          10.0
5                  1.0                  0.0  ...                  1.0          12.0

最后,将其插入到管道中:

from sklearn.pipeline import Pipeline
Pipeline([('preprocessing', ct),
          ('regressor', LinearRegression())])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接