При поиске параллельных корпусов для своих нужд, — это может быть обучение модели машинного перевода или изучение иностранного языка, можно столкнуться с тем, что их не так уж и много, особенно, если речь идет не об английском, а каком-то редком языке. В этой статье мы попробуем создать свой корпус для популярной языковой пары русский-немецкий на основе романа Ремарка "Три товарища". Любителям параллельного чтения книг и разработчикам систем машинного перевода посвящается. Такая задача называется выравниванием текстов и может быть до какой-то степени решена следующими способами: В качестве моделей, из которых мы будем брать эмбеддинги, возьмем Universal Sentence Encoder, Sentence Transformers и недавно вышедший LaBSE (Language Agnostic BERT Sentence Embeddings). Как бы не была хороша модель, одна она не справится, потому что при переводе текста с одного языка на другой переводчик частенько может объединять два предложение в одно, а одно сложное предложение разбивать на несколько простых. Особенно это характерно при переводе с русского на китайский. Для таких случаев можно придумать эвристики, наподобие такой — если длинна предложений отличается больше чем в два раза, то либо разбиваем одно из них по знаку препинания, либо склеиваем короткое со следующим или предыдущим. Потом оставляем наиболее близкие пары. Модели, которые мы будем использовать, являются не только мультиязыковыми, но и выровненными, это означает, что, если им на вход подавать предложения на разных языках, то вектора все равно будут сохранять между собой семантическое расстояние, — вектор для "I love cats" будет близок вектору "Я люблю кошек". Разумеется, модель должна поддерживать необходимые нам языки, список таких приведен в таблице 1. Самый быстрый инференс у USE, если вам нужны более-менее редкие языки, то используйте xlm-r-100langs-bert-base или LaBSE. *В документации sentence transformers отмечается, что модели также дают неплохой результат для языков вне поддерживаемого списка. Чтобы любой мог сразу же поиграться с моделями и что-то сделать самостоятельно, эксперименты будем проводить в Colab'е, общедоступном jupyter блокноте. Все ссылки будут в конце статьи. Нам понадобятся библиотеки для разбиения текстов на предложения и загрузки предобученных моделей. Установим их в нашу среду приступим к выравниванию. Итак, возьмем первую главу замечательного романа "Три товарища" в оригинале (1936 год) и в переводе И. Шрайбера и
Л. Яковленко (1959 год). Первым шагом будет разбить текст на предложения и посмотреть насколько сильно они отличаются по количеству. Так это просто сырые тексты из интернета, предварительно немного почистим текст. По предложениям текст разобъем razdel'ом (бывшая библиотека natasha), для немецкого языка такой способ тоже подойдет, если мы позаботимся о кавычках (в немецком языке они обратные — »«). Предложения на русском: И на немецком: По количеству их получилось 570 на русском против 561-го на немецком. Так как количество предложений различается не сильно, то скорее всего получится выровнять тексты с хорошим качеством. Чтобы не грузить в модель сразу все вектора будем считать их батчами, при этом введем специальный коэффициент, который будет учитывать разницу в колчестве выравниваемых предложений для различных языков. Это необходимо, когда разница в количестве бдует более существенная. В качестве модели возьмем sentence-transformers (distiluse-base-multilingual-cased), так как она поддерживает немецкий и русский языки, относительно немного весит (~500 Mb), и дает очень хорошие вектора. Полученные эмбеддинги представляют собой вектора размерностью 512. Посчитаем матрицу состоящую из косинусных близостей между парами векторов. Обсчитывать будем не все пары, а только те, которые находятся в окне — какое-то количество предложений вперед и назад от "оси выравнивания". Под осью понимается главная диагональ нашей матрицы. Посмотрим сначала на матрицу близостей для первых 50 строк. Красиво будет выглядеть heatmap, построеная через seaborn.  Для каждой строки будем брать наиболее близкий вариант. После это наша матрица будем выглядеть следующим образом.  А вот так для всего текста.  Видим, что в некоторых местах модель не смогла сопоставить предложения, основные причины я вижу такие: Решать все эти проблемы можно по разному, можно взять наиболее удачные сопоставления, в них будет и авторский стиль и имена, и дообучить нашу модель на этих данных. Можно применить простые и хитрые эвристики, — если два предложения уверенно сошлись, то и то, что между ними, должно соответствовать, даже если модель не очень уверена. Пока же посмотрим, что у нас получилось. Мы получили неплохой результат, в следующий раз мы попытаемся его улучшить и попробуем выровнять текст с участием редкого языка, которого на текущий момент нет в данных моделях. Якутский? Чувашский? Предлагайте и до новых встреч! [1] Поиграйтесь в Google Colab. [2] Sentence Transformers. [3] Universal Sentence Encoder. [4] Language Agnostic BERT Sentence Encoder. ML Engineer