Преобразование документов в векторы

Преобразование документов через командную строку

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

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

Для сегментации предложений можно использовать любые открытые решения: spacy, razdel.

Пример сегментации текста с помощью 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)

Запуск преобразования

Директория с текстами texts должна находится в рабочей директории, также необходимо собрать список всех файлов с помощью команды.

$ find texts/ -name "*.txt" > files.txt

В рабочую директорию также необходимо выкачать предобученную модель models.def.pt.

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

docker run  --gpus=1  --rm  -v $(pwd):/temp/ -w /temp \
semvectors/doc_enc:0.1.2 \
docenccli docs -i /temp/files.txt -o /temp/vecs -m /temp/models.def.pt

Результаты преобразования

Вектора будут сохранены в директории vecs вместе с именами файлов, с помощью функции numpy.savez. Пример загрузки векторов из этих файлов:

import numpy as np

obj = np.load('vecs/0000.npz')
print(obj['ids'][:2])
print(obj['embs'][:2])

Основные опции docenccli

docenccli поддерживает следующие опции:

  • --output_dir или -o - директорию, в которую будет сохранен результат.

  • --model_path или -m - путь к файлу с моделью.

  • --gpu или -g - номер GPU устройства, на котором будет осуществляться вывод (по умолчанию 0).

  • --batch_size или -b - документы будут разбиваться на батчи размером batch_size (по умолчанию 1000).

  • --max_sents_per_batch или -l - размер мини-батча при преобразовании в векторы (по умолчанию 2048).

  • --save_as_fp16 - сохранять вектора с типом float16 (по умолчанию false).

Преобразование документов с помощью программного интерфейса

Пример кода, использующий API библиотеки src/enc.py:

#!/usr/bin/env python3

from doc_enc.doc_encoder import DocEncoder, DocEncoderConf

conf = DocEncoderConf(
        model_path='/work/models.def.pt',
        use_gpu=0
)
doc_encoder = DocEncoder(conf)

docs = [['simple sentence','second sentence'], ['Sentences are already segmented']]

result = doc_encoder.encode_docs(docs)
print("shape", result.shape)
print(result)

Для запуска этого кода выполните (в рабочей директории должна лежать предобученная модель models.def.pt):

docker run -v $(pwd):/work -w /work  --gpus=1  --rm \
semvectors/doc_enc:0.1.2 python src/enc.py

Также вы можете создать докер-образ на основе образа библиотеки. Простейший проект будет включать два файла: Dockerfile и src/enc.py. Содержимое Dockerfile:

FROM semvectors/doc_enc:0.1.2

COPY src/ .

ENTRYPOINT [ "python", "./enc.py" ]

Собрать и запустить код можно этими командами:

$ docker build -t temp .
$ docker run -v $(pwd):/work  --gpus=1  --rm temp:latest

Описание API

DocEncoder - основной класс, предоставляющий несколько методов по преобразованию документов/предложений в вектора. При создании класса необходимо передать экземпляр с настройками DocEncoderConf. Структура DocEncoderConf содержит следующие параметры:

  • model_path - путь к предобученной модели (по умолчанию не задан).

  • use_gpu - номер GPU, на которой будет проходить обучение (по умолчанию 0).

  • async_batch_gen - количество асинхронных процессов, которые будут задействованы в подготовки мини-батчей для обучения (по умолчанию 2).

  • max_sents - максимальное количество предложений в мини-батче (по умолчанию 2048).

  • max_tokens - максимальное количество токенов в мини-батче (по умолчанию 96_000).

Список методов DocEncoder

  • encode_sents - преобразует список предложений в вектора.

    Возвращаемое значение - numpy массив.

  • encode_sents_stream - кодирует поток предложений (представленных с помощью генератора) в векторы. Принимает на вход: sents_generator, sents_batch_size. sents_generator – генератор, который должен возвращать текст предложений. Также генератор может возвращать дополнительные объекты. Эти объекты будут возвращены вместе с соответствующими им векторами. Это может быть удобно в случае, если с каждым предложением связан идентификатор или какая-нибудь иная информация. Пример реализации функции sents_generator:

    def sents_generator(sent_file):
        with open(sent_file, 'r', encoding='utf8') as fp:
            for l in fp:
                sent_id, sent = l.rstrip().split('\t', 1)
                yield sent, sent_id
    

    Количество кодируемых за раз предложений определяется параметром sents_batch_size. Полученный из генератора список предложений передается в encode_sents.

    Этот метод является генератором, он возвращает кортеж состоящий из трех элементов: список текстов предложений, numpy массив и список дополнительных объектов, которые были возвращены пользовательским генератором.

  • encode_docs_from_path_list кодирует тексты из файловой системы в векторы. Принимает на вход список путей к текстовым файлам. Тексты должны быть предварительно сегментированы, т.е. каждое предложение должно быть размещено на отдельной строке.

    Возвращаемое значение - numpy массив.

  • encode_docs_from_dir принимает на вход путь к директории с текстовыми файлами. Рекурсивный обход вложенных директорий не поддерживается. Тексты должны быть предварительно сегментированы, т.е. каждое предложение должно быть размещено на отдельной строке

    Возвращаемое значение - кортеж, содержащий список путей к файлам и numpy массив.

  • encode_docs - кодирует список документов в векторное представление. Документ должен быть представлен как список предложений или текст (строка), в котором каждое предложение размещено на новой строке.

    Возвращаемое значение - numpy массив.

  • encode_docs_stream преобразует поток документов в вектора. Принимает на вход: doc_id_generator, fetcher, batch_size. sents_generator – генератор, который должен возвращать идентификаторы документов. fetcher - это функция, в которую будет передаваться порция идентификаторов, для которых она должна вернуть кортеж, состоящий из двух элементов: индекс документа в списке, текст документа. fetcher может быть генератором, как например реализованный в библиотеке file_path_fetcher, используемый при расположение файлов в файловой системе. Пример реализации функции fetcher:

    def file_path_fetcher(paths):
        for idx, path in enumerate(paths):
            with open(path, 'r', encoding='utf8') as fp:
                sents = []
                for s in fp:
                    sents.append(s.rstrip())
                yield idx, sents
    

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

    Этот метод является генератором, он возвращает кортеж состоящий из двух элементов: список идентификаторов документов и numpy массив.