在机器学习中,对非分层分类特征进行编码的最佳方法是什么?

时间:2019-02-10 06:53:44

标签: python-3.x pandas machine-learning scikit-learn feature-engineering

对于顺序无关紧要的String功能,最好使用虚拟变量或oneHotEncoder?

例如,在此熊猫数据框上:

df_with_cat = pd.DataFrame({'A': ['ios', 'android', 'web', 'NaN', 'ios','ios', 'NaN', 'android'], 'B' : [4, 4, 'NaN', 2, 'NaN', 3, 3, 'NaN']})

df_with_cat.head()

    A        B
---------------
0   ios      4
1   android  4
2   web      NaN
3   NaN      2
4   ios      NaN
5   ios      3
6   NaN      3
7   android  NaN

我知道现在为了处理它们(删除缺失值等),我必须对它们进行编码,如下所示:

from sklearn.preprocessing import LabelEncoder

df_with_cat_orig = df_with_cat.copy()
la_encoder = LabelEncoder()
df_with_cat['A'] = la_encoder.fit_transform(df_with_cat.A)

输出:

df_with_cat.head(10)

    A   B
-----------
0   2   4
1   1   4
2   3   NaN
3   0   2
4   2   NaN
5   2   3
6   0   3
7   1   NaN

但是现在看来好像有0到3的顺序,但事实并非如此……'ios' ->2不一定大于'android' ->1

3 个答案:

答案 0 :(得分:1)

分类特征与数字特征的不同之处在于,分类特征是一组离散值,而数字特征形成了连续的序列。例如 对于功能“动物”,如果1->猫,而2->狗,则不能为1.5,则是1或2。在此设置中,狗不一定比cat大-一个和两个仅仅是“真实”功能的编码。

另一方面,对于“价格”功能,您有很多可能的值,并且明确定义了哪些值大于其他值。

在处理分类特征方面,您会发现-我们对它们进行了编码。例如,sklearn.preprocessing有一个OrdinalEncoder,它仅将分类特征(主要是诸如“ male”,“ female”等字符串)转换为整数。

现在,我对sklearn及其所需的编码不太熟悉,但是我觉得我应该讨论一些更多的“高级”方式来编码分类特征。根据您使用的机器学习模型的不同,这些模型可能适用也可能不适用。我个人主要将它们与神经网络一起使用。

最简单的一种是单热编码,类似于您将每个类别编码为整数的默认设置。除了这次要摆脱模型将一个类别视为大于另一个类别的问题以外,它使用一个由一和零组成的数组。即“猫”-> 0-> [1,0,0],“狗”-> 1-> [0,1,0],“鸟”-> 2-> [0,0,1]。本质上,每个类别都编码为一个整数索引,并且您的结果是一个全零的数组,但该索引处只有一个零。

我们编码的另一种方法是使用嵌入。这与一次热编码非常相似,因为您正在将整数索引(用于类别)转换为n维向量。但是,它可以节省空间,因为向量的大小可以小于类别数。这通常在处理语义信息的神经网络中使用。每个词都作为整数索引传递到模型中,但是嵌入层将每个索引转换为n维向量。在训练模型时,嵌入层会越来越好地代表每个类别。

答案 1 :(得分:1)

您只需要一个OneHotEncoder

from sklearn.preprocessing import LabelEncoder

df_with_cat_orig = df_with_cat.copy()
la_encoder = LabelEncoder()
df_with_cat['A'] = la_encoder.fit_transform(df_with_cat.A)

from sklearn.preprocessing import OneHotEncoder

oh_enc = OneHotEncoder(categorical_features=[0])
df_with_cat = oh_enc.fit_transform(df_with_cat).toarray()

df_with_cat = df_with_cat[:, 1:]       # remove first column to avoid dummy variable trap

答案 2 :(得分:0)

我刚刚在上面回答了我的问题(并与下面标记的黄色有关):

当您将它们编码为数字并将其全部保留为单个功能时,该模型会假设该顺序意味着某种意义,因为“ ios”(映射为2)大于“ android”(后者等于1)

  

但是现在好像有一些命令0-3,但这不是   情况...'ios'-> 2不一定大于'android'-> 1

如果针对特定功能的类别不太多,则很容易在它们上使用傻瓜:

data_with_dummies = pd.get_dummies(df_with_cat, columns=['A'], drop_first=True)


        B A_1 A_2   A_3
------------------------
    0   4   0   1   0
    1   4   1   0   0
    2   NaN 0   0   1
    3   2   0   0   0
    4   NaN 0   1   0
    5   3   0   1   0
    6   3   0   0   0
    7   NaN 1   0   

现在,我们避免了我最初提到的问题,这应该可以大大改善模型的性能

或者仅使用OneHotEncoder-如上面答案中所述的@Primusa