【问题标题】:In Machine learning, What is the best way to encode non hierarchic categorial features?在机器学习中,编码非分层分类特征的最佳方法是什么?
【发布时间】:2019-07-03 23:25:08
【问题描述】:

对于顺序无关紧要的字符串功能,get dummies 或 oneHotEncoder 哪个更好?

例如,在这个 pandas 数据框上:

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

【问题讨论】:

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


    【解决方案1】:

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

    另一方面,对于特征“价格”,您有很大范围的可能值,并且对于哪些值大于其他值有一个明确的定义。

    在处理分类特征方面,您是正确的 - 我们对它们进行编码。例如sklearn.preprocessing 有一个OrdinalEncoder,它只是将分类特征(主要是“男性”、“女性”等字符串)转换为整数。

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

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

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

    【讨论】:

      【解决方案2】:

      我刚刚得到了我上面问题的答案(与下面标记的黄色有关):

      当您将它们编码为数字并将它们全部保留为单个特征时,模型会假设顺序意味着某些东西,因此“ios”(映射到 2)大于“android”(等于 1)

      但现在似乎有一些顺序 0-3 但这不是 case... '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 所述

      【讨论】:

      • 在上面编辑了我的答案以表扬你!并投票赞成你的答案:)
      【解决方案3】:

      你只需要 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
      

      【讨论】:

        猜你喜欢
        • 2021-07-15
        • 2019-11-30
        • 1970-01-01
        • 2016-08-16
        • 2018-08-20
        • 2020-10-11
        • 1970-01-01
        • 2010-11-04
        • 2013-03-25
        相关资源
        最近更新 更多