Преобразование сгенерированной Spacy зависимости в формат CoNLL не может обрабатывать более одного ROOT?
Я использовал библиотеку SpaCy для генерации зависимостей и сохранения ее в формате CoNLL, используя приведенный ниже код.
import pandas as pd
import spacy
df1 = pd.read_csv('cleantweets', encoding='latin1')
df1['tweet'] = df1['tweet'].astype(str)
tweet_list = df1['tweet'].values.tolist()
nlp = spacy.load("en_core_web_sm")
for i in tweet_list:
doc = nlp(i)
for sent in doc.sents:
print('\n')
for i, word in enumerate(sent):
if word.head is word:
head_idx = 0
else:
head_idx = doc[i].head.i + 1
print("%d\t%s\t%d\t%s\t%s\t%s" % (
i+1,
word.head,
head_idx,
word.text,
word.dep_,
word.pos_,
))
Это работает, но в моем наборе данных есть несколько предложений, которые Spacy разбивает на две части, потому что у них два КОРНЯ. В результате получается два поля для одного предложения в формате CoNLL.
Пример: случайное предложение из моего набора данных: "Теанна Трамп, наверное, чище твиттер, но"
в формате CoNLL он сохраняется как:
1 trump 2 teanna compound
2 cleaner 4 trump nsubj
3 cleaner 4 probably advmod
4 cleaner 4 cleaner ROOT
5 hoe 6 twitter amod
6 cleaner 4 hoe dobj
1 but 2 but ROOT
Есть ли способ сохранить все это в одном поле вместо двух, даже если у него две КОРНИ, так что "но" становится 7-м элементом в поле номер 1? Это означает, что вместо этого это будет выглядеть так
1 trump 2 teanna compound
2 cleaner 4 trump nsubj
3 cleaner 4 probably advmod
4 cleaner 4 cleaner ROOT
5 hoe 6 twitter amod
6 cleaner 4 hoe dobj
7 but 2 but ROOT
1 ответ
Я бы рекомендовал использовать (или адаптировать) текстовый экспортер CoNLL, чтобы получить правильный формат, см.: Как сгенерировать.conllu из объекта Doc?
Парсер Spacy выполняет сегментацию предложений, и вы повторяете doc.sents
, поэтому вы увидите каждое экспортированное предложение отдельно. Если вы хотите обеспечить собственную сегментацию предложения, вы можете сделать это с помощью специального компонента, например:
def set_custom_boundaries(doc):
for token in doc[:-1]:
if token.text == "...":
doc[token.i+1].is_sent_start = True
return doc
nlp.add_pipe(set_custom_boundaries, before="parser")
Подробности (особенно о том, как обращаться с None
vs. False
vs. True
): https://spacy.io/usage/linguistic-features
Модели Spacy по умолчанию не обучаются тексту, подобному твиттеру, поэтому синтаксический анализатор, вероятно, не будет хорошо работать с границами предложений здесь.
(Пожалуйста, задавайте несвязанные вопросы как отдельные вопросы, а также просмотрите документы spacy: https://spacy.io/usage/linguistic-features)