Zestaw narzędzi języka naturalnego - łączenie tagerów

Łączenie taggerów

Łączenie tagerów lub łączenie tagerów ze sobą jest jedną z ważnych cech NLTK. Główna koncepcja łączenia taggerów polega na tym, że w przypadku, gdy jeden tagger nie wie, jak oznaczyć słowo, zostanie ono przekazane do połączonego taggera. Aby osiągnąć ten cel,SequentialBackoffTagger zapewnia nam Backoff tagging funkcja.

Oznaczanie wycofywania

Jak wspomniano wcześniej, tagowanie wycofywania jest jedną z ważnych funkcji platformy SequentialBackoffTagger, co pozwala nam łączyć taggery w taki sposób, że jeśli jeden tagger nie wie, jak oznaczyć słowo, słowo zostanie przekazane do następnego taggera i tak dalej, aż nie będzie już żadnych backoff taggerów do sprawdzenia.

Jak to działa?

Właściwie każda podklasa SequentialBackoffTaggermoże przyjąć argument słowa kluczowego „backoff”. Wartość tego argumentu słowa kluczowego jest kolejną instancją plikuSequentialBackoffTagger. Teraz, kiedy toSequentialBackoffTaggerclass zostanie zainicjowana, zostanie utworzona wewnętrzna lista znaczników wycofania (ze sobą jako pierwszym elementem). Ponadto, jeśli podano znacznik wycofywania, dołączana byłaby wewnętrzna lista tych znaczników.

W poniższym przykładzie bierzemy DefaulTagger jako znacznik wycofywania w powyższej recepturze Pythona, z którym wytrenowaliśmy UnigramTagger.

Przykład

W tym przykładzie używamy DefaulTaggerjako znacznik wycofywania. Zawsze, gdyUnigramTagger nie jest w stanie oznaczyć słowa, backoff tagger, tj DefaulTagger, w naszym przypadku oznaczy go tagiem „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)

Wynik

0.9061975746536931

Z powyższego wyniku można zauważyć, że przez dodanie znacznika wycofania dokładność wzrasta o około 2%.

Ratowanie taggerów z marynatą

Jak widzieliśmy, szkolenie taggera jest bardzo uciążliwe i wymaga czasu. Aby zaoszczędzić czas, możemy zaliczyć wyszkolonego taggera do późniejszego wykorzystania. W poniższym przykładzie zrobimy to naszemu już przeszkolonemu taggerowi o nazwie‘Uni_tagger’.

Przykład

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)

Klasa NgramTagger

Z diagramu hierarchii omówionego w poprzednim rozdziale, UnigramTagger jest dziedziczona z NgarmTagger class, ale mamy jeszcze dwie podklasy NgarmTagger klasa -

Podklasa BigramTagger

W rzeczywistości ngram jest podciągiem n elementów, stąd, jak nazwa wskazuje, BigramTaggersubclass patrzy na te dwa elementy. Pierwsza pozycja to poprzednie oznaczone słowo, a druga to bieżące słowo ze znacznikiem.

Podklasa TrigramTagger

Z tego samego powodu BigramTagger, TrigramTagger subclass analizuje trzy elementy, tj. dwa poprzednie słowa ze znacznikami i jedno aktualne słowo ze znacznikami.

Praktycznie, jeśli się zgłosimy BigramTagger i TrigramTaggerpodklasy indywidualnie, tak jak to zrobiliśmy z podklasą UnigramTagger, obie działają bardzo słabo. Spójrzmy na poniższe przykłady:

Korzystanie z podklasy 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)

Wynik

0.44669191071913594

Korzystanie z podklasy 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)

Wynik

0.41949863394526193

Możesz porównać wydajność UnigramTaggera, którego używaliśmy wcześniej (dała około 89% dokładności) z BigramTaggerem (dała około 44% dokładności) i TrigramTagger (dała około 41% dokładności). Powodem jest to, że taggery Bigram i Trigram nie mogą nauczyć się kontekstu z pierwszego słowa (słów) w zdaniu. Z drugiej strony, klasa UnigramTagger nie dba o poprzedni kontekst i zgaduje najczęściej spotykany znacznik dla każdego słowa, dzięki czemu może mieć wysoką dokładność linii bazowej.

Łączenie taggerów ngram

Jak z powyższych przykładów, jest oczywiste, że taggery Bigram i Trigram mogą wnieść swój wkład, gdy połączymy je z tagowaniem wycofywania. W poniższym przykładzie łączymy taggery Unigram, Bigram i Trigram z tagowaniem wycofywania. Koncepcja jest taka sama jak w przypadku poprzedniego przepisu, łącząc UnigramTagger z backoff tagger. Jedyną różnicą jest to, że do operacji backoff używamy funkcji o nazwie backoff_tagger () z tagger_util.py, podanej poniżej.

def backoff_tagger(train_sentences, tagger_classes, backoff=None):
   for cls in tagger_classes:
      backoff = cls(train_sentences, backoff=backoff)
   return backoff

Przykład

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)

Wynik

0.9234530029238365

Z powyższego wyniku widać, że zwiększa dokładność o około 3%.