在 keras 中使用预训练的 gensim Word2vec 嵌入

Posted

技术标签:

【中文标题】在 keras 中使用预训练的 gensim Word2vec 嵌入【英文标题】:Using pretrained gensim Word2vec embedding in keras 【发布时间】:2019-02-07 03:22:37 【问题描述】:

我已经在 gensim 中训练了 word2vec。在 Keras 中,我想用它来使用该词嵌入来制作句子矩阵。由于存储所有句子的矩阵非常空间和内存效率低下。所以,我想在 Keras 中制作嵌入层来实现这一点,以便它可以在更多层(LSTM)中使用。你能详细告诉我怎么做吗?

PS:这与其他问题不同,因为我使用 gensim 进行 word2vec 训练而不是 keras。

【问题讨论】:

这里如何将 GENSIM 模型合并到 Keras ***.com/a/62747179/10375049 【参考方案1】:

假设您有以下需要编码的数据

docs = ['Well done!',
        'Good work',
        'Great effort',
        'nice work',
        'Excellent!',
        'Weak',
        'Poor effort!',
        'not good',
        'poor work',
        'Could have done better.']

您必须像这样使用 Keras 中的 Tokenizer 对其进行标记并找到 vocab_size

t = Tokenizer()
t.fit_on_texts(docs)
vocab_size = len(t.word_index) + 1

然后你可以把它编码成这样的序列

encoded_docs = t.texts_to_sequences(docs)
print(encoded_docs)

然后您可以填充序列,使所有序列都具有固定长度

max_length = 4
padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post')

然后使用word2vec模型制作嵌入矩阵

# load embedding as a dict
def load_embedding(filename):
    # load embedding into memory, skip first line
    file = open(filename,'r')
    lines = file.readlines()[1:]
    file.close()
    # create a map of words to vectors
    embedding = dict()
    for line in lines:
        parts = line.split()
        # key is string word, value is numpy array for vector
        embedding[parts[0]] = asarray(parts[1:], dtype='float32')
    return embedding

# create a weight matrix for the Embedding layer from a loaded embedding
def get_weight_matrix(embedding, vocab):
    # total vocabulary size plus 0 for unknown words
    vocab_size = len(vocab) + 1
    # define weight matrix dimensions with all 0
    weight_matrix = zeros((vocab_size, 100))
    # step vocab, store vectors using the Tokenizer's integer mapping
    for word, i in vocab.items():
        weight_matrix[i] = embedding.get(word)
    return weight_matrix

# load embedding from file
raw_embedding = load_embedding('embedding_word2vec.txt')
# get vectors in the right order
embedding_vectors = get_weight_matrix(raw_embedding, t.word_index)

一旦你有了嵌入矩阵,你就可以像这样在Embedding 层中使用它

e = Embedding(vocab_size, 100, weights=[embedding_vectors], input_length=4, trainable=False)

这个层可以用来制作这样的模型

model = Sequential()
e = Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=4, trainable=False)
model.add(e)
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
# compile the model
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
# summarize the model
print(model.summary())
# fit the model
model.fit(padded_docs, labels, epochs=50, verbose=0)

所有代码均改编自this awesome blog post。关注它以了解更多关于使用 Glove 进行嵌入的信息

有关使用 word2vec 的信息,请参阅 this 帖子

【讨论】:

如果我的 Word2vec 嵌入是使用 gensim 训练的,它会起作用吗? 我问是因为 gensim 的 word2vec 训练模型不是 txt 文件,而你已经为文本文件编写了 不,是模型文件。但是有一些方法可以将它保存在 .bin 中。我去做。这对它有用吗? 是的。如果有bin文件,可以保存到txt【参考方案2】:

有了新的 Gensim 版本,这很容易:

w2v_model.wv.get_keras_embedding(train_embeddings=False)

你有你的 Keras 嵌入层

【讨论】:

简单优雅 如果您尝试使用 tf.keras 和“纯” keras,这似乎有问题 如果调用这个函数,我还应该使用Tokenizer吗?如果这个嵌入层真的适合Tokenizer 创建的表示,我有点困惑。如果没有,那么我该如何标记文本样本? 好的,我设法找到了答案:您可以从 gensim 模型中提取词索引并提供给分词器:``` 词汇表 = word: vector.index for word, vector in embedding.vocab.items() tk = Tokenizer(num_words=len(vocabulary)) tk.word_index = 词汇 tk.texts_to_sequences(samples) ```【参考方案3】:

我的 gensim 训练 w2v 模型代码。假设在 w2v 模型中训练的所有单词现在都是一个名为 all_words 的列表变量。

from keras.preprocessing.text import Tokenizer
import gensim
import pandas as pd
import numpy as np
from itertools import chain

w2v = gensim.models.Word2Vec.load("models/w2v.model")
vocab = w2v.wv.vocab    
t = Tokenizer()

vocab_size = len(all_words) + 1
t.fit_on_texts(all_words)

def get_weight_matrix():
    # define weight matrix dimensions with all 0
    weight_matrix = np.zeros((vocab_size, w2v.vector_size))
    # step vocab, store vectors using the Tokenizer's integer mapping
    for i in range(len(all_words)):
        weight_matrix[i + 1] = w2v[all_words[i]]
    return weight_matrix

embedding_vectors = get_weight_matrix()
emb_layer = Embedding(vocab_size, output_dim=w2v.vector_size, weights=[embedding_vectors], input_length=FIXED_LENGTH, trainable=False)

【讨论】:

合并数据到底是什么? @AleksandarMakragić 已编辑。 whats all_words,不是 all_word == vocab?

以上是关于在 keras 中使用预训练的 gensim Word2vec 嵌入的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Gensim doc2vec 与预训练的词向量一起使用?

gensim doc2vec 从预训练模型中训练更多文档

如何在 Gensim 的 Word2Vec 中正确使用 get_keras_embedding()?

如何在 Keras 中使用预训练的 CNN 实现连体网络?

在 keras 中微调预训练模型

Keras 使用 TimeDistributed 预训练 CNN