问题
假设我们有一个看起来像这样的数据框:
age job friends label
23 'engineer' ['World of Warcraft', 'Netflix', '9gag'] 1
35 'manager' NULL 0
...
如果我们有兴趣训练一个分类器,使用年龄、工作和朋友作为特征来预测标签,那么我们应该如何将这些特征转换成可以输入模型的数字数组呢?
- 年龄很简单,因为它已经是数字了。
- 工作可以进行哈希/索引,因为它是一个分类变量。
- 朋友是一个分类变量列表。我应该怎么表示这个特征呢?
方法:
对列表中的每个元素进行哈希处理。假设我们的哈希函数具有以下映射,使用示例数据框:
NULL -> 0
engineer -> 42069
World of Warcraft -> 9001
Netflix -> 14
9gag -> 9
manager -> 250
假设朋友列表的最大长度是5。如果朋友列表长度小于5,则在右侧填充零。如果朋友列表长度大于5,则选择前5个元素。
方法1:哈希和堆栈
特征转换后的数据框如下所示:
feature label
[23, 42069, 9001, 14, 9, 0, 0] 1
[35, 250, 0, 0, 0, 0, 0] 0
限制
考虑以下内容:
age job friends label
23 'engineer' ['World of Warcraft', 'Netflix', '9gag'] 1
35 'manager' NULL 0
26 'engineer' ['Netflix', '9gag', 'World of Warcraft'] 1
...
比较第一条和第三条记录的功能:
feature label
[23, 42069, 9001, 14, 9, 0, 0] 1
[35, 250, 0, 0, 0, 0, 0] 0
[26, 42069, 14, 9, 9001, 0] 1
这两个记录有相同的朋友集合,但由于排序不同,导致特征哈希不同,尽管它们应该是相同的。
方法2:哈希、排序和堆叠
为了解决方法1的限制,只需按照 朋友 特征的哈希值进行排序即可。这将导致以下特征转换(假设按降序排列):
feature label
[23, 42069, 9001, 14, 9, 0, 0] 1
[35, 250, 0, 0, 0, 0, 0] 0
[26, 42069, 9001, 14, 9, 0, 0] 1
这种方法也有限制。考虑以下情况:
age job friends label
23 'engineer' ['World of Warcraft', 'Netflix', '9gag'] 1
35 'manager' NULL 0
26 'engineer' ['Netflix', '9gag', 'World of Warcraft'] 1
42 'manager' ['Netflix', '9gag'] 1
...
应用特征变换并进行排序,我们得到:
row feature label
1 [23, 42069, 9001, 14, 9, 0, 0] 1
2 [35, 250, 0, 0, 0, 0, 0] 0
3 [26, 42069, 9001, 14, 9, 0, 0] 1
4 [44, 250, 14, 9, 0, 0, 0] 1
以上特征存在什么问题?好吧,第1行和第3行的Netflix和9gag哈希在数组中具有相同的索引,但在第4行却没有。这会影响训练结果。
方法3:将数组转换为列
如果我们将“朋友”转换为5列,并像处理任何分类变量一样处理每个结果列,会怎么样?
嗯,假设“朋友”的词汇量很大(>100k)。那么去创建>100k的列,其中每个列负责相应词汇元素的哈希值,就太疯狂了。
方法4:独热编码再求和
如何处理这种情况?将每个哈希转换为独热向量,然后将所有这些向量相加。
例如,在这种情况下,第1行的特征会是这样的:
[23, 42069, 01x8, 1, 01x4, 1, 01x8986, 1, 01x(max_hash_size-8987)]
其中01x8表示一个由8个零组成的行。
这种方法的问题在于,这些向量将非常庞大且稀疏。
方法5:使用嵌入层和1D-Conv
使用此方法,我们将friends数组中的每个单词馈送到嵌入层中,然后进行卷积。与Keras IMDB示例类似:https://keras.io/examples/imdb_cnn/
限制:需要使用深度学习框架。我想要一个可以与传统机器学习一起使用的方法。我想要做逻辑回归或决策树。
你对此有何想法?