Uczenie maszynowe i sztuczne sieci neuronowe/Ćwiczenia 9: Różnice pomiędzy wersjami

Z Brain-wiki
Linia 122: Linia 122:
  
 
=Klasyfikacja tekstów=
 
=Klasyfikacja tekstów=
 +
Ten przykład demonstruje jak można poradzić sobie z klasyfiakcją tematyczną dokumentów stosując technikę "worek ze słowami"
 +
'''This is an example showing how scikit-learn can be used to classify documents by topics using a bag-of-words approach. This example uses a scipy.sparse matrix to store the features and demonstrates various classifiers that can efficiently handle sparse matrices.
 +
The dataset used in this example is the 20 newsgroups dataset. It will be automatically downloaded, then cached.'''
 +
 +
# -*- 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
 +
 +
# 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]
 +
print data_train.target[id]
 +
print categories[data_train.target[id]]
 +
 +
# 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 = TfidfVectorizer(sublinear_tf=True, max_df=0.75, stop_words='english')
 +
X_train = vectorizer.fit_transform(data_train.data)
 +
print("Dane treningowe: n_samples: %d, n_features: %d" % X_train.shape)
 +
print
 +
 +
X_test = vectorizer.transform(data_test.data)
 +
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
 +
clf = MultinomialNB(alpha=.01)
 +
clf.fit(X_train, y_train)
 +
 +
# Benchmark
 +
pred = clf.predict(X_test)
 +
score = accuracy_score(y_test, pred)
 +
print("accuracy:  %0.3f" % score)
 +
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
 +
 +
print("classification report:")
 +
print(classification_report(y_test, pred, target_names=categories))
 +
 +
print("confusion matrix:")
 +
print(confusion_matrix(y_test, pred))

Wersja z 15:08, 30 gru 2015

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 klasyfiakcją tematyczną dokumentów stosując technikę "worek ze słowami" This is an example showing how scikit-learn can be used to classify documents by topics using a bag-of-words approach. This example uses a scipy.sparse matrix to store the features and demonstrates various classifiers that can efficiently handle sparse matrices. The dataset used in this example is the 20 newsgroups dataset. It will be automatically downloaded, then cached.

  1. -*- coding: utf-8 -*-
  2. Przykład oparty na kodzie z:
  3. http://scikit-learn.org/stable/auto_examples/text/document_classification_20newsgroups.html
  4. Authors: Peter Prettenhofer <peter.prettenhofer@gmail.com>
  5. Olivier Grisel <olivier.grisel@ensta.org>
  6. Mathieu Blondel <mathieu@mblondel.org>
  7. Lars Buitinck <L.J.Buitinck@uva.nl>
  8. License: BSD 3 clause
  9. 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

  1. kategorie dla których zbudujemy klasyfikator

categories = [

       'alt.atheism',
       'talk.religion.misc',
       'comp.graphics',
       'sci.space'  ]


  1. Ładujemy dane z newsgroups dataset dla wybranch kategorii
  2. korzystamy z funkcji sklearn.datasets.fetch_20newsgroups
  3. 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

  1. zobaczmy jak wyglądają przykładowe dane

id =57 print data_train.data[id] print data_train.target[id] print categories[data_train.target[id]]

  1. upraszczamy nazewnictwo

y_train, y_test = data_train.target, data_test.target

  1. przekodowujemy wiadomości na wekotry cech
  2. korzystamy z funkcji: sklearn.feature_extraction.text.TfidfVectorizer
  3. http://scikit-learn.org/stable/modules/generated/sklearn.feature_extraction.text.TfidfVectorizer.html#sklearn.feature_extraction.text.TfidfVectorizer

vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.75, stop_words='english') X_train = vectorizer.fit_transform(data_train.data) print("Dane treningowe: n_samples: %d, n_features: %d" % X_train.shape) print

X_test = vectorizer.transform(data_test.data) print("Dane testowe: n_samples: %d, n_features: %d" % X_test.shape) print

  1. odwrotne mapowanie z cech na słowa

feature_names = vectorizer.get_feature_names() feature_names = np.asarray(feature_names)

  1. tworzymy instancję i uczymy klasyfikator

clf = MultinomialNB(alpha=.01) clf.fit(X_train, y_train)

  1. Benchmark

pred = clf.predict(X_test) score = accuracy_score(y_test, pred) print("accuracy: %0.3f" % score) 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

print("classification report:") print(classification_report(y_test, pred, target_names=categories))

print("confusion matrix:") print(confusion_matrix(y_test, pred))