Keras 嵌入层:它们如何工作?

Keras embedding layers: how do they work?

我开始使用 Keras 构建神经网络模型。

我有一个分类问题,其中的特征是离散的。 为了处理这种情况,标准程序包括使用单热编码转换二进制数组中的离散特征。

然而,对于 Keras,这一步似乎不是必需的,因为可以简单地使用嵌入层来创建这些离散特征的特征向量表示。

这些embeddings是如何执行的?

我的理解是,如果离散特征 f 可以取 k 值,那么嵌入层会创建一个具有 k 列的矩阵。每次我收到该特征的值时,比如 i,在训练阶段,只会更新矩阵的 i 列。

我的理解正确吗?

人们可能很容易注意到 - one-hot 向量与 Embedding 矩阵的乘法可以在恒定时间内有效地执行,因为它可能被理解为矩阵切片。这正是 Embedding 层在计算过程中所做的。它只是使用 gather 后端函数选择适当的索引。这意味着你对Embedding层的理解是正确的。

Keras 中的嵌入层(通常也是如此)是一种创建密集字编码的方法。您应该将其视为乘以单热编码 (OHE) 矩阵的矩阵,或简单地视为 OHE 矩阵上的线性层。

它总是用作直接附加到输入的层。

稀疏密集字编码表示编码效率。

One-hot-encoding (OHE) 模型是稀疏词编码模型。例如,如果我们有 1000 个输入激活,则每个输入特征将有 1000 个 OHE 向量。

假设我们知道一些输入激活是相关的,并且我们有 64 个潜在特征。我们会有这样的嵌入:

e = Embedding(1000, 64, input_length=50)

1000 告诉我们计划总共编码 1000 个单词。 64 告诉我们使用 64 维向量 space。 50 告诉输入文档每个有 50 个单词。

嵌入层将随机填充非零值,需要学习参数。

here

中创建Embedding层时还有其他参数

嵌入层的输出是什么?

嵌入层的输出是一个二维向量,在输入的单词序列(输入文档)中每个单词都有一个嵌入。

注意:如果您希望将 Dense 层直接连接到 Embedding 层,您必须首先使用 .[=44= 将 2D 输出矩阵展平为 1D 向量]

假设您有 N 个不直接具有数学表示的对象。例如单词。

由于神经网络只能处理张量,因此您应该寻找一些方法将这些对象转换为张量。 解决方案在一个巨大的矩阵(嵌入矩阵)中,它将对象的每个索引与其转换为张量相关联。

object_index_1: vector_1
object_index_1: vector_2
...
object_index_n: vector_n

选择特定对象的向量可以通过以下方式转换为矩阵乘积:

其中 v 是决定需要翻译哪个单词的单热向量。 M是嵌入矩阵。

如果我们提出通常的管道,它将是:

  1. 我们有一个对象列表。
objects = ['cat', 'dog', 'snake', 'dog', 'mouse', 'cat', 'dog', 'snake', 'dog']
  1. 我们将这些对象转换为索引(我们计算唯一对象)。
unique = ['cat', 'dog', 'snake', 'mouse'] # list(set(objects))
objects_index = [0, 1, 2, 1, 3, 0, 1, 2, 1] #map(unique.index, objects)

  1. 我们将这些索引转换为一个热向量(记住索引所在的位置只有一个)
objects_one_hot = [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], 
     [0, 0 , 0, 1], [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0]] # map(lambda x: [int(i==x) for i in range(len(unique))], objects_index)
#objects_one_hot is matrix is 4x9
  1. 我们创建或使用嵌入矩阵:
#M = matrix of dim x 4 (where dim is the number of dimensions you want the vectors to have). 
#In this case dim=2
M = np.array([[1, 1], [1, 2], [2, 2], [3,3]]).T # or... np.random.rand(2, 4)
#objects_vectors = M * objects_one_hot
objects_vectors = [[1, 1], [1, 2], [2, 2], [1, 2], 
    [3, 3], [1, 1], [1, 2], [2,2], [1, 2]] # M.dot(np.array(objects_one_hot).T)

通常在同一模型学习期间学习嵌入矩阵,以适应每个对象的最佳向量。我们已经有了对象的数学表示!

如您所见,我们使用了一个热产品,后来又使用了一个矩阵产品。您真正要做的是获取代表该词的 M 列。

在学习过程中,这个 M 将被调整以改进对象的表示,因此损失会下降。

当我们在任何领域(例如NLP)处理单词和句子时,我们都喜欢将单词和句子以向量的形式表示,以便机器可以轻松识别单词并将其用于数学建模。例如,我们的词汇表中有 10 个单词。我们想唯一地表示每个单词。最简单的方法是为每个单词分配一个数字并创建一个包含 10 个元素的向量,并仅激活具有该数字的元素并停用所有其他元素。例如,在我们的词汇表中,我们有狗作为一个词,我们分配了数字 3。所以向量将是这样的

{0,0,1,0,0,0,0,0,0,0}

同样,换句话说,它会激活其他元素。 上面的例子很简单,但是效率很低。假设我们有 100000 个词汇。为了表示 100000 个单词,我们将有 100000 [1*100000] vectors.so 来有效地完成此任务,我们可以使用嵌入。它们以密集(比如只有 32 个元素的向量)形式表示单词。狗可以表示为

{0.24,0.97}

在数学建模方面效率更高,效果更好