【问题标题】:Using pre-trained word embeddings in a keras model?在 keras 模型中使用预训练的词嵌入?
【发布时间】:2019-11-14 17:48:13
【问题描述】:

我正在关注 keras 团队的 github 代码,了解如何使用预训练的词嵌入。我能够理解其中的大部分内容,但我对矢量大小有疑问。我希望有人可以帮助我。

首先我们定义Tokenizer(num_words=MAX_NUM_WORDS)

根据 keras docs forTokenizer() num_words 参数只考虑 MAX_NUM_WORDS - 1 所以如果 MAX_NUM_WORDS=20000 我会有大约 19999 字。

num_words:要保留的最大单词数,基于单词 频率。只会保留最常见的 num_words-1 个单词。

接下来在代码中,我们准备一个基于手套向量的Embedding Matrix。这样做时,我们正在考虑一个大小为 (20001, 100)np.zeros((MAX_NUM_WORDS+1, 100)) 的矩阵。如果我们的词汇表中只有 19999 单词,我不明白为什么要考虑使用 20001 的矩阵。

然后我们将num_words 传递给嵌入层。根据 input_dim 参数的嵌入层文档,它说,

input_dim: int > 0. 词汇的大小,即最大整数索引 + 1。

embedding_layer = Embedding(input_dim=num_words,
                            output_dim=EMBEDDING_DIM,
                            embeddings_initializer=Constant(embedding_matrix),
                            input_length=MAX_SEQUENCE_LENGTH,
trainable=False)

根据Tokenizer()函数,这里我们的词汇量将是19999,对吧?那么为什么我们将20001 传递为input_dim

这是取自该 github 链接的一小段代码。

MAX_NUM_WORDS = 20000
MAX_SEQUENCE_LENGTH = 1000
EMBEDDING_DIR = 100

tokenizer = Tokenizer(num_words=MAX_NUM_WORDS)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)

data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)

# prepare embedding matrix
num_words = MAX_NUM_WORDS + 1
embedding_matrix = np.zeros((num_words, EMBEDDING_DIM))
for word, i in word_index.items():
    if i > MAX_NUM_WORDS:
        continue
    embedding_vector = embeddings_index.get(word)
    if embedding_vector is not None:
        embedding_matrix[i] = embedding_vector

embedding_layer = Embedding(num_words,
                            EMBEDDING_DIM,
                            embeddings_initializer=Constant(embedding_matrix),
                            input_length=MAX_SEQUENCE_LENGTH,
                            trainable=False)

【问题讨论】:

    标签: python python-3.x tensorflow keras


    【解决方案1】:

    我认为你的怀疑是正确的。在代码的this commit 中进行了更改,以保留index = MAX_NUM_WORDS 的单词。在此之前,Tokenizer 上有一个 commit,以使其保留 num_words 单词而不是 num_words - 1 单词。但是Tokenizer的这个变化后来是reverted。所以我猜示例更新的作者可能假设Tokenizer 在提交更新时保留了num_words 字词。

    【讨论】:

      【解决方案2】:

      对于嵌入,输入 dim(以下代码中的 num_words)是词汇表的大小。例如,如果您的数据被整数编码为 0-10 之间的值,那么词汇表的大小将为 11 个单词。这就是将 1 添加到 len(word_index) 和 MAX_NUM_WORDS 的最小值的原因。

      嵌入矩阵将具有词汇大小和向量长度的维度

      embedding_layer = Embedding(num_words,
                                  EMBEDDING_DIM,
                                  embeddings_initializer=Constant(embedding_matrix),
                                  input_length=MAX_SEQUENCE_LENGTH,
                                  trainable=False)
      
      num_words = min(MAX_NUM_WORDS, len(word_index)) + 1
      

      创建了一个简单的标记器来解释这一点。

      t  = Tokenizer(num_words=5)
      fit_text = ["The earth is an awesome place live"]
      t.fit_on_texts(fit_text)
      word_index = t.word_index
      ​
      print('word_index : ',word_index)
      print('len word_index : ',len(t.word_index))
      word_index :  {'the': 1, 'earth': 2, 'is': 3, 'an': 4, 'awesome': 5, 'place': 6, 'live': 7}
      len word_index :  7
      

      在下面的例子中,你只覆盖了一个大小为 4 的词汇表,因为分词器索引从 1 开始。

      embedding_matrix = np.zeros((5, 10))
      embedding_matrix
      array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
             [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]])
      
      for word, i in word_index.items():
          if i < 5:       
              embedding_matrix[i] = [0,1,0,0,0,0,0,0,0,0]
      
      print (embedding_matrix)
      [[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]
      

      在下面的情况下,你需要添加 1 (5+1) 来覆盖大小为 5 的词汇表来覆盖索引 0

      embedding_matrix = np.zeros((6, 10))
      for word, i in word_index.items():
          if i < 6:       
              embedding_matrix[i] = [0,1,0,0,0,0,0,0,0,0]
      
      print (embedding_matrix)
      
      [[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
       [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]]
      

      【讨论】:

      • 我没明白你的意思?请参阅我在上面发布的代码。我正在考虑MAX_NUM_WORDS=20000,然后我将它传递给Tokenizer()。根据标记器文档MAX_NUM_WORDS-1 的话会被保留吗?那么为什么我在构建嵌入矩阵时要添加 + 1 是我的问题?这里我的词汇量是 19,999 对吧??
      • 你是对的,tokenizer 保持 (numwords-1)。但是索引会从 1 开始。当你创建一个嵌入矩阵时,你需要将词汇量加 1 以覆盖索引 0。
      • 我刚刚添加了一个示例代码来解释embedding_matrix。
      • 这正是我的疑问。根据标记器,我们只有 4 个单词,对吗?那么为什么我们需要覆盖 5 的词汇量呢?我们不应该建立嵌入矩阵来覆盖 4 的词汇量吗?这让我很困惑。
      • 请问,当我使用 len(word_index) + 1 时,我得到“层权重形状 (9, 128) 与提供的权重形状 (8, 128) 不兼容”,这意味着我需要将我的零索引的另一个向量添加到我的嵌入矩阵中吗?
      猜你喜欢
      • 1970-01-01
      • 2018-12-21
      • 2020-09-03
      • 1970-01-01
      • 2019-02-07
      • 1970-01-01
      • 1970-01-01
      • 2019-10-27
      • 1970-01-01
      相关资源
      最近更新 更多