Как определить границы предложений с помощью 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 (-> быстро) и openNLP (-> качество)?


person SRRussel    schedule 06.08.2015    source источник
comment
если вы не получили ответа здесь, возможно, вам повезет на корпусная лингвистика с форумом R   -  person drammock    schedule 08.08.2015
comment
Я открыл это как задачу на странице HitHub stringi: github.com/Rexamine/stringi/issues/184   -  person Tyler Rinker    schedule 11.08.2015
comment
OpenNLP и stringi отличаются друг от друга тем, как определять границы предложений. stringi работает с набором правил. И openNLP работает с моделью процесса обучения. Но я все еще не вижу, где находится горлышко бутылки...   -  person SRRussel    schedule 13.08.2015


Ответы (2)


Анализ границ текста (в данном случае границы предложения) в ICU (и, следовательно, в stringi) регулируется правилами, описанными в Unicode UAX29, см. также Руководство пользователя ICU по этой теме. Мы читаем:

[Правила Unicode] не могут обнаруживать такие случаи, как «...Mr. Джонс...»; для обнаружения таких случаев потребуется более сложная адаптация.

Другими словами, это невозможно сделать без пользовательского словаря непрерывных слов, который, собственно, и реализован в openNLP. Таким образом, несколько возможных сценариев включения stringi для выполнения этой задачи включают:

  1. Используйте stri_split_boundaries, а затем напишите функцию, определяющую, какие неправильно разделенные токены следует объединить.
  2. Вручную вводите в текст неразрывные пробелы (возможно, после точек после etc., господин, т.е. и т. д. (обратите внимание, что это в факт необходим при подготовке документов в LaTeX — в противном случае вы получите слишком большие пробелы между словами).
  3. Включите пользовательский непрерывный список слов в регулярное выражение и примените stri_split_regex.

и так далее.

person gagolews    schedule 11.08.2015
comment
Это вдохновило вас на лучшее решение ниже, которое вы, возможно, сможете включить в stringi в какой-то момент. - person Tyler Rinker; 15.08.2015

Это может быть жизнеспособным решением регулярного выражения:

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"
person Tyler Rinker    schedule 11.08.2015