
Uczenie maszynowe i sztuczne sieci neuronowe/Ćwiczenia 10: Różnice pomiędzy wersjami
(Utworzono nową stronę "=Klasyfikacja za pomocą algorytmu wektorów wspierających (SVM)= == Materiały == Na tych ćwiczeniach zapoznamy się z zastosowaniem SVM do klasyfikacji. Poniżej zna...") |
m |
||
Linia 1: | Linia 1: | ||
+ | [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw]]/SVM1 | ||
=Klasyfikacja za pomocą algorytmu wektorów wspierających (SVM)= | =Klasyfikacja za pomocą algorytmu wektorów wspierających (SVM)= | ||
== Materiały == | == Materiały == | ||
Linia 550: | Linia 551: | ||
</source> | </source> | ||
{{hidden end}} | {{hidden end}} | ||
+ | |||
+ | [[Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw]]/SVM1 |
Wersja z 14:15, 29 mar 2016
Uczenie_maszynowe_i_sztuczne_sieci_neuronowe_cw/SVM1
Klasyfikacja za pomocą algorytmu wektorów wspierających (SVM)
Materiały
Na tych ćwiczeniach zapoznamy się z zastosowaniem SVM do klasyfikacji. Poniżej znajduje się moduł dostarczający kilku funkcji, z których dziś będziemy korzystać. Proszę zapisać go w bieżącym katalogu.
Potrzebne będą nam też następujące zestawy danych:
Plik:Dane1.txt, Plik:Dane2.txt, Plik:Dane3.txt.
Proszę pobrać te pliki i zapisać je w bieżącym katalogu.
Ćwiczenie 1: Dane separowalne liniowo
Poniższy kod prezentuje zastosowanie SVM do problemu, który jest separowalny liniowo. Wykonując poniższy kod proszę zwrócić uwagę na punkt należący do klasy1 o współrzędnych (0.09, 4).
Jak pamiętamy z wykładu parametr C to współczynnik regularyzacji SVM, który karze za naruszanie marginesów. Proszę wykonać kod dla C o wartościach {1,2,5,10,20,30,60,120} i zaobserwować wyniki.
# -*- coding: utf-8 -*-
#importujemy potrzebne moduły i klasy
import numpy as np
import pylab as py
from svm_modul import *
#==================================================================
# Program
#==================================================================
# wczytywanie danych
dane = np.loadtxt('Dane1.txt') # dane zorganizowane są w trzech kolumnach
N_przyk, N_wej = dane.shape
X = dane[:,0:2] # pierwsze dwie kolumny to wejście
y = dane[:,2] # trzecia kolumna to etykiety klas
# narysujmy te dane
rysujDaneGrup(X, y, marker=('or','xb'), xlabel='x0', ylabel='x1',legend_list=('klasa0','klasa1'))
py.show()
# trenujemy model
model = svmTrain(X, y, C=100, kernelFunction = 'linearKernel', tol = 1e-3, max_passes = 20,sigma = 10)
# prezentujemy podział przestrzeni wejść reprezentowany przez model
rysujDaneGrup(X, y, marker=('or','xb'), xlabel='x0', ylabel='x1',legend_list=('klasa0','klasa1'))
rysujPodzial(model,X)
py.show()
Ćwiczenie 2: jądro Gaussowskie
W poprzednim programie proszę zmodyfikować wywołanie svmTrain:
- podmienić funkcję jądra na 'gaussianKernel'.
- ustawić C = 10
- zmieniać sigma na wartości: {0.1, 0.2, 0.4, 0.8, 1, 2, 4, 8}
Ćwiczenie 3: skomplikowany podział nieliniowy
Przy pomocy kodu z ćwiczenia 2 proszę dobrać parametry C i sigma aby otrzymać sensownie wyglądający podział przestrzeni dla danych zawartych w pliku dane2.txt.
Ćwiczenie 4: automatyzacja dobierania parametrów C i sigma
W wielu prawdziwych zastosowaniach chcielibyśmy aby nasz wybór parametrów był optymalny a jednocześnie możliwie obiektywny.
Powszechnie stosowaną metodą jest przeszukanie przestrzeni parametrów (C,sigma). Generuje się siatkę wartości (C,sigma) i dla każdego punktu siatki:
- estymuje się model
- ocenia się jakość generalizacji
Do oceny jakości w każdym punkcie siatki można zastosować albo zbiór monitorujący albo metody typu leave-one-out.
Uwaga: podział przestrzeni często wykonuje się w skali logarytmicznej.
Ćwiczenie wykonamy dla zbioru uczącego z pliku dane3.txt.
Musimy ten zbiór podzielić na dane do trenowania i dane do testowania np. w proporcji 3:1, Można to zrobić tak:
# wczytywanie danych
dane = np.loadtxt('dane3.txt') # dane zorganizowane są w trzech kolumnach
N_przyk, N_wej = dane.shape
X = dane[:,0:2] # pierwsze dwie kolumny to wejście
y = dane[:,2] # trzecia kolumna to etykiety klas
#podział na zbiór uczący i testujący
grupa0, = np.where(y==-1)
grupa1, = np.where(y==1)
# mieszamy kolejność indexów
np.random.shuffle(grupa0)
np.random.shuffle(grupa1)
# kopiujemy dane do zbioru uczącego (pierwsze 75% grupy0 i grupy1)
Xu = X[np.concatenate((grupa0[0: int(0.75*len(grupa0))],grupa1[0:int(0.75*len(grupa0))]))]
yu = y[np.concatenate((grupa0[0: int(0.75*len(grupa0))],grupa1[0:int(0.75*len(grupa0))]))]
# kopiujemy dane do zbioru testowego (końcowe 25% grupy0 i grupy1)
Xt = X[np.concatenate((grupa0[int(0.75*len(grupa0)):], grupa1[int(0.75*len(grupa0)):]))]
yt = y[np.concatenate((grupa0[int(0.75*len(grupa0)):], grupa1[int(0.75*len(grupa0)):]))]
# narysujmy te dane
rysujDaneGrup(Xu, yu, marker=('xr','xb'), xlabel='x0', ylabel='x1',legend_list=('klasa0','klasa1'))
rysujDaneGrup(Xt, yt, marker=('or','ob'), xlabel='x0', ylabel='x1',legend_list=('klasa0_test','klasa1_test'))
py.show()
Mając taki podział danych możemy dopasować model SVM do części uczącej:
model = svmTrain(Xu, yu, C=10, kernelFunction = 'gaussianKernel', tol = 1e-3, max_passes = 20,sigma = 0.5)
A następnie ocenić jego jakość na części testowej (funkcja svmPredict dostarczana jest przez moduł svm_modul.py):
TPR = np.sum(yt == svmPredict(model,Xt))/float(len(yt))
Proszę napisać program, który
- skanuje przestrzeń (C,sigma): C w zakresie od 0.1 do 100, sigma w zakresie od 0.1 do 10. Do wygenerowania zakresu ze skalą logarytmiczną można wykorzystać np. takie polecenie: zakresC = np.logspace(np.log2(0.1),np.log2(100),8, base=2)
- znajduje najlepsze parametry
- rysuje podział przestrzeni dla najlepszych parametrów.
Dodatek: implementacja w oparciu o bibliotekę LIBSVM
Do praktycznych zastosowań zaleca się stosowanie zoptymalizowanych bibliotek, np. LIBSVM (http://www.csie.ntu.edu.tw/~cjlin/libsvm/). Poniżej prezentujemy przykłady implementacji ćwiczenia 3 i ćwiczenia 4 w oparciu o tą bibliotekę. Aby móc wykonać te programy potrzebna jest skompilowana biblioteka libsvm i moduły pythonowe svm.py oraz svmutil. Cały zestaw wraz z instrukcją komilacji można pobrać z http://www.csie.ntu.edu.tw/~cjlin/libsvm/#download. Uwaga: w bibliotece tej jest nieco inna konwencja notacji jądra Gaussowskiego: [math]K(x,z) =\exp(-g ||x-z||^2)[/math], tzn. parametr [math]g = \frac{1}{2 \sigma^2}[/math]