Utilisation de word2vec préformé avec LSTM pour la génération de mots
LSTM / RNN peut être utilisé pour la génération de texte. montre la façon d'utiliser des embeddings de mot de gant pré-formé pour le modèle Keras.
- comment utiliser les imbrications de mots Word2Vec préformées avec Keras LSTM modèle? post a aidé.
- Comment prédire / générer mot lorsque le modèle est fourni avec la séquence de mots en entrée?
Exemple d'approche essayé:
# 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')
Code de L'échantillon / psuedocode pour former LSTM et de prédire que ce sera apprécié.
1 réponses
j'ai créé un gist avec un générateur simple qui s'appuie sur votre idée initiale: il s'agit d'un réseau LSTM relié à des embeddings word2vec pré-formés, formés pour prédire le mot suivant dans une phrase. Les données sont le liste de résumés à partir d'arXiv site web.
je vais mettre en évidence les parties les plus importantes ici.
Gensim Word2Vec
Ton code est très bien, sauf pour le nombre d'itérations pour le former. Le par défaut iter=5
semble plutôt faible. De plus, ce n'est certainement pas le goulot d'étranglement -- la formation LSTM prend beaucoup plus de temps. iter=100
regarde mieux.
word_model = gensim.models.Word2Vec(sentences, 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]
la matrice d'intégration des résultats est sauvegardée dans pretrained_weights
array qui a une forme (vocab_size, emdedding_size)
.
Keras modèle
votre code est presque correct, sauf pour la fonction de perte. Puisque le modèle prédit le mot suivant, c'est une tâche de classification, donc la perte devrait être categorical_crossentropy
ou sparse_categorical_crossentropy
. J'ai choisi le ce dernier pour des raisons d'efficacité: de cette façon, il évite l'encodage à chaud, ce qui est assez coûteux pour un grand vocabulaire.
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')
notez qu'il faut passer les poids pré-entraînés à weights
.
préparation des Données
afin de travailler avec sparse_categorical_crossentropy
perte, les deux phrases, et les étiquettes doivent être mot indices. Les phrases courtes doivent être assorties de zéros à la longueur courante.
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])
production d'échantillons
C'est assez simple: le modèle produit le vecteur des probabilités, dont le mot suivant est échantillonné et ajouté à l'entrée. Notez que le texte serait mieux et plus diversifiée, si le mot suivant est échantillonnés plutôt que choisiargmax
. L'échantillonnage aléatoire basé sur la température que j'ai utilisé est décrit ici.
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)
Exemples de texte généré
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
N'a pas trop de sens, mais est capable produire des phrases qui semblent au moins grammaticalement solides (parfois).
Le lien complet exécutable le script.