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%.