web-dev-qa-db-fra.com

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. This montre comment utiliser les incorporations GloVe Word pré-formées pour le modèle Keras.

  1. Comment utiliser les incorporations Word2Vec Word pré-formées avec le modèle Keras LSTM? Ce message a aidé.
  2. Comment prédire/générer le prochain mot lorsque le modèle est fourni avec la séquence de mots comme entrée?

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é.

21
Vishal Shukla

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.

Gensim Word2Vec

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).

Modèle Keras

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.

Préparation des données

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])

Génération d'échantillon

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)

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

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 .

29
Maxim