LSTM/RNN peut être utilisé pour la génération de texte. This montre comment utiliser les incorporations GloVe Word pré-formées pour le modèle Keras.
Exemple d'approche essayée:
# 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')
Un exemple de code/pseudo-code pour former le LSTM et prévoir sera apprécié.
J'ai créé un Gist avec un générateur simple qui s'appuie sur votre idée initiale: c'est un réseau LSTM câblé aux intégrations Word2vec pré-entraînées, formé pour prédire le prochain mot dans une phrase. Les données sont les liste des résumés du site Web arXiv .
Je vais souligner ici les parties les plus importantes.
Votre code est correct, sauf pour le nombre d'itérations pour le former. Le défaut iter=5
semble plutôt faible. En outre, 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 résultante est enregistrée dans pretrained_weights
tableau qui a une forme (vocab_size, emdedding_size)
.
Votre code est presque correct, à l'exception de la fonction de perte. Comme le modèle prédit le prochain mot, il s'agit d'une tâche de classification, d'où la perte devrait être categorical_crossentropy
ou sparse_categorical_crossentropy
. J'ai choisi ce dernier pour des raisons d'efficacité: de cette façon, il évite l'encodage à chaud, ce qui est assez cher pour un gros 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 le passage des poids pré-entraînés à weights
.
Pour travailler avec sparse_categorical_crossentropy
perte, les phrases et les étiquettes doivent être des indices Word. Les phrases courtes doivent être complétées par des zéros à la longueur commune.
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])
C'est assez simple: le modèle génère le vecteur de probabilités, dont le prochain mot est échantillonné et ajouté à l'entrée. Notez que le texte généré serait meilleur et plus diversifié si le prochain mot est échantillonné , plutôt que choisi comme argmax
. 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)
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
Cela n'a pas trop de sens, mais est capable de produire des phrases qui semblent au moins grammaticalement saines (parfois).
Le lien vers le script exécutable complet .