我用gensim来建立我的语料库的word2vec嵌入。 目前,我正在使用gensim模型将(填充的)输入句子转换为单词向量。 此向量用作模型的输入。
model = Sequential()
model.add(Masking(mask_value=0.0, input_shape=(MAX_SEQUENCE_LENGTH, dim)))
model.add(Bidirectional(
LSTM(num_lstm, dropout=0.5, recurrent_dropout=0.4, return_sequences=True))
)
...
model.fit(training_sentences_vectors, training_labels, validation_data=validation_data)
在没有keras嵌入层的情况下直接使用单词向量有什么缺点吗?
我目前还通过将输入标记连接到每个单词向量来向输入标记添加其他(单热编码)标记,这种方法有意义吗?
答案 0 :(得分:1)
在当前设置中,缺点是您将无法将单词向量设置为可训练的。您将无法为任务微调模型。
我的意思是,Gensim只学习了“语言模型”。它了解您的语料库及其内容。但是,它不知道如何针对使用keras的任何下游任务进行优化。模型的权重将有助于微调模型,但是,如果您从gensim中提取嵌入,使用它们初始化keras嵌入层,然后将索引而不是单词向量传递给输入层,则可能会提高性能。 。
答案 1 :(得分:0)
有一种优雅的方法可以满足您的需求。
您的解决方案存在的问题是:
(batch_size, MAX_SEQUENCE_LENGTH, dim)
,可能不适合内存。您可以改用(batch_size, MAX_SEQUENCE_LENGTH)
。 keras嵌入层允许您传递单词索引并获取向量。因此,42 -> Embedding Layer -> [3, 5.2, ..., 33]
。
便捷地,gensim的w2v模型具有函数get_keras_embedding
,该函数可以使用经过训练的权重为您创建所需的嵌入层。
gensim_model = # train it or load it
embedding_layer = gensim_model.wv.get_keras_embedding(train_embeddings=True)
embedding_layer.mask_zero = True # No need for a masking layer
model = Sequential()
model.add(embedding_layer) # your embedding layer
model.add(Bidirectional(
LSTM(num_lstm, dropout=0.5, recurrent_dropout=0.4, return_sequences=True))
)
但是,您必须确保数据中单词的索引与word2vec模型的索引相同。
word2index = {}
for index, word in enumerate(model.wv.index2word):
word2index[word] = index
使用上面的word2index
字典将输入数据转换为与gensim模型具有相同的索引。
例如,您的数据可能是:
X_train = [["hello", "there"], ["General", "Kenobi"]]
new_X_train = []
for sent in X_train:
temp_sent = []
for word in sent:
temp_sent.append(word2index[word])
# Add the padding for each sentence. Here I am padding with 0
temp_sent += [0] * (MAX_SEQUENCE_LENGTH - len(temp_sent))
new_X_train.append(temp_sent)
X_train = numpy.as_array(new_X_train)
现在您可以使用X_train
,它将类似于:[[23, 34, 0, 0], [21, 63, 0, 0]]
嵌入层会自动将索引映射到该向量,并在需要时对其进行训练。
我认为这是最好的方法,但是我将深入研究gensim希望如何完成它,并在需要时更新此帖子。