Подготовка наборов данных

В данном разделе описан процесс сбора и подготовки данных для обучения.

Параллельные предложения

Вы можете воспользоваться готовым датасетом русско-английских параллельных предложений:

Русско-английские пары параллельных предложений были собраны из нескольких источников. Часть из них доступна на сайте Opus:

  • News Commentary

  • TED Talks 2013

  • MultiUN

  • ParaCrawl

  • Wiki

  • JW300

  • QED

  • Tatoeba

В эти данные были добавлены предложения из параллельного корпуса Яндекса, CCmatrix, WikiMatrix и Parapat. Полная версия включает более 130 миллионов предложений. Предложения были разделены на данные для обучения, тестирования и валидации (train/test/dev). Каждое предложение было дополнено трудными негативными примерами.

Подготовка предложений

В случае если необходимо создать обучающие данные для новой языковой пары или добавить предложения определенной тематики, то необходимо следовать установленному формату. Используется формат tsv, все колонки в файлах разделены символом табуляции Файлы, из которых состоит набор данных включают в себя файлы с расширениями: tgt, src, hns и dup. Имя файла может быть одним из нескольких train/dev/test.

  • tgt, src - файлы содержащие предложения на разных языках, выравненные по номеру строки в файле. Каждая строка начинается с идентификатора, далее текст предложения.

  • hns - трудные негативные примеры (hard negatives). Этот файл является опциональным, во время обучения можно отключить его использование с помощью опции dont_use_hns. Первое число это идентификатор из файла .src, второе число это id из файла .tgt, а третья колонка это текст предложения.

  • dup - нечеткие дубликаты предложений. Предложения с этими идентификаторами должны отсутствовать в текущем мини-батче. В первой колонке находится идентификатор из файла .src, во второй список идентификаторов, разделенных пробелом, из .tgt файла. Этот файл является опциональным, во время обучения можно отключить его использование с помощью опции dont_use_dups.

Процесс подготовки трудных негативных примеров.

Датасет похожих документов

В качестве обучающих данных следует использовать пары документов с определенными отношениями сходства. Например, пары научная статья/патент и соответствующая полному тексту аннотация; пары, состоящие из научных статей, в которых одна из статей ссылается на другую; пары научных статей, содержащие большое количество общих исходящих ссылок. Один текст из пары будет считаться текстом-запросом, а все связанные с ним тексты — позитивными примерами, все остальные тексты негативными.

Вы можете воспользоваться готовыми датасетами для обучения:

Также сегментированные данные можно скачать по ссылке.

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

SimEnWiki и SimRuWiki - наборы данных, полученные путем выбора близких документов по входящим и исходящим ссылкам документов. В качестве трудных негативных примеров были добавлены документы, которые имели небольшое сходство по исходящим ссылкам. Суммарное количество пар документов превышает 35 млн. Пары предложений были разделены на данные для обучения, тестирования и валидации (train/test/dev).

Статистика и описание процесса подготовки датасетов ParalWiki, SimEnWiki, SimRuWiki.

Формат

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

Датасет состоит из csv-файла, описывающего отношение между парами текстов.

doc_id_1,title_1,doc_id_2,title_2,label[,extra,fields...]

Все записи должны быть отсортированы по doc_id_1. Если заголовка нет, то поле title_{1,2} остается пустым. В случае если, идентификаторы пар документов находятся в общем пространстве, все тексты должны находится в папке texts. Если возможны конфликты по id для документов из групп doc_id_1, doc_id_2, то документы должны находится в папках texts_1, texts_2 соответственно. Имя файла формируется на основе id: <doc_id>.txt. Опционально для каждого текста может присутствовать файл с мета-информацией: <doc_id>.json.

Структура json файла

{
"sections": [
    {
    "title": "...",
    "offsets": [
        0,
        100
    ]
    }
]
}

sections - это список всех секций. Секции не должны быть вложенными (т.е. интервалы в offsets не должны пересекаться между собой). title - заголовок секции (может быть пустым, если это абстракт или первая секция из вики) offsets - пара офсетов, по которым можно получить текст секции, т.е. следующий код должен выдавать текст секции:

t = open('some_text.text').read()
t[offsets[0]:offsets[1]]

Подготовка текстов

Тексты должны быть предварительно сегментированы на предложения. Предложение в файле должны быть разделены символами переноса строки. Пример сегментации текста с помощью spacy:

import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp('This is the first sentence. This is the second sentence.')
for sent in doc.sents:
        print(sent)

Следует отметить, что если в качестве текстов используются статьи из Википедии, то следует почистить данные: убрать из статей информацию о категориях, к которому принадлежит статья. Это можно сделать следующим образом:

for i in texts/*; do [[ $(tail -1 $i) ==  Категория:* ]] &&  sed -i '$d' "$i"  ; done
for i in texts/*; do [[ $(tail -1 $i) ==  Category:* ]] && sed -i '$d' "$i"  ; done

Токенизатор

Готовая модель, обученная на параллельных предложениях, текстах вики и текстах научных статей, доступна по ссылке.

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

[ -z "$DICT_SIZE" ] && DICT_SIZE=80000
[ -z "$SENTS_CNT" ] && SENTS_CNT=200100200
[ -z "$MODEL" ] && MODEL=bpe

base_name="${MODEL}_$((DICT_SIZE/1000))k_from_$((SENTS_CNT/1000/1000))M"
spm_train --input=<(cut -f2 -d $'\t' sents.src),<(cut -f2 -d $'\t' sents.tgt),wiki_sents \
        --pad_id=3 \
        --control_symbols='<frgb>,<frge>,<docb>,<doce>' \
        --model_prefix="${base_name}.spm" \
        --vocab_size=$DICT_SIZE \
        --character_coverage=0.9998 \
        --model_type=$MODEL \
        --input_sentence_size=$SENTS_CNT \
        --max_sentence_length=2096 \
        --shuffle_input_sentence=true \
        --train_extremely_large_corpus=true \
        --num_threads=18 &> "${base_name}.log"