【问题标题】:Feature Hashing on multiple categorical features(columns)多个分类特征(列)的特征散列
【发布时间】:2019-06-13 10:20:48
【问题描述】:

我想将特征“流派”散列到 6 列中,并将“出版商”特征分别散列到另外 6 列中。我想要类似下面的东西:

      Genre      Publisher  0    1    2    3    4    5      0    1    2    3    4    5 
0     Platform  Nintendo  0.0  2.0  2.0 -1.0  1.0  0.0    0.0  2.0  2.0 -1.0  1.0  0.0
1       Racing      Noir -1.0  0.0  0.0  0.0  0.0 -1.0   -1.0  0.0  0.0  0.0  0.0 -1.0
2       Sports     Laura -2.0  2.0  0.0 -2.0  0.0  0.0   -2.0  2.0  0.0 -2.0  0.0  0.0
3  Roleplaying      John -2.0  2.0  2.0  0.0  1.0  0.0   -2.0  2.0  2.0  0.0  1.0  0.0
4       Puzzle      John  0.0  1.0  1.0 -2.0  1.0 -1.0    0.0  1.0  1.0 -2.0  1.0 -1.0
5     Platform      Noir  0.0  2.0  2.0 -1.0  1.0  0.0    0.0  2.0  2.0 -1.0  1.0  0.0

下面的代码做了我想做的事情

import pandas as pd
d = {'Genre': ['Platform', 'Racing','Sports','Roleplaying','Puzzle','Platform'], 'Publisher': ['Nintendo', 'Noir','Laura','John','John','Noir']}
df = pd.DataFrame(data=d)
from sklearn.feature_extraction import FeatureHasher
fh1 = FeatureHasher(n_features=6, input_type='string')
fh2 = FeatureHasher(n_features=6, input_type='string')
hashed_features1 = fh.fit_transform(df['Genre'])
hashed_features2 = fh.fit_transform(df['Publisher'])
hashed_features1 = hashed_features1.toarray()
hashed_features2 = hashed_features2.toarray()
pd.concat([df[['Genre', 'Publisher']], pd.DataFrame(hashed_features1),pd.DataFrame(hashed_features2)],
          axis=1)

这适用于上述两个特征,但如果我有 40 个分类特征,那么这种方法会很乏味。还有其他办法吗?

【问题讨论】:

  • 非常好的第一个问题 - 我添加了更多标签,这样它就可以暴露给具有正确技能的 ppl。
  • 40 个分类特征,40 列分类数据??
  • 是 40 列分类数据。
  • 谢谢帕特里克·阿特纳。

标签: python pandas dataframe scikit-learn feature-extraction


【解决方案1】:

散列(更新)

假设新类别可能会出现在某些功能中,散列是可行的方法。只需 2 条注释:

  • 注意碰撞的可能性并相应调整特征数量
  • 在您的情况下,您希望分别对每个功能进行哈希处理

一个热向量

如果每个特征的类别数量固定且不太大,则使用一种热编码。

我建议使用两者之一:

  1. sklearn.preprocessing.OneHotEncoder
  2. pandas.get_dummies

示例

import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.feature_extraction import FeatureHasher
from sklearn.preprocessing import OneHotEncoder

df = pd.DataFrame({'feature_1': ['A', 'G', 'T', 'A'],
                   'feature_2': ['cat', 'dog', 'elephant', 'zebra']})

# Approach 0 (Hashing per feature)
n_orig_features = df.shape[1]
hash_vector_size = 6
ct = ColumnTransformer([(f't_{i}', FeatureHasher(n_features=hash_vector_size, 
                        input_type='string'), i) for i in range(n_orig_features)])

res_0 = ct.fit_transform(df)  # res_0.shape[1] = n_orig_features * hash_vector_size

# Approach 1 (OHV)
res_1 = pd.get_dummies(df)

# Approach 2 (OHV)
res_2 = OneHotEncoder(sparse=False).fit_transform(df)

res_0

array([[ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  0.,  1., -1.,  0., -1.],
       [ 0.,  0.,  0.,  1.,  0.,  0.,  0.,  2., -1.,  0.,  0.,  0.],
       [ 0., -1.,  0.,  0.,  0.,  0., -2.,  2.,  2., -1.,  0., -1.],
       [ 0.,  0.,  0.,  0.,  1.,  0.,  0.,  2.,  1., -1.,  0., -1.]])

res_1

   feature_1_A  feature_1_G  feature_1_T  feature_2_cat  feature_2_dog  feature_2_elephant  feature_2_zebra
0            1            0            0              1              0                   0                0
1            0            1            0              0              1                   0                0
2            0            0            1              0              0                   1                0
3            1            0            0              0              0                   0                1

res_2

array([[1., 0., 0., 1., 0., 0., 0.],
       [0., 1., 0., 0., 1., 0., 0.],
       [0., 0., 1., 0., 0., 1., 0.],
       [1., 0., 0., 0., 0., 0., 1.]])

【讨论】:

  • 不,我不能使用一个热编码,因为我正在以块的形式获取数据,并且可能会发生一个新块在一个特性/特性中包含一些在特性/特性中不存在的分类值第一块。在这种情况下,与第一个块相比,onehot 编码将产生更多列。由于我需要将数据应用于 partial_fit 分类器,因此每次迭代中我需要相同数量的列。请查看此链接 (stackoverflow.com/questions/54096164/…)
  • 您的代码很有帮助。谢谢你。但正如你所说的“注意碰撞的可能性并相应地调整特征的数量”。因此,如果有 40 个特征列,那么每列可能需要散列到不同数量的列。例如,在您的代码中,我希望 feature_1 散列到 6 的向量(hash_vector_size=6),而 feature_2 散列到 5 的向量(hash_vector_size=5)我如何修改代码。 PS:我尝试自己做,但做不到。
  • 我会创建一个字典,其中键是原始特征名称,列是该给定特征的 hash_vector_size。然后在实例化 ColumnTransformer 时简单地使用这个字典。请参阅文档中的 transformers 参数:scikit-learn.org/stable/modules/generated/…
  • ~~~ ct = ColumnTransformer([(f't_{i_key}', FeatureHasher(n_features=i_value, input_type='string'),i_key ) for i_key, i_value in dict_hashed_vector_size.items() ]) ~~~我已经按照你的建议做了。我猜它正在工作。
  • 方法 0 有点奇怪。正如您在结果中看到的那样,它为第一行生成 4 个索引而不是 2。我也希望得到 2 个索引,因为有 2 个不同的列.原因是,如果您使用输入类型为“字符串”的特征哈希,它需要一个字符串列表。如果你只是输入一个字符串,那么每个字符都会被散列。因此,对于第一行 ['A', 'cat'] 你会得到 4 个索引而不是 2 个。
【解决方案2】:

尽管我来晚了,但从我在 Kaggle 上看到的示例来看,FeatureHashing 是同时针对多个列(即在 DataFrame 上)执行的,而不是针对单个列并连接稀疏矩阵。请参阅 Kaggle 上的笔记本,herehere。我还使用了两种方法对this 数据执行特征散列,即:

一个。散列各个分类列并连接结果
湾。一次散列 DataFrame 的所有分类列

当遵循方法 (b) 而不是方法 (a) 时,逻辑回归分类器的结果明显更好。

【讨论】:

    猜你喜欢
    • 2014-12-14
    • 2012-01-30
    • 2017-04-01
    • 1970-01-01
    • 2022-04-26
    • 1970-01-01
    • 2018-05-04
    • 2018-10-20
    • 2011-04-07
    相关资源
    最近更新 更多