Mais Taggers do Kit de Ferramentas de Linguagem Natural
Affix Tagger
Uma outra classe importante da subclasse ContextTagger é AffixTagger. Na classe AffixTagger, o contexto é prefixo ou sufixo de uma palavra. Essa é a razão pela qual a classe AffixTagger pode aprender tags com base em substrings de comprimento fixo do início ou do final de uma palavra.
Como funciona?
Seu funcionamento depende do argumento denominado affix_length que especifica o comprimento do prefixo ou sufixo. O valor padrão é 3. Mas como ele distingue se a classe AffixTagger aprendeu o prefixo ou o sufixo da palavra?
affix_length=positive - Se o valor de affix_lenght for positivo, significa que a classe AffixTagger aprenderá os prefixos das palavras.
affix_length=negative - Se o valor de affix_lenght for negativo, significa que a classe AffixTagger aprenderá os sufixos da palavra.
Para tornar mais claro, no exemplo abaixo, estaremos usando a classe AffixTagger em frases de treebank marcadas.
Exemplo
Neste exemplo, AffixTagger aprenderá o prefixo da palavra porque não estamos especificando nenhum valor para o argumento affix_length. O argumento terá o valor padrão 3 -
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Prefix_tagger = AffixTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Prefix_tagger.evaluate(test_sentences)
Resultado
0.2800492099250667
Vamos ver no exemplo abaixo qual será a precisão quando fornecermos o valor 4 para o argumento affix_length -
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Prefix_tagger = AffixTagger(train_sentences, affix_length=4 )
test_sentences = treebank.tagged_sents()[1500:]
Prefix_tagger.evaluate(test_sentences)
Resultado
0.18154947354966527
Exemplo
Neste exemplo, AffixTagger aprenderá o sufixo da palavra porque especificaremos o valor negativo para o argumento affix_length.
from nltk.tag import AffixTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Suffix_tagger = AffixTagger(train_sentences, affix_length = -3)
test_sentences = treebank.tagged_sents()[1500:]
Suffix_tagger.evaluate(test_sentences)
Resultado
0.2800492099250667
Brill Tagger
Brill Tagger é um tagger baseado em transformação. NLTK forneceBrillTagger classe que é o primeiro tagger que não é uma subclasse de SequentialBackoffTagger. Ao contrário, uma série de regras para corrigir os resultados de um tagger inicial é usada porBrillTagger.
Como funciona?
Para treinar um BrillTagger classe usando BrillTaggerTrainer definimos a seguinte função -
def train_brill_tagger(initial_tagger, train_sentences, **kwargs) -
templates = [
brill.Template(brill.Pos([-1])),
brill.Template(brill.Pos([1])),
brill.Template(brill.Pos([-2])),
brill.Template(brill.Pos([2])),
brill.Template(brill.Pos([-2, -1])),
brill.Template(brill.Pos([1, 2])),
brill.Template(brill.Pos([-3, -2, -1])),
brill.Template(brill.Pos([1, 2, 3])),
brill.Template(brill.Pos([-1]), brill.Pos([1])),
brill.Template(brill.Word([-1])),
brill.Template(brill.Word([1])),
brill.Template(brill.Word([-2])),
brill.Template(brill.Word([2])),
brill.Template(brill.Word([-2, -1])),
brill.Template(brill.Word([1, 2])),
brill.Template(brill.Word([-3, -2, -1])),
brill.Template(brill.Word([1, 2, 3])),
brill.Template(brill.Word([-1]), brill.Word([1])),
]
trainer = brill_trainer.BrillTaggerTrainer(initial_tagger, templates, deterministic=True)
return trainer.train(train_sentences, **kwargs)
Como podemos ver, esta função requer initial_tagger e train_sentences. Leva uminitial_tagger argumento e uma lista de modelos, que implementa o BrillTemplateinterface. oBrillTemplate interface é encontrada no nltk.tbl.templatemódulo. Uma dessas implementações ébrill.Template classe.
A principal função do tagger baseado em transformação é gerar regras de transformação que corrigem a saída do tagger inicial para ficar mais alinhada com as frases de treinamento. Deixe-nos ver o fluxo de trabalho abaixo -
Exemplo
Para este exemplo, usaremos combine_tagger que criamos ao pentear taggers (na receita anterior) de uma cadeia de backoff de NgramTagger aulas, como initial_tagger. Primeiro, vamos avaliar o resultado usandoCombine.tagger e usar isso como initial_tagger para treinar marcador de brill.
from tagger_util import backoff_tagger
from nltk.tag import UnigramTagger
from nltk.tag import BigramTagger
from nltk.tag import TrigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Combine_tagger = backoff_tagger(
train_sentences, [UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger
)
test_sentences = treebank.tagged_sents()[1500:]
Combine_tagger.evaluate(test_sentences)
Resultado
0.9234530029238365
Agora, vamos ver o resultado da avaliação quando Combine_tagger é usado como initial_tagger treinar o marcador de brill -
from tagger_util import train_brill_tagger
brill_tagger = train_brill_tagger(combine_tagger, train_sentences)
brill_tagger.evaluate(test_sentences)
Resultado
0.9246832510505041
Podemos notar que BrillTagger classe tem um ligeiro aumento de precisão em relação ao Combine_tagger.
Exemplo de implementação completo
from tagger_util import backoff_tagger
from nltk.tag import UnigramTagger
from nltk.tag import BigramTagger
from nltk.tag import TrigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Combine_tagger = backoff_tagger(train_sentences,
[UnigramTagger, BigramTagger, TrigramTagger], backoff = back_tagger)
test_sentences = treebank.tagged_sents()[1500:]
Combine_tagger.evaluate(test_sentences)
from tagger_util import train_brill_tagger
brill_tagger = train_brill_tagger(combine_tagger, train_sentences)
brill_tagger.evaluate(test_sentences)
Resultado
0.9234530029238365
0.9246832510505041
TnT Tagger
TnT Tagger, que significa Trigrams'nTags, é um tagger estatístico baseado em modelos de Markov de segunda ordem.
Como funciona?
Podemos entender o funcionamento do tagger TnT com a ajuda das seguintes etapas -
Com base em dados de treinamento, a TnT tegger mantém vários FreqDist e ConditionalFreqDist instâncias.
Depois disso, os unigramas, bigramas e trigramas serão contados por essas distribuições de frequência.
Agora, durante a marcação, por meio de frequências, ele calculará as probabilidades de possíveis marcações para cada palavra.
É por isso que, em vez de construir uma cadeia de backoff de NgramTagger, ele usa todos os modelos ngram juntos para escolher a melhor tag para cada palavra. Vamos avaliar a precisão com o tagger TnT no exemplo a seguir -
from nltk.tag import tnt
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
tnt_tagger = tnt.TnT()
tnt_tagger.train(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
tnt_tagger.evaluate(test_sentences)
Resultado
0.9165508316157791
Temos menos precisão do que com Brill Tagger.
Por favor, note que precisamos ligar train() antes evaluate() caso contrário, obteremos precisão de 0%.