# 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']
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kssk.gitbook.io/msi/1.-klasyfikacja-jako-przyklad-rozpoznawania-wzorcow/1.3-proces-uczenia-i-predykcja.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
