Объект 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
, мы рассмотрим добавление этой функции в качестве встроенной поддержки.