
Uczenie maszynowe i sztuczne sieci neuronowe/Ćwiczenia 9: Różnice pomiędzy wersjami
|  (Utworzono nową stronę "=Naiwny kalsyfikator Bayesa= Z klasyfikatorem tym zapoznamy się próbując klasyfikować gatunki irysów. Jest to klasyczny już problem, często wykorzystywany przy po...") | m | ||
| (Nie pokazano 8 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
| Linia 1: | Linia 1: | ||
| − | =Naiwny  | + | [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw]]/Bayes | 
| + | =Naiwny klasyfikator Bayesa= | ||
| Z klasyfikatorem tym zapoznamy się próbując klasyfikować gatunki irysów. Jest to klasyczny już problem, często wykorzystywany przy porównywaniu różnych technik klasyfikacji. Więcej o pochodzeniu tych danych i problemie można przeczytać tu [https://en.wikipedia.org/wiki/Iris_flower_data_set] | Z klasyfikatorem tym zapoznamy się próbując klasyfikować gatunki irysów. Jest to klasyczny już problem, często wykorzystywany przy porównywaniu różnych technik klasyfikacji. Więcej o pochodzeniu tych danych i problemie można przeczytać tu [https://en.wikipedia.org/wiki/Iris_flower_data_set] | ||
| Linia 96: | Linia 97: | ||
| # rysowanie wyników klasyfikacji               | # rysowanie wyników klasyfikacji               | ||
| # przekształcamy siatkę w macierz dwukolumnową - kolumny odpowiadają cechom | # przekształcamy siatkę w macierz dwukolumnową - kolumny odpowiadają cechom | ||
| − | XX = np.c_[xx.ravel(), yy.ravel()]  | + | XX = np.c_[xx.ravel(), yy.ravel()]        | 
| − | Z =  | + | # dla każdego punktu siatki oblicz predykcję klasyfikatora   | 
| + | Z = .... | ||
| + | # te predykcje narysujemy w przestrzeni cech za pomocą funkcji  plt.contourf  | ||
| plt.figure(3) | plt.figure(3) | ||
| Z = Z.reshape(xx.shape) | Z = Z.reshape(xx.shape) | ||
| − | plt.contourf( | + | plt.contourf(..., ..., ..., cmap=plt.cm.Paired) | 
| − | plt.scatter | + | # i dorzucamy oryginalne punkty | 
| + | plt.scatter... | ||
| plt.title(u'Podział przestrzeni cech na klasy') | plt.title(u'Podział przestrzeni cech na klasy') | ||
| plt.show() | plt.show() | ||
| − | + | # Teraz zajmiemy się ewaluacją dopasowanego modelu. Skorzystamy z | |
| # http://scikit-learn.org/stable/modules/model_evaluation.html | # http://scikit-learn.org/stable/modules/model_evaluation.html | ||
| + | # upewnij się, że dokładnie rozumiesz co zwracają te funkcje | ||
| + | # porównaj z definicjami z wykładu  | ||
| + | # http://haar.zfb.fuw.edu.pl/edu/index.php/Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład_Ocena_jakości_klasyfikacji | ||
| print("classification report:") | print("classification report:") | ||
| − | print(classification_report( | + | print(classification_report...) | 
| + | print("confusion matrix:") | ||
| + | print(confusion_matrix...) | ||
| + | </source> | ||
| + | |||
| + | =Klasyfikacja tekstów= | ||
| + | Ten przykład demonstruje jak można poradzić sobie z klasyfikacją tematyczną dokumentów stosując technikę "worek ze słowami".  | ||
| + | O tej technice więcej można przeczytać tu: [http://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction] | ||
| + | |||
| + | W skrócie:  | ||
| + | |||
| + | * tekst jest zamieniany na  pojedyncze słowa.  | ||
| + | * ze słów otrzymanych dla dużej ilości tekstów tworzony jest słownik - wektor możliwych słów  | ||
| + | * dla konkretnego tekstu zliczana jest ilość wystąpień każdego ze | ||
| + | * te zliczenia mogą być normalizowane na różne sposoby | ||
| + | O metodzie tej mówi się "worek ze słowami", bo zaniedbujemy w niej kolejność słów w dokumencie i wszelkie korelacje między ich wzajemnymi pozycjami.  | ||
| + | |||
| + | Często stosowana wersja normalizacji to tzw. transformacja tf-idf (term frequency - inverse document frequency)[https://en.wikipedia.org/wiki/Tf–idf].  | ||
| + | Transformacja ta zasadza się na iloczynie wagi i specyficzności danego słowa. W najprostszym przypadku: | ||
| + | * waga danego słowa jest proporcjonalna do częstości występowania słowa w dokumencie | ||
| + | * specyficzność słowa może być określona jako odwrotnie proporcjonalna do liczby dokumentów, w których występuje | ||
| + | Możliwe są różne wersje funkcji stosowanych w obu  składnikach. | ||
| + | |||
| + | Dane pochodzą z 20 list dyskusyjnych. | ||
| + | Jako klasyfikator wykorzystamy naiwny klasyfikator Bayesa dla rozkładów wielorakich: <tt>MultinomialNB</tt>. | ||
| + | Proszę uzupełnić poniższy kod: | ||
| + | |||
| + | <source lang = python> | ||
| + | # -*- coding: utf-8 -*- | ||
| + | # Przykład oparty na kodzie z:  | ||
| + | # http://scikit-learn.org/stable/auto_examples/text/document_classification_20newsgroups.html | ||
| + | # Authors: Peter Prettenhofer <peter.prettenhofer@gmail.com> | ||
| + | #         Olivier Grisel <olivier.grisel@ensta.org> | ||
| + | #         Mathieu Blondel <mathieu@mblondel.org> | ||
| + | #         Lars Buitinck <L.J.Buitinck@uva.nl> | ||
| + | # License: BSD 3 clause | ||
| + | # adaptacja: Jarosław Żygierewicz | ||
| + | |||
| + | |||
| + | import numpy as np | ||
| + | from sklearn.datasets import fetch_20newsgroups | ||
| + | from sklearn.feature_extraction.text import TfidfVectorizer | ||
| + | from sklearn.naive_bayes import  MultinomialNB | ||
| + | from sklearn.metrics import accuracy_score, classification_report, confusion_matrix | ||
| + | |||
| + | # W całym zbiorze danych jest 20 list dyskusyjnych, tu wykorzystamy podzbiór: | ||
| + | # kategorie dla których zbudujemy klasyfikator | ||
| + | categories = [ | ||
| + |         'alt.atheism', | ||
| + |         'talk.religion.misc', | ||
| + |         'comp.graphics', | ||
| + |         'sci.space'  ] | ||
| + | |||
| + | |||
| + | # Ładujemy dane z newsgroups dataset dla wybranch kategorii | ||
| + | # korzystamy z funkcji sklearn.datasets.fetch_20newsgroups | ||
| + | # http://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_20newsgroups.html#sklearn.datasets.fetch_20newsgroups | ||
| + | data_train = fetch_20newsgroups(subset='train', categories=categories, | ||
| + |                                 shuffle=True, random_state=42, | ||
| + |                                 remove=('headers', 'footers', 'quotes')) | ||
| + | |||
| + | data_test = fetch_20newsgroups(subset='test', categories=categories, | ||
| + |                                shuffle=True, random_state=42, | ||
| + |                                remove=('headers', 'footers', 'quotes')) | ||
| + | |||
| + | categories = data_train.target_names   | ||
| + | |||
| + | # zobaczmy jak wyglądają przykładowe dane | ||
| + | id =57 | ||
| + | print data_train.data[id]          # lista wiadomości | ||
| + | print data_train.target[id]       # lista kodów tematycznych | ||
| + | print categories[data_train.target[id]] # nazwy kategorii odpowiadających kodom | ||
| + | |||
| + | # upraszczamy nazewnictwo | ||
| + | y_train, y_test = data_train.target, data_test.target | ||
| + | |||
| + | |||
| + | # przekodowujemy wiadomości na wekotry cech  | ||
| + | # korzystamy z funkcji: sklearn.feature_extraction.text.TfidfVectorizer  | ||
| + | # http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer | ||
| + | |||
| + | vectorizer = ....# stwórz instancje obiektu TfidfVectorizer | ||
| + | X_train = ....# naucz vctorizer słownika i przetransformuj dane uczące.   | ||
| + | # wypisz rozmiary danych treningowych | ||
| + | print("Dane treningowe: n_samples: %d, n_features: %d" % X_train.shape) | ||
| + | # Dane uczące są przechowywane w macierzy rzadkiej (sparse matrix) | ||
| + | # proszę podejrzeć jak wyglądają tak przekodowane dane: | ||
| + | print ... | ||
| + | |||
| + | |||
| + | X_test = ... # wektoryzujemy też dane testowe | ||
| + | print("Dane testowe: n_samples: %d, n_features: %d" % X_test.shape) | ||
| + | print | ||
| + | |||
| + | # odwrotne mapowanie z cech na słowa | ||
| + | feature_names = vectorizer.get_feature_names() | ||
| + | feature_names = np.asarray(feature_names) | ||
| + | |||
| + | # tworzymy instancję i uczymy klasyfikator MultinomialNB | ||
| + | clf = ... | ||
| + | clf.... | ||
| + | |||
| + | # Benchmark: tu będziemy korzystać z funkcji zaimplementowanych w  | ||
| + | # http://scikit-learn.org/stable/modules/classes.html#module-sklearn.metrics | ||
| + | |||
| + | pred = clf.... # obliczamy predykcję dla tekstów ze zbioru testowego | ||
| + | accur = ... # dokladność | ||
| + | print("dokładność:   %0.3f" % accur) | ||
| + | print("classification report:") # wypisz raport klasyfikacji  | ||
| + | print(...) | ||
| + | |||
| + | print("Macierz błędów") # wypisz macierz (confusion matrix) | ||
| + | print(...) | ||
| + | |||
| + | # wypiszemy teraz po 10 najbardziej znaczących słów w każdej klasie | ||
| + | print("top 10 keywords per class:") | ||
| + | for i, category in enumerate(categories): | ||
| + |     top10 = np.argsort(clf.coef_[i])[-10:] | ||
| + |     print("%s: %s" % (category, " ".join(feature_names[top10]))) | ||
| + | print | ||
| + | |||
| − | |||
| − | |||
| </source> | </source> | ||
| + | [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw]]/Bayes | ||
Aktualna wersja na dzień 12:14, 29 mar 2016
Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw/Bayes
Naiwny klasyfikator Bayesa
Z klasyfikatorem tym zapoznamy się próbując klasyfikować gatunki irysów. Jest to klasyczny już problem, często wykorzystywany przy porównywaniu różnych technik klasyfikacji. Więcej o pochodzeniu tych danych i problemie można przeczytać tu [1]
Kod napiszemy w oparciu o implementacje klasyfikatora Bayesa z biblioteki scikit-learn [2]
Zaczerpniemy stamtąd:
- obiekt klasyfikatora GaussianNB
- zbiór danych
- funkcje do oceny jakości
Zatem importujemy:
# -*- coding: utf-8 -*-
from sklearn import datasets
from sklearn.naive_bayes import GaussianNB
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
Przyda nam się potem funkcja rysująca dwuwymiarowe rozkłady Gaussa
def plot_gauss(mu,sigma,xx,yy):
    ''' Funkcja rysująca kontury funkcji gęstości prawdopodobieństwa 
       dwuwymiarowego rozkładu Gaussa'''
    XX = np.c_[xx.ravel(), yy.ravel()]    
    R = XX - mu 
    invS = np.linalg.inv(np.diag(sigma))
    z = np.zeros(len(R))
    for i in range(len(R)):
        z[i] = np.exp(-0.5*np.dot( R[i,:].T,np.dot(invS,R[i,:])))
    z.shape = xx.shape
    plt.contourf(xx,yy,z,alpha = 0.5)
    plt.plot(mu[0],mu[1],'o')
Zapoznajemy się z danymi i wybieramy ich podzbiór do dalszej zabawy:
#ładujemy dane
iris = datasets.load_iris() #https://en.wikipedia.org/wiki/Iris_flower_data_set
# zapoznajemy się z tymi danymi
print iris['DESCR']
# rysujemy zależniści między cechami
# przygotowujemy własną mapę kolorów
color_map = {-1: (1, 1, 1), 0: (0, 0, .9), 1: (1, 0, 0), 2: (.5, .5, 0)}
# wytwarzamy wektor, który każdemu wierszowi w tabeli danych przypisze kolor odpowiadający gatunkowi irysa
colors = [color_map[y] for y in iris.target]
plt.figure(1)
plt.title(u'rozkłady cech w klasach')
for i, name in enumerate(iris['feature_names']):
    for j, name in enumerate(iris['feature_names']):
        plt.subplot(4,4,i*4+j+1)
        plt.scatter(iris.data[:,i],iris.data[:,j],c = colors)
          
# wybieramy cechy 2 i 3 i normalizujemy je
X = np.zeros((iris.data.shape[0],2))
X[:,0] = (iris.data[:,2] - np.mean(iris.data[:,2]))/np.std(iris.data[:,2])
X[:,1] = (iris.data[:,3] - np.mean(iris.data[:,3]))/np.std(iris.data[:,3])  
plt.figure(2)
plt.scatter(X[:,0],X[:,1],c = colors)  
plt.title('Wybrane cechy po normalizacji')
plt.show()
Poniżej znajduje się kod służący klasyfikacji. Proszę go uzupełnić zgodnie z komentarzami i dokumentacją [3]
#########################################################
gnb =... # stwórz instancję klasyfikatora  Gaussian Naive Bayes 
... # dofituj parametry klasyfikatora 
# przedstaw rozkłady Gaussa, które zostały dopasowane do danych, skorzystaj z funkcji plot_gauss()
# średnie tych rozkładów są w gnb.theta_
# standardowe odchylenia są w gnb.sigma_
# przygotowanie siatki na której będą rysowane kontury Gaussów
x_min, x_max = -3,3
y_min, y_max = -3,3
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.1),
                     np.arange(y_min, y_max, 0.1))
plt.figure(4)
for i in range(3):
    plot_gauss(...,...,xx,yy)
# dorzućmy do rysunku jeszcze oryginalne dane
plt.scatter(...,...,c = colors)
plt.title(u'Rozkłady Gaussa dopasowane do danych')
plt.show()        
      
# rysowanie wyników klasyfikacji             
# przekształcamy siatkę w macierz dwukolumnową - kolumny odpowiadają cechom
XX = np.c_[xx.ravel(), yy.ravel()]       
# dla każdego punktu siatki oblicz predykcję klasyfikatora  
Z = ....
# te predykcje narysujemy w przestrzeni cech za pomocą funkcji  plt.contourf 
plt.figure(3)
Z = Z.reshape(xx.shape)
plt.contourf(..., ..., ..., cmap=plt.cm.Paired)
# i dorzucamy oryginalne punkty
plt.scatter...
plt.title(u'Podział przestrzeni cech na klasy')
plt.show()
 
# Teraz zajmiemy się ewaluacją dopasowanego modelu. Skorzystamy z
# http://scikit-learn.org/stable/modules/model_evaluation.html
# upewnij się, że dokładnie rozumiesz co zwracają te funkcje
# porównaj z definicjami z wykładu 
# http://haar.zfb.fuw.edu.pl/edu/index.php/Uczenie_maszynowe_i_sztuczne_sieci_neuronowe/Wykład_Ocena_jakości_klasyfikacji
print("classification report:")
print(classification_report...)
print("confusion matrix:")
print(confusion_matrix...)
Klasyfikacja tekstów
Ten przykład demonstruje jak można poradzić sobie z klasyfikacją tematyczną dokumentów stosując technikę "worek ze słowami". O tej technice więcej można przeczytać tu: [4]
W skrócie:
- tekst jest zamieniany na pojedyncze słowa.
- ze słów otrzymanych dla dużej ilości tekstów tworzony jest słownik - wektor możliwych słów
- dla konkretnego tekstu zliczana jest ilość wystąpień każdego ze
- te zliczenia mogą być normalizowane na różne sposoby
O metodzie tej mówi się "worek ze słowami", bo zaniedbujemy w niej kolejność słów w dokumencie i wszelkie korelacje między ich wzajemnymi pozycjami.
Często stosowana wersja normalizacji to tzw. transformacja tf-idf (term frequency - inverse document frequency)[5]. Transformacja ta zasadza się na iloczynie wagi i specyficzności danego słowa. W najprostszym przypadku:
- waga danego słowa jest proporcjonalna do częstości występowania słowa w dokumencie
- specyficzność słowa może być określona jako odwrotnie proporcjonalna do liczby dokumentów, w których występuje
Możliwe są różne wersje funkcji stosowanych w obu składnikach.
Dane pochodzą z 20 list dyskusyjnych. Jako klasyfikator wykorzystamy naiwny klasyfikator Bayesa dla rozkładów wielorakich: MultinomialNB. Proszę uzupełnić poniższy kod:
# -*- coding: utf-8 -*-
# Przykład oparty na kodzie z: 
# http://scikit-learn.org/stable/auto_examples/text/document_classification_20newsgroups.html
# Authors: Peter Prettenhofer <peter.prettenhofer@gmail.com>
#         Olivier Grisel <olivier.grisel@ensta.org>
#         Mathieu Blondel <mathieu@mblondel.org>
#         Lars Buitinck <L.J.Buitinck@uva.nl>
# License: BSD 3 clause
# adaptacja: Jarosław Żygierewicz
import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import  MultinomialNB
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# W całym zbiorze danych jest 20 list dyskusyjnych, tu wykorzystamy podzbiór:
# kategorie dla których zbudujemy klasyfikator
categories = [
        'alt.atheism',
        'talk.religion.misc',
        'comp.graphics',
        'sci.space'  ]
# Ładujemy dane z newsgroups dataset dla wybranch kategorii
# korzystamy z funkcji sklearn.datasets.fetch_20newsgroups
# http://scikit-learn.org/stable/modules/generated/sklearn.datasets.fetch_20newsgroups.html#sklearn.datasets.fetch_20newsgroups
data_train = fetch_20newsgroups(subset='train', categories=categories,
                                shuffle=True, random_state=42,
                                remove=('headers', 'footers', 'quotes'))
data_test = fetch_20newsgroups(subset='test', categories=categories,
                               shuffle=True, random_state=42,
                               remove=('headers', 'footers', 'quotes'))
categories = data_train.target_names 
# zobaczmy jak wyglądają przykładowe dane
id =57
print data_train.data[id]          # lista wiadomości
print data_train.target[id]       # lista kodów tematycznych
print categories[data_train.target[id]] # nazwy kategorii odpowiadających kodom
# upraszczamy nazewnictwo
y_train, y_test = data_train.target, data_test.target
# przekodowujemy wiadomości na wekotry cech 
# korzystamy z funkcji: sklearn.feature_extraction.text.TfidfVectorizer 
# http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer
vectorizer = ....# stwórz instancje obiektu TfidfVectorizer
X_train = ....# naucz vctorizer słownika i przetransformuj dane uczące.  
# wypisz rozmiary danych treningowych
print("Dane treningowe: n_samples: %d, n_features: %d" % X_train.shape)
# Dane uczące są przechowywane w macierzy rzadkiej (sparse matrix)
# proszę podejrzeć jak wyglądają tak przekodowane dane:
print ...
X_test = ... # wektoryzujemy też dane testowe
print("Dane testowe: n_samples: %d, n_features: %d" % X_test.shape)
print
# odwrotne mapowanie z cech na słowa
feature_names = vectorizer.get_feature_names()
feature_names = np.asarray(feature_names)
# tworzymy instancję i uczymy klasyfikator MultinomialNB
clf = ...
clf....
# Benchmark: tu będziemy korzystać z funkcji zaimplementowanych w 
# http://scikit-learn.org/stable/modules/classes.html#module-sklearn.metrics
pred = clf.... # obliczamy predykcję dla tekstów ze zbioru testowego
accur = ... # dokladność
print("dokładność:   %0.3f" % accur)
print("classification report:") # wypisz raport klasyfikacji 
print(...)
print("Macierz błędów") # wypisz macierz (confusion matrix)
print(...)
# wypiszemy teraz po 10 najbardziej znaczących słów w każdej klasie
print("top 10 keywords per class:")
for i, category in enumerate(categories):
    top10 = np.argsort(clf.coef_[i])[-10:]
    print("%s: %s" % (category, " ".join(feature_names[top10])))
print

