> For the complete documentation index, see [llms.txt](https://kssk.gitbook.io/msi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kssk.gitbook.io/msi/1.-klasyfikacja-jako-przyklad-rozpoznawania-wzorcow/1.3-proces-uczenia-i-predykcja.md).

# 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.

```python
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`.

```python
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.

```python
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.

```python
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.

```python
# 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.

```python
# 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.

```python
prediction = clf.classes_[prediction]
print(prediction)
```

```
['Iris-virginica' 'Iris-versicolor' 'Iris-setosa' ... 'Iris-virginica'
 'Iris-virginica' 'Iris-virginica']
```
