【问题标题】:OneHotEncoding MappingOneHotEncoding 映射
【发布时间】:2016-12-23 01:29:18
【问题描述】:

为了离散化分类特征,我使用了 LabelEncoder 和 OneHotEncoder。我知道 LabelEncoder 按字母顺序映射数据,但是 OneHotEncoder 是如何映射数据的呢?

我有一个 pandas 数据框,dataFeat,有 5 个不同的列和 4 个可能的标签,如上所示。 dataFeat = data[['Feat1', 'Feat2', 'Feat3', 'Feat4', 'Feat5']]

Feat1  Feat2  Feat3  Feat4  Feat5
  A      B      A      A      A
  B      B      C      C      C
  D      D      A       A     B
  C      C      A       A     A  

我像这样申请labelencoder

le = preprocessing.LabelEncoder()

intIndexed = dataFeat.apply(le.fit_transform)

这是 LabelEncoder 编码标签的方式

Label   LabelEncoded
 A         0
 B         1
 C         2
 D         3

然后我像这样应用 OneHotEncoder

enc = OneHotEncoder(sparse = False)

encModel = enc.fit(intIndexed)

dataFeatY = encModel.transform(intIndexed)

intIndexed.shape = 94,5dataFeatY.shape=94,20

我对@9​​87654330@ 的形状有点困惑 - 它不应该也是 95,5 吗?

按照下面的 MhFarahani 回答,我这样做是为了查看标签是如何映射的

import numpy as np

S = np.array(['A', 'B','C','D'])
le = LabelEncoder()
S = le.fit_transform(S)
print(S)

[0 1 2 3]

ohe = OneHotEncoder()
one_hot = ohe.fit_transform(S.reshape(-1,1)).toarray()
print(one_hot.T)

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

这是否意味着标签是这样映射的,还是每列都不同? (这可以解释形状是 94,20)

Label   LabelEncoded    OneHotEncoded
 A         0               1.  0.  0.  0
 B         1               0.  1.  0.  0.
 C         2               0.  0.  1.  0.
 D         3               0.  0.  0.  1.

【问题讨论】:

    标签: scikit-learn one-hot-encoding


    【解决方案1】:

    一种热编码意味着您创建一和零的向量。所以顺序无关紧要。 在sklearn 中,首先需要将分类数据编码为数值数据,然后将它们提供给OneHotEncoder,例如:

    from sklearn.preprocessing import LabelEncoder
    from sklearn.preprocessing import OneHotEncoder
    
    S = np.array(['b','a','c'])
    le = LabelEncoder()
    S = le.fit_transform(S)
    print(S)
    ohe = OneHotEncoder()
    one_hot = ohe.fit_transform(S.reshape(-1,1)).toarray()
    print(one_hot)
    

    导致:

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

    但是pandas直接转换分类数据:

    import pandas as pd
    S = pd.Series( {'A': ['b', 'a', 'c']})
    print(S)
    one_hot = pd.get_dummies(S['A'])
    print(one_hot)
    

    哪个输出:

    A    [b, a, c]
    dtype: object
    
       a  b  c
    0  0  1  0
    1  1  0  0
    2  0  0  1
    

    正如您在映射过程中看到的那样,为每个分类特征创建了一个向量。向量的元素在分类特征的位置为 1,在其他位置为 0。这是一个系列中只有两个分类特征的示例:

    S = pd.Series( {'A': ['a', 'a', 'c']})
    print(S)
    one_hot = pd.get_dummies(S['A'])
    print(one_hot)
    

    结果:

    A    [a, a, c]
    dtype: object
    
       a  c
    0  1  0
    1  1  0
    2  0  1
    

    编辑以回答新问题

    让我们从这个问题开始:我们为什么要执行单热编码?如果您将 ['a','b','c'] 之类的分类数据编码为整数 [1,2,3](例如使用 LableEncoder),除了对分类数据进行编码之外,您还可以给它们一些权重1

    对于您示例中的数组,一个热门编码器将是:

    features ->  A   B   C   D 
    
              [[ 1.  0.  0.  0.]
               [ 0.  1.  0.  0.]
               [ 0.  0.  1.  0.]
               [ 0.  0.  0.  1.]]
    

    您有 4 个分类变量“A”、“B”、“C”、“D”。因此,OneHotEncoder 会将您的 (4,) 数组填充到 (4,4) 以便为每个分类变量(这将是您的新功能)提供一个向量(或列)。由于“A”是数组的 0 元素,因此第一列的索引 0 设置为 1,其余设置为 0。类似地,第二个向量(列)属于特征“B”,并且由于“B”是在数组的索引 1 中,“B”向量的索引 1 设置为 1,其余设置为零。这同样适用于其他功能。

    让我改变你的数组。也许它可以帮助您更好地了解标签编码器的工作原理:

    S = np.array(['D', 'B','C','A'])
    S = le.fit_transform(S)
    enc = OneHotEncoder()
    encModel = enc.fit_transform(S.reshape(-1,1)).toarray()
    print(encModel)
    

    现在结果如下。这里第一列是“A”,因为它是数组的最后一个元素(索引 = 3),所以第一列的最后一个元素是 1。

    features ->  A   B   C   D
              [[ 0.  0.  0.  1.]
               [ 0.  1.  0.  0.]
               [ 0.  0.  1.  0.]
               [ 1.  0.  0.  0.]]
    

    关于您的 pandas 数据框 dataFeat,即使在第一步中您对 LableEncoder 的工作原理也是错误的。当您应用LableEncoder 时,它适合当时的每一列并对其进行编码;然后,它转到下一列并重新适应该列。这是你应该得到的:

    from sklearn.preprocessing import LabelEncoder
    df =  pd.DataFrame({'Feat1': ['A','B','D','C'],'Feat2':['B','B','D','C'],'Feat3':['A','C','A','A'],
                        'Feat4':['A','C','A','A'],'Feat5':['A','C','B','A']})
    print('my data frame:')
    print(df)
    
    le = LabelEncoder()
    intIndexed = df.apply(le.fit_transform)
    print('Encoded data frame')
    print(intIndexed)
    

    结果:

    my data frame:
      Feat1 Feat2 Feat3 Feat4 Feat5
    0     A     B     A     A     A
    1     B     B     C     C     C
    2     D     D     A     A     B
    3     C     C     A     A     A
    
    Encoded data frame
       Feat1  Feat2  Feat3  Feat4  Feat5
    0      0      0      0      0      0
    1      1      0      1      1      2
    2      3      2      0      0      1
    3      2      1      0      0      0
    

    请注意,在第一列 Feat1 中,“A”被编码为 0,但在第二列 Feat2 中,“B”元素为 0。这是因为 LableEncoder 适合每一列并分别对其进行转换。请注意,在('B','C','D')之间的第二列中,变量'B'按字母顺序排列。

    最后,这是您正在寻找的sklearn

    from sklearn.preprocessing import LabelEncoder
    from sklearn.preprocessing import OneHotEncoder
    
    encoder = OneHotEncoder()
    label_encoder = LabelEncoder()
    data_lable_encoded = df.apply(label_encoder.fit_transform).as_matrix()
    data_feature_onehot = encoder.fit_transform(data_lable_encoded).toarray()
    print(data_feature_onehot)
    

    给你:

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

    如果你使用pandas,你可以比较结果,希望能给你一个更好的直觉:

    encoded = pd.get_dummies(df)
    print(encoded)
    

    结果:

         Feat1_A  Feat1_B  Feat1_C  Feat1_D  Feat2_B  Feat2_C  Feat2_D  Feat3_A  \
    0        1        0        0        0        1        0        0        1   
    1        0        1        0        0        1        0        0        0   
    2        0        0        0        1        0        0        1        1   
    3        0        0        1        0        0        1        0        1   
    
         Feat3_C  Feat4_A  Feat4_C  Feat5_A  Feat5_B  Feat5_C  
    0        0        1        0        1        0        0  
    1        1        0        1        0        0        1  
    2        0        1        0        0        1        0  
    3        0        1        0        1        0        0  
    

    完全一样!

    【讨论】:

    • 谢谢@MhFarahani,我现在明白了。我用更具体的问题更新了我的帖子。 :) 我不想使用get_dummies,因为我希望能够在不同的数据集上使用我训练过的模型
    • 通常,人们首先对他们的分类数据进行编码,然后将它们拆分为训练和测试数据集。我编辑了我的答案以使其更清楚。您对 LableEncoder 如何处理数据框的理解是错误的。
    • 优秀的答案,谢谢!我的印象是LabelEncoder 适合整个数据框,而不是逐列。我现在了解LabelEncoderOneHotEncoder 的工作原理。因此,如果我想确保以相同的方式对更多单独的数据进行编码,我是否只需保存已拟合的 LabelEncoderOneHotEncoder 对象以供将来使用?
    • 如果你腌制你的编码器,你就可以使用它。您需要导入 pickle 并将您的编码器转储到那里。但要小心LableEncoder。它只会适应数据框的最后一列!
    猜你喜欢
    • 2017-08-27
    • 2017-02-07
    • 2020-06-30
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    • 2020-12-27
    • 1970-01-01
    相关资源
    最近更新 更多