在keras模型中使用预训练的单词嵌入?

时间:2019-07-04 03:25:19

标签: python python-3.x tensorflow keras

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

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

根据Tokenizer()的keras文档编码,仅考虑MAX_NUM_WORDS - 1来考虑MAX_NUM_WORDS=20000,所以如果19999我会在{{ 1}}个单词。

  

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

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

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

  

input_dim :整数>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)

根据19999函数,我们的词汇量是Tokenizer()吗?那么为什么我们将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)

2 个答案:

答案 0 :(得分:1)

对于嵌入,输入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.]]

答案 1 :(得分:1)

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