Преобразование файла CONLL в список объектов Doc

#spacy

#spacy

Вопрос:

Есть ли способ преобразовать файл CONLL в список Doc объектов без необходимости разбора предложения с использованием nlp объекта. У меня есть список аннотаций, которые я должен передать автоматическому компоненту, использующему Doc объекты в качестве входных данных. Я нашел способ создать документ:

     doc = Doc(nlp.vocab, words=[...])
  

И что я могу использовать from_array функцию для воссоздания других лингвистических функций. Этот массив можно воссоздать, используя значение индекса из StringStore object , я успешно создал объект Doc с информацией о ЛЕММЕ и ТЕГЕ, но не могу воссоздать данные HEAD. Мой вопрос заключается в том, как передать данные заголовка в объект Doc, используя метод from_array.

Запутанная вещь в заголовке заключается в том, что для предложения с такой структурой:

 Ona 2
je 2
otišla 2
u 4
školu 2
. 2
  

Вывод этого фрагмента кода:

 from spacy.attrs import TAG, HEAD, DEP
doc.to_array([TAG, HEAD, DEP])
  

является:

 array([[10468770234730083819,                    2,                  429],
       [ 5333907774816518795,                    1,                  405],
       [11670076340363994323,                    0,  8206900633647566924],
       [ 6471273018469892813,                    1,  8110129090154140942],
       [ 7055653905424136462, 18446744073709551614,                  435],
       [ 7173976090571422945, 18446744073709551613,                  445]],
      dtype=uint64)
  

Я не могу сопоставить центральный столбец вывода from_array с приведенной выше структурой дерева зависимостей.

Заранее спасибо за помощь,

Даниэль

Ответ №1:

Хорошо, итак, я, наконец, взломал его, кажется, что head — index, если индекс меньше head и 18446744073709551616 — index в противном случае. Это функция, которую я использовал, если кому-то еще это было нужно:

 import numpy as np
from spacy.tokens import Doc
docs = []
for sent in sents:
    generated_doc = Doc(doc.vocab, words=[word["word"] for word in sent])
    heads = []
    for idx, word in enumerate(sent):
        if word["pos"] not in doc.vocab.strings:
            doc.vocab.strings.add(word["pos"])
        if word["dep"] not in doc.vocab.strings:
            doc.vocab.strings.add(word["dep"])
        if word["head"] >= idx:
            heads.append(word["head"] - idx)
        else:
            heads.append(18446744073709551616-idx)
    
    np_array = np.array([np.array([doc.vocab.strings[word["pos"]], heads[idx], doc.vocab.strings[word["dep"]]], dtype=np.uint64) for idx, word in enumerate(sent)], dtype=np.uint64)
    generated_doc.from_array([TAG, HEAD, DEP], np_array)
    docs.append(generated_doc) 
  

Комментарии:

1. Заголовки в doc.to_array() являются относительными, а не абсолютными заголовками, а затем они преобразуются в uint64 , поэтому отрицательные заголовки (голова влево, а не вправо) в конечном итоге выглядят вот так.

2. @aab спасибо за ответ, да, именно так 🙂 , хотя я не нашел никакой документации по этому вопросу.

3. Нет, это скорее внутренний метод. Типичный способ — создать Doc файл с words помощью and spaces (вы можете использовать get_words_and_spaces from spacy.util , если у вас есть words and text ), а затем задать свойства Doc непосредственно как в doc[3].head = doc[2] or doc[10].tag_ = "ABC" .

4. В предстоящей версии spacy v3 будет больше методов преобразования, которые преобразуют в Doc . Здесь представлен предварительный просмотр полноценного конвертера CoNLL-U с некоторой дополнительной обработкой NER в столбце MISC и объединением многословных токенов: github.com/explosion/spaCy/blob /…

5. Уважаемый @aab, не знал, что я могу добавлять свойства напрямую, у меня было некоторое представление о том, что документы несколько неизменяемы. Большое спасибо за советы 🙂