Keras中的嵌入层(Embedding Layer)文档介绍说:
将正整数(索引)转换为固定大小的密集向量。例如,
[[4], [20]]
->[[0.25, 0.1], [0.6, -0.2]]
我认为这也可以通过将输入编码为长度为vocabulary_size
的独热向量,并将其馈送到Dense Layer中来实现。
嵌入层仅是这个两步过程的便利之处,还是底层进行了更高级的操作呢?
Keras中的嵌入层(Embedding Layer)文档介绍说:
将正整数(索引)转换为固定大小的密集向量。例如,
[[4], [20]]
->[[0.25, 0.1], [0.6, -0.2]]
我认为这也可以通过将输入编码为长度为vocabulary_size
的独热向量,并将其馈送到Dense Layer中来实现。
嵌入层仅是这个两步过程的便利之处,还是底层进行了更高级的操作呢?
想象一下带有这些权重的单词嵌入层:
w = [[0.1, 0.2, 0.3, 0.4],
[0.5, 0.6, 0.7, 0.8],
[0.9, 0.0, 0.1, 0.2]]
一个密集层将把它们视为实际的权重,用于执行矩阵乘法。而嵌入层将简单地将这些权重视为向量列表,每个向量表示一个单词;词汇表中的第0个单词是w[0],第1个是w[1]等等。
[0, 2, 1, 2]
一个天真的基于Dense
的网络需要将该句子转换为1热编码。[[1, 0, 0],
[0, 0, 1],
[0, 1, 0],
[0, 0, 1]]
然后进行矩阵乘法运算
[[1 * 0.1 + 0 * 0.5 + 0 * 0.9, 1 * 0.2 + 0 * 0.6 + 0 * 0.0, 1 * 0.3 + 0 * 0.7 + 0 * 0.1, 1 * 0.4 + 0 * 0.8 + 0 * 0.2],
[0 * 0.1 + 0 * 0.5 + 1 * 0.9, 0 * 0.2 + 0 * 0.6 + 1 * 0.0, 0 * 0.3 + 0 * 0.7 + 1 * 0.1, 0 * 0.4 + 0 * 0.8 + 1 * 0.2],
[0 * 0.1 + 1 * 0.5 + 0 * 0.9, 0 * 0.2 + 1 * 0.6 + 0 * 0.0, 0 * 0.3 + 1 * 0.7 + 0 * 0.1, 0 * 0.4 + 1 * 0.8 + 0 * 0.2],
[0 * 0.1 + 0 * 0.5 + 1 * 0.9, 0 * 0.2 + 0 * 0.6 + 1 * 0.0, 0 * 0.3 + 0 * 0.7 + 1 * 0.1, 0 * 0.4 + 0 * 0.8 + 1 * 0.2]]
=
[[0.1, 0.2, 0.3, 0.4],
[0.9, 0.0, 0.1, 0.2],
[0.5, 0.6, 0.7, 0.8],
[0.9, 0.0, 0.1, 0.2]]
然而,Embedding
层只需查看[0, 2, 1, 2]
,并获取索引为零、二、一和二的层权重即可立即获得结果。
[w[0],
w[2],
w[1],
w[2]]
等于[[0.1, 0.2, 0.3, 0.4],
[0.9, 0.0, 0.1, 0.2],
[0.5, 0.6, 0.7, 0.8],
[0.9, 0.0, 0.1, 0.2]]
因此,这是相同的结果,只是希望以更快的方式获得。
嵌入层
有以下限制:
但是,如果您只想将一个整数编码的单词转换为嵌入,则上述任何限制都不应该再成问题。
数学上,两者的区别在于:
嵌入层执行选择操作。在Keras中,该层等效于:
K.gather(self.embeddings, inputs) # just one matrix
稠密层执行点积运算,加上可选的激活函数:
outputs = matmul(inputs, self.kernel) # a kernel matrix
outputs = bias_add(outputs, self.bias) # a bias vector
return self.activation(outputs) # an activation function
你可以通过使用one-hot编码的全连接层来模拟嵌入层,但密集嵌入的整个重点在于避免one-hot表示。在NLP中,单词词汇量可以达到100k的数量级(有时甚至是百万级别)。此外,通常需要处理一批单词序列。处理单词索引序列的批次比处理一批one-hot向量序列更有效率。而且,gather
操作本身在前向和后向传递中都比矩阵点积快。
在这里,我想通过提供更多细节来改善已经被投票选中的答案:
我们通常使用嵌入层以将稀疏的one-hot输入向量转换为更密集的表现形式。
嵌入层很像一张查找表。当这张表很小时,速度非常快。
但当这张表很大时,查找速度就会变得很慢。实际上,我们可以使用密集层作为尺寸缩减器,来代替在这种情况下使用嵌入层来减少one-hot输入。