LSTM Языковая модель уровня Word PTB (проблемы со временем обучения) - PullRequest
0 голосов
/ 06 августа 2020

Моя задача - построить модель предсказания следующего слова как для французского, так и для английского sh. Некоторое время назад я нашел статью, описывающую регуляризацию отсева на архитектурах LSTM, что привело к заключительному недоумению около 114 на нерегуляризованной LSTM и около 70 на большой регуляризованной модели.

Вот репозиторий github реализация небольшой нерегуляризованной модели: https://github.com/tmatha/lstm

Моя модель в основном имитирует ту же архитектуру, но поскольку мне нужен метод model.predict, и я хотел бы сохранить модель, у меня есть реализовал то же самое, используя слои keras, например:

def lstm_model(seq_length, vocab_size):
    print('Build LSTM model.')
    model = Sequential()
    model.add(LSTM(rnn_size, input_shape=(seq_length, vocab_size), return_sequences=True, 
    kernel_initializer = tf.random_uniform_initializer(minval=-0.1,maxval=0.1)))
    #model.add(Dropout(0.5))
    #model.add(LSTM(rnn_size, return_sequences = True))
    #model.add(Dropout(0.5))
    model.add(LSTM(rnn_size))
    #model.add(Dropout(0.5))
    model.add(Dense(rnn_size, activation='relu', kernel_initializer = tf.random_uniform_initializer(minval=-0.1,maxval=0.1)))
    model.add(Dense(vocab_size, activation='softmax'))
    
    optimizer = Adam(lr=learning_rate)
    callbacks=[EarlyStopping(patience=2, monitor='val_loss')]
    model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=[categorical_accuracy])
    return model

Вот как я обучаю свою модель:

callbacks=[EarlyStopping(patience=4, monitor='val_loss'),
           ModelCheckpoint(filepath='' + "/" + 'my_model_gen_sentences_lstm.{epoch:02d}-{val_loss:.2f}.hdf5',\
                           monitor='val_loss', verbose=0, mode='auto', period=2)]

(sentences, next_words), (sentences_test, next_words_test) = shuffle_and_split_training_set(
        sentences, next_words
    )

history = md.fit(generator(sentences, next_words, batch_size),
                        steps_per_epoch=int(len(sentences)/batch_size) + 1,
                        epochs=num_epochs,
                        callbacks = callbacks,
                        validation_data=generator(sentences_test,next_words_test,batch_size),
                        validation_steps=int(len(sentences_test)/batch_size) + 1)

Для справки, вот мой код генератора:

def generator(sentence_list, next_word_list, batch_size):
    index = 0
    while True:
        x = np.zeros((batch_size, WORD_LENGTH, len(unique_words)), dtype=np.bool)
        y = np.zeros((batch_size, len(unique_words)), dtype=np.bool)
        for i in range(batch_size):
            for t, w in enumerate(sentence_list[index % len(sentence_list)]):
                x[i, t, unique_word_index[w]] = 1
            y[i, unique_word_index[next_word_list[index % len(sentence_list)]]] = 1
            index = index + 1
        yield x, y

Используя ту же предварительную обработку (токенизацию и все) с французскими текстовыми данными объемом 5 МБ, с репозиторием github я могу тренироваться на графическом процессоре Colab примерно за 15-20 минут, используя последовательности длиной 20, но с моим кодом, если я установил последовательность длина до 20 Я легко беру более 1 часа на эпоху.

Я не понимаю, почему мой код занимает так много времени на одном и том же наборе данных и sa мне GPU. Если я использую последовательность длиной 5, я могу тренироваться (около 10-12 часов) и в итоге получаю точность только 0,3 (в лучшем случае), тогда как с кодом github в том же наборе данных я могу легко достичь лучших результатов в 20 минут.

Также часто я замечал, что у меня не только проблема с конвергенцией (с точки зрения потерь, которые не уменьшаются или не уменьшаются медленно), но и моя точность проверки снижается с увеличением количества эпох, что странно. Я предположил, что моя проблема связана с набором данных (недостаточно похожих последовательностей), но даже с набором данных PTB у меня такая же проблема, поэтому я исключил эту возможность.

Если бы кто-нибудь мог мне помочь с этим, это было бы здорово! В качестве альтернативы, как мне включить в код github метод прогнозирования и сохранения класса, чтобы получить все, что я хочу, из моей модели?

Вот текущие гиперпараметры:

#Hyperparam tuning 

rnn_size = 200 # size of RNN
batch_size = 20 # minibatch size
seq_length = 6 # sequence length
num_epochs = 20 # number of epochs
learning_rate = 1. #learning rate
sequences_step = 1 #step to create sequences
vocab_size = len(unique_words) #this is 2090

...