предисловие
Содержание этой статьи в основном основано на англо-французском параллельном корпусе для реализации простой модели англо-французского перевода.В структуре кода используется TensorFlow 1.6.
Эта статья похожа на статью «Реализация модели Seq2Seq от кодировщика к декодеру», которую я опубликовал в колонке Zhihu «Машина не обучается» в прошлом году.
Тянь Юсу: Внедрение модели Seq2Seq от кодировщика к декодеруИтак, почему вы переписываете эту статью сегодня? Есть четыре причины для обновления этой статьи и кода:
- В прошлом году реализация интерфейса статьи была реализована с использованием TensorFlow 1.1, и некоторые интерфейсы изменились, что привело к тому, что некоторые фрагменты перестали нормально запускаться после загрузки кода;
- Описание части письменного содержания статьи недостаточно понятно, в статье реконструированы некоторые неуместные выражения;
- Предыдущая модель Seq2Seq сортирует буквы слов, и часть обработки данных относительно проста. На этот раз для построения модели перевода будет использоваться англо-французский параллельный корпус, а также будут добавлены некоторые операции обработки данных;
- В следующей статье в рубрике будет написано об улучшенной версии модели машинного перевода, в том числе модели с использованием BiRNN и механизма Attention (который будет реализован в Keras), эту статью можно использовать как предвестник.
Рабочая среда
Основная цель написания колонки - понять алгоритм через код.В предыдущих статьях многие студенты будут задавать некоторые вопросы по интерфейсу.Я обычно занят и не могу отвечать на них по одному.На основные вопросы по интерфейсу и код, пожалуйста, Baidu или Google, в принципе можно решить. Среда, на которой основана эта статья и код:
- Системная среда: Mac OS High Sierra
- Среда Python: Python 3.6
- Версия TensorFlow: 1.6
- Anaconda (Jupyter Notebook)
Код полного адреса:NELSONZHAO/zhihu
Добро пожаловать в Звезды и Вилки.
текст
Эта статья в основном состоит из двух частей:Обработка данных и построение модели. В части обработки данных мы преобразуем исходный параллельный корпус в данные, необходимые нашей модели. В части построения модели мы будем шаг за шагом строить самую простую модель Seq2Seq на основе TensorFlow 1.6, а также обучать и прогнозировать на основе имеющегося у нас параллельного корпуса.
Часть 1 Обработка данных
В части обработки данных мы в основном включаем следующие четыре шага:
1. Загрузите данные.Данные, используемые в этой статье, представляют собой англо-французский параллельный корпус.
- Файл small_vocab_en содержит исходный английский корпус, где каждая строка представляет собой полное предложение.
- Файл small_vocab_fr содержит исходный французский корпус, где каждая строка представляет собой полное предложение.
2. Исследование данных.То есть статистическое описание корпусного текста.
3. Предварительная обработка данных.
- Построить словарь английского языка (словарный запас) и закодировать слова
- Составить французский словарь (лексикон), кодируя слова
4. Корпусное преобразование.
- Преобразование необработанного английского текста в машинно-распознаваемую кодировку
- Преобразование необработанного французского текста в распознаваемую компьютером кодировку
1. Загрузите данные
Поскольку эта статья в основном предназначена для перевода с английского на французский, мы вводим английский и ожидаем, что выведем французский. Поэтому мы называем английский исходным, а французский — целевым. Переменные именуются таким образом в следующих статьях.
Наши данные представляют собой параллельный корпус, то есть каждая строка представляет собой полное предложение, и одна и та же строка в двух файлах соответствует английскому и французскому выражениям одного и того же предложения.
2. Описательная статистика
Описательная статистика в основном помогает нам понять данные.
Вышеприведенный код в основном предназначен для статистического анализа загруженных исходного текста и целевого_текста. Наш исходный корпус был весь в нижнем регистре.
- 4-5 строк кода подсчитывают количество уникальных строк (включая слова и знаки препинания) в исходном тексте;
- 9-13 строк кода сегментируют и сегментируют исходный текст, а также подсчитывают количество предложений, среднюю длину предложения и максимальную длину предложения;
- 16-17 строк кода сегментируют и сегментируют целевой текст, а также подсчитывают количество предложений, среднюю длину предложения и максимальную длину предложения;
- Строки 24-28 выводят первые 10 предложений данных на английском и французском языках соответственно.
Статистический анализ показывает, что в нашей выборке более 13W предложений, из которых средняя длина английских предложений составляет 13,2, а средняя длина французских предложений — 14,2. Английские предложения имеют максимальную длину 17, а французские предложения относительно длиннее, с максимальной длиной предложения 23.
3. Предварительная обработка данных
Базовой архитектурой модели машинного перевода является модель Seq2Seq.Перед построением модели нам необходимо обработать корпус. Преобразование текстового корпуса в числа, которые могут распознавать машины. Например, для английского предложения: я люблю машинное обучение и глубокое обучение, закодированное в виде чисел [28, 29, 274, 873, 12, 983, 873]. Таким образом, эта часть в основном выполняет следующие задачи:
- Создание англо-французских словарей на основе корпуса (лексики)
- Создайте карту английского языка для французского, словарь, который преобразует слова в числа
- Построить обратное отображение английского языка на французский, то есть словарь из чисел в слова.
Составление словаря (Vocabulary)
Приведенный выше код выполняет статистику слов по исходному и целевому текстам соответственно и создает словарь. Поскольку у нас меньше текста, у нас также меньше уникальных слов. В английском корпусе наш размер словаря составляет 227, а во французском корпусе размер словаря составляет 354.
Построить карту
С помощью словаря мы можем построить сопоставление слов в соответствии со словарем и преобразовать текст корпуса в машинно-распознаваемый код.
首先,我们先定义了特殊字符
: Из-за специфики проблем перевода длина наших предложений часто несовместима. Когда RNN обрабатывает пакетные данные, нам необходимо убедиться, что предложения в пакете имеют одинаковую длину. В настоящее время нам нужно передать к предложениям недостаточной длины. :Unknown字符,用来处理模型未见过的生僻单词; : при переводе предложения используется, чтобы сказать предложению начать перевод. используется только в цели; : при переводе предложения используется, чтобы сказать предложению закончить перевод. Используется только в цели.
Во второй части блока кода мы построили сопоставления английских и французских слов в соответствии со словарем и специальными символами. Видно, что размер картографического словаря для английского языка равен 229, а размер картографического словаря для французского — 358.
4. Преобразование корпуса
С результатами вышеуказанной предварительной обработки данных мы можем выполнить преобразование текста на исходном корпусе, то есть преобразовать текст в числа. В процессе преобразования, поскольку наш LSTM может обрабатывать только данные фиксированной длины, нам необходимо убедиться, что длина Tx входного корпуса и длина Ty выходного корпуса остаются фиксированными. Предполагая, что Tx=20, PAD выполняется для предложений, содержащих менее 20 слов, и усекается для предложений, содержащих более 20 слов.
Например, для входного предложения «Я люблю машинное обучение и глубокое обучение» используется кодировка [28, 29, 274, 873, 12, 983, 873, 0, 0, 0, 0, 0, 0, 0, 0. , 0 , 0, 0, 0, 0].
Здесь мы реализуем функцию для преобразования, которая принимает полное предложение и возвращает результат сопоставления.
- Параметр предложения — это полное предложение;
- map_dict — это сопоставление слов с числами, а именно сгенерированные выше source_vocab_to_int и target_vocab_to_int;
- max_length относится к максимальной длине предложения;
- is_target используется, чтобы указать, обрабатывать ли целевое предложение, потому что есть разница в обработке источника и цели.В target нам нужно добавить символ
в конце каждого предложения, но эта операция не требуется в источнике . . .
После того, как функция построена, мы можем обрабатывать английский корпус и французский корпус отдельно.
Среди них я указал, что максимальная длина английских предложений составляет 20, то есть предложения, содержащие менее 20 слов, завершаются, а предложения, содержащие более 20 слов, усекаются. Французские предложения относительно длинные, и я выбрал 25 в качестве максимальной длины.
Мы случайным образом выбираем обработанный результат для просмотра.Как показано выше, два предложения соответствуют двум выражениям на английском и французском языках.После обработки они становятся цифровыми кодами, а те, у которых недостаточно длины, заполняются 0.
На этом наша часть обработки данных в основном завершена.В этой части мы преобразовываем текстовый корпус в распознаваемый компьютером цифровой код, создавая словарь, картирование и т. д. В следующей части мы начнем строить модель.
Часть II Построение модели
При построении данных в первой части мы преобразовали исходный текст корпуса в числовой код, который может распознать машина. Во второй части мы соберем нашу модель из трех частей. Прежде всего, в базовой модели Seq2Seq мы вводим последовательность и преобразуем последовательность в вектор фиксированной длины (вектор контекста) через сторону кодировщика.Этот вектор содержит информацию о входной последовательности, и этот вектор передается как вход на сторону декодера для создания новой последовательности. Возьмем перевод в качестве примера, как показано на следующем рисунке:
Мы вводим «Я люблю машинное обучение» и ожидаем, что он сгенерирует соответствующий английский перевод: «Я люблю машинное обучение». От ввода до вывода он прошел следующие этапы:
- Токенизировать текст «Я люблю машинное обучение», чтобы получилось четыре слова «я», «люблю», «машина», «обучение»;
- Вложение каждого слова в плотный вектор;
- Вход в LSTM для обучения;
- Последовательность обучения LSTM получает вектор контекста фиксированной длины;
- Вектор контекста передается в качестве входных данных на сторону декодера для генерации нового слова;
- Получите результат перевода «Я люблю машинное обучение».
На приведенном выше рисунке нижняя левая часть — это сторона кодировщика, а верхняя правая часть — сторона декодера, поэтому мы также следуем структуре модели с точки зрения функций и компонентов кода. Наш модуль кода модели в основном разделен на следующие четыре части:
- входные данные модели model_inputs
- Сторона кодировщика encoder_layer
- Сторона декодера
- Вход декодера decoder_layer_inputs
- Обучение декодеру decoder_layer_train
- Предсказание/вывод декодера decoder_layer_inference
- Модель Seq2Seq
1. Ввод модели
Ввод модели в основном заключается в реализации построения тензора.
Эта функция создает тензоры, такие как входные данные, цели и т. д. В частности, входные данные представляют собой двумерный тензор, первое измерение представляет размер пакета, второе измерение — длину последовательности, и то же самое верно для целей. Как показано ниже:
inputs — это закодированная текстовая последовательность (цифры на рисунке написаны мной просто для иллюстрации), если мы в это время передаем в модель только одну партию, форма inputs будет [1, 4], из которых 1 соответствует пакету. Размер 4 соответствует длине последовательности. То же самое верно и для целей.
2. Сторона энкодера
Сторона кодировщика является стороной кодирования, и ее цель состоит в том, чтобы отобразить последовательность в вектор фиксированной длины путем ее изучения. Конкретный код реализации:
Во-первых, нам нужно выполнить встраивание вектора слов во входные данные, а затем использовать LSTM для обучения последовательности. пройти черезtf.nn.dynamic_rnnМетод возвращает состояние последовательности LSTM, где encoder_states — это нужный нам вектор контекста.
В частности, encoder_embed — это вектор встроенного слова.Если encoder_embed_size указан как 100, встроенный вектор каждого полученного слова будет 100-мерным, как показано на рисунке выше. Результатом конечного состояния LSTM является вектор контекста.
3. Сторона декодера
Со стороны декодера мы разделены на три модуля:
- decoder_layer_inputs: в основном используется для обработки ввода декодера;
- decoder_layer_train: декодер, используемый в процессе обучения;
- decoder_layer_infer: декодер, используемый в процессе тестирования.
(1) Вход декодера
Вход на стороне декодера требует специальной обработки, как показано на следующем рисунке:
На стороне декодера мы используем вектор контекста и выходные данные предыдущего раунда для генерации слов текущего этапа. Когда мы находимся на последнем этапе, последнем раунде изучения входных результатов, в это время мы выводим
Кроме того, нам нужно использовать «
10-я строка кода используется для удаления последнего символа каждого предложения во всем пакете, а 12-я строка кода добавляет начальный символ «
Подробности следующие:
Сначала удалите последний символ «
(2) Обучение декодированию
После завершения построения ввода нам нужно построить функции обучения (обучения) и прогнозирования (вывода) на стороне декодера. Почему обучение и вывод здесь разделены? Мы знаем, что в LSTM выходные данные предыдущего раунда будут использоваться в качестве входных данных для следующего раунда.Например, при прогнозировании «обучения» мы будем использовать выходные данные предыдущего раунда «машины» в качестве входных данных, но если предыдущий раунд Если входные данные недостаточно точны или есть ошибка, это означает, что все последующие результаты прогнозирования будут затронуты.
Как это решить? В частности, поскольку мы знаем, какова основная истина каждого раунда во время процесса обучения, мы можем форсировать обучение с реальным вводом.Этот метод называется принуждением учителя, как показано на следующем рисунке:
В первой строке мы тренируемся в обычном режиме, то есть используем вывод предыдущего раунда как ввод следующего раунда.Когда мы делаем ошибку в определенном раунде, то есть любовь сама должна выводить машину, но он выводит яблоко.Такие ошибки будут продолжать накапливаться при последующем обучении, что приведет к совершенно неправильным результатам перевода;при использовании форсирования учителя, поскольку мы знаем, что реальными целями обучающих выборок должны быть Я люблю машинное обучение, каждый раунд нашего ввод использует реальную метку для обучения, что может гарантировать, что влияние ошибок на последующее обучение будет смягчено в процессе обучения.
Но метод Teacher Forcing подходит только для тренировочного процесса, потому что в процессе предсказания мы не можем знать истинную метку, в качестве текущего входа можно использовать только вывод предыдущего. Итак, здесь нам нужно построить две функции, чтобы различать процессы обучения и прогнозирования.
Создайте вспомогательный объект через TrainingHelper в TensorFlow и передайте его в BasicDecoder.
В методе dynamic_decode, когда impute_finished имеет значение True, когда прогноз помечен как завершенный, вектор состояния предыдущего раунда автоматически копируется, и все выходные параметры устанавливаются равными 0.
Python boolean. If True, then states for batch entries which are marked as finished get copied through and the corresponding outputs get zeroed out.
(3) Предсказание декодера
На этапе прогнозирования создайте объект GreedyEmbeddingHelper и передайте его в BasicDecoder.
Определение GreedyEmbeddingHelper в интерфейсе TensorFlow:
A helper for use during inference.
Uses the argmax of the output (treated as logits) and passes the result through an embedding layer to get the next input.
(4) Уровень декодера
Уровень декодера собирает вышеуказанные функции.
Вышеупомянутая функция в основном определяет несколько содержимого:
- Строки с 19 по 20 кода встраивают входные данные на стороне декодера;
- Строка 26 используется для построения слоя LSTM;
- 29-я строка кода используется для построения полносвязного слоя;
- Строки 31-49 используются для вызова train и вывода для получения логитов.
4. Модель Seq2Seq
С помощью приведенных выше функций мы определили каждый модуль на стороне кодировщика и декодера, а затем создали функцию для объединения этих компонентов.
Приведенный выше код в основном разделен на три шага:
- 24-я строка кода предназначена для получения результата кодирования входной исходной последовательности на стороне кодировщика;
- 27-я строка кода используется для обработки ввода стороны декодера;
- Строка 29 вызывает сторону декодера, чтобы получить вывод train и infer.
Часть III Обучение модели и прогнозирование
После части обработки данных и части построения модели мы завершили подготовку к обучению. Далее нам нужно определить гиперпараметры, запустить наш график и передать данные для обучения.
Определены следующие гиперпараметры:
Установлено 10 итераций, 1 слой LSTM, размерность встроенного вектора слов кодировщика и декодера составляет 100 измерений, а результат указывается для печати каждые 50 раундов обучения.
Так как наш обучающий корпус относительно небольшой, всего 13W, а машинный перевод, модель с большими параметрами для изучения, требует много обучающего текста, поэтому я не разделял здесь обучение и валидацию, а использовал все данные 13W для обучения.
После обучения модели мы видим, что обученный Loss, наконец, колеблется около 0,01, и вы также можете повторно настроить параметры для обучения.
В части прогнозирования мы введем несколько предложений, которые должны сами данные обучения, чтобы увидеть, как работает перевод:
---------------------------------------【Пример 1】------- --------------------------------
Мы набираем «Соединенные Штаты никогда не бывают красивыми в марте, а летом обычно расслабляются».
Результат, выдаваемый моделью, таков: «les états-unis est jamais belle en mars, et il est restalanthavuellement en hiver.
Переводчик Google выдает: «les États — unis n’est jamais beau en mars, et il est reguluellement Relaxant en été».
Неважно, если вы не понимаете французский язык, мы воспользуемся Google, чтобы перевести результат французского перевода, предоставленный моделью, на английский язык и увидим: «Соединенные Штаты прекрасны в марте и расслабляются, как правило, зимой. "
Можно видеть, что наша модель перевела оригинальное английское лето на зиму, указывая на то, что модель уловила здесь сезонные слова, но конкретные времена года неверны. Кроме того, в первой половине предложения отсутствует отрицательное слово «никогда».
----------------------------------------【Пример 2】------ - --------------------------------
Мы вводим «Я не люблю грейпфруты, лимоны и персики».
Результат, выдаваемый моделью, таков: «je n'aime pamplemousses, les citrons et les mangues.
Переводчик Google выдает "je déteste les pamplemousses, citrons, et les pêches".
Давайте воспользуемся Google, чтобы перевести французский результат перевода, данный моделью, на английский язык: «я не люблю грейпфрут, лимон и манго».
На этот раз результат перевода относительно хорош.Модель неправильно переводит «персики» в «манго», а также улавливает, что это фрукт, но конкретный фрукт плохо изучен.
В целом, модель все еще может соответствовать обучающим данным. Читатели также могут попробовать предложения из других обучающих данных для тестирования. Но если вы введете предложения, которых не было в процессе обучения, результаты перевода будут сильно снижены.
Суммировать
В этой статье создается базовая модель Seq2Seq на основе версии TensorFlow 1.6 и реализуется простая модель англо-французского перевода с помощью этой модели. То есть входная последовательность изучается через кодировщик, и получается закодированный вектор контекста, а затем вектор контекста передается в декодер для обучения, и генерируется результат преобразования. На стороне декодера метод форсирования тренера используется на этапе обучения, а наземная правда используется в качестве входных данных; в то время как на этапе прогнозирования в качестве входных данных используется результат предыдущего поколения. Окончательная модель неплохо справляется с переводом обучающих данных.
Основная цель этой статьи — дать каждому общее представление об базовой модели Seq2Seq и модели трансляции с помощью кода, поэтому некоторые реализации модели упрощены. Эта модель в основном имеет следующие недостатки:
- Учебный корпус слишком мал.Он не очень подходит для крупномасштабных моделей, зависящих от данных, таких как модели перевода;
- Обучающая и тестовая выборки не разделены.Это также вызвано слишком маленьким объемом обучающих материалов.Разделение обучения и проверки приведет к меньшему количеству обучающих данных модели
- Метрики оценки слишком упрощены.В общем, эффект модели перевода оценивается BLEU (дублером двуязычной оценки), а потеря просто используется для наблюдения за конвергенцией обучения;
- Завершение корпусных данных слишком просто.Вообще говоря, длина предложений корпуса непостоянна, и большой корпус включает не только длинные предложения, но и некоторые короткие предложения. Видно, что почти весь корпус в этой статье представляет собой короткие предложения, максимальная длина английских предложений — 17, а максимальная длина французских предложений — 23. На практике наши предложения могут быть длиннее.В настоящее время не так уместно завершать короткие предложения в соответствии с максимальной длиной предложения, а эффективность разработки очень низкая.Поэтому ведра часто используются для группировки корпусов разной длины.
Базовая модель Seq2Seq относительно проста, на самом деле существует много способов улучшить модель, например, добавить BiRNN для сбора более полной информации о входной последовательности, добавить внимание, использовать разные векторы контекста при переводе каждого слова и т. д. Последующие столбцы будут еще больше улучшать модель перевода на основе Keras.
Столбец:Машины не учатся
Личный профиль:Тиан Юсу
Гитхаб:NELSONZHAO
Для перепечатки, пожалуйста, свяжитесь с автором для разрешения.