AI z Pythonem - pakiet NLTK
W tym rozdziale dowiemy się, jak rozpocząć pracę z pakietem Natural Language Toolkit.
Warunek wstępny
Jeśli chcemy budować aplikacje z przetwarzaniem języka naturalnego, to zmiana kontekstu sprawia, że jest to najtrudniejsze. Czynnik kontekstowy wpływa na to, jak maszyna rozumie dane zdanie. Dlatego musimy opracowywać aplikacje języka naturalnego przy użyciu metod uczenia maszynowego, aby maszyna mogła również zrozumieć sposób, w jaki człowiek może zrozumieć kontekst.
Do budowania takich aplikacji użyjemy pakietu Python o nazwie NLTK (Natural Language Toolkit Package).
Importowanie NLTK
Musimy zainstalować NLTK przed jego użyciem. Można go zainstalować za pomocą następującego polecenia -
pip install nltk
Aby zbudować pakiet Conda dla NLTK, użyj następującego polecenia -
conda install -c anaconda nltk
Teraz po zainstalowaniu pakietu NLTK musimy go zaimportować za pomocą wiersza poleceń Pythona. Możemy go zaimportować, pisząc następujące polecenie w wierszu polecenia Pythona -
>>> import nltk
Pobieranie danych NLTK
Teraz po zaimportowaniu NLTK musimy pobrać wymagane dane. Można to zrobić za pomocą następującego polecenia w wierszu poleceń Pythona -
>>> nltk.download()
Instalowanie innych niezbędnych pakietów
Aby zbudować aplikacje przetwarzające język naturalny przy użyciu NLTK, musimy zainstalować niezbędne pakiety. Pakiety są następujące -
gensim
Jest to solidna biblioteka do modelowania semantycznego, przydatna w wielu aplikacjach. Możemy go zainstalować, wykonując następujące polecenie -
pip install gensim
wzór
Służy do robienia gensimpakiet działa poprawnie. Możemy go zainstalować, wykonując następujące polecenie
pip install pattern
Pojęcie tokenizacji, stemming i lemmatyzacji
W tej sekcji zrozumiemy, czym jest tokenizacja, wyprowadzanie i lematyzacja.
Tokenizacja
Można to zdefiniować jako proces dzielenia danego tekstu, czyli ciągu znaków na mniejsze jednostki zwane tokenami. Żetonami mogą być słowa, cyfry lub znaki interpunkcyjne. Nazywa się to również segmentacją słów. Oto prosty przykład tokenizacji -
Input - Mango, banan, ananas i jabłko to owoce.
Output -
Proces łamania podanego tekstu można przeprowadzić za pomocą zlokalizowania granic słów. Koniec słowa i początek nowego słowa nazywane są granicami słów. System pisma i struktura typograficzna słów wpływają na granice.
W module Python NLTK mamy różne pakiety związane z tokenizacją, które możemy wykorzystać do podzielenia tekstu na tokeny zgodnie z naszymi wymaganiami. Niektóre z pakietów są następujące -
pakiet sent_tokenize
Jak sama nazwa wskazuje, pakiet ten podzieli tekst wejściowy na zdania. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.tokenize import sent_tokenize
pakiet word_tokenize
Ten pakiet dzieli tekst wejściowy na słowa. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.tokenize import word_tokenize
Pakiet WordPunctTokenizer
Ten pakiet dzieli wprowadzany tekst na słowa oraz znaki interpunkcyjne. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.tokenize import WordPuncttokenizer
Przybitka
Podczas pracy ze słowami spotykamy się z wieloma wariacjami ze względów gramatycznych. Pojęcie wariacji oznacza tutaj, że mamy do czynienia z różnymi formami tych samych słówdemocracy, democratic, i democratization. Maszyny muszą zrozumieć, że te różne słowa mają tę samą podstawową formę. W ten sposób warto wyodrębnić podstawowe formy słów podczas analizy tekstu.
Możemy to osiągnąć poprzez wykorzenienie. W ten sposób możemy powiedzieć, że rymowanie jest heurystycznym procesem wyodrębniania podstawowych form słów przez odcinanie końcówek słów.
W module Python NLTK mamy różne pakiety związane z rodzicielstwem. Te pakiety mogą być używane do uzyskania podstawowych form słowa. Te pakiety używają algorytmów. Niektóre z pakietów są następujące -
Pakiet PorterStemmer
Ten pakiet Pythona używa algorytmu Portera do wyodrębnienia formy podstawowej. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.stem.porter import PorterStemmer
Na przykład, jeśli damy słowo ‘writing’ jako dane wejściowe do tego stempla otrzymamy słowo ‘write’ po wyhodowaniu.
Pakiet LancasterStemmer
Ten pakiet Pythona użyje algorytmu Lancastera do wyodrębnienia formy podstawowej. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.stem.lancaster import LancasterStemmer
Na przykład, jeśli damy słowo ‘writing’ jako dane wejściowe do tego stempla otrzymamy słowo ‘write’ po wyhodowaniu.
Pakiet SnowballStemmer
Ten pakiet Pythona użyje algorytmu kuli śnieżnej do wyodrębnienia formy podstawowej. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.stem.snowball import SnowballStemmer
Na przykład, jeśli damy słowo ‘writing’ jako dane wejściowe do tego stempla otrzymamy słowo ‘write’ po wyhodowaniu.
Wszystkie te algorytmy mają różny poziom ścisłości. Jeśli porównamy te trzy łodygi, to łodygi Porter są najmniej surowe, a Lancaster - najsurowsze. Patyk do śnieżek jest dobry w użyciu zarówno pod względem szybkości, jak i ścisłości.
Lemmatyzacja
Możemy również wyodrębnić podstawową formę słów przez lematyzację. Zasadniczo wykonuje to zadanie przy użyciu słownictwa i analizy morfologicznej słów, zwykle mając na celu usunięcie tylko końcówek fleksyjnych. Ten rodzaj bazowej formy dowolnego słowa nazywa się lemat.
Główną różnicą między tematyzacją a lematyzacją jest użycie słownictwa i analiza morfologiczna słów. Inną różnicą jest to, że wygłaszanie najczęściej powoduje upadek słów pokrewnych derywacyjnie, podczas gdy lematyzacja zwykle powoduje upadek tylko różnych form fleksyjnych lematu. Na przykład, jeśli podamy słowo widziane jako słowo wejściowe, to funkcja rymowania może zwrócić słowo „s”, ale lematyzacja będzie próbowała zwrócić słowo „zobacz” lub „zobaczył”, w zależności od tego, czy użyto tokenu, czy też rzeczownika.
W module Python NLTK mamy następujący pakiet związany z procesem lematyzacji, za pomocą którego możemy uzyskać podstawowe formy słowa -
Pakiet WordNetLemmatizer
Ten pakiet Pythona wyodrębni podstawową formę słowa w zależności od tego, czy jest używany jako rzeczownik, czy jako czasownik. Możemy zaimportować ten pakiet za pomocą następującego kodu Pythona -
from nltk.stem import WordNetLemmatizer
Chunking: dzielenie danych na kawałki
Jest to jeden z ważnych procesów w przetwarzaniu języka naturalnego. Głównym zadaniem fragmentacji jest identyfikacja części mowy i krótkich fraz, takich jak frazy rzeczownikowe. Przebadaliśmy już proces tokenizacji, tworzenie tokenów. Zasadniczo fragmentacja to etykietowanie tych tokenów. Innymi słowy, fragmentacja pokaże nam strukturę zdania.
W następnej sekcji dowiemy się o różnych typach fragmentacji.
Rodzaje kruszenia
Istnieją dwa rodzaje fragmentacji. Rodzaje są następujące -
Kawałki
W tym procesie dzielenia obiekt, rzeczy itp. Stają się bardziej ogólne, a język staje się bardziej abstrakcyjny. Jest więcej szans na porozumienie. W tym procesie pomniejszamy. Na przykład, jeśli podzielimy się pytaniem, „do czego służą samochody”? Odpowiedź brzmi „transport”.
Kruszenie się
W tym procesie rozdrabniania przedmiot, rzeczy itp. Stają się bardziej szczegółowe, a język staje się bardziej penetrowany. Głębsza struktura zostanie zbadana podczas kruszenia. W tym procesie powiększamy. Na przykład, jeśli podzielimy pytanie „Opowiedz konkretnie o samochodzie”? Otrzymamy mniejsze informacje o samochodzie.
Example
W tym przykładzie wykonamy fragmentację rzeczownik-fraza, kategorię fragmentacji, która znajdzie fragmenty wyrażeń rzeczownikowych w zdaniu, używając modułu NLTK w Pythonie -
Follow these steps in python for implementing noun phrase chunking −
Step 1- Na tym etapie musimy zdefiniować gramatykę fragmentów. Składałby się z zasad, których musimy przestrzegać.
Step 2- W tym kroku musimy stworzyć parser fragmentów. Sparsowałby gramatykę i dałby wynik.
Step 3 - W ostatnim kroku dane wyjściowe są tworzone w formacie drzewa.
Zaimportujmy niezbędny pakiet NLTK w następujący sposób -
import nltk
Teraz musimy zdefiniować zdanie. Tutaj DT oznacza wyznacznik, VBP oznacza czasownik, JJ przymiotnik, IN przyimek, a NN rzeczownik.
sentence=[("a","DT"),("clever","JJ"),("fox","NN"),("was","VBP"),
("jumping","VBP"),("over","IN"),("the","DT"),("wall","NN")]
Teraz musimy podać gramatykę. Tutaj podamy gramatykę w postaci wyrażenia regularnego.
grammar = "NP:{<DT>?<JJ>*<NN>}"
Musimy zdefiniować parser, który będzie analizował gramatykę.
parser_chunking = nltk.RegexpParser(grammar)
Parser analizuje zdanie w następujący sposób -
parser_chunking.parse(sentence)
Następnie musimy uzyskać dane wyjściowe. Dane wyjściowe są generowane w prostej zmiennej o nazwieoutput_chunk.
Output_chunk = parser_chunking.parse(sentence)
Po wykonaniu poniższego kodu możemy narysować nasz wynik w postaci drzewa.
output.draw()
Model worka słowa (BoW)
Bag of Word (BoW), model przetwarzania języka naturalnego, jest zasadniczo używany do wyodrębniania cech z tekstu, dzięki czemu tekst może być używany w modelowaniu w algorytmach uczenia maszynowego.
Teraz pojawia się pytanie, dlaczego musimy wyodrębnić cechy z tekstu. Dzieje się tak, ponieważ algorytmy uczenia maszynowego nie mogą pracować z surowymi danymi i potrzebują danych numerycznych, aby móc wydobyć z nich znaczące informacje. Konwersja danych tekstowych na dane numeryczne nazywana jest wyodrębnianiem cech lub kodowaniem cech.
Jak to działa
Jest to bardzo prosta metoda wyodrębniania cech z tekstu. Załóżmy, że mamy dokument tekstowy i chcemy go przekonwertować na dane liczbowe lub powiedzieć, że chcemy wyodrębnić z niego cechy, a następnie ten model wyodrębnia słownictwo ze wszystkich słów w dokumencie. Następnie, używając macierzy terminów dokumentu, zbuduje model. W ten sposób BoW przedstawia dokument wyłącznie jako zbiór słów. Wszelkie informacje o kolejności lub strukturze słów w dokumencie są odrzucane.
Pojęcie macierzy terminów dokumentu
Algorytm BoW buduje model przy użyciu macierzy terminów dokumentu. Jak sama nazwa wskazuje, macierz terminów dokumentu jest macierzą różnych liczb słów występujących w dokumencie. Za pomocą tej macierzy dokument tekstowy można przedstawić jako ważoną kombinację różnych słów. Ustawiając próg i wybierając słowa, które są bardziej znaczące, możemy zbudować histogram wszystkich słów w dokumentach, które można wykorzystać jako wektor cech. Poniżej znajduje się przykład zrozumienia pojęcia matrycy terminów dokumentu -
Example
Załóżmy, że mamy następujące dwa zdania -
Sentence 1 - Używamy modelu Bag of Words.
Sentence 2 - Model Bag of Words służy do wyodrębniania cech.
Teraz, biorąc pod uwagę te dwa zdania, mamy następujące 13 różnych słów -
- we
- are
- using
- the
- bag
- of
- words
- model
- is
- used
- for
- extracting
- features
Teraz musimy zbudować histogram dla każdego zdania, używając liczby słów w każdym zdaniu -
Sentence 1 - [1,1,1,1,1,1,1,1,0,0,0,0,0]
Sentence 2 - [0,0,0,1,1,1,1,1,1,1,1,1,1]
W ten sposób otrzymaliśmy wyodrębnione wektory cech. Każdy wektor cech jest 13-wymiarowy, ponieważ mamy 13 różnych słów.
Pojęcie statystyki
Pojęcie statystyki nazywa się TermFrequency-Inverse Document Frequency (tf-idf). W dokumencie każde słowo jest ważne. Statystyki pomagają nam zrozumieć znaczenie każdego słowa.
Termin Częstotliwość (tf)
Jest miarą częstotliwości występowania każdego słowa w dokumencie. Można to uzyskać, dzieląc liczbę każdego słowa przez całkowitą liczbę słów w danym dokumencie.
Odwrotna częstotliwość dokumentów (idf)
Jest miarą unikalności danego słowa w danym dokumencie w danym zestawie dokumentów. Aby obliczyć idf i sformułować wektor cech charakterystycznych, musimy zmniejszyć wagę powszechnie występujących słów, takich jak the, i zważyć rzadkie słowa.
Tworzenie modelu worka słów w NLTK
W tej sekcji zdefiniujemy kolekcję ciągów za pomocą CountVectorizer do tworzenia wektorów z tych zdań.
Zaimportujmy niezbędny pakiet -
from sklearn.feature_extraction.text import CountVectorizer
Teraz zdefiniuj zestaw zdań.
Sentences = ['We are using the Bag of Word model', 'Bag of Word model is
used for extracting the features.']
vectorizer_count = CountVectorizer()
features_text = vectorizer.fit_transform(Sentences).todense()
print(vectorizer.vocabulary_)
Powyższy program generuje dane wyjściowe, jak pokazano poniżej. Pokazuje, że mamy 13 różnych słów w powyższych dwóch zdaniach -
{'we': 11, 'are': 0, 'using': 10, 'the': 8, 'bag': 1, 'of': 7,
'word': 12, 'model': 6, 'is': 5, 'used': 9, 'for': 4, 'extracting': 2, 'features': 3}
Są to wektory cech (tekst do postaci liczbowej), które można wykorzystać do uczenia maszynowego.
Rozwiązywanie problemów
W tej sekcji rozwiążemy kilka powiązanych problemów.
Przewidywanie kategorii
W zestawie dokumentów ważne są nie tylko słowa, ale także kategoria słów; do której kategorii tekstu należy dane słowo. Na przykład chcemy przewidzieć, czy dane zdanie należy do kategorii e-mail, wiadomości, sport, komputer itp. W poniższym przykładzie użyjemy tf-idf do sformułowania wektora cech, aby znaleźć kategorię dokumentów. Wykorzystamy dane z 20 zbioru danych grupy dyskusyjnej sklearn.
Musimy zaimportować niezbędne pakiety -
from sklearn.datasets import fetch_20newsgroups
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
Zdefiniuj mapę kategorii. Używamy pięciu różnych kategorii: Religia, Samochody, Sport, Elektronika i Kosmos.
category_map = {'talk.religion.misc':'Religion','rec.autos''Autos',
'rec.sport.hockey':'Hockey','sci.electronics':'Electronics', 'sci.space': 'Space'}
Utwórz zestaw treningowy -
training_data = fetch_20newsgroups(subset = 'train',
categories = category_map.keys(), shuffle = True, random_state = 5)
Zbuduj wektoryzator zliczania i wyodrębnij termin counts -
vectorizer_count = CountVectorizer()
train_tc = vectorizer_count.fit_transform(training_data.data)
print("\nDimensions of training data:", train_tc.shape)
Transformator tf-idf jest tworzony w następujący sposób -
tfidf = TfidfTransformer()
train_tfidf = tfidf.fit_transform(train_tc)
Teraz zdefiniuj dane testowe -
input_data = [
'Discovery was a space shuttle',
'Hindu, Christian, Sikh all are religions',
'We must have to drive safely',
'Puck is a disk made of rubber',
'Television, Microwave, Refrigrated all uses electricity'
]
Powyższe dane pomogą nam wytrenować wielomianowy klasyfikator Bayesa naiwny -
classifier = MultinomialNB().fit(train_tfidf, training_data.target)
Przekształć dane wejściowe za pomocą wektoryzatora zliczania -
input_tc = vectorizer_count.transform(input_data)
Teraz przekształcimy wektoryzowane dane za pomocą transformatora tfidf -
input_tfidf = tfidf.transform(input_tc)
Przewidujemy kategorie wyjściowe -
predictions = classifier.predict(input_tfidf)
Dane wyjściowe są generowane w następujący sposób -
for sent, category in zip(input_data, predictions):
print('\nInput Data:', sent, '\n Category:', \
category_map[training_data.target_names[category]])
Predykator kategorii generuje następujące dane wyjściowe -
Dimensions of training data: (2755, 39297)
Input Data: Discovery was a space shuttle
Category: Space
Input Data: Hindu, Christian, Sikh all are religions
Category: Religion
Input Data: We must have to drive safely
Category: Autos
Input Data: Puck is a disk made of rubber
Category: Hockey
Input Data: Television, Microwave, Refrigrated all uses electricity
Category: Electronics
Wyszukiwarka płci
W tym stwierdzeniu problemu klasyfikator zostałby przeszkolony w znajdowaniu płci (mężczyzny lub kobiety) poprzez podanie imion. Musimy użyć heurystyki, aby skonstruować wektor cech i wytrenować klasyfikator. Będziemy używać oznaczonych danych z pakietu scikit-learn. Poniżej znajduje się kod Pythona do tworzenia wyszukiwarki płci -
Zaimportujmy niezbędne pakiety -
import random
from nltk import NaiveBayesClassifier
from nltk.classify import accuracy as nltk_accuracy
from nltk.corpus import names
Teraz musimy wyodrębnić ostatnie N liter ze słowa wejściowego. Te litery będą działać jako cechy -
def extract_features(word, N = 2):
last_n_letters = word[-N:]
return {'feature': last_n_letters.lower()}
if __name__=='__main__':
Utwórz dane treningowe, używając nazwisk (zarówno mężczyzn, jak i kobiet) dostępnych w NLTK -
male_list = [(name, 'male') for name in names.words('male.txt')]
female_list = [(name, 'female') for name in names.words('female.txt')]
data = (male_list + female_list)
random.seed(5)
random.shuffle(data)
Teraz dane testowe zostaną utworzone w następujący sposób -
namesInput = ['Rajesh', 'Gaurav', 'Swati', 'Shubha']
Zdefiniuj liczbę próbek używanych do trenowania i testowania za pomocą następującego kodu
train_sample = int(0.8 * len(data))
Teraz musimy iterować przez różne długości, aby można było porównać dokładność -
for i in range(1, 6):
print('\nNumber of end letters:', i)
features = [(extract_features(n, i), gender) for (n, gender) in data]
train_data, test_data = features[:train_sample],
features[train_sample:]
classifier = NaiveBayesClassifier.train(train_data)
Dokładność klasyfikatora można obliczyć w następujący sposób -
accuracy_classifier = round(100 * nltk_accuracy(classifier, test_data), 2)
print('Accuracy = ' + str(accuracy_classifier) + '%')
Teraz możemy przewidzieć wynik -
for name in namesInput:
print(name, '==>', classifier.classify(extract_features(name, i)))
Powyższy program wygeneruje następujące dane wyjściowe -
Number of end letters: 1
Accuracy = 74.7%
Rajesh -> female
Gaurav -> male
Swati -> female
Shubha -> female
Number of end letters: 2
Accuracy = 78.79%
Rajesh -> male
Gaurav -> male
Swati -> female
Shubha -> female
Number of end letters: 3
Accuracy = 77.22%
Rajesh -> male
Gaurav -> female
Swati -> female
Shubha -> female
Number of end letters: 4
Accuracy = 69.98%
Rajesh -> female
Gaurav -> female
Swati -> female
Shubha -> female
Number of end letters: 5
Accuracy = 64.63%
Rajesh -> female
Gaurav -> female
Swati -> female
Shubha -> female
Na powyższym wyjściu widzimy, że dokładność maksymalnej liczby końcowych liter wynosi dwa i maleje wraz ze wzrostem liczby końcowych liter.
Modelowanie tematów: identyfikowanie wzorców w danych tekstowych
Wiemy, że generalnie dokumenty są pogrupowane tematycznie. Czasami musimy zidentyfikować wzorce w tekście, które odnoszą się do określonego tematu. Technika wykonywania tego nazywana jest modelowaniem tematycznym. Innymi słowy, możemy powiedzieć, że modelowanie tematyczne jest techniką odkrywania abstrakcyjnych tematów lub ukrytej struktury w danym zestawie dokumentów.
Możemy wykorzystać technikę modelowania tematu w następujących scenariuszach -
Klasyfikacja tekstu
Przy pomocy modelowania tematów można ulepszyć klasyfikację, ponieważ grupuje ona podobne słowa, zamiast używać każdego słowa oddzielnie jako cechy.
Systemy rekomendujące
Za pomocą modelowania tematycznego możemy budować systemy rekomendujące przy użyciu miar podobieństwa.
Algorytmy do modelowania tematycznego
Modelowanie tematyczne można zaimplementować za pomocą algorytmów. Algorytmy są następujące -
Ukryty przydział Dirichleta (LDA)
Ten algorytm jest najpopularniejszy w modelowaniu tematycznym. Wykorzystuje probabilistyczne modele graficzne do wdrażania modelowania tematycznego. Musimy zaimportować pakiet gensim w Pythonie, aby używać algorytmu LDA.
Ukryta analiza semantyczna (LDA) lub ukryte indeksowanie semantyczne (LSI)
Algorytm ten jest oparty na algebrze liniowej. Zasadniczo wykorzystuje koncepcję SVD (rozkład wartości osobliwych) na matrycy terminów dokumentu.
Nieujemna faktoryzacja macierzy (NMF)
Opiera się również na algebrze liniowej.
Wszystkie wyżej wymienione algorytmy modelowania tematycznego miałyby rozszerzenie number of topics jako parametr, Document-Word Matrix jako wejście i WTM (Word Topic Matrix) & TDM (Topic Document Matrix) jako wyjście.