1.3 Proces uczenia i predykcja
Skoro dysponujemy już podziałem zbioru, możemy przystąpić do procesu uczenia. W tym celu posłużymy się popularnym, prostym klasyfikatorem k najbliższych sąsiadów (kNN).
W problemie klasyfikacji, naszym zadaniem jest stworzenie algorytmu (programu), który na podstawie znanych sobie, opisanych wzorców, będzie w stanie efektywnie rozpoznawać wzorce nieopisane i dotąd sobie nieznane.
Dziś nie będziemy jeszcze zajmować się projektowaniem własnych algorytmów, a nauczymy się wykorzystywać te, które znajdują się już w pakiecie scikit-learn
. Wszystkie znajdujące tam rozwiązania są pogrupowane w moduły, związane wprost z rodzinami algorytmów. My, na początek, skorzystamy z algorytmu k najbliższych sąsiadów (k-NN), będącego częścią modułu neighbors
. Zaimportujmy więc go do naszego skryptu.
from sklearn import neighbors
Po zaimportowaniu modułu, możemy uzyskać od niego obiekt konkretnego klasyfikatora. Przyjętą konwencją jest przypisywanie takiego obiektu do zmiennej clf
.
clf = neighbors.KNeighborsClassifier()
Dysponując podzielonym w poprzedniej części zbiorem danych i klasyfikatorem, możemy wytrenować go używając naszego zbioru uczącego. W konwencji sklearn
, dla zapewnienia spójności nazwy metody dla algorytmów poświęconych różnym zadaniom rozpoznawania wzorców, uczenie nazywa się dopasowaniem, stąd posłużymy się metodą fit()
, przekazując do niej przestrzeń cech i zbiór etykiet zbioru.
clf.fit(X_train, y_train)
Model klasyfikatora został wyuczony i teoretycznie moglibyśmy już określić jego jakość, używając wbudowanej w każdy klasyfikator metody score()
, przyjmującej zbiór testowy.
score = clf.score(X_test, y_test)
print(score)
0.98
Uzyskaliśmy miarę 0.98
. Z kilku przyczyn nie jest to jednak przesadnie dobre rozwiązanie. Możemy co prawda w przypadku większości klasyfikatorów założyć, że miara ta to dokładność klasyfikatora (odsetek poprawnie sklasyfikowanych próbek), ale programiści mają zupełną dowolność w doborze miary zwracanej z tej metody. Ponadto, nie uzyskujemy w ten sposób faktycznych decyzji podjętych wobec każdego wzorca ze zbioru testowego, co mogłoby okazać się przydatne zarówno w wyliczeniu innych miar jakości, jak i w ewentualnej konstrukcji komitetów klasyfikatorów, o których opowiemy sobie na jednych z kolejnych zajęć.
Wyliczmy więc jakość naszego klasyfikatora w bardziej cywilizowany sposób. Większość algorytmów klasyfikacji jest zdolna do zwrócenia, oprócz prostej decyzji o przynależności wzorca do jednej z klasy, również tak zwanego wektora wsparcia. Określa on prawdopodobieństwo przynależności obiektu do każdej z możliwych klas i zawsze sumuje się do jedynki. W wypadku zbioru iris
powinniśmy więc móc uzyskać po trzy wartości dla każdej próbki ze zbioru testowego.
Do wyliczania wektora wsparć dla zbioru służy metoda predict_proba()
klasyfikatora. Przekażmy do niej nasz zbiór testowy.
# Uzyskanie wektora wsparć
support_vector = clf.predict_proba(X_test)
print(support_vector)
[[0. 0. 1. ]
[0. 1. 0. ]
[1. 0. 0. ]
...
[0. 0. 1. ]
[0. 0.4 0.6]
[0. 0. 1. ]]
Wynik klasyfikacji (przypisanie wzorca do klasy) nazywamy predykcją. Możemy ją uzyskać wyliczając indeks najwyższej wartości w wektorze wsparcia (funkcja argmax
) dla każdej sklasyfikowanej próbki.
# Wyznaczenie predykcji
prediction = np.argmax(support_vector,axis = 1)
print(prediction)
[2 1 0 ... 2 2 2]
Choć często klasy w zbiorach danych są oznaczane przez kolejne liczby całkowite, licząc od zera, w zbiorze iris
były one łańcuchami znakowymi. Obiekt klasyfikatora przechowuje wszystkie klasy znalezione w zbiorze uczącym w atrybucie classes_
. Możemy więc posłużyć się nim do przetłumaczenia indeksów klas predykcji na odpowiadające im łańcuchy znakowe.
prediction = clf.classes_[prediction]
print(prediction)
['Iris-virginica' 'Iris-versicolor' 'Iris-setosa' ... 'Iris-virginica'
'Iris-virginica' 'Iris-virginica']
Last updated