ChatGPT解决这个技术问题 Extra ChatGPT

什么是 Keras 中的嵌入?

Keras 文档并不清楚这实际上是什么。我知道我们可以使用它来将输入特征空间压缩成一个更小的空间。但是从神经设计的角度来看,这是如何做到的呢?它是自动编码器,RBM 吗?

这是一个可以训练的查找表
它只是简单地创建和索引一个权重矩阵;请参阅下面的详细答案(stackoverflow.com/a/53101566/9024698)。
尽管投票最多的答案说它是矩阵乘法,但源代码和其他答案表明实际上它们只是一个可训练的矩阵。输入单词只是选择此矩阵中的相应行。

K
KF2

据我所知,Embedding 层是一个简单的矩阵乘法,将单词转换为对应的单词嵌入。

Embedding 层的权重是形状 (vocabulary_size, embedding_dimension)。对于每个训练样本,它的输入都是整数,代表某些单词。整数在词汇表大小的范围内。嵌入层将每个整数 i 转换为嵌入权重矩阵的第 i 行。

为了以矩阵乘法的形式快速执行此操作,输入整数不存储为整数列表,而是存储为 one-hot 矩阵。因此,输入形状是 (nb_words, words_size),每行有一个非零值。如果将其乘以嵌入权重,您将得到形状中的输出

(nb_words, vocab_size) x (vocab_size, embedding_dim) = (nb_words, embedding_dim)

因此,通过简单的矩阵乘法,您可以将样本中的所有单词转换为相应的单词嵌入。


绝对是一种有效的方法(参见 Semi-Supervised Sequence Learning )。您还可以使用自动编码器学习嵌入,然后将它们用作嵌入层的初始化,以降低神经网络的复杂性(我假设您在嵌入层之后执行其他操作)。
Here 是一篇关于词嵌入及其优势的精彩博文。
在我介绍的情况下,每个训练输入都是一组单词(可以是一个句子)。每个单词都表示为 one-hot 向量并嵌入到密集向量中。这种方法的缺点是,由于输入需要具有恒定长度,因此您的所有句子都需要具有相同数量的单词。另一种选择是 paragraph vectors,它可以将句子、段落甚至文档嵌入到向量中。
Embedding 层只会优化其权重以最小化损失。也许这意味着它会考虑语义相似性,也许不会。你永远不会知道神经网络。如果您想确保嵌入遵循某个公式(例如 w2v),请使用该公式。如果您有足够的数据,您可能需要使用嵌入层并训练嵌入。试试看,看看你是否喜欢结果。
我同意 user36624(下面的答案)。它不是一个简单的矩阵乘法。
O
Outcast

Keras Embedding 层不执行任何矩阵乘法,而只是:

1. 创建一个 (vocabulary_size)x(embedding_dimension) 维度的权重矩阵

2.索引这个权重矩阵

查看源代码以了解类的作用总是很有用的。在这种情况下,我们将看看从名为 Layer 的基础层 class 继承的 class Embedding

(1) - 创建 (vocabulary_size)x(embedding_dimension) 维度的权重矩阵:

这发生在 Embeddingbuild 函数中:

def build(self, input_shape):
    self.embeddings = self.add_weight(
        shape=(self.input_dim, self.output_dim),
        initializer=self.embeddings_initializer,
        name='embeddings',
        regularizer=self.embeddings_regularizer,
        constraint=self.embeddings_constraint,
        dtype=self.dtype)
    self.built = True

如果您查看基类 Layer,您会发现上面的函数 add_weight 只是创建了一个可训练权重矩阵(在本例中为 (vocabulary_size)x(embedding_dimension) 维度) :

def add_weight(self,
               name,
               shape,
               dtype=None,
               initializer=None,
               regularizer=None,
               trainable=True,
               constraint=None):
    """Adds a weight variable to the layer.
    # Arguments
        name: String, the name for the weight variable.
        shape: The shape tuple of the weight.
        dtype: The dtype of the weight.
        initializer: An Initializer instance (callable).
        regularizer: An optional Regularizer instance.
        trainable: A boolean, whether the weight should
            be trained via backprop or not (assuming
            that the layer itself is also trainable).
        constraint: An optional Constraint instance.
    # Returns
        The created weight variable.
    """
    initializer = initializers.get(initializer)
    if dtype is None:
        dtype = K.floatx()
    weight = K.variable(initializer(shape),
                        dtype=dtype,
                        name=name,
                        constraint=constraint)
    if regularizer is not None:
        with K.name_scope('weight_regularizer'):
            self.add_loss(regularizer(weight))
    if trainable:
        self._trainable_weights.append(weight)
    else:
        self._non_trainable_weights.append(weight)
    return weight

(2) - 索引这个权重矩阵

这发生在 Embeddingcall 函数中:

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

此函数返回 Embedding 层的输出,即 K.gather(self.embeddings, inputs)tf.keras.backend.gather 的确切作用是根据应该是正整数列表的 inputs 索引权重矩阵 self.embeddings(参见上面的 build 函数)。

可以检索这些列表,例如,如果您将文本/单词输入传递给 Keras 的 one_hot 函数,该函数将文本编码为大小为 n 的单词索引列表(这不是一种热编码 - 另请参阅此示例以获取更多信息信息:https://machinelearningmastery.com/use-word-embedding-layers-deep-learning-keras/)。

因此,仅此而已。没有矩阵乘法。

相反,Keras Embedding 层之所以有用,是因为它恰好避免了执行矩阵乘法,因此它节省了一些计算资源。

否则,您可以只使用 Keras Dense 层(在对输入数据进行编码之后)来获得可训练权重矩阵((vocabulary_size)x(embedding_dimension) 维度),然后只需进行乘法运算即可得到与 Embedding 层的输出完全相同的输出。


y
yannis

在 Keras 中,Embedding不是简单的矩阵乘法层,而是一个查找表层(参见下面的调用函数或原始的 definition)。

def call(self, inputs):
    if K.dtype(inputs) != 'int32':
        inputs = K.cast(inputs, 'int32')
    out = K.gather(self.embeddings, inputs)
    return out

它所做的是将inputs中的每个已知整数n映射到一个可训练的特征向量W[n],其维度就是所谓的嵌入特征长度。


好吧,当您将一组单热表示的向量与矩阵相乘时,乘积就变成了查找。所以Embedding确实是一个矩阵乘法。
除了没有地方 keras 执行这种乘法。它只是定义“嵌入 = 可训练矩阵”,并使用输入索引从矩阵中收集单词。
因此,这种嵌入通过简单地不创建任何单热版本的输入来节省大量内存。
A
Ali Mirzaei

简单来说(从功能的角度来看),它是一个单热编码器和全连接层。层权重是可训练的。