# 1.4 Miary oceny jakości klasyfikacji

Narzędzia do oceny jakości (czy też ewaluacji) klasyfikacji znajdują się w module `metrics` pakietu `sklearn`. Zaimportujmy go do skryptu.

```python
from sklearn import metrics
```

Po poprawnym przeprowadzeniu klasyfikacji na zbiorze testowym uzyskaliśmy **wektor predykcji** (`prediction`). Na etapie podziału, od tego samego zbioru, oddzieliliśmy również wektor oryginalnych etykiet (`y_test`).

> Dla oryginalnego zbioru etykiet czasami stosuje się również nazwę *ground truth*. Nie w każdym przypadku jest to poprawne określenie, ale jego stosowanie nie jest naganne. A zawsze brzmi niemal jak byśmy wiedzieli o czym mówimy.

Ocena jakości klasyfikacji polega na odpowiednim porównaniu ze sobą tych dwóch wektorów. Podstatowym narzędziem takiej oceny jest tak zwana **macierz pomyłek** (*confussion matrics*). Wyliczmy ją dla naszej pary porównawczej.

```python
confusion_matrix = metrics.confusion_matrix(y_test, prediction)
print(confusion_matrix)
```

```
[[16  0  0]
 [ 0 18  1]
 [ 0  0 15]]
```

Dane zapisane po przekątnej macierzy pomyłek (tej, w której indeks wiersza i kolumny jest równy) informują o wzorcach poprawnie przypisanych do swoich klas. Pozostałe komórki macierzy oznaczają poszczególne błędy przypisania.

Najprostszą i jednocześnie najbardziej powszechnie stosowaną miarą jakości klasyfikacji (do której na tę chwilę się ograniczymy) jest jej dokładność, czyli stosunek sumy wartości znajdujących się na przekątnej macierzy pomyłek do sumy wszystkich wartości macierzy. Możemy uzyskać ją używając funkcji `accuracy_score()`.

```python
accuracy = metrics.accuracy_score(y_test, prediction)
print accuracy
```

```
0.98
```

> Zgodnie z literaturą, miarą bardziej poprawną od jakości klasyfikacji, jest jej **błąd**. Wynosi on dokładnie `1 - dokładność`.

W większości eksperymentów nie będziemy stosować prostego podziału zbioru, a k-foldowej walidacji krzyżowej. W takim wypadku uzyskamy `k` wartości wybranej przez nas miary jakości. Dokonując pomiarów, na poczet późniejszych testów statystycznych powinniśmy zapisywać wszystkie `k` wyliczonych miar.

> Deklarujemy parametr `k`, przyjmując dla niego wartość `10` podziałów. Inicjalizujemy obiekt podziału w zmiennej `cv`. Inicjalizujemy pustą listę `accuracies`, w której będziemy składować kolejne wyliczone dokładności. Następnie iterujemy obiekt podziału, przy każdej pętli uzyskując krotkę `(train,test)`. Musimy pamiętać, że zwraca ona nie podzielone obiekty, a jedynie ich indeksy. W związku z tym do kolejnych zmiennych przypisujemy już odpowiednie podzbiory tablic `X` i `y`. Po podziale uczymy klasyfikator (`fit`), wyliczamy wektory wsparć (`predict_proba`), wyliczamy i *tłumaczymy* predykcję i wyliczamy dokładność (`accuracy`). Na koniec, na koniec listy `accuracies` dodajemy wyliczoną dokładność. *Serwować podgrzane.*

```python
k = 10
cv = model_selection.StratifiedKFold(n_splits=k)

accuracies = []
for train, test in cv.split(X, y):
    X_train, y_train = X[train], y[train]
    X_test, y_test = X[test], y[test]

    clf.fit(X_train, y_train)
    probas = clf.predict_proba(X_test)
    prediction = np.argmax(probas,axis = 1)
    prediction = clf.classes_[prediction]
    accuracy = metrics.accuracy_score(y_test, prediction)
    accuracies.append(accuracy)

print accuracies
```

```
[1.0, 0.9333333333333333, 1.0, 1.0, 0.8666666666666667, 0.9333333333333333, 0.9333333333333333, 1.0, 1.0, 1.0]
```

Podając wynik klasyfikacji, nie chwalimy się całym wektorem dokładności, a prezentujemy jego uśrednioną dokładność i jej odchylenie standardowe.

```python
mean_accuracy = np.mean(accuracies)
std_accuracy = np.std(accuracies)
print "Średnia dokładność %.3f (+- %.2f)" % (mean_accuracy, std_accuracy)
```

```
Średnia dokładność 0.967 (+- 0.04)
```
