Как определить границы предложения с помощью OpenNLP и stringi?
Я хочу разбить следующий string
на предложения:
library(NLP) # NLP_0.1-7
string <- as.String("Mr. Brown comes. He says hello. i give him coffee.")
Я хочу продемонстрировать два разных способа. Один из пакетов openNLP
:
library(openNLP) # openNLP_0.2-5
sentence_token_annotator <- Maxent_Sent_Token_Annotator(language = "en")
boundaries_sentences<-annotate(string, sentence_token_annotator)
string[boundaries_sentences]
[1] "Mr. Brown comes." "He says hello." "i give him coffee."
И второе происходит из пакета stringi
:
library(stringi) # stringi_0.5-5
stri_split_boundaries( string , opts_brkiter=stri_opts_brkiter('sentence'))
[[1]]
[1] "Mr. " "Brown comes. "
[3] "He says hello. i give him coffee."
После этого второго пути мне нужно подготовить предложения, чтобы удалить лишние пробелы или снова разбить новую строку на предложения. Могу ли я отрегулировать функцию stringi для улучшения качества результата?
Когда речь идет о больших данных, openNLP
(очень) медленнее, чем stringi
.
Есть ли способ объединить stringi
(- > fast) и openNLP
(- > качество)?
Ответы
Ответ 1
Анализ границы текста (в данном случае, граница предложения) в ICU (и, следовательно, в stringi) регулируется правилами, описанными в Unicode UAX29, см. также Руководство пользователя ICU по теме. Мы читаем:
[Правила Unicode] не могут обнаружить такие случаи, как "... Mr. Jones..."; для обнаружения таких случаев потребуется более сложный пошив.
Другими словами, это невозможно сделать без специального словаря без остановок, который фактически реализован в openNLP
. Таким образом, несколько возможных сценариев включения stringi для выполнения этой задачи включают:
- Используйте
stri_split_boundaries
, а затем напишите функцию, определяющую, к чему должны быть присоединены неправильно разделенные маркеры.
- Вручную вводить неразрывные пробелы в текст (возможно, после точек, следующих и т.д., г-н, т.е. и т.д. (обратите внимание, что это действительно необходимо при подготовке документов в LaTeX - иначе вы получите слишком большие пробелы между словами).
- Включите пользовательский список без остановок в регулярное выражение и примените
stri_split_regex
.
и т.д.
Ответ 2
Это может быть жизнеспособным регулярным выражением:
string <- "Mr. Brown comes. He says hello. i give him coffee."
stringi::stri_split_regex(string, "(?<!\\w\\.\\w.)(?<![A-Z][a-z]\\.)(?<=\\.|\\?|\\!)\\s")
## [[1]]
## [1] "Mr. Brown comes." "He says hello." "i give him coffee."
Выполняется менее эффективно:
string <- "Mr. Brown comes! He says hello. i give him coffee. i will got at 5 p. m. eastern time. Or somewhere in between"