【问题标题】:Tensorflow Embedding Layer Vocabulary SizeTensorflow 嵌入层词汇量大小
【发布时间】:2020-08-19 22:10:46
【问题描述】:

我正在学习 Tensorflow,并且遇到了 tensorflow 中的 Embedding 层,用于学习自己的词嵌入。该层采用以下参数:

keras.layers.Embedding(input_dim, 
                       output_dim, 
                       embeddings_initializer='uniform',
                       embeddings_regularizer=None, 
                       activity_regularizer=None, 
                       embeddings_constraint=None, 
                       mask_zero=False, 
                       input_length=None)

“输入昏暗”应与词汇表大小相同,即唯一词。如果我想将词汇表限制为前 25000 个最常用的单词 - 我应该怎么做?

我是否可以简单地将“input_dim”更改为 25000,或者我是否必须通过我的语料库并将前 25000 个单词之外的任何单词替换为例如标记?

【问题讨论】:

    标签: python tensorflow word-embedding


    【解决方案1】:

    实际上,如果你使用tensorflow.keras,你必须确保你的语料库中的tokens不要超过words_size或者嵌入层的input_dim,否则会报错。

    如果您使用keras,那么您可以在嵌入层中更改input_dim,而无需更改语料库或令牌中的任何内容。 keras 将用 zero 向量替换词汇表之外的标记。

    首先,如果使用tensorflow.keras会报错。

    张量流

    from tensorflow.keras.models import Model
    from tensorflow.keras.layers import Embedding, Input
    import numpy as np
    
    ip = Input(shape = (3,))
    emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
    
    model = Model(ip, emb)
    input_array = np.array([[5, 3, 1], [1, 2, 3]]) # out of vocabulary
    
    model.compile("rmsprop", "mse")
    
    output_array = model.predict(input_array)
    
    print(output_array)
    
    print(output_array.shape)
    
    model.summary()
    

    但如果我使用 keras 2.3.1,我不会收到任何错误。

    keras 2.3.1

    from keras.models import Model
    from keras.layers import Embedding, Input
    import numpy as np
    
    ip = Input(shape = (3,))
    emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
    
    model = Model(ip, emb)
    input_array = np.array([[5, 3, 1], [1, 2, 3]])
    
    model.compile("rmsprop", "mse")
    
    output_array = model.predict(input_array)
    
    print(output_array)
    
    print(output_array.shape)
    
    model.summary()
    

    keras 对嵌入层有不同的实现。为了验证这一点,让我们去 keras 嵌入层。

    https://github.com/keras-team/keras/blob/master/keras/layers/embeddings.py#L16

    现在让我们看看调用函数。

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

    N.B:如果你想要 keras 2.3.1 的确切源代码,请到这里下载源代码:https://github.com/keras-team/keras/releases

    但是如果我们去实现 tensorflow,那就不一样了。

    https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/embedding_ops.py

    只是为了验证一下,调用函数写的不一样。

      def call(self, inputs):
        dtype = K.dtype(inputs)
        if dtype != 'int32' and dtype != 'int64':
          inputs = math_ops.cast(inputs, 'int32')
        out = embedding_ops.embedding_lookup(self.embeddings, inputs)
        return out
    

    让我们像以前一样设计一个简单的网络并观察权重矩阵。

    from keras.models import Model
    from keras.layers import Embedding, Input
    import numpy as np
    
    ip = Input(shape = (3,))
    emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
    
    model = Model(ip, emb)
    input_array = np.array([[5, 3, 1], [1, 2, 3]])
    
    model.compile("rmsprop", "mse")
    
    output_array = model.predict(input_array)
    
    print(output_array)
    
    print(output_array.shape)
    
    model.summary()
    

    模型给出以下输出。

    [[[0. 0.]
      [0. 0.]
      [0. 0.]]
    
     [[0. 0.]
      [0. 0.]
      [0. 0.]]]
    (2, 3, 2)
    Model: "model_18"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_21 (InputLayer)        (None, 3)                 0         
    _________________________________________________________________
    embedding_33 (Embedding)     (None, 3, 2)              2         
    =================================================================
    Total params: 2
    Trainable params: 2
    Non-trainable params: 0
    

    好的,我们得到了一堆零,但默认的 weight_initializer 不是零!

    那么,现在让我们观察一下权重矩阵吧。

    import keras.backend as K
    
    w = model.layers[1].get_weights()
    print(w)
    
    
    [array([[ 0.03680499, -0.04904002]], dtype=float32)]
    

    其实也不是全零。

    那么,为什么我们会得到零?

    让我们改变对模型的输入。

    作为 input_dim = 1 的唯一词汇索引,为 0。让我们将 0 作为输入之一传递。

    from keras.models import Model
    from keras.layers import Embedding, Input
    import numpy as np
    
    ip = Input(shape = (3,))
    emb = Embedding(1, 2, trainable=True, mask_zero=True)(ip)
    
    model = Model(ip, emb)
    input_array = np.array([[5, 0, 1], [1, 2, 0]])
    
    model.compile("rmsprop", "mse")
    
    output_array = model.predict(input_array)
    
    print(output_array)
    
    print(output_array.shape)
    
    model.summary()
    

    现在,我们通过 0 的位置得到非零向量。

    [[[ 0.          0.        ]
      [-0.04339869 -0.04900574]
      [ 0.          0.        ]]
    
     [[ 0.          0.        ]
      [ 0.          0.        ]
      [-0.04339869 -0.04900574]]]
    (2, 3, 2)
    Model: "model_19"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #   
    =================================================================
    input_22 (InputLayer)        (None, 3)                 0         
    _________________________________________________________________
    embedding_34 (Embedding)     (None, 3, 2)              2         
    =================================================================
    Total params: 2
    Trainable params: 2
    Non-trainable params: 0
    

    简而言之,Keras 使用零向量映射任何词汇表外的词索引,这是合理的,因为对于那些位置,前向传递将确保所有贡献都是 NIL(尽管偏差可能会起作用)。这有点违反直觉,因为将词汇标记传递给模型似乎是一种开销(而不是仅仅在预处理步骤中删除它们)和不好的做法,但它是一个很好的解决方法来测试不同的 input_dim 而无需重新- 计算代币。

    【讨论】:

    • Zabir,非常感谢 - 这非常有帮助!我很欣赏如此全面的答案。 tensorflow.keras 和 keras 如此不同有什么原因吗?
    • 它们并没有太大的不同,但绝对 tensorflow.keras 维护得更好。 keras 在很多情况下都有不同的实现,所以即使语法几乎相同,也会有一些不一致。
    • 谢谢,扎比尔。我是否也可以使用 TensorFlow Tokenizer 类来预处理文本,并使用 OOV_token 设置“num_words”(上例中为 25000)??
    • 是的,如果你使用keras而不是tensorflow.keras
    猜你喜欢
    • 2020-06-03
    • 1970-01-01
    • 2020-09-29
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-06
    • 2020-03-02
    相关资源
    最近更新 更多