Как создать переводчик, который переводит лучше, чем Google Translate

МЕНЮ


Главная страница
Поиск
Регистрация на сайте
Помощь проекту
Архив новостей

ТЕМЫ


Новости ИИРазработка ИИВнедрение ИИРабота разума и сознаниеМодель мозгаРобототехника, БПЛАТрансгуманизмОбработка текстаТеория эволюцииДополненная реальностьЖелезоКиберугрозыНаучный мирИТ индустрияРазработка ПОТеория информацииМатематикаЦифровая экономика

Авторизация



RSS


RSS новости


Помню, как еще в школе на Basic я писал программу-переводчик. И это было то время, когда ты сам составлял словарь, зашивал перевод каждого слова, а затем разбивал строки на слова и переводил каждое слово в отдельности. В то время я, конечно же, не мог и представить, как сильно продвинутся технологии, и программы-переводчики станут в основе использовать механизмы глубокого обучения с архитектурой трансформера и блоками внимания.

В это раз я решил окунуться немного в прошлое и сделать то, что хорошо сделать тогда у меня не получилось.

В современных задачах системы перевода нужны достаточно часто, а специалисту, занимающемуся машинным обучением, возможно чаще, чем в других видах деятельности. Потребность в переводчике стала мне необходима, и я решил прибегнуть к использованию облачных решений, в частности Google Translate.

Я программирую на python, и в python есть отличная библиотека translators. Данная библиотека позволяет использовать множество различных сервисов по переводу. Причем абсолютно бесплатно. Однако, все же данное решение не идеально по нескольким причинам:

  1. Перевод выполняется достаточно долго.

  2. При большом количестве запросов, переводчик начинает пропускать предложения, т.е. оставляет их в непереведенном виде. Причем никаких ошибок при этом не выводится.

  3. Качество перевода не самое высокое, как я это проверял, я расскажу в своей статье ниже.

Конечно же, не стоит изобретать велосипед, поэтому я стал использовать отличное готовое решение Argos Translate. Это open-source бесплатное решение для машинного перевода. Поддерживается огромное количество языков. Может работать в разных режимах: и как десктоп приложение, и как веб приложение, и как библиотека к python.

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

Автор проекта Argos Translate поставляет свой скрипт обучения, доступный всем желающим. Для обучения своей модели я взял его за основу, однако в процессе несколько его видоизменил. Далее я покажу основные составляющие процесса обучения модели машинного перевода и разобью их на составные части для лучшего понимания.

Этап 1: Подготовка данных для обучения

Для обучения модели машинного перевода необходимо большое количество параллельных корпусов текстов, к счастью, в сети есть очень большое количество параллельных корпусов текста, за основу я взял датасеты с сайта https://opus.nlpl.eu/

В качестве данных для обучения я использовал список корпусов текстов: ada83.en-ru, bible-uedin.en-ru, Books.en-ru, CCMatrix.en-ru, ELRC_2922.en-ru, EUbookshop.en-ru, GlobalVoices.en-ru, GNOME.en-ru, infopankki.en-ru, KDE4.en-ru, MultiUN.en-ru, News-Commentary.en-ru, OpenSubtitles.en-ru, ParaCrawl.en-ru, PHP.en-ru, QED.en-ru, Tanzil.en-ru, Tatoeba.en-ru, TED2013.en-ru, TED2020.en-ru, tico-19.en-ru, TildeMODEL.en-ru, Ubuntu.en-ru, UN.en-ru, WikiMatrix.en-ru, wikimedia.en-ru, WMT-News.en-ru

В общем итоге у меня получилось собрать тренировочный корпус размером более 80 млн пар предложений.

Для последующей тренировки все данные нам необходимо собрать в файлы:

  1. src-train.txt - все исходные предложения на русском языке,

  2. tgt-train.txt - все переводы предложений на английском языке,

  3. all.txt - все предложения корпуса на двух языках, данный файл необходим для генерации общего словаря,

  4. src-val.txt - 2000 предложений для валидации,

  5. tgt-val.txt - 2000 переводов предложений для валидации.

Этап 2: Генерация словаря токенов

В качестве основного движка модели используется библиотека нейронного машинного перевода OpenNMT-py с открытым исходным кодом на pytorch.

Библиотека для тренировки использует yml конфигурационные файлы, в которых описываются параметры тренировки модели.

Я использовал стандартный конфиг из репозитория argos-train: https://github.com/argosopentech/argos-train/blob/master/config.yml

В моделях перевода argos translate используется общий словарь для обоих языков.

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

#!/bin/bash spm_train --input=run/split_data/all.txt --model_prefix=run/sentencepiece --vocab_size=50000 --character_coverage=0.9995 --input_sentence_size=10000000 --shuffle_input_sentence=true --split_digits

В качестве генерации словаря используется очень популярный токенизатор SentencePiece, который использует в качестве словаря наиболее частотные единицы подслов.

Для перевода модели токенизатора SentencePiece в словарь модели используется команда:

#!/bin/bash onmt_build_vocab -config config.yml -n_sample -1

и часть конфига отвечающая за формирование словаря:

#config.yml  ## Where the samples will be written save_data: run/opennmt_data ## Where the vocab(s) will be written src_vocab: run/opennmt_data/openmt.vocab tgt_vocab: run/opennmt_data/openmt.vocab   # Should match the vocab size for SentencePiece # https://forum.opennmt.net/t/opennmt-py-error-when-training-with-large-amount-of-data/4310/12?u=argosopentech src_vocab_size: 50000 tgt_vocab_size: 50000  share_vocab: True  # Corpus opts: data:     corpus_1:         path_src: run/split_data/src-train.txt         path_tgt: run/split_data/tgt-train.txt         transforms: [sentencepiece, filtertoolong]     valid:         path_src: run/split_data/src-val.txt         path_tgt: run/split_data/tgt-val.txt         transforms: [sentencepiece, filtertoolong]   ### Transform related opts: #### https://opennmt.net/OpenNMT-py/FAQ.html#how-do-i-use-the-transformer-model #### Subword src_subword_model: run/sentencepiece.model tgt_subword_model: run/sentencepiece.model src_subword_nbest: 1 src_subword_alpha: 0.0 tgt_subword_nbest: 1 tgt_subword_alpha: 0.0 #### Filter src_seq_length: 150 tgt_seq_length: 150

Этап 3: Тренировка модели

В качестве архитектуры обучаемой модели используется архитектура трансформера, состоящая из кодировщика и декодировщика, каждый размером 6 слоев. 8 голов самовнимания. Размером эмбединга – 512, и размером скрытого связующего состояния между кодировщиком и декодировщиком – 2048.

#config.yml  # Model encoder_type: transformer decoder_type: transformer position_encoding: true enc_layers: 6 dec_layers: 6 heads: 8 rnn_size: 512 word_vec_size: 512 transformer_ff: 2048 dropout_steps: [0] dropout: [0.1] attention_dropout: [0.1]

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

Для запуска процесса обучения используется команда:

#!/bin/bash onmt_train -config config.yml

Обучение моей модели длилось 100 000 шагов и в общем случае занимает от 2 до 5 дней, в зависимости от конфигурации оборудования.

Этап 4: Тестирование качества модели

После обучения нам необходимо проверить, насколько хорошо переводит наша модель.

Для оценки качества модели я использовал отдельный параллельный корпус "Yandex Translate corpus 1m version 1.3" размером в 1 млн пар предложений, в качестве метрики я использовал метрику BLEU Score.

Я использовал следующий скрипт для тестирования модели

#!/bin/bash #тестирование модели по метрике BLEU #https://opennmt.net/OpenNMT-py/examples/Translation.html?highlight=bleu  echo "Step 001 Токенизируем наш корпус тестирования"   spm_encode --model=run/sentencepiece.model       < argos-train/csv/test_crps/src-test.txt       > argos-train/csv/test_crps/src-test.txt.sp spm_encode --model=run/sentencepiece.model       < argos-train/csv/test_crps/tgt-test.txt       > argos-train/csv/test_crps/tgt-test.txt.sp  echo "Step 002 Переведем наш корпус с помощью модели"  for checkpoint in run/openmt.model_step*.pt; do     echo "# Translating with checkpoint $checkpoint"     base=$(basename $checkpoint)     onmt_translate          -gpu 0          -batch_size 2048 -batch_type tokens          -beam_size 5          -model $checkpoint          -src argos-train/csv/test_crps/src-test.txt.sp          -tgt argos-train/csv/test_crps/tgt-test.txt.sp          -output run/wmt/test.ru.hyp_${base%.*}.sp done  echo "Step 003 Декодируем перевод из токенов обратно в текст"  for checkpoint in run/openmt.model_step*.pt; do     base=$(basename $checkpoint)     spm_decode          -model=run/sentencepiece.model          -input_format=piece          < run/wmt/test.ru.hyp_${base%.*}.sp          > run/wmt/test.ru.hyp_${base%.*} done  echo "Step 004 Сравним два корпуса по оценке BLEU Score"  for checkpoint in run/openmt.model_step*.pt; do     echo "$checkpoint"     base=$(basename $checkpoint)     sacrebleu argos-train/csv/test_crps/tgt-test.txt < run/wmt/test.ru.hyp_${base%.*} done  echo "Step End"

По итогам обучения моя модель получила метрику BLEU: 21.6

Для сравнения с другим переводчиком, я перевел 1 млн предложений из тестового корпуса Yandex через библиотеку translators, переводчиком Google Translate.

Отдельно сравнил качество с помощью команды:

#!/bin/bash sacrebleu argos-train/csv/test_crps/tgt-test.txt < argos-train/csv/test_crps/tgt-test_google.txt

В итоге получил метрику BLEU Score полученного перевода бесплатного Google переводчика BLEU: 18.7

Что означает, что полученная мною модель переводит с русского на английский лучше, чем бесплатный Google Translate.

Этап 5: Упаковываем модель в Argos Translate

Для упаковки модели в формат Argos Translate, необходимо выполнить ряд преобразований.

  1. Конвертация модели из checkpoint:

    #!/bin/bash ./../OpenNMT-py/tools/average_models.py -m run/openmt.model_step_100000.pt run/openmt.model_step_100000.pt -o run/averaged.pt
  2. Квантизация модели:

#!/bin/bash ct2-opennmt-py-converter --model_path run/averaged.pt --output_dir run/model --quantization int8
  1. Конвертация модели в формат argos translate:

    #!/usr/bin/env python3  from pathlib import Path import json import subprocess import shutil import sys  import argostrain from argostrain.dataset import * from argostrain import data from argostrain import opennmtutils from argostrain import settings  import stanza  from_code = input("From code (ISO 639): ") to_code = input("To code (ISO 639): ") from_name = input("From name: ") to_name = input("To name: ") version = input("Version: ") package_version = version argos_version = "1.5"  package_version_code = package_version.replace(".", "_") model_dir = f"translate-{from_code}_{to_code}-{package_version_code}" model_path = Path("run") / model_dir  subprocess.run(["mkdir", model_path])  subprocess.run(["cp", "-r", "run/model", model_path])  subprocess.run(["cp", "run/sentencepiece.model", model_path])  # Include a Stanza sentence boundary detection model stanza_model_located = False stanza_lang_code = from_code while not stanza_model_located:     try:         stanza.download(stanza_lang_code, dir="run/stanza", processors="tokenize")         stanza_model_located = True     except:         print(f"Could not locate stanza model for lang {stanza_lang_code}")         print(             "Enter the code of a different language to attempt to use its stanza model."         )         print(             "This will work best for with a similar language to the one you are attempting to translate."         )         print(             "This will require manually editing the Stanza package in the finished model to change its code"         )         stanza_lang_code = input("Stanza language code (ISO 639): ")   subprocess.run(["cp", "-r", "run/stanza", model_path])  subprocess.run(["cp", "run/metadata.json", model_path]) subprocess.run(["cp", "run/README.md", model_path])  package_path = (     Path("run") / f"translate-{from_code}_{to_code}-{package_version_code}.argosmodel" )  shutil.make_archive(model_dir, "zip", root_dir="run", base_dir=model_dir) subprocess.run(["mv", model_dir + ".zip", package_path])  # Make .argoscheckpoint zip  latest_checkpoint = opennmtutils.get_checkpoints()[-1] print(latest_checkpoint) print(latest_checkpoint.name) print(latest_checkpoint.num)  print(f"Package saved to {str(package_path.resolve())}")

Далее мы получаем готовую модель файла в виде "translate-en_ru-1_7.argosmodel", которую можно подгрузить и использовать в продукте Argos Translate.

В качестве заключения

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

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

Так как продукт Argos Translate является бесплатным, то я поделился с сообществом своей обученной моделью в комьюнити продукта. Разработчики Argos Translate приняли мою модель Russian - English и включили в основной репозиторий моделей машинного перевода в качестве основной модели под версией 1.7.

Если у вас есть идеи, как еще можно улучшить качество перевода данной модели, пишите их в комментариях, и мы вместе сможем еще сильнее улучшить данную модель!

Эксперт по Машинному обучению в IT-компании Lad.


Источник: habr.com

Комментарии: