Использование предварительно подготовленного word2vec с LSTM для генерации слов

LSTM/RNN может использоваться для генерации текста. В этом показан способ использования предварительно подготовленных словесных вложений GloVe для модели Keras.

  • Как использовать предварительно подготовленные словарные вставки Word2Vec с Keras LSTM модель? Это сообщение помогло.
  • Как предсказать/сгенерировать следующее слово, когда модель снабжена последовательностью слов в качестве ее ввода?

Примерный подход:

# 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')

Пример кода /psuedocode для обучения LSTM и прогнозирования будет оценен.

Ответы

Ответ 1

Я создал суть с простым генератором, который строится поверх вашей первоначальной идеи: это сеть LSTM, подключенная к предварительно подготовленным вложениям word2vec, обученная предсказать следующее слово в предложении. Данные - это список тезисов с сайта arXiv.

Здесь я расскажу о наиболее важных частях.

Gensim Word2Vec

Ваш код в порядке, за исключением количества итераций для его обучения. Значение по умолчанию iter=5 выглядит довольно низким. Кроме того, это определенно не узкое место - обучение LSTM занимает гораздо больше времени. iter=100 выглядит лучше.

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]

Матрица внедрения результата сохраняется в массив 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, оба предложения и метки должны быть индексами слов. Короткие предложения должны быть дополнены нулями до общей длины.

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

Создание образца

Это довольно прямолинейно: модель выводит вектор вероятностей, из которых следующее слово отбирается и добавляется к входу. Обратите внимание, что сгенерированный текст будет лучше и разнообразнее, если будет выбрано следующее слово, а не выбрано как argmax. Здесь описывается случайная выборка, основанная на температуре.

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

Не имеет особого смысла, но способен вырабатывать предложения, которые выглядят как минимум грамматически звуковыми (иногда).

Ссылка на полный исполняемый скрипт.