Uczenie maszynowe i sztuczne sieci neuronowe/DrzewaDecyzyjne cw: Różnice pomiędzy wersjami
(Nie pokazano 14 pośrednich wersji utworzonych przez tego samego użytkownika) | |||
Linia 1: | Linia 1: | ||
+ | [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw]]/Drzewa decyzyjne | ||
=Wstęp= | =Wstęp= | ||
− | W bibliotece scikit-learn drzewa | + | W bibliotece scikit-learn drzewa decyzyjne implementowane są przez klasę [http://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html#sklearn.tree.DecisionTreeClassifier DecisionTreeClassifier] |
+ | Szczegóły implementacji opisane są tu [http://scikit-learn.org/stable/modules/tree.html#tips-on-practical-use]. | ||
+ | |||
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. | 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. | ||
Linia 29: | Linia 32: | ||
iris = load_iris() | iris = load_iris() | ||
clf = tree.DecisionTreeClassifier() | clf = tree.DecisionTreeClassifier() | ||
− | + | clf.fit(iris.data, iris.target) | |
</source> | </source> | ||
− | Po wytrenowaniu można zilustrować wynik za pomocą | + | Po wytrenowaniu można zilustrować wynik za pomocą narzędzia [http://www.graphviz.org/ Graphiz] (wymaga to zainstalowania w systemie tego narzędzia), oraz doinstalowania do pythona biblioteki <tt>pydot</tt>: |
<source lang = python> | <source lang = python> | ||
from sklearn.externals.six import StringIO | from sklearn.externals.six import StringIO | ||
Linia 38: | Linia 41: | ||
tree.export_graphviz(clf, out_file=dot_data) | tree.export_graphviz(clf, out_file=dot_data) | ||
graph = pydot.graph_from_dot_data(dot_data.getvalue()) | graph = pydot.graph_from_dot_data(dot_data.getvalue()) | ||
− | graph.write_pdf("iris.pdf") | + | graph[0].write_pdf("iris.pdf") |
</source> | </source> | ||
+ | |||
+ | Można też podejrzeć wyniki w pythonie: | ||
+ | <source lang = python> | ||
+ | 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[0].create_png()) | ||
+ | </source> | ||
+ | Po dopasowaniu model ten może być zastosowany do przewidywania przynależności przykładów do klas: | ||
+ | <source lang = python> | ||
+ | clf.predict(iris.data[:1, :]) | ||
+ | </source> | ||
+ | lub estymowania prawdopodobieństwa przynależności do klas: | ||
+ | <source lang = python> | ||
+ | clf.predict_proba(iris.data[:1, :]) | ||
+ | </source> | ||
+ | |||
+ | =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 > | ||
+ | # -*- 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(...) | ||
+ | </source> | ||
+ | |||
+ | ==Zadanie: Badanie zależności jakości klasyfikacji od hiperparametrów drzewa== | ||
+ | Bazując na powyższym kodzie zbadaj: | ||
+ | * zależność miary F1 od parametru: | ||
+ | ** głębokości drzewa | ||
+ | ** ilości cech wykorzystanych w klasyfikacji | ||
+ | * Dla optymalnych parametrów DEPTH i MAX_FEAT zbadaj zależność dokładności (accuracy) od liczby przykładów w zbiorze uczącym | ||
+ | |||
+ | ==Analiza struktury drzewa== | ||
+ | Proszę przeanalizować ten tutorial: | ||
+ | http://scikit-learn.org/stable/auto_examples/tree/plot_unveil_tree_structure.html#sphx-glr-auto-examples-tree-plot-unveil-tree-structure-py | ||
+ | |||
+ | Na tej podstawie przeanalizować strukturę drzewa wyhodowanego do rozpoznawania cyfr. |
Aktualna wersja na dzień 12:57, 7 gru 2018
Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw/Drzewa decyzyjne
Spis treści
Wstęp
W bibliotece scikit-learn drzewa decyzyjne implementowane są przez klasę DecisionTreeClassifier Szczegóły implementacji opisane są tu [1].
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.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[0].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[0].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(...)
Zadanie: Badanie zależności jakości klasyfikacji od hiperparametrów drzewa
Bazując na powyższym kodzie zbadaj:
- zależność miary F1 od parametru:
- głębokości drzewa
- ilości cech wykorzystanych w klasyfikacji
- Dla optymalnych parametrów DEPTH i MAX_FEAT zbadaj zależność dokładności (accuracy) od liczby przykładów w zbiorze uczącym
Analiza struktury drzewa
Proszę przeanalizować ten tutorial: http://scikit-learn.org/stable/auto_examples/tree/plot_unveil_tree_structure.html#sphx-glr-auto-examples-tree-plot-unveil-tree-structure-py
Na tej podstawie przeanalizować strukturę drzewa wyhodowanego do rozpoznawania cyfr.