Uczenie maszynowe i sztuczne sieci neuronowe/DrzewaDecyzyjne cw: Różnice pomiędzy wersjami

Z Brain-wiki
Linia 63: Linia 63:
  
 
=Przykład klasyfikacji cyfr=
 
=Przykład klasyfikacji cyfr=
 +
Teraz spróbujmy klasyfikacji ręcznie pisanych cyfr. Pierwszą rzeczą z jaką musimy sobie poradzić to reprezentacja cyfr tak aby dało się z nich zbudować ciąg uczący.
 +
 +
W surowej postaci dostalibyśmy obrazek, tzn. macierz pikseli <math> n \times m</math>. W naszym przypadku pierwotne obrazki były skanowane i rozdzielane na poszczególne cyfry przez otaczanie każdej cyfry pudełkiem centrowanym na środku masy piksli, a nastepnie znormalizowane do rozmiarów <math>20 \times 20 </math>.
 +
 +
Dane z których będziemy korzystać stanowią obrazek przetworzony do formatu jednowymiarowego przez ułżenie kolejnych wierszy. Dane te pochodzą z bazy danych ręcznie pisanych cyfr MNIST (http://yann.lecun.com/exdb/mnist/).
 +
 +
W pliku: [http://www.fuw.edu.pl/~jarekz/SIECI/cyfry.mat cyfry.mat] jest dostępna wersja matlabowa tych danych. Proszę zapisać wskazywany plik w katalogu roboczym.
 +
 +
 +
Poniższy kod (po uzupełnieniu) będzie wykonywał klasyfikację cyfr.
  
 
<source lang = python >
 
<source lang = python >
Linia 72: Linia 82:
 
from sklearn import tree
 
from sklearn import tree
 
from sklearn.cross_validation import train_test_split
 
from sklearn.cross_validation import train_test_split
 
 
from scipy.io import loadmat
 
from scipy.io import loadmat
 
plt.close('all')
 
  
  
 
###############################################################################
 
###############################################################################
 
# podglądanie obrazków cyfr
 
# podglądanie obrazków cyfr
 
+
# funkcja pomocnicza
 +
#
 
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
 
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
 
     plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
 
     plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
Linia 108: Linia 116:
 
###############################################################################
 
###############################################################################
 
# Wypisz dane o zbiorze cyfr  
 
# Wypisz dane o zbiorze cyfr  
print("dane zawierają %d cyfr po %d pixli"
+
print("dane zawierają %d cyfr po %d pixli" % (X.shape[0], X.shape[1]))
      % (X.shape[0], X.shape[1]))
 
  
 
# Pokaż kilka przykładowych cyfr:
 
# Pokaż kilka przykładowych cyfr:
Linia 116: Linia 123:
  
 
###############################################################################
 
###############################################################################
# Podziel zbiór na dane treningowe i testowe  
+
# Podziel zbiór na dane treningowe i testowe za pomocą funkcji opisanej tu w proporcji 5:1 :
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
+
# http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.train_test_split.html
 +
#
 +
X_train, X_test, y_train, y_test = ...
  
  
  
 
###############################################################################
 
###############################################################################
 
+
#
DEPTH =8
+
DEPTH = 10
MAX_FEAT=50
+
MAX_FEAT = 100
clf = tree.DecisionTreeClassifier(criterion='entropy',
+
clf = ... # instancja klasyfikatora DecisionTreeClassifier
        splitter='best',
+
clf = ...# fitowanie do danych treningowych
        max_depth=DEPTH,
+
y_pred = ...# predykcja na danych testowych
        min_samples_split=2,
 
        min_samples_leaf=1,
 
        min_weight_fraction_leaf=0.0,
 
        max_features=MAX_FEAT,
 
        random_state=None,
 
        max_leaf_nodes=None,
 
        class_weight=None,
 
        presort=False)
 
       
 
   
 
 
 
clf = clf.fit(X_train,  y_train)
 
y_pred=clf.predict(X_test)
 
  
  
Linia 147: Linia 143:
 
plt.show()
 
plt.show()
  
#F1[MAX_FEAT] = f1_score(y_test, y_pred,average='weighted')
+
# uzupełnij miary klasyfikacji
 +
print("wynik F1: " ...# uzupełnij
 
print("confusion matrix:")
 
print("confusion matrix:")
print(confusion_matrix(y_test, y_pred))
+
print(...)
print(classification_report(y_test, y_pred, labels=range(0,10)))
+
print("raport klasyfikacji:")
 
+
print(...)
 
 
 
 
 
 
 
</source>
 
</source>

Wersja z 12:44, 4 sty 2016

Wstęp

W bibliotece scikit-learn drzewa decyzyjne implementowane są przez klasę DecisionTreeClassifier

Aby nauczyć taki klasyfikator potrzebujemy tablicę X o rozmiarach [N_przykładów, N_cech] i wektor Y określający przynależność przykładów w X do klas.

Najprostszy przykład:

from sklearn import tree
X = [[0, 0], [1, 1]]
Y = [0, 1]
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, Y)

Po dopasowaniu można przewidywać przynależność nowych przykładów:

clf.predict([[2., 2.]])

Albo estymować prawdopodobieństwo przynależności do klas:

clf.predict_proba([[2., 2.]])

Przykład zbiór danych Iris

from sklearn.datasets import load_iris
from sklearn import tree
iris = load_iris()
clf = tree.DecisionTreeClassifier()
clf = clf.fit(iris.data, iris.target)

Po wytrenowaniu można zilustrować wynik za pomocą narzędzia Graphiz (wymaga to zainstalowania w systemie tego narzędzia), oraz doinstalowania do pythona biblioteki pydot:

from sklearn.externals.six import StringIO  
import pydot 
dot_data = StringIO() 
tree.export_graphviz(clf, out_file=dot_data) 
graph = pydot.graph_from_dot_data(dot_data.getvalue()) 
graph.write_pdf("iris.pdf")

Można też podejrzeć wyniki w pythonie:

from IPython.display import Image  
dot_data = StringIO()  
tree.export_graphviz(clf, out_file=dot_data,    feature_names=iris.feature_names,  
                         class_names=iris.target_names,  
                         filled=True, rounded=True,  
                         special_characters=True) 
graph = pydot.graph_from_dot_data(dot_data.getvalue())  
Image(graph.create_png())

Po dopasowaniu model ten może być zastosowany do przewidywania przynależności przykładów do klas:

clf.predict(iris.data[:1, :])

lub estymowania prawdopodobieństwa przynależności do klas:

clf.predict_proba(iris.data[:1, :])


Przykład klasyfikacji cyfr

Teraz spróbujmy klasyfikacji ręcznie pisanych cyfr. Pierwszą rzeczą z jaką musimy sobie poradzić to reprezentacja cyfr tak aby dało się z nich zbudować ciąg uczący.

W surowej postaci dostalibyśmy obrazek, tzn. macierz pikseli [math] n \times m[/math]. W naszym przypadku pierwotne obrazki były skanowane i rozdzielane na poszczególne cyfry przez otaczanie każdej cyfry pudełkiem centrowanym na środku masy piksli, a nastepnie znormalizowane do rozmiarów [math]20 \times 20 [/math].

Dane z których będziemy korzystać stanowią obrazek przetworzony do formatu jednowymiarowego przez ułżenie kolejnych wierszy. Dane te pochodzą z bazy danych ręcznie pisanych cyfr MNIST (http://yann.lecun.com/exdb/mnist/).

W pliku: cyfry.mat jest dostępna wersja matlabowa tych danych. Proszę zapisać wskazywany plik w katalogu roboczym.


Poniższy kod (po uzupełnieniu) będzie wykonywał klasyfikację cyfr.

# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import classification_report, confusion_matrix, f1_score
from sklearn import tree
from sklearn.cross_validation import train_test_split
from scipy.io import loadmat


###############################################################################
# podglądanie obrazków cyfr
# funkcja pomocnicza 
#
def plot_gallery(images, titles, h, w, n_row=3, n_col=4):
    plt.figure(figsize=(1.8 * n_col, 2.4 * n_row))
    plt.subplots_adjust(bottom=0, left=.01, right=.99, top=.90, hspace=.05)
    for i in range(n_row * n_col):
        plt.subplot(n_row, n_col, i + 1)
        plt.imshow(images[i].reshape((h, w)).T, cmap=plt.cm.gray)
        plt.title(titles[i], size=12)
        plt.xticks(())
        plt.yticks(())


###############################################################################
# wczytywanie danych
dane = loadmat('cyfry.mat')
#przepisanie danych do osobnych tablic:
X = dane['X']
y = dane['y']
for i in range(X.shape[0]):
    X[i,:] = X[i,:]/np.std(X[i,:])
y[np.where(y==10)]=0 # przekodoeanie cyfry 0 tak, żeby w wektorze y też odpowiadąło jej 0 (w oryginalnym zbiorze danych było 10)

# wysokość i szerokość obrazka z cyfrą 
h = 20
w = 20

###############################################################################
# Wypisz dane o zbiorze cyfr 
print("dane zawierają %d cyfr po %d pixli" % (X.shape[0], X.shape[1]))

# Pokaż kilka przykładowych cyfr:
plot_gallery(X[0:5000:200,:], y[0:5000:200], h, w, n_row=5, n_col=5)
plt.show()

###############################################################################
# Podziel zbiór na dane treningowe i testowe za pomocą funkcji opisanej tu w proporcji 5:1 :
# http://scikit-learn.org/stable/modules/generated/sklearn.cross_validation.train_test_split.html
# 
X_train, X_test, y_train, y_test = ...



###############################################################################
# 
DEPTH = 10
MAX_FEAT = 100
clf = ... # instancja klasyfikatora DecisionTreeClassifier
clf = ...# fitowanie do danych treningowych
y_pred = ...# predykcja na danych testowych


# Pokaż kilka przykładowych klasyfikacji:
plot_gallery(X_test[0:40,:], y_pred[0:40], h, w, n_row=5, n_col=8)
plt.show()

# uzupełnij miary klasyfikacji
print("wynik F1: " ...# uzupełnij
print("confusion matrix:")
print(...)
print("raport klasyfikacji:")
print(...)