Creo que hay un error en el tokenizador de oraciones estándar sent_tokenize
. El problema es que no divide el texto en oraciones en ciertos casos. Aquí está este caso, donde el tokenizador no puede dividir el texto en dos oraciones:
[sent for sent in nltk.sent_tokenize('Model wears size S. Fits size.')]
Esto devuelve ['Model wears size S. Fits size.']
, en lugar de ['Model wears size S.', 'Fits size.']
. El problema parece aparecer cuando la última cadena antes de .
contiene solo un carácter. Si el número de caracteres es >= 2
, entonces divide correctamente el texto.
Esto parece muy difícil de solucionar en el tokenizador de oraciones si considera que S. Fits puede ser el nombre y apellido de una persona.
Creo que el camino a seguir es crear una subclase o copiar y pegar el tokenizador de oraciones NLTK predeterminado y modificarlo para que se ajuste a su aplicación. Por ejemplo, si no espera tales nombres de personas en el texto, elimine las reglas que manejan nombres de personas. Otra opción es usar una solución alternativa como reemplazar size <X>
con size_<X>
antes de la tokenización y reemplazarlos nuevamente después de dividir el texto en oraciones.
Mmm. Intenté de nuevo. Entonces, el primer caso que presenté no se divide correctamente. Pero si utilizo diferentes caracteres, ¡a veces se divide! Por eso escribí esta prueba rápida:
import nltk
import pprint
pp = pprint.PrettyPrinter(indent=4)
s = 'Test {}. Test {}.'
[nltk.sent_tokenize(s.format(char, char)) for char in 'abcdefghijklmnopqrstuvwxyz']
[pp.pprint(nltk.sent_tokenize(s.format(char, char))) for char in 'abcdefghijklmnopqrstuvwxyz']
Producción:
['Test a.', 'Test a.']
['Test b.', 'Test b.']
['Test c. Test c.']
['Test d. Test d.']
['Test e. Test e.']
['Test f. Test f.']
['Test g. Test g.']
['Test h. Test h.']
['Test i.', 'Test i.']
['Test j.', 'Test j.']
['Test k. Test k.']
['Test l. Test l.']
['Test m. Test m.']
['Test n. Test n.']
['Test o.', 'Test o.']
['Test p. Test p.']
['Test q.', 'Test q.']
['Test r. Test r.']
['Test s. Test s.']
['Test t. Test t.']
['Test u.', 'Test u.']
['Test v. Test v.']
['Test w. Test w.']
['Test x.', 'Test x.']
['Test y.', 'Test y.']
['Test z.', 'Test z.']
@kmike , como puede ver, es muy inconsistente.
@JernejJerin No es un tokenizador basado en reglas, por lo que no podría controlar / explicar las "reglas" de división usando una explicación similar a la expresión regular.
El algoritmo utilizado para entrenar el sent_tokenizer
es el algoritmo punkt de Kiss y Strunk (2006) . Es un sistema estadístico que intenta aprender los límites de la oración, por lo que no es perfecto, pero es consistente con las probabilidades generadas a partir del modelo (pero no reglas necesarias similares a las humanas).
Solo quiero agregar un ejemplo del mundo real de BookCorpus , extraído de "Three Plays", publicado por Mike Suttons en Smashwords.
sent_tokenize('The weather is terrible, and my day was ok. You are supposed to take your medicine.')
Producción
['The weather is terrible, and my day was ok. You are supposed to take your medicine.']
Confirmó que nltk no reconoció k.
como separador de oraciones.
Comentario más útil
Solo quiero agregar un ejemplo del mundo real de BookCorpus , extraído de "Three Plays", publicado por Mike Suttons en Smashwords.
sent_tokenize('The weather is terrible, and my day was ok. You are supposed to take your medicine.')
Producción
['The weather is terrible, and my day was ok. You are supposed to take your medicine.']
Confirmó que nltk no reconoció
k.
como separador de oraciones.