Определите предложения в тексте - PullRequest
4 голосов
/ 17 мая 2019

У меня возникли проблемы с правильным определением предложений в тексте для конкретных угловых случаев:

  1. Если используется точка, точка, точка, это не будет сохранено.
  2. Если задействовано ".
  3. Если предложение случайно начинается со строчной буквы.

Так я до сих пор идентифицировал предложения в тексте (источник: Переформатирование субтитров, чтобы завершить полное предложение ):

re.findall part в основном ищет фрагмент str, который начинается с заглавной буквы [A-Z], затем что-нибудь, кроме знаков препинания, а затем заканчивается пунктуацией, [\.?!].

import re
text = "We were able to respond to the first research question. Next, we also determined the size of the population."
    for sentence in re.findall(r'([A-Z][^\.!?]*[\.!?])', text):
        print(sentence + "\n")
We were able to respond to the first research question.

Next, we also determined the size of the population.

Угловой корпус 1: Точка, Точка, Точка

Точка, точка, точка не сохраняется, поскольку не дано никаких инструкций о том, что делать, если в строке появляются три точки. Как это можно изменить?

text = "We were able to respond to the first research question... Next, we also determined the size of the population."
for sentence in re.findall(r'([A-Z][^\.!?]*[\.!?])', text):
    print(sentence + "\n")
We were able to respond to the first research question.

Next, we also determined the size of the population.

Угловой корпус 2: "

Символ " успешно удерживается в предложении, но, как и точка после пунктуации, он будет удален в конце.

text = "We were able to respond to the first \"research\" question: \"What is this?\" Next, we also determined the size of the population."
for sentence in re.findall(r'([A-Z][^\.!?]*[\.!?])', text):
    print(sentence + "\n")
We were able to respond to the first "research" question: "What is this?

Next, we also determined the size of the population.

Угловой регистр 3: начало предложения в нижнем регистре

Если предложение случайно начинается со строчной буквы, предложение будет проигнорировано. Цель состоит в том, чтобы определить, что предыдущее предложение закончилось (или текст только что начался), и, следовательно, новое предложение должно начинаться.

text = "We were able to respond to the first research question. next, we also determined the size of the population."
for sentence in re.findall(r'([A-Z][^\.!?]*[\.!?])', text):
    print(sentence + "\n")

We were able to respond to the first research question.

Большое спасибо за любую помощь!

Edit:

Я проверял это:

import spacy
from spacy.lang.en import English

raw_text = 'Hello, world. Here are two sentences.'
nlp = English()
doc = nlp(raw_text)
sentences = [sent.string.strip() for sent in doc.sents]

... но я получаю:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-157-4fd093d3402b> in <module>()
      6 nlp = English()
      7 doc = nlp(raw_text)
----> 8 sentences = [sent.string.strip() for sent in doc.sents]

<ipython-input-157-4fd093d3402b> in <listcomp>(.0)
      6 nlp = English()
      7 doc = nlp(raw_text)
----> 8 sentences = [sent.string.strip() for sent in doc.sents]

doc.pyx in sents()

ValueError: [E030] Sentence boundaries unset. You can add the 'sentencizer' component to the pipeline with:

nlp.add_pipe (nlp.create_pipe ('круглое предложение)) В качестве альтернативы, добавьте анализатор зависимостей или установите границы предложений, установив документ [я] .is_sent_start.

Ответы [ 4 ]

2 голосов
/ 17 мая 2019

Вы можете изменить свое регулярное выражение в соответствии с вашими угловыми случаями.

Прежде всего, вам не нужно бежать . внутрь []

Для первого углового случая вы можете жадно сопоставить жетон конечного отправления с [.!?]*

Для второго вы можете потенциально соответствовать " после [.!?]

Для последнего вы можете начать отправку с верхнего или нижнего:

import re

regex = r'([A-z][^.!?]*[.!?]*"?)'

text = "We were able to respond to the first research question... Next, we also determined the size of the population."
for sentence in re.findall(regex, text):
    print(sentence)
print()

text = "We were able to respond to the first \"research\" question: \"What is this?\" Next, we also determined the size of the population."
for sentence in re.findall(regex, text):
    print(sentence)
print()

text = "We were able to respond to the first research question. next, we also determined the size of the population."
for sentence in re.findall(regex, text):
    print(sentence)

Объяснение

  • [A-z], каждое совпадение должно начинаться с буквы, верхней или нижней.
  • [^.?!]*, он жадно совпадает с любым символом, который не является ., ? или ! (символ окончания отправления)
  • [.?!]*, он жадно соответствует конечным символам, поэтому ...??!!??? будет совпадать как часть отправления
  • "?, в конце концов оно соответствует кавычке в конце отправления

Угловой шкаф 1:

Мы смогли ответить на первый вопрос исследования ... Далее мы также определили численность населения.

Угловой шкаф 2:

Мы смогли ответить на первый «исследовательский» вопрос: «Что это?» Далее мы также определили численность населения.

Угловой шкаф 3:

Мы смогли ответить на первый вопрос исследования. Далее мы также определили численность населения.

2 голосов
/ 17 мая 2019

Вы можете использовать некоторые промышленные пакеты для этого. Например, spacy имеет очень хороший токенизатор предложений.

from __future__ import unicode_literals, print_function
from spacy.en import English

raw_text = 'Hello, world. Here are two sentences.'
nlp = English()
doc = nlp(raw_text)
sentences = [sent.string.strip() for sent in doc.sents]

Ваши сценарии:

  1. результат -> ['We were able to respond to the first research question...', 'Next, we also determined the size of the population.']

  2. результат -> ['We were able to respond to the first "research" question: "What is this?"', 'Next, we also determined the size of the population.']

  3. результат -> ['We were able to respond to the first research question.', 'next, we also determined the size of the population.']

1 голос
/ 17 мая 2019

Вы можете использовать nltk sent_tokenize. Это позволит избежать большей части Хейзел.

from nltk import sent_tokenize
# Corner Case 1: Dot, Dot, Dot
text_dot_dot_dot = "We were able to respond to the first research question... Next, we also determined the size of the population."
print("Corner Case 1: ", sent_tokenize(text_dot_dot_dot))
# Corner Case 1: "
text_ = "We were able to respond to the first \"research\" question: \"What is this?\" Next, we also determined the size of the population."
print("Corner Case 2: ", sent_tokenize(text_))
# Corner Case 1: lower case
text_lower = "We were able to respond to the first research question. next, we also determined the size of the population."
print("Corner Case 2: ", sent_tokenize(text_lower))

Результат:

Corner Case 1:  ['We were able to respond to the first research question... Next, we also determined the size of the population.']
Corner Case 2:  ['We were able to respond to the first "research" question: "What is this?"', 'Next, we also determined the size of the population.']
Corner Case 2:  ['We were able to respond to the first research question.', 'next, we also determined the size of the population.']
0 голосов
/ 17 мая 2019

Попробуйте это регулярное выражение: ([A-Z] [^.!?] * [.!?] + [ "]?)

'+' означает один или несколько

'?' означает ноль или более

Это должно пройти все 3 угловых случая, которые вы упомянули выше

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...