【问题标题】:Keras embedding layers: how do they work?Keras 嵌入层:它们是如何工作的?
【发布时间】:2017-08-03 10:08:58
【问题描述】:

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

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

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

这些embeddings 是如何执行的?

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

我的理解正确吗?

【问题讨论】:

    标签: python machine-learning neural-network keras embedding


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

      它始终用作直接附加到输入的层。

      Sparsedense字编码表示编码的有效性。

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

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

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

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

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

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

      Embedding 层的输出是什么?

      Embedding 层的输出是一个 2D 向量,对于输入的单词序列(输入文档)中的每个单词都有一个嵌入。

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

      【讨论】:

        【解决方案3】:

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

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

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

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

        其中 v 是确定需要翻译哪个单词的 one-hot 向量。 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 将被调整以改善对象的表示,因此损失会下降。

        【讨论】:

        • 一个非常好的详细解释。谢谢!
        【解决方案4】:

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

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

        与其他词类似,它会激活其他元素。 上面的例子很简单,但效率很低。假设我们有 100000 个词汇。为了表示 100000 个单词,我们将有 100000 [1*100000] 个向量。所以为了有效地完成这项任务,我们可以使用嵌入。它们以密集(比如只有 32 个元素的向量)形式表示单词。狗可以表示为

        {0.24,0.97}

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

        【讨论】:

          猜你喜欢
          • 2019-09-15
          • 2017-10-25
          • 2018-08-12
          • 1970-01-01
          • 2019-10-15
          • 2018-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多