Я хочу, чтобы spaCy
использовал границы сегментации предложения, которые я предоставляю вместо собственной обработки.
Например:
get_sentences("Bob meets Alice. @SentBoundary@ They play together.")
# => ["Bob meets Alice.", "They play together."] # two sents
get_sentences("Bob meets Alice. They play together.")
# => ["Bob meets Alice. They play together."] # ONE sent
get_sentences("Bob meets Alice, @SentBoundary@ they play together.")
# => ["Bob meets Alice,", "they play together."] # two sents
Это то, что я до сих пор (заимствование из документации здесь):
import spacy
nlp = spacy.load('en_core_web_sm')
def mark_sentence_boundaries(doc):
for i, token in enumerate(doc):
if token.text == '@SentBoundary@':
doc[i+1].sent_start = True
return doc
nlp.add_pipe(mark_sentence_boundaries, before='parser')
def get_sentences(text):
doc = nlp(text)
return (list(doc.sents))
Но я получаю следующие результаты:
# Ex1
get_sentences("Bob meets Alice. @SentBoundary@ They play together.")
#=> ["Bob meets Alice.", "@SentBoundary@", "They play together."]
# Ex2
get_sentences("Bob meets Alice. They play together.")
#=> ["Bob meets Alice.", "They play together."]
# Ex3
get_sentences("Bob meets Alice, @SentBoundary@ they play together.")
#=> ["Bob meets Alice, @SentBoundary@", "they play together."]
Ниже приводятся основные проблемы, с которыми я сталкиваюсь:
@SentBoundary@
token.spaCy
из расщепления, если @SentBoundary@
нет.Следующий код работает:
import spacy
nlp = spacy.load('en_core_web_sm')
def split_on_breaks(doc):
start = 0
seen_break = False
for word in doc:
if seen_break:
yield doc[start:word.i-1]
start = word.i
seen_break = False
elif word.text == '@SentBoundary@':
seen_break = True
if start < len(doc):
yield doc[start:len(doc)]
sbd = SentenceSegmenter(nlp.vocab, strategy=split_on_breaks)
nlp.add_pipe(sbd, first=True)
def get_sentences(text):
doc = nlp(text)
return (list(doc.sents)) # convert to string if required.
# Ex1
get_sentences("Bob meets Alice. @SentBoundary@ They play together.")
# => ["Bob meets Alice.", "They play together."] # two sentences
# Ex2
get_sentences("Bob meets Alice. They play together.")
# => ["Bob meets Alice. They play together."] # ONE sentence
# Ex3
get_sentences("Bob meets Alice, @SentBoundary@ they play together.")
# => ["Bob meets Alice,", "they play together."] # two sentences
Правильно было проверить SentenceSegmenter, а не ручную настройку границы (примеры здесь). Этот вопрос github был также полезен.