tematica redaccion partes parrafos parrafo para oracion metodos estructura elaborar ejemplos construccion ruby text parsing split nlp
versión 3.5.0 completa de Stanford TaggerStanford CoreNLP versión 3.5.0

redaccion - ¿Cómo se analiza un párrafo de texto en oraciones?(Perferiblemente en Ruby)



partes de un parrafo (15)

¡ GRACIAS !

Realmente disfruté esta discusión, así que me interesé por el analizador sintáctico. Lo probé y escribí algunas notas sobre cómo hacer que todo funcione con Ruby and Rails.

Tratar de ir con la expresión regular fue una pesadilla ...

mis 2 centavos

¿Cómo se toma un párrafo o una gran cantidad de texto y se divide en oraciones (preferiblemente usando Ruby) teniendo en cuenta casos como Mr. y Dr. y USA? (Suponiendo que acaba de poner las oraciones en una matriz de matrices)

ACTUALIZACIÓN: Una posible solución que pensé involucra el uso de un etiquetador de partes de discurso (POST) y un clasificador para determinar el final de una oración:

Obteniendo información del Sr. Jones sintió el cálido sol en su rostro cuando salió al balcón de su casa de verano en Italia. Estaba feliz de estar vivo.

CLASIFICADOR Sr./PERSON Jones / PERSONA sintió / O el / O cálido / O sol / O en / O su / O cara / O como / O él / O pisó / O fuera / O en / O el / O balcón / O de / O his / O summer / O home / O en / O Italy / LOCATION ./O He / O was / O happy / O a / O be / O alive / O ./O

POST Sr./NNP Jones / NNP sintió / VBD el / DT cálido / JJ sol / NN en / IN his / PRP $ cara / NN como / IN él / PRP pisó / VBD out / RP en / EN el / DT balcón / NN de / IN his / PRP $ summer / NN home / NN in / IN Italy./NNP He / PRP was / VBD happy / JJ to / TO be / VB alive./IN

¿Podemos suponer, dado que Italia es un lugar, el período es el final válido de la oración? Desde que termina en "Mr." no tendría otras partes del discurso, ¿podemos suponer que este no es un período válido al final de la oración? ¿Es esta la mejor respuesta a mi pregunta?

¿Pensamientos?


¿Tal vez intentar dividirlo por un período seguido de un espacio seguido de una letra mayúscula? No estoy seguro de cómo encontrar letras mayúsculas, pero ese sería el patrón que comenzaría a buscar.

Editar: Encontrar letras mayúsculas con Ruby.

Otra edición:

Verifique la puntuación final de la oración que sigue a las palabras que no comienzan con letras mayúsculas.


Bueno, obviamente, paragraph.split(''.'') No lo cortará

#split tomará una expresión regular como respuesta, por lo que puede intentar usar un lookbehind de ancho cero para buscar una palabra que comience con una letra mayúscula. Por supuesto, esto se dividirá en sustantivos propios, por lo que es posible que tengas que recurrir a una expresión regular como esta /(Mr/.|Mrs/.|U/.S/.A ...) que sería tremendamente fea a menos que construyas la expresión regular mediante programación .


Creo que esto no siempre es resuelto, pero podría dividirse en función de "." (Un período seguido de un espacio vacío) y verificar que la palabra anterior al período no figura en una lista de palabras como Mr, Dr, etc.

Pero, por supuesto, su lista puede omitir algunas palabras, y en ese caso obtendrá malos resultados.


De acuerdo con la respuesta aceptada, usar Stanford Core NLP es una obviedad.

Sin embargo, en 2016 hay algunas incompatibilities Stanford Parser y las versiones posteriores de stanford core nlp (tuve problemas con Stanford Core NLP v3.5 ).

Esto es lo que hice para analizar texto en oraciones usando Ruby haciendo interfaz con Stanford Core NLP :

  1. Instale la gema Stanford CoreNLP , todavía se mantiene y funciona, ha sido una lucha encontrar gemas de rubí NLP que funcionen últimamente:

    gem install stanford-core-nlp

  2. Luego siga las instrucciones en el archivo Léame para Usar la última versión de Stanford CoreNLP :

El uso de la versión más reciente de Stanford CoreNLP (versión 3.5.0 a partir del 31/10/2014) requiere algunos pasos manuales adicionales:

  • Descargue Stanford CoreNLP versión 3.5.0 desde http://nlp.stanford.edu/ .

  • Coloque el contenido del archivo extraído dentro de la carpeta / bin / de la joya stanford-core-nlp (por ejemplo [...] / gems / stanford-core-nlp-0.x / bin /) o dentro de la ubicación del directorio configurada estableciendo StanfordCoreNLP.jar_path.

  • Descargue la versión 3.5.0 completa de Stanford Tagger desde http://nlp.stanford.edu/ .
  • Cree un directorio llamado ''taggers'' dentro de la carpeta / bin / de la joya stanford-core-nlp (por ejemplo [...] / gems / stanford-core-nlp-0.x / bin /) o dentro del directorio configurado por estableciendo StanfordCoreNLP.jar_path.
  • Coloque el contenido del archivo extraído dentro del directorio de los etiquetadores.
  • Descargue el archivo bridge.jar de https://github.com/louismullie/stanford-core-nlp .
  • Coloque el archivo bridger.jar descargado dentro de la carpeta / bin / de la gema stanford-core-nlp (por ejemplo [...] / gems / stanford-core-nlp-0.x / bin / taggers /) o dentro del directorio configurado configurando StanfordCoreNLP.jar_path.

Luego, el código ruby ​​para dividir el texto en oraciones:

require "stanford-core-nlp" #I downloaded the StanfordCoreNLP to a custom path: StanfordCoreNLP.jar_path = "/home/josh/stanford-corenlp-full-2014-10-31/" StanfordCoreNLP.use :english StanfordCoreNLP.model_files = {} StanfordCoreNLP.default_jars = [ ''joda-time.jar'', ''xom.jar'', ''stanford-corenlp-3.5.0.jar'', ''stanford-corenlp-3.5.0-models.jar'', ''jollyday.jar'', ''bridge.jar'' ] pipeline = StanfordCoreNLP.load(:tokenize, :ssplit) text = ''Mr. Josh Weir is writing some code. '' + ''I am Josh Weir Sr. my son may be Josh Weir Jr. etc. etc.'' text = StanfordCoreNLP::Annotation.new(text) pipeline.annotate(text) text.get(:sentences).each{|s| puts "sentence: " + s.to_s} #output: #sentence: Mr. Josh Weir is writing some code. #sentence: I am Josh Weir Sr. my son may be Josh Weir Jr. etc. etc.


Eche un vistazo al separador de frases de Python en NLTK (Kit de herramientas de lenguaje natural):

Tokenizador de oraciones Punkt

Está basado en el siguiente artículo:

Kiss, Tibor y Strunk, Jan (2006): Detección de límites de oraciones multilingües no supervisadas . Lingüística Computacional 32: 485-525.

El enfoque en el documento es bastante interesante. Reducen el problema de la división de oraciones al problema de determinar qué tan fuertemente se asocia una palabra con la siguiente puntuación. La sobrecarga de períodos después de abreviaturas es responsable de la mayoría de los períodos ambiguos, por lo que si puede identificar las abreviaturas puede identificar los límites de las oraciones con una alta probabilidad.

He probado esta herramienta informalmente un poco y parece dar buenos resultados para una variedad de idiomas (humanos).

Transmitirlo a Ruby no sería trivial, pero podría darte algunas ideas.


Este es un problema difícil si realmente te importa hacerlo bien. Descubrirá que los paquetes de analizador NLP probablemente proporcionan esta funcionalidad. Si quieres algo más rápido, necesitarás terminar duplicando parte de esa funcionalidad con una función probabilística entrenada de una ventana de tokens (probablemente quieras contar un avance de línea como un token, ya que puedo descartar un período si es el final de un párrafo).

Edición: recomiendo el analizador de Stanford si puedes usar Java. No tengo ninguna recomendación para otros idiomas, pero estoy muy interesado en saber qué más hay de código abierto.



La respuesta del Dr. Manning es la más adecuada si está considerando JAVA (y Ruby también de manera difícil;)). Es aquí-

Hay un separador de oraciones: edu.stanford.nlp.process.DocumentPreprocessor. Pruebe el comando: java edu.stanford.nlp.process.DocumentPreprocessor /u/nlp/data/lexparser/textDocument.txt

oneTokenizedSentencePerLine.txt. (Esto se hace a través de un FSM (bueno pero heurístico), por lo que es rápido; no está ejecutando el analizador probabilístico).

Pero una pequeña sugerencia si modificamos el comando java edu.stanford.nlp.process.DocumentPreprocessor /u/nlp/data/lexparser/textDocument.txt> oneTokenizedSentencePerLine.txt TO java edu.stanford.nlp.process.DocumentPreprocessor -file / u /nlp/data/lexparser/textDocument.txt> oneTokenizedSentencePerLine.txt . Funcionará bien, ya que necesita especificar qué tipo de archivo se presenta como entrada. So-archivo para archivo de texto, -html para HTML, etc.


Lamentablemente, no soy un tipo Ruby, pero tal vez un ejemplo en Perl te lleve en la dirección correcta. Usando una apariencia que no coincida para la puntuación final, algunos casos especiales en un espacio no detrás seguido de cualquier cantidad de espacio seguido de una letra mayúscula. Estoy seguro de que esto no es perfecto, pero espero que te indique la dirección correcta. No estoy seguro de cómo sabría si Estados Unidos está realmente al final de la oración ...

#!/usr/bin/perl $string = "Mr. Thompson is from the U.S.A. and is 75 years old. Dr. Bob is a dentist. This is a string that contains several sentances. For example this is one. Followed by another. Can it deal with a question? It sure can!"; my @sentances = split(/(?:(?<=/.|/!|/?)(?<!Mr/.|Dr/.)(?<!U/.S/.A/.)/s+(?=[A-Z]))/, $string); for (@sentances) { print $_."/n"; }


No lo he intentado, pero si el inglés es el único idioma que le interesa, le sugiero que le de una mirada a Lingua::EN::Readability .

Lingua :: EN :: Readability es un módulo de Ruby que calcula estadísticas en texto en inglés. Puede proporcionar recuentos de palabras, oraciones y sílabas. También puede calcular varias medidas de legibilidad, como un índice de niebla y un nivel de Flesch-Kincaid. El paquete incluye el módulo Lingua :: EN :: Sentence, que divide el texto en inglés en oraciones con las abreviaturas, y Lingua :: EN :: Sílaba, que puede adivinar el número de sílabas en una palabra escrita en inglés. Si hay un diccionario de pronunciación disponible, puede buscar el número de sílabas en el diccionario para una mayor precisión

El bit que desea está en sentence.rb siguiente manera:

module Lingua module EN # The module Lingua::EN::Sentence takes English text, and attempts to split it # up into sentences, respecting abbreviations. module Sentence EOS = "/001" # temporary end of sentence marker Titles = [ ''jr'', ''mr'', ''mrs'', ''ms'', ''dr'', ''prof'', ''sr'', ''sen'', ''rep'', ''rev'', ''gov'', ''atty'', ''supt'', ''det'', ''rev'', ''col'',''gen'', ''lt'', ''cmdr'', ''adm'', ''capt'', ''sgt'', ''cpl'', ''maj'' ] Entities = [ ''dept'', ''univ'', ''uni'', ''assn'', ''bros'', ''inc'', ''ltd'', ''co'', ''corp'', ''plc'' ] Months = [ ''jan'', ''feb'', ''mar'', ''apr'', ''may'', ''jun'', ''jul'', ''aug'', ''sep'', ''oct'', ''nov'', ''dec'', ''sept'' ] Days = [ ''mon'', ''tue'', ''wed'', ''thu'', ''fri'', ''sat'', ''sun'' ] Misc = [ ''vs'', ''etc'', ''no'', ''esp'', ''cf'' ] Streets = [ ''ave'', ''bld'', ''blvd'', ''cl'', ''ct'', ''cres'', ''dr'', ''rd'', ''st'' ] @@abbreviations = Titles + Entities + Months + Days + Streets + Misc # Split the passed text into individual sentences, trim these and return # as an array. A sentence is marked by one of the punctuation marks ".", "?" # or "!" followed by whitespace. Sequences of full stops (such as an # ellipsis marker "..." and stops after a known abbreviation are ignored. def Sentence.sentences(text) text = text.dup # initial split after punctuation - have to preserve trailing whitespace # for the ellipsis correction next # would be nicer to use look-behind and look-ahead assertions to skip # ellipsis marks, but Ruby doesn''t support look-behind text.gsub!( /([/.?!](?:/"|/'|/)|/]|/})?)(/s+)/ ) { $1 << EOS << $2 } # correct ellipsis marks and rows of stops text.gsub!( /(/././.*)#{EOS}/ ) { $1 } # correct abbreviations # TODO - precompile this regex? text.gsub!( /(#{@@abbreviations.join("|")})/.#{EOS}/i ) { $1 << ''.'' } # split on EOS marker, strip gets rid of trailing whitespace text.split(EOS).map { | sentence | sentence.strip } end # add a list of abbreviations to the list that''s used to detect false # sentence ends. Return the current list of abbreviations in use. def Sentence.abbreviation(*abbreviations) @@abbreviations += abbreviations @@abbreviations end end end end


No soy un Ruby, sino un RegEx que se divide en

^(Mr|Mrs|Ms|Mme|Sta|Sr|Sra|Dr|U/.S/.A)[/./!/?/"] [A-Z]

sería mi mejor apuesta, una vez que tenga el párrafo (dividido en / r / n). Esto supone que tus oraciones son correctas.

Obviamente, este es un RegEx bastante feo. ¿Qué hay de forzar dos espacios entre oraciones?


Para dejarlo en claro, no hay una solución simple para eso. Este es un tema de investigación de PNL, como lo muestra una búsqueda rápida en Google .

Sin embargo, parece que hay algunos proyectos de código abierto que tratan con NLP que apoyan la detección de oraciones. Encontré el siguiente conjunto de herramientas basado en Java:

openNLP

Comentario adicional: El problema de decidir dónde comienzan y terminan las oraciones también se denomina desambiguación de límites de oraciones (SBD) en el procesamiento del lenguaje natural .



Romper un período seguido de un espacio y una letra en mayúscula no significaría títulos como "Mr. Brown".

Los períodos dificultan las cosas, pero un caso fácil de manejar son los signos de exclamación y los signos de interrogación. Sin embargo, hay casos que harían que esto no funcionara. es decir, el nombre corporativo de Yahoo!