嵌入层和密集层有什么区别?
What is the difference between an Embedding Layer and a Dense Layer?
Keras 中 Embedding Layer 的文档说:
Turns positive integers (indexes) into dense vectors of fixed size. eg. [[4], [20]]
-> [[0.25, 0.1], [0.6, -0.2]]
我相信这也可以通过将输入编码为长度 vocabulary_size
的单热向量并将它们输入 Dense Layer.
来实现
嵌入层仅仅是为这个两步过程提供便利,还是在幕后发生了一些更奇妙的事情?
从数学上讲,区别是这样的:
嵌入层执行select操作。在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
您可以通过单热编码模拟具有全连接层的嵌入层,但密集嵌入的重点是避免 单热表示。在 NLP 中,单词词汇量可以达到 100k(有时甚至是一百万)的数量级。最重要的是,通常需要批量处理单词序列。处理一批单词索引序列比一批单热向量序列更有效率。此外,gather
操作本身比矩阵点积更快,无论是前向还是后向传播。
嵌入层更快,因为它本质上等同于进行简化假设的密集层。
想象一个具有这些权重的词到嵌入层:
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]]
A Dense
层会将这些视为 执行矩阵乘法的实际权重 。嵌入层会将这些权重简单地视为一个向量列表,每个向量代表一个词;词汇表中的第 0 个单词是 w[0]
,第一个单词是 w[1]
,等等
举个例子,使用上面的权重和这句话:
[0, 2, 1, 2]
一个天真的基于 Dense
的网络需要将该句子转换为 1-hot 编码
[[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]
并在索引 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]]
所以这是相同的结果,只是以一种希望更快的方式获得。
Embedding
层确实有限制:
- 输入必须是 [0, vocab_length) 范围内的整数。
- 没有偏见。
- 没有激活。
但是,如果您只想将整数编码的单词转换为嵌入,那么 none 这些限制应该很重要。
在这里,我想通过提供更多细节来改进投票答案:
当我们使用嵌入层时,通常是将one-hot个输入向量(稀疏的)减少为更密集的表示。
嵌入层很像 table 查找。 table小的时候速度快
当 table 很大时,table 查找会慢很多。实际上,在这种情况下,我们将使用密集层作为降维器来减少 one-hot 输入而不是嵌入层。
Keras 中 Embedding Layer 的文档说:
Turns positive integers (indexes) into dense vectors of fixed size. eg.
[[4], [20]]
->[[0.25, 0.1], [0.6, -0.2]]
我相信这也可以通过将输入编码为长度 vocabulary_size
的单热向量并将它们输入 Dense Layer.
嵌入层仅仅是为这个两步过程提供便利,还是在幕后发生了一些更奇妙的事情?
从数学上讲,区别是这样的:
嵌入层执行select操作。在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
您可以通过单热编码模拟具有全连接层的嵌入层,但密集嵌入的重点是避免 单热表示。在 NLP 中,单词词汇量可以达到 100k(有时甚至是一百万)的数量级。最重要的是,通常需要批量处理单词序列。处理一批单词索引序列比一批单热向量序列更有效率。此外,gather
操作本身比矩阵点积更快,无论是前向还是后向传播。
嵌入层更快,因为它本质上等同于进行简化假设的密集层。
想象一个具有这些权重的词到嵌入层:
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]]
A Dense
层会将这些视为 执行矩阵乘法的实际权重 。嵌入层会将这些权重简单地视为一个向量列表,每个向量代表一个词;词汇表中的第 0 个单词是 w[0]
,第一个单词是 w[1]
,等等
举个例子,使用上面的权重和这句话:
[0, 2, 1, 2]
一个天真的基于 Dense
的网络需要将该句子转换为 1-hot 编码
[[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]
并在索引 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]]
所以这是相同的结果,只是以一种希望更快的方式获得。
Embedding
层确实有限制:
- 输入必须是 [0, vocab_length) 范围内的整数。
- 没有偏见。
- 没有激活。
但是,如果您只想将整数编码的单词转换为嵌入,那么 none 这些限制应该很重要。
在这里,我想通过提供更多细节来改进投票答案:
当我们使用嵌入层时,通常是将one-hot个输入向量(稀疏的)减少为更密集的表示。
嵌入层很像 table 查找。 table小的时候速度快
当 table 很大时,table 查找会慢很多。实际上,在这种情况下,我们将使用密集层作为降维器来减少 one-hot 输入而不是嵌入层。