spaCy добавляет указатель на другой токен в пользовательском компоненте - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь найти способ реализации token.head и token.children.Я хочу воспроизвести эту реализацию при добавлении пользовательского компонента в мой конвейер spaCy для SRL.

То есть каждый токен может указывать на предикаты, для которых он является аргументом.Интуитивно, я думаю, что это должно работать как token.children, в котором (я думаю) он возвращает генератор фактически зависимых дочерних объектов токенов.

Я предполагаю, что я не должен просто хранить атрибут этого токенапоскольку это не кажется эффективным с точки зрения памяти и довольно избыточным.Кто-нибудь знает правильный способ реализации этого?Или это косвенно обрабатывается методом spaCy Underscore.set?

Спасибо!

1 Ответ

0 голосов
/ 05 июня 2018

Объект Token - это только представление - это что-то вроде удержания ссылки на объект Doc и индекса для токена.Объект Span тоже такой.Это гарантирует, что есть единственный источник правды и только одна копия данных.

Вы можете найти определение ключевых структур в файле spacy/structs.pxd.Это определяет атрибуты структуры TokenC.Затем объект Doc содержит их массив и длину.Объекты Token создаются на лету, когда вы индексируете в Doc.Определение данных для объекта Doc можно найти в spacy/tokens/doc.pxd, а реализация доступа к токену - в spacy/tokens/doc.pyx.

Способ кодирования дерева разбора в spaCy немного неудовлетворителен.Я поставил вопрос об этом на трекере - похоже, что должно быть лучшее решение.

Мы кодируем смещение головы относительно токена.Так что если вы сделаете &doc.c[i] + doc.c[i].head, вы получите указатель на голову.Эта часть в порядке.Немного страннее то, что мы отслеживаем левый и правый края поддерева токена и количество прямых левых и правых потомков.Чтобы получить самого правого или самого левого ребенка, мы перемещаемся в пределах этого региона.На практике это работает довольно хорошо, потому что мы имеем дело с непрерывным блоком памяти, и циклы в Cython быстрые.Но это все еще выглядит немного неуклюже.

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

Нет способа прикрепить «настоящие» атрибуты к объектам Doc или Token, так как они определены как типы уровня C - так что ихструктура определяется статически;это не динамично.Вы можете создать подкласс Doc, но это довольно уродливо: вам нужно также создать подкласс.

Вот почему у нас есть атрибуты подчеркивания и словарь doc.user_data.Это действительно единственный способ расширить объекты.К счастью, вы не должны столкнуться с проблемой избыточности данных.Ничего не хранится на объектах Token.Определения ваших расширений хранятся глобально, в классе Underscore.Данные хранятся в объекте Doc, даже если он применяется к токену - опять же, Token является представлением.Он не может иметь ничего.Так что Doc должен отметить, что у нас есть какое-то значение, присвоенное токену i.

Если вы определяете древовидную систему навигации, я бы рекомендовал рассмотреть ее как собственный класс Cython,так что вы можете использовать структуры.Если вы используете нативные типы Python, он будет довольно медленным и довольно большим.Если вы упакуете данные в массивы numpy, представление будет более компактным, но написание кода будет довольно жалким опытом, и производительность, вероятно, будет невелика.

Короче:

  • Определите свои собственные типы в Cython.Поместите данные в структуру, принадлежащую классу cdef, и предоставьте методы доступа к классу.

  • Используйте атрибуты подчеркивания для доступа к данным из объектов spaCy Doc, Span и Token.

  • Если у вас есть привлекательный API для SRL, и данные можно компактно кодировать в структуру TokenC, мы рассмотрим добавление этой функции в качестве встроенной поддержки.

...