Авторы: Вячеслав Ковалевский, Гаутам Госвами и Ёнхи Квон. Отказ от ответственности: наши мнения являются нашими собственными.

Tf-seq2seq - это новый фреймворк, основанный на TensorFlow, который можно использовать для множества задач, в которых используются модели seq2seq. Приведу цитату авторов фреймворка.

tf-seq2seq - это универсальный фреймворк кодировщика-декодера для Tensorflow, который можно использовать для машинного перевода, суммирования текста, диалогового моделирования, создания подписей к изображениям и т. д.

В этой статье мы будем использовать его для обучения чат-бота. Точнее, мы будем использовать следующий учебник по нейронному машинному переводу (NMT). Если вам интересно, как модель NMT может использоваться для чат-бота, прочтите мою предыдущую статью (Собственный чат-бот на основе рекуррентной нейронной сети
за 6 $ / 6 часов и ~ 100 строк кода
).

Здесь можно спросить, хорошо, я понимаю, в чем дело, но как можно обучить модель бесплатно? Google недавно объявил, что они бесплатно предоставляют один графический процессор Nvidia K80 на 12 часов со своей новой услугой C olab. По сути, Colab - это кастомная версия Jupyter Notebook.

Итак, похоже, у нас есть оба компонента:

  • Модель, которую мы хотим тренировать и
  • сервис с Nvidia K80, который мы будем использовать для фактического обучения.

Начнем наше путешествие ...

Подготовка записной книжки Colab

Мы готовы воспользоваться сервисом colab и создать свой первый блокнот. На момент написания этой статьи colab по умолчанию использовал бы блокнот hello world, который удобен для ознакомления с окружающей средой. Давайте создадим новый блокнот с поддержкой Python3:

Как только записная книжка будет создана, нам нужно изменить тип среды выполнения:

И установите его на GPU:

Наш блокнот готов, и мы можем перейти ко второму шагу:

Подготовка обучающих данных

Начнем с подготовки данных. Мы будем использовать тот же старый скрипт, который мы использовали во всех предыдущих статьях. Только на этот раз все это будем делать в колабе.

Мы будем использовать NLTK lib, который требует некоторого «предварительного подогрева»:

Теперь мы можем клонировать ветку и запустить логику, которая подготавливает обучающие данные:

%%bash
rm -rf dialog_converter
git clone https://github.com/b0noI/dialog_converter.git
cd dialog_converter
git checkout b9cc7b7d82a959c80e5048b18e956841233c7688
python3 ./converter.py
ls

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

… Изучение модели на основе слов имеет несколько недостатков. Поскольку модели NMT выводят распределение вероятностей для слов, они могут стать очень медленными при большом количестве возможных слов. Если вы включаете орфографические ошибки и производные слова в свой словарь, количество возможных слов по существу бесконечно, и нам нужно наложить искусственное ограничение на то, как из наиболее распространенных слов мы хотим, чтобы наша модель обрабатывала. Это также называется размером словаря и обычно устанавливается в диапазоне от 10 000 до 100 000. Еще один недостаток обучения токенам слов заключается в том, что модель не узнает об общих «основах» слов. Например, он будет рассматривать «любимый» и «любящий» как совершенно разные классы, несмотря на их общий корень.

Один из способов справиться с проблемой открытого словаря - выучить подсловные единицы для заданного текста. Например, слово любимый можно разделить на любить и эд, а любить можно разделить на любить и инг. Это позволяет моделировать обобщение для новых слов, а также приводит к меньшему объему словарного запаса. Есть несколько методов для изучения таких подслов, включая Кодирование пар байтов (BPE), которое мы использовали в этом руководстве. Чтобы сгенерировать BPE для заданного текста, вы можете следовать инструкциям в официальном репозитории subword-nmt:

Итак, наши следующие логические шаги:

  • Получите все необходимое программное обеспечение, которое может выучить словарный запас BPE из учебного текста
  • Преобразуйте данные обучения в BPE и создайте словарь
  • Преобразуйте весь текст со словарём.

A. Получите все необходимое программное обеспечение, которое может выучить словарный запас BPE из учебного текста

Будем устанавливать пакет subword-nmt pip для выполнения необходимых манипуляций. Для этого выполните в ячейке следующую команду:

%%bash
rm -rf subword-nmt
git clone https://github.com/b0noI/subword-nmt.git
cd subword-nmt
git checkout dbe97c8f95f14d06b2e46b8053e2e2f9b9bf804e

теперь мы наконец готовы

Б. Преобразование обучающих данных в BPE и создание словаря

Нам нужно будет выполнить это в следующих 3 шагах.

Шаг 1. Этот шаг отвечает за создание словаря на основе вводимых данных обучения и заданного размера словарного запаса. Он создает code.bpe, который по сути представляет собой «сжатое дерево» всех слов в обучающих данных. Он также генерирует наиболее часто встречающиеся слова из обучающих данных вместе с их частотами в файлах vocab.train.bpe. {A, b}.

%%bash
# Create unique words (vocabulary) from training data
subword-nmt/learn_joint_bpe_and_vocab.py --input dialog_converter/train.a dialog_converter/train.b -s 50000 -o code.bpe --write-vocabulary vocab.train.bpe.a vocab.train.bpe.b

Шаг 2. В наших обучающих данных есть несколько вкладок, которые не нужны в словарном запасе, поэтому давайте очистим словарный запас.

%%bash
# Remove the tab from vocabulary 
sed -i '/\t/d' ./vocab.train.bpe.a
sed -i '/\t/d' ./vocab.train.bpe.b

Шаг 3: Выходные файлы vocab.train. {a, b} содержат список слов с указанием их частот, tf-seq2seq принимает ввод как набор слов, поэтому мы можем избавиться от частоты. .

%%bash
# Remove the frequency from vocabulary
cat vocab.train.bpe.a | cut -f1 --delimiter=' ' > revocab.train.bpe.a
cat vocab.train.bpe.b | cut -f1 --delimiter=' ' > revocab.train.bpe.b

C. Преобразование всего текста со словарем.

Эта ячейка создаст кодировку BPE и словари для каждого необработанного файла. И теперь мы можем повторно применить эти словари к нашим необработанным файлам:

%%bash
subword-nmt/apply_bpe.py -c code.bpe --vocabulary vocab.train.bpe.a --vocabulary-threshold 5 < dialog_converter/train.a > train.bpe.a
subword-nmt/apply_bpe.py -c code.bpe --vocabulary vocab.train.bpe.b --vocabulary-threshold 5 < dialog_converter/train.b > train.bpe.b
subword-nmt/apply_bpe.py -c code.bpe --vocabulary vocab.train.bpe.a --vocabulary-threshold 5 < dialog_converter/test.a > test.bpe.a
subword-nmt/apply_bpe.py -c code.bpe --vocabulary vocab.train.bpe.b --vocabulary-threshold 5 < dialog_converter/test.b > test.bpe.b

Подготовка к обучению

Шаг 1. Загрузите модель nmt.

%%bash
rm -rf /content/nmt_model
rm -rf nmt
git clone https://github.com/tensorflow/nmt/

Шаг 2: переместите все необходимые файлы для обучения в одно место. Что включает в себя данные обучения, данные тестирования и словарный запас (просто набор слов).

%%bash
mkdir -p /content/nmt_model
cp dialog_converter/train.a /content/nmt_model
cp dialog_converter/train.b /content/nmt_model
cp dialog_converter/test.a /content/nmt_model
cp dialog_converter/test.b /content/nmt_model
cp revocab.train.bpe.a /content/nmt_model
cp revocab.train.bpe.b /content/nmt_model
cp train.bpe.a /content/nmt_model
cp test.bpe.a /content/nmt_model
cp train.bpe.b /content/nmt_model
cp test.bpe.b /content/nmt_model

Начать обучение:

!cd nmt && python3 -m nmt.nmt \
    --src=a --tgt=b \
    --vocab_prefix=/content/nmt_model/revocab.train.bpe \
    --train_prefix=/content/nmt_model/train.bpe \
    --dev_prefix=/content/nmt_model/test.bpe \
    --test_prefix=/content/nmt_model/test.bpe \
    --out_dir=/content/nmt_model \
    --num_train_steps=45000000 \
    --steps_per_stats=100000 \
    --num_layers=2 \
    --num_units=128 \
    --batch_size=16 \
    --num_gpus=1 \
    --dropout=0.2 \
    --learning_rate=0.2 \
    --metrics=bleu

Здесь следует отметить несколько моментов:

  • num_train_steps - это количество шагов, которые сеть предпримет перед остановкой, сделайте это большим, так как всегда лучше оказаться в ситуации, когда вам нужно остановить обучение вручную, чем в ситуации, когда сеть остановилась, когда вы этого не ожидали прекратить;
  • steps_per_stats - частота, с которой сеть будет выводить статистику. Здесь следует иметь в виду: вывод статистики требует времени, поэтому вам нужно найти баланс между слишком частым выводом и обучением модели в полной темноте;
  • метрики - логика вычисления расстояния между 2 предложениями для оценки качества модели;

Здесь важно не использовать «%% bash», а использовать «!». «%% bash» будет ждать полного выполнения ячейки перед отображением вывода, что означает почти навсегда из-за обучения модели. Напротив, знак «!» показывает вывод динамически.

Как только обучение закончится, вы можете начать общение с моделью.

Обязательно завершите обучение, если оно еще продолжается, иначе вы не сможете поболтать с моделью.

Затем скопируйте и вставьте следующий код в файл (скажем, chat.sh) в каталоге nmt и запустите его как ./chat.sh ‹путь к модели. ›. Возможно, вам потребуется изменить разрешение, например chmod + x chat.sh.

%%bash
pwd
cd nmt
touch /content/output
chat () {
   echo $1 > /content/input
   $HOME/subword-nmt/apply_bpe.py -c $HOME/code.bpe --vocabulary $HOME/vocab.train.bpe.a --vocabulary-threshold 5 < /content/input > /content/input.bpe
   cd $HOME/nmt
   python -m nmt.nmt  --out_dir=/content/nmt_model --inference_input_file=/content/input.bpe --inference_output_file=/content/output > /dev/null 2>&1
   cat /content/output
}
chat "hi"

PS: Мы все еще играем с разными конфигурациями моделей, следите за обновлениями статьи. Также в будущем мы загрузим предварительно обученную модель!

Последнее обновление: июль 72018