Подготовка наборов данных¶
В данном разделе описан процесс сбора и подготовки данных для обучения.
Параллельные предложения¶
Вы можете воспользоваться готовым датасетом русско-английских параллельных предложений:
Русско-английские пары параллельных предложений были собраны из нескольких источников. Часть из них доступна на сайте 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"