Рубрики
Без рубрики

Прикладное введение в LSTMS для генерации текста – использование KERAS и GPU-с поддержкой Kaggle Kaggle

Автор оригинала: FreeCodeCapm Team.

Меган Рисдал

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

С Kaggle Учить , Керас Документация и прохладные данные натурального языка из FreeCodecamp У меня было все, что мне нужно было продвинуться от Случайные леса рецидивирующие нейронные сети.

В этом сообщении я покажу вам, как я использовал текст от FreeCodecamp’s Gitter Chat Logs DataSet Опубликовано на DataSets Kaggle для подготовки сети LSTM, которая генерирует новый вывод текста.

Вы можете найти весь мой воспроизводимый код в этом Ядро ноутбука Python Отказ

Теперь, когда вы можете использовать GPUS В ядрах – Kaggle’s, облачная размещенная платформа ноутбука – с 6 часов времени выполнения Вы можете тренировать гораздо больше вычислительно интенсивных моделей, чем когда-либо прежде, на Kaggle.

Я буду использовать GPU для обучения модели в этой ноутбуке. (Вы можете запросить GPU для вашей сессии, нажав на вкладку «Настройки» из редактора ядра.)

import tensorflow as tfprint(tf.test.gpu_device_name())# See https://www.tensorflow.org/tutorials/using_gpu#allowing_gpu_memory_growthconfig = tf.ConfigProto()config.gpu_options.allow_growth = True

Я буду использовать текст из одного из самых плодовитых идентификаторов пользователей канала в качестве учебных данных. Есть две части к этой ноутбуке:

  1. Чтение, исследуя и подготовка данных
  2. Обучение LSTM на журналах чата одного пользователя пользователя и генерация нового текста в качестве вывода

Вы можете следить, просто прочитав ноутбук или вы можете вилить его (Нажмите «Fork Notebook») и запустите сами клетки, чтобы узнать, какая каждая часть делает интерактивно. К концу вы узнаете Как отформатировать текстовые данные в качестве входа на модель LSHM на уровне символов, реализованную в KERAS И в свою очередь используйте прогнозы уровня характера модели для Создание новых последовательностей текста Отказ

Перед тем, как я попаду в код, что такое LSTM (длинная краткосрочная память ») в любом случае?

В этом руководстве мы возьмем практический подход к реализации этого аромата рецидивирующей нейронной сети, особенно оснащенной для обработки зависимостей на более длительные расстояния (включая те, которые вы получаете с языком) в KERAS, глубокой структуре обучения.

Если вы хотите просмотреть больше теоретических недостатков, я рекомендую проверить этот отличный пост блога, Понимание сети LSTM Кристофер Ола.

Часть одна: подготовка данных

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

Две хорошие вещи о следующем в этом учебном пособии, используя ядра, заключается в том, что а) я постараюсь дать вам удары в данные на каждом значении; и 2) вы всегда можете Вилка это тетрадь А? бум? У вас есть копия моей среды, данные, Docker Image, и все без загрузки или устанавливается не требуется. Особенно, если у вас есть опыт установки CUDA, чтобы использовать графический процессор для глубокого обучения, вы будете признателен за то, как у вас замечательно настроить среду для вас.

Читать данные

import pandas as pdimport numpy as np# Read in only the two columns we need chat = pd.read_csv('../input/freecodecamp_casual_chatroom.csv', usecols = ['fromUser.id', 'text'])
# Removing user id for CamperBotchat = chat[chat['fromUser.id'] != '55b977f00fc9f982beab7883'] chat.head()

Выглядит неплохо!

Исследуйте данные

На моем сюжете ниже вы можете увидеть количество сообщений от десяти самых активных участников чата по их идентификатору пользователя в Gitter FreeCodeCamp:

import matplotlib.pyplot as pltplt.style.use('fivethirtyeight')f, g = plt.subplots(figsize=(12, 9))chat['fromUser.id'].value_counts().head(10).plot.bar(color="green")g.set_xticklabels(g.get_xticklabels(), rotation=25)plt.title("Most active users in freeCodeCamp's Gitter channel")plt.show(g)

Итак, UserID 55A7C9E08A7B72F55C3F991E является наиболее активным пользователем в канале с более чем 140 000 сообщений. Мы будем использовать их сообщения для обучения LSTM для генерации романа 55A7C9E08A7B72F55C3F991E – подобные предложения. Но сначала давайте посмотрим на первые несколько сообщений от 55A7C9E08A7B72F55C3F991E Чтобы получить смысл для того, о чем они общаются:

chat[chat['fromUser.id'] == "55a7c9e08a7b72f55c3f991e"].text.head(20)

Я вижу слова и фразы, такие как «Документация», «Парная кодировка», «Bash», «Bootstrap», «CSS» и т. Д. И я могу принимать только предложение, начинающиеся «со всеми различными рамками …», относятся к JavaScript Отказ Да, звучит как они находятся на тему, насколько FreeCodecamp идет. Поэтому мы ожидаем, что наши новые приговоры примерно подобно этому, если мы успешны.

Подготовьте данные последовательности для ввода в LSTM

Сейчас у нас есть DataFrame с столбцами, соответствующими идентификаторами пользователя и текста сообщения, где каждая строка соответствует одному сообщению. Это довольно далеко от 3D-формы, входной слой нашей сети LSTM требует: model.add (lstm (batch_size, input_shape = (time_steps, htain))) где batch_size это количество последовательностей в каждом образце (может быть одним или несколькими), time_steps Размер наблюдений в каждом образце и Особенности Это количество возможных наблюдаемых функций (то есть символов в нашем случае).

Итак, как мы получаем от DataFrame для последовательности данных в правильной форме? Я сломаю это на три шага:

  1. Поднимите данные, чтобы сформировать корпус
  2. Формат корпус из # 1 в массивы полуопределенных последовательностей равномерной длины и следующих символов
  3. Представляют данные последовательности из # 2, как редкие логические тензоры

Поднимите данные, чтобы сформировать корпус

В следующих двух ячейках мы схватим только сообщения от 55A7C9E08A7B72F55C3F991E ( 'fromuser.id' ) Чтобы поднять данные и свернуть вектор строк в одну строку. Поскольку нам все равно, если наша модель генерирует текст с правильной капитализацией, мы используем Tollower () Отказ Это дает модель по меньшей измерении, чтобы узнать.

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

user = chat[chat['fromUser.id'] == '55a7c9e08a7b72f55c3f991e'].textn_messages = len(user)n_chars = len(' '.join(map(str, user)))print("55a7c9e08a7b72f55c3f991e accounts for %d messages" % n_messages)print("Their messages add up to %d characters" % n_chars)
sample_size = int(len(user) * 0.2)user = user[:sample_size]user = ' '.join(map(str, user)).lower()user[:100] # Show first 100 characters

Форматируйте корпус в массивы полуопределенных последовательностей равномерной длины и следующих символов

Остальная часть используемого здесь пристраивается с Этот пример скрипта Первоначально написано Cholet François Cholet (автор Keras and Kaggler), чтобы подготовить данные в правильном формате для обучения LSTM. Поскольку мы тренируем модель персонажа, мы связываем уникальные символы (такие как «A», «B», «C», …) до числовых показателей в ячейке ниже. Если вы перезагрузите этот код, нажав «Форк ноутбук» Вы можете распечатать все используемые символы.

chars = sorted(list(set(user)))print('Count of unique characters (i.e., features):', len(chars))
char_indices = dict((c, i) for i, c in enumerate(chars))indices_char = dict((i, c) for i, c in enumerate(chars))

Этот следующий шаг клетки дает нам массив, Предложения состоит из Maxlen (40) Последовательности символов, расточенные на шагах из 3 символов из нашего корпуса Пользователь и next_chars , массив одного персонажа из Пользователь на I + Maxlen для каждого Я Отказ Я напечатал первые 10 строк в массиве, чтобы вы могли видеть, что мы ограничиваем корпус в частично перекрывающуюся, равную длину «предложения».

maxlen = 40step = 3sentences = []next_chars = []for i in range(0, len(user) - maxlen, step):    sentences.append(user[i: i + maxlen])    next_chars.append(user[i + maxlen])print('Number of sequences:', len(sentences), "\n")print(sentences[:10], "\n")print(next_chars[:10])

Вы можете посмотреть, как следующий персонаж после первой последовательности 'Привет народ. Просто делаю новый Signee Stuf ' это персонаж F закончить слово «вещи». И следующий символ после последовательности 'близкие. Просто делаю новые знаки. ' это персонаж H Начать слово «Привет». Таким образом, теперь должно быть понятно, как next_chars Является ли «этикетки данных» или наземная правда для наших последовательностей в Предложения И наша модель, обученная этим меченным данным, сможет сгенерировать Новые следующие символы как прогнозы даны последовательность ввода.

Представляют данные последовательности как редкие логические тензоры

Следующая ячейка займет несколько секунд, если вы Следуя в интерактивном режиме в ядре Отказ Мы создаем редкие логические тензоры х и y Кодирование функций уровня символов от Предложения и next_chars использовать в качестве входных данных к модели, которую мы тренируем. Форма, которую мы в конечном итоге будем: input_shape = (maxlen, len (chars)) где Maxlen 40 и Лен (Чарс) это количество функций (то есть уникальный счетчик персонажей из нашего корпуса).

x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool)y = np.zeros((len(sentences), len(chars)), dtype=np.bool)for i, sentence in enumerate(sentences):    for t, char in enumerate(sentence):        x[i, t, char_indices[char]] = 1    y[i, char_indices[next_chars[i]]] = 1

Часть вторая: моделирование

В первой части мы делаем фактическую модель обучения и поколения текста. Мы изучили данные и исправляли ее правильно, чтобы мы могли использовать его как вход в нашу модель LSTM. Для этой части есть два раздела:

  1. Определение модели сети LSTM
  2. Обучение модели и генерации прогнозов

Определение модели сети LSTM

Давайте начнем с чтения в наших библиотеках. Я использую KERAS, который является популярным и простым в использовании интерфейс для геркон Tensorflow. Узнайте больше о Зачем использовать KERAS в качестве глубокой структуры обучения здесь Отказ Ниже вы можете увидеть модели, слои, оптимизеры и обратные вызовы, которые мы будем использовать.

from keras.models import Sequentialfrom keras.layers import Dense, Activationfrom keras.layers import LSTMfrom keras.optimizers import RMSpropfrom keras.callbacks import LambdaCallback, ModelCheckpointimport randomimport sysimport io

В цифре ниже мы определяем модель. Начнем с последовательной модели и добавьте LSTM в качестве входного слоя. Форма, которую мы определяем для нашего ввода, идентична нашим данным на этот момент, которая именно то, что нам нужно. Я выбрал batch_size Из 128, что является количеством образцов или последовательностей, наша модель смотрит на тренировку до обновления. Вы можете поэкспериментировать с разными номерами здесь, если хотите. Я также добавляю плотный выходной слой. Наконец, мы будем использовать добавить слой активации с Softmax Как наша функция активации, поскольку мы, по сути, делаем классификацию мультикласс, чтобы предсказать следующий символ в последовательности.

model = Sequential()model.add(LSTM(128, input_shape=(maxlen, len(chars))))model.add(Dense(len(chars)))model.add(Activation('softmax'))

Теперь мы можем скомпилировать нашу модель. Мы будем использовать RMSPROP с курсом обучения 0,1 Чтобы оптимизировать вес в нашей модели (вы можете экспериментировать с различными курсами обучения здесь) и категория_crossentropy как наша функция потери. Крестная энтропия такая же, как потеря журнала, обычно используемой в качестве метрики оценки в конкурсах бинарной классификации на Kaggle (за исключением нашего случая, существует более двух возможных результатов).

optimizer = RMSprop(lr=0.01)model.compile(loss='categorical_crossentropy', optimizer=optimizer)

Теперь наша модель готова. Прежде чем проводить его какие-либо данные, клетку ниже определяет пару функций помощника С Code Modified из этого скрипта Отказ Первый, Образец () , образцы индекса из массива вероятностей с некоторыми температура Отказ Быстрая пауза, чтобы спросить, то, что именно температура?

Во всяком случае, поэтому второй определяет функцию обратного вызова для распечатки прогнозируемого текста, сгенерированного нашим обученным LSTM в первую очередь, а затем каждую последующую пятую эпоху с пятью различными настройками температура Каждый раз (см. Линию для разнообразия в [0,2, 0,5, 1,0, 1.2]: для значений Температура ; Не стесняйтесь настроить их тоже!). Таким образом, мы можем возиться с температура Ручка, чтобы увидеть, что заставляет нас лучшее сгенерированное текст, начиная от консервативных для творчества. Обратите внимание, что мы используем нашу модель для прогнозирования на основе случайной последовательности или «семян», из наших оригинальных подключенных данных Пользователь : start_index.randint (0, len (пользователь) - maxlen - 1) Отказ

Наконец, мы называем наш обратный вызов Generate_Text Что мы добавим к списку обратных вызовов, когда мы подходим нашу модель в ячейке после этого.

def sample(preds, temperature=1.0):    # helper function to sample an index from a probability array    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 on_epoch_end(epoch, logs):    # Function invoked for specified epochs. Prints generated text.    # Using epoch+1 to be consistent with the training epochs printed by Keras    if epoch+1 == 1 or epoch+1 == 15:        print()        print('----- Generating text after Epoch: %d' % epoch)        start_index = random.randint(0, len(user) - maxlen - 1)        for diversity in [0.2, 0.5, 1.0, 1.2]:            print('----- diversity:', diversity)            generated = ''            sentence = user[start_index: start_index + maxlen]            generated += sentence            print('----- Generating with seed: "' + sentence + '"')            sys.stdout.write(generated)            for i in range(400):                x_pred = np.zeros((1, maxlen, len(chars)))                for t, char in enumerate(sentence):                    x_pred[0, t, char_indices[char]] = 1.                preds = model.predict(x_pred, verbose=0)[0]                next_index = sample(preds, diversity)                next_char = indices_char[next_index]                generated += next_char                sentence = sentence[1:] + next_char                sys.stdout.write(next_char)                sys.stdout.flush()            print()    else:        print()        print('----- Not generating text after Epoch: %d' % epoch)generate_text = LambdaCallback(on_epoch_end=on_epoch_end)

Обучение модели и генерации прогнозов

Наконец мы сделали это! Наши данные готовы ( x для последовательностей, y для следующих символов) мы выбрали batch_size 128 И мы определили функцию обратного вызова, которая будет печать сгенерированного текста, используя Model.Predict () В конце первой эпохи следуют каждую пятую эпоху с пятью разными температура Установка каждый раз. У нас есть другой обратный вызов, ModelCheckPoint , который сохранит лучшую модель в каждой эпоху, если она улучшится на основе нашей стоимости потери (найдите сохраненные весовые веса Вес. HDF5 на вкладке «Выходные» ядра).

Давайте подберем нашу модель с этими спецификациями и эпохи для количества эпохи на тренировку. И, конечно же, давайте не будем забывать поставить наш графический процессор на использование! Это сделает тренинг/прогноз намного быстрее, чем если бы мы использовали ЦП. В любом случае, вы все равно захотите схватить несколько обедов или пойти на прогулку, пока вы ждете, пока модель тренируйся и генерируйте прогнозы, если вы используете этот код интерактивно.

Снимание Если вы используете это в интерактивном режиме в своем собственном ноутбуке на Kaggle, вы можете нажать кнопку Blue Square «Стоп» рядом с консолью в нижней части экрана, чтобы прервать модель обучения.

# define the checkpointfilepath = "weights.hdf5"checkpoint = ModelCheckpoint(filepath,                              monitor='loss',                              verbose=1,                              save_best_only=True,                              mode='min')# fit model using our gpuwith tf.device('/gpu:0'):    model.fit(x, y,              batch_size=128,              epochs=15,              verbose=2,              callbacks=[generate_text, checkpoint])

Заключение

И там у вас есть! Если вы запустили эту ноутбук в Kaggle ядра , вы, надеюсь, поймали модель, опираясь с генерируемым текстовым символом-символом для драматического эффекта.

Я надеюсь, что вам понравилось узнать, как начать с DataFrame, содержащих строки текста на использование модели LSTM, реализованную с помощью KERAS в ядрах для создания новых предложений благодаря мощности GPUS. Вы можете посмотреть, как наша модель улучшилась с первой эпохи до последней. Текст, генерируемый прогнозами модели в первой эпохе, действительно не похоже на английский язык. И в целом более низкие уровни разнообразия генерируют текст с большим количеством повторений, тогда как более высокие уровни разнообразия соответствуют большему количеству GobleteGook.

Можете ли вы настроить модель или его гиперпарамеры для генерации еще лучшего текста? Попробуй для себя Выполнение этого ноутбука ядро (Нажмите «Fork Notebook» в верхней части).

Вдохновение для следующих шагов

Вот лишь несколько идей для того, как взять то, что вы узнали здесь и расширяете его:

  1. Эксперимент с различными (Hyper) -параметрами, как количество учебных данных, количество эпох или пакетных размеров, температура , так далее.
  2. Попробуйте один и тот же код с разными данными; Вилка Этот ноутбук, перейдите на вкладку «Данные» и удалите источник данных FreeCodecamp, а затем добавьте другой набор данных ( Хорошие примеры здесь ).
  3. Попробуйте более сложные сетевые архитектуры, такие как добавление слоев выпадения.
  4. Узнайте больше о глубоком обучении на Kaggle Учить , серия видео и практических учебных пособий в ядрах.
  5. Использовать Вес .hdf5 В «выходе» для прогнозирования на основе разных данных в новом ядре то, что было бы похоже, если пользователь в этом руководстве выполнен чужие предложения.
  6. Сравните ускоренное влияние на использование процессора по сравнению с графическим процессором в минимальном примере.