Nltk: O tokenizador de frases não divide corretamente

Criado em 23 nov. 2015  ·  5Comentários  ·  Fonte: nltk/nltk

Acho que há um bug no tokenizer de frase padrão sent_tokenize . O problema é que não está dividindo o texto em sentenças em certos casos. Aqui está este caso, em que o tokenizer falha em dividir o texto em duas frases:

[sent for sent in nltk.sent_tokenize('Model wears size S. Fits size.')]

Isso retorna ['Model wears size S. Fits size.'] , em vez de ['Model wears size S.', 'Fits size.'] . O problema parece aparecer, quando a última string antes de . contém apenas um caractere. Se o número de caracteres for >= 2 , ele divide o texto corretamente.

inactive tokenizer

Comentários muito úteis

Só quero adicionar um exemplo do mundo real de BookCorpus , extraído de "Three Plays", publicado por Mike Suttons na Smashwords.

sent_tokenize('The weather is terrible, and my day was ok. You are supposed to take your medicine.')

Saída

['The weather is terrible, and my day was ok. You are supposed to take your medicine.']

Ele confirmou que nltk não reconheceu k. como um separador de frase.

Todos 5 comentários

Isso parece muito difícil de corrigir no tokenizer de frase se você considerar que S. Fits pode ser o nome e o sobrenome de uma pessoa.

Acho que o caminho a percorrer é criar uma subclasse ou copiar e colar o tokenizer de frase NLTK padrão e modificá-lo para se adequar ao seu aplicativo. Por exemplo, se você não espera esses nomes de pessoas no texto, remova as regras que tratam de nomes de pessoas. Outra opção é usar uma solução alternativa como substituir size <X> por size_<X> antes da tokenização e substituí-los novamente após o texto ser dividido em frases.

Hmmm. Apenas tentei novamente. Portanto, o primeiro caso que apresentei não está se dividindo corretamente. Mas se eu usar personagens diferentes, às vezes ele se divide! É por isso que escrevi este teste rápido:

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']

Saída:

['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 você pode ver, é muito inconsistente.

@JernejJerin Não é um tokenizer baseado em regras, então não seria capaz de controlar / explicar as "regras" de divisão usando uma explicação do tipo regex.

O algoritmo usado para treinar o sent_tokenizer é o algoritmo punkt de Kiss e Strunk (2006) . É um sistema estatístico que tenta aprender o limite da frase, então não é perfeito, mas é consistente com as probabilidades geradas a partir do modelo (mas não com regras humanas necessárias).

Só quero adicionar um exemplo do mundo real de BookCorpus , extraído de "Three Plays", publicado por Mike Suttons na Smashwords.

sent_tokenize('The weather is terrible, and my day was ok. You are supposed to take your medicine.')

Saída

['The weather is terrible, and my day was ok. You are supposed to take your medicine.']

Ele confirmou que nltk não reconheceu k. como um separador de frase.

Esta página foi útil?
0 / 5 - 0 avaliações