使用带有 LSTM 的预训练 word2vec 进行单词生成
Posted
技术标签:
【中文标题】使用带有 LSTM 的预训练 word2vec 进行单词生成【英文标题】:Using pre-trained word2vec with LSTM for word generation 【发布时间】:2017-06-23 05:05:27 【问题描述】:LSTM/RNN 可用于文本生成。 This 展示了将预训练的 GloVe 词嵌入用于 Keras 模型的方法。
-
如何将预训练的 Word2Vec 词嵌入与 Keras LSTM 结合使用
模型? This 帖子确实有帮助。
当模型以单词序列作为输入时,如何预测/生成下一个单词?
尝试的示例方法:
# Sample code to prepare word2vec word embeddings
import gensim
documents = ["Human machine interface for lab abc computer applications",
"A survey of user opinion of computer system response time",
"The EPS user interface management system",
"System and human system engineering testing of EPS",
"Relation of user perceived response time to error measurement",
"The generation of random binary unordered trees",
"The intersection graph of paths in trees",
"Graph minors IV Widths of trees and well quasi ordering",
"Graph minors A survey"]
sentences = [[word for word in document.lower().split()] for document in documents]
word_model = gensim.models.Word2Vec(sentences, size=200, min_count = 1, window = 5)
# Code tried to prepare LSTM model for word generation
from keras.layers.recurrent import LSTM
from keras.layers.embeddings import Embedding
from keras.models import Model, Sequential
from keras.layers import Dense, Activation
embedding_layer = Embedding(input_dim=word_model.syn0.shape[0], output_dim=word_model.syn0.shape[1], weights=[word_model.syn0])
model = Sequential()
model.add(embedding_layer)
model.add(LSTM(word_model.syn0.shape[1]))
model.add(Dense(word_model.syn0.shape[0]))
model.add(Activation('softmax'))
model.compile(optimizer='sgd', loss='mse')
训练 LSTM 和预测的示例代码/伪代码将不胜感激。
【问题讨论】:
这里如何将 GENSIM 模型合并到 Keras ***.com/a/62747179/10375049 【参考方案1】:我创建了一个gist,它带有一个基于您最初想法的简单生成器:它是一个连接到预先训练的 word2vec 嵌入的 LSTM 网络,经过训练可以预测句子中的下一个单词。数据为list of abstracts from arXiv website。
我将在这里强调最重要的部分。
Gensim Word2Vec
您的代码很好,除了训练它的迭代次数。默认的iter=5
似乎相当低。此外,这绝对不是瓶颈——LSTM 训练需要更长的时间。 iter=100
看起来更好。
word_model = gensim.models.Word2Vec(sentences, vector_size=100, min_count=1,
window=5, iter=100)
pretrained_weights = word_model.wv.syn0
vocab_size, emdedding_size = pretrained_weights.shape
print('Result embedding shape:', pretrained_weights.shape)
print('Checking similar words:')
for word in ['model', 'network', 'train', 'learn']:
most_similar = ', '.join('%s (%.2f)' % (similar, dist)
for similar, dist in word_model.most_similar(word)[:8])
print(' %s -> %s' % (word, most_similar))
def word2idx(word):
return word_model.wv.vocab[word].index
def idx2word(idx):
return word_model.wv.index2word[idx]
结果嵌入矩阵被保存到pretrained_weights
数组中,该数组的形状为(vocab_size, emdedding_size)
。
Keras 模型
您的代码几乎是正确的,除了损失函数。由于模型预测下一个词,这是一个分类任务,因此损失应该是categorical_crossentropy
或sparse_categorical_crossentropy
。出于效率原因,我选择了后者:这样可以避免一次性编码,这对于大量词汇来说是相当昂贵的。
model = Sequential()
model.add(Embedding(input_dim=vocab_size, output_dim=emdedding_size,
weights=[pretrained_weights]))
model.add(LSTM(units=emdedding_size))
model.add(Dense(units=vocab_size))
model.add(Activation('softmax'))
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy')
注意将预训练的权重传递给weights
。
数据准备
为了使用sparse_categorical_crossentropy
loss,句子和标签都必须是单词索引。短句必须用零填充到共同长度。
train_x = np.zeros([len(sentences), max_sentence_len], dtype=np.int32)
train_y = np.zeros([len(sentences)], dtype=np.int32)
for i, sentence in enumerate(sentences):
for t, word in enumerate(sentence[:-1]):
train_x[i, t] = word2idx(word)
train_y[i] = word2idx(sentence[-1])
样本生成
这非常简单:模型输出概率向量,其中下一个词被采样并附加到输入。请注意,如果下一个单词是sampled,而不是像argmax
那样picked,生成的文本会更好、更多样化。我使用的基于温度的随机采样是described here。
def sample(preds, temperature=1.0):
if temperature <= 0:
return np.argmax(preds)
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
def generate_next(text, num_generated=10):
word_idxs = [word2idx(word) for word in text.lower().split()]
for i in range(num_generated):
prediction = model.predict(x=np.array(word_idxs))
idx = sample(prediction[-1], temperature=0.7)
word_idxs.append(idx)
return ' '.join(idx2word(idx) for idx in word_idxs)
生成文本示例
deep convolutional... -> deep convolutional arithmetic initialization step unbiased effectiveness
simple and effective... -> simple and effective family of variables preventing compute automatically
a nonconvex... -> a nonconvex technique compared layer converges so independent onehidden markov
a... -> a function parameterization necessary both both intuitions with technique valpola utilizes
没有太多意义,但能够产生至少在语法上看起来不错的句子(有时)。
complete runnable script 的链接。
【讨论】:
我的印象是keras.layers.Embedding
和 weights
的格式如果你检查这个 (keras.io/layers/embeddings) 和这个 (github.com/tensorflow/tensorflow/issues/14392) 就会被弃用
@PoeteMaudit 不推荐使用。 weights
参数由基类 Layer
支持,因此所有层 (source code) 都自动支持。从 2017 年开始,这也是一种推荐传递权重的方式 (source)。 AFAIK,它仍然是。但你是对的,embeddings_initializer
也受支持。感谢您的反对!
感谢您的回答。我希望你是对的,weights
参数也受支持(但也是Trainable
参数?)。老实说,我只是对你的帖子投了反对票,否则你可能不会关心我的评论。如果我现在可以回来,那么我会这样做,但您必须编辑 *** 的答案才能让我这样做。
我相信答案中的代码有效,但如果您觉得有些细节也值得一提,请继续编辑。这里没问题。
说实话,我什至没有测试weights
参数当前是否有效。我刚刚看到这个人的帖子,他声称它不起作用。在您的帖子中,您最好在末尾添加至少一个更新说明,以告知读者此(潜在)更改。以上是关于使用带有 LSTM 的预训练 word2vec 进行单词生成的主要内容,如果未能解决你的问题,请参考以下文章