一种热编码与词嵌入 - 何时选择一种或另一种?

数据挖掘 预处理 词嵌入 嵌入 编码
2021-09-24 01:32:35

我的一位同事遇到了一个有趣的情况,他对定义的分类特征有相当多的可能性(+/- 300 个不同的值)

通常的数据科学方法是执行 One-Hot Encoding。但是,使用非常大的字典(+/- 300 值)执行一些 One-Hot 编码会不会有点极端?关于何时选择嵌入向量或 One-Hot Encoding 是否有任何最佳实践?


附加信息:如果可以将新值添加到字典中,您将如何处理前一种情况。重新训练似乎是唯一的解决方案,但是使用 One-Hot Encoding 时,数据维度会同时增加,这可能会导致额外的麻烦,相反,嵌入向量即使出现新值也可以保持相同的维度。

你会如何处理这种情况?嵌入向量显然对我来说似乎更合适,但是我想验证我的观点并检查是否有另一种更合适的解决方案。

2个回答

One-Hot Encoding 是一种可以对任何分类特征进行矢量化的通用方法。创建和更新矢量化既简单又快速,只需在矢量中添加一个新条目,每个新类别都有一个条目。然而,这种速度和简单性也通过为每个类别创建一个新维度而导致“维度灾难”。

嵌入是一种需要大量数据的方法,无论是数据总量还是单个样本的重复出现,以及较长的训练时间。结果是一个具有固定、任意维数的密集向量。

它们在预测阶段也有所不同:One-Hot Encoding 不会告诉您项目的语义;每个向量化都是另一个维度的正交表示。嵌入将在表示空间中将共同出现的项目组合在一起。

如果您有足够的训练数据、足够的训练时间以及应用更复杂的训练算法(例如 word2vec 或 GloVe)的能力,请使用 Embeddings。否则,回退到 One-Hot Encoding。

似乎嵌入向量是这里最好的解决方案。

但是,您可以考虑一种称为“one-hot hashing trick”的 one-hot 编码的变体。在这种变体中,当唯一词的数量太大而无法在字典中分配唯一索引时,可能会散列成固定大小的向量。

您的用例中的一个优势是您可以执行在线编码。如果您还没有遇到每个词汇,您仍然可以分配一个哈希值。然后稍后,可以将新词添加到词汇表中。但一个陷阱是“哈希冲突”。事实上,两个不同的词有可能最终得到相同的哈希值。

我在François Chollet 的优秀“Python 深度学习”中找到了这种散列技巧的一个例子

import numpy as np
samples = ['The cat sat on the mat.', 'The dog ate my homework.']
dimensionality = 1000
max_length = 10

results = np.zeros((len(samples), max_length, dimensionality))
for i, sample in enumerate(samples):
    for j, word in list(enumerate(sample.split()))[:max_length]:
        # the word is given a hash with a random integer
        index = abs(hash(word)) % dimensionality
        results[i, j, index] = 1.0

结果数组:

results.shape
(2, 10, 1000)

您可以观察到两个句子之间的常用词被赋予相同的索引:The在两个句子的位置 0(维度 2 的位置 0 和 6)。

np.where(results > 0)
(array([0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1], dtype=int64),
 array([0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4], dtype=int64),
 array([ 23,  58, 467, 442,  83,  77,  23, 798, 618, 301, 942], dtype=int64))