Natural Language Toolkit - Combinando Taggers
Combinando Taggers
Combinar taggers ou encadear taggers entre si é uma das características importantes do NLTK. O principal conceito por trás da combinação de taggers é que, caso um tagger não saiba etiquetar uma palavra, ela seria passada para o tagger encadeado. Para alcançar este propósito,SequentialBackoffTagger nos fornece o Backoff tagging característica.
Marcação de backoff
Como dito anteriormente, a marcação de backoff é uma das características importantes do SequentialBackoffTagger, que nos permite combinar etiquetadores de forma que se um etiquetador não souber como etiquetar uma palavra, a palavra será passada para o próximo etiquetador e assim por diante até que não haja nenhum etiquetador de backoff para verificar.
Como funciona?
Na verdade, cada subclasse de SequentialBackoffTaggerpode receber um argumento de palavra-chave 'recuar'. O valor deste argumento de palavra-chave é outra instância de umSequentialBackoffTagger. Agora sempre que issoSequentialBackoffTaggerclasse é inicializada, uma lista interna de taggers de backoff (com ele mesmo como o primeiro elemento) será criada. Além disso, se um tagger de backoff for fornecido, a lista interna desses taggers de backoff será anexada.
No exemplo abaixo, estamos pegando DefaulTagger como o tagger de backoff na receita Python acima com a qual treinamos o UnigramTagger.
Exemplo
Neste exemplo, estamos usando DefaulTaggercomo o identificador de backoff. Sempre queUnigramTagger é incapaz de marcar uma palavra, backoff tagger, ou seja, DefaulTagger, no nosso caso, irá marcá-lo com 'NN'.
from nltk.tag import UnigramTagger
from nltk.tag import DefaultTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
back_tagger = DefaultTagger('NN')
Uni_tagger = UnigramTagger(train_sentences, backoff = back_tagger)
test_sentences = treebank.tagged_sents()[1500:]
Uni_tagger.evaluate(test_sentences)
Resultado
0.9061975746536931
A partir da saída acima, você pode observar que ao adicionar um tagger de backoff a precisão aumenta em cerca de 2%.
Salvando picles com picles
Como vimos, treinar um tagger é muito complicado e também leva tempo. Para economizar tempo, podemos escolher um tagger treinado para usá-lo mais tarde. No exemplo abaixo, vamos fazer isso com nosso tagger já treinado chamado‘Uni_tagger’.
Exemplo
import pickle
f = open('Uni_tagger.pickle','wb')
pickle.dump(Uni_tagger, f)
f.close()
f = open('Uni_tagger.pickle','rb')
Uni_tagger = pickle.load(f)
Classe NgramTagger
A partir do diagrama de hierarquia discutido na unidade anterior, UnigramTagger é herdado de NgarmTagger classe, mas temos mais duas subclasses de NgarmTagger classe -
Subclasse BigramTagger
Na verdade, um ngram é uma subsequência de n itens, portanto, como o nome indica, BigramTaggera subclasse analisa os dois itens. O primeiro item é a palavra marcada anterior e o segundo item é a palavra marcada atual.
Subclasse TrigramTagger
Na mesma nota de BigramTagger, TrigramTagger subclass olha para os três itens, ou seja, duas palavras com tag anteriores e uma palavra com tag atual.
Praticamente se aplicarmos BigramTagger e TrigramTaggersubclasses individualmente como fizemos com a subclasse UnigramTagger, ambas têm um desempenho muito ruim. Vejamos nos exemplos abaixo:
Usando a subclasse BigramTagger
from nltk.tag import BigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Bi_tagger = BigramTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Bi_tagger.evaluate(test_sentences)
Resultado
0.44669191071913594
Usando a subclasse TrigramTagger
from nltk.tag import TrigramTagger
from nltk.corpus import treebank
train_sentences = treebank.tagged_sents()[:2500]
Tri_tagger = TrigramTagger(train_sentences)
test_sentences = treebank.tagged_sents()[1500:]
Tri_tagger.evaluate(test_sentences)
Resultado
0.41949863394526193
Você pode comparar o desempenho do UnigramTagger, que usamos anteriormente (forneceu cerca de 89% de precisão) com BigramTagger (deu cerca de 44% de precisão) e TrigramTagger (deu cerca de 41% de precisão). A razão é que os marcadores Bigram e Trigram não podem aprender o contexto da (s) primeira (s) palavra (s) em uma frase. Por outro lado, a classe UnigramTagger não se preocupa com o contexto anterior e adivinha a tag mais comum para cada palavra, portanto, capaz de ter alta precisão de linha de base.
Combinando ngram taggers
A partir dos exemplos acima, é óbvio que os etiquetadores Bigram e Trigram podem contribuir quando os combinamos com etiquetagem de backoff. No exemplo abaixo, estamos combinando os identificadores Unigram, Bigram e Trigram com a marcação de backoff. O conceito é o mesmo da receita anterior, combinando o UnigramTagger com o backoff tagger. A única diferença é que estamos usando a função chamada backoff_tagger () de tagger_util.py, fornecida abaixo, para a operação de backoff.
def backoff_tagger(train_sentences, tagger_classes, backoff=None):
for cls in tagger_classes:
backoff = cls(train_sentences, backoff=backoff)
return backoff
Exemplo
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
Pela saída acima, podemos ver que aumenta a precisão em cerca de 3%.