Как импортировать текст из формата CoNNL с именованными объектами в spaCy, вывести объекты с моей моделью и записать их в тот же набор данных (с Python)?

У меня есть набор данных в формате CoNLL NER, который в основном представляет собой файл TSV с двумя полями. Первое поле содержит токены из некоторого текста - по одному токену на строку (каждый символ пунктуации также считается там токеном), а второе поле содержит теги именованных сущностей для токенов в формате BIO.

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

nlp = spacy.load("some_spacy_ner_model")
text = "text from conll dataset"
doc = nlp(text)

Также мне удалось преобразовать набор данных CoNLL в формат json spaCy с помощью этой команды CLI:

python -m spacy convert conll_dataset.tsv /Users/user/docs -t json -c ner

Но я не знаю, что делать дальше. Не удалось найти, как загрузить этот json файл в формат spaCy Doc. Я пробовал этот фрагмент кода (нашел его в документации spaCy):

from spacy.tokens import Doc
from spacy.vocab import Vocab
doc = Doc(Vocab()).from_disk("sample.json")

но выдает ошибку ExtraData: unpack(b) received extra data..

Также я не знаю, как записать числа из объекта doc обратно в тот же файл TSV, выравнивая токены и теги NER с существующими строками файла TSV.

А вот выдержка из файла TSV в качестве примера данных, с которыми я имею дело:

The O
epidermal   B-Protein
growth  I-Protein
factor  I-Protein
precursor   O
.   O

person Sergey Zakharov    schedule 09.10.2019    source источник
comment
Большое спасибо за этот вопрос!   -  person ChrisChross    schedule 26.11.2020


Ответы (1)


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

Затем вы можете преобразовать необработанные GoldParse аннотации в нужный формат и вручную добавить их в Doc. Вот набросок сущностей:

import spacy
from spacy.gold import GoldCorpus
nlp = spacy.load('en')
gc = GoldCorpus("file.json", "file.json")
for doc, gold in gc.dev_docs(nlp, gold_preproc=True):
    doc.ents = spacy.gold.spans_from_biluo_tags(doc, gold.ner)
    spacy.displacy.serve(doc, style='ent')

dev_docs() используется здесь, потому что он загружает документы без дальнейшего перемешивания, дополнения и т. Д., Как это может быть для обучения, и загружает файл во втором аргументе GoldCorpus. GoldCorpus требуется файл обучения и файл разработки, поэтому первый аргумент необходим, но мы больше ничего не делаем с данными, загруженными из первого аргумента.

А пока используйте для этого spacy 2.1.8, поскольку в 2.2.1 есть ошибка для параметра gold_preproc. gold_preproc сохраняет исходную токенизацию, а не повторно токенизирует с пространством. Если вы не заботитесь о сохранении токенизации, вы можете установить gold_preproc=False, и тогда предоставленные spacy модели будут работать немного лучше, потому что токенизация идентична.

person aab    schedule 09.10.2019
comment
Спасибо за ответ, вроде работает! Мне удалось загрузить набор данных, а затем ввести новые теги NER с другой моделью. Не могли бы вы дать мне совет, как мне сохранить результаты обратно в формат CoNLL с тегами IOB (tsv с двумя полями - токен и его тег)? - person Sergey Zakharov; 11.10.2019
comment
Теги IOB доступны через token.ent_iob_ и token.ent_type_. См. Атрибуты токена здесь: spacy.io/api/token#attributes - person aab; 11.10.2019