Klasyfikacja KNN zbiór iris
Python

Python uczenie maszynowe klasyfikacja

W artykule przedstawiam uczenie maszynowe w Pythonie. Prezentuję algorytm klasyfikacji k-najbliższych sąsiadów dla zbioru danych Iris. Analizę przeprowadzam w aplikacji Spyder.  

Import modułów języka Python

Do przeprowadzenia analizy potrzebujesz zainstalować bibliotekę Anaconda. Informacje, w jaki sposób ją zainstalować znajdziesz w artykule Python Anaconda instalacja 

Instalator pobiera z Internetu i zapisuje na dysku Anacondę i wszystkie dostępne w niej moduły. Podczas instalacji automatycznie importuje się tylko część modułów. Pozostałe, w miarę potrzeby, należy zaimportować.

Do przeprowadzenia analizy potrzebne nam będą moduły: 

  • sys
  • numpy
  • pandas
  • matplotlib
  • sklearn

W/w moduły musimy zaimportować, gdyż nie są one importowane automatycznie.

Do importu modułów i przeprowadzenia analizy możesz użyć aplikacji Spyder lub Jupyter Notebook. Modele tworzę w Jupyter Notebook i zapisuję w nim finalne efekty pracy, gdyż aplikacja ta umożliwia przechowywanie kodu i notatek. Spydera używam na tzw. etapie roboczym do eksperymentowania np. sprawdzania zmiennych. 

W tym artykule posłużę się Spyderem do przeprowadzenia analizy. 

Wyszukaj w menu Start Spyder i otwórz aplikację. Aplikację instaluje instalator Anaconda. 

Aplikacja Spyder

Wpisz #%% i kliknij Enter aby utworzyć nową komórkę. W komórce wklej poniższe polecenia i kliknij Ctrl + Enter aby je uruchomić:

import sys
print(f"Python version: {sys.version}")
import numpy as np
import pandas as pd
print(f"NumPy version: {np.__version__}")
print(f"pandas version: {pd.__version__}")
import matplotlib.pyplot as plt
import matplotlib
print(f"matplotlib version: {matplotlib.__version__}")
import sklearn
print("scikit-learn version: {}".format(sklearn.__version__))

Opis poleceń:

PolecenieOpis
import sysimport modułu sys
import sysimport modułu sys
print(f”Python version: {sys.version}”)sprawdzenie wersji Pythona
import numpy as npimport modułu numpy
import pandas as pdimport modułu pandas
print(f”NumPy version: {np.__version__}”)sprawdzenie wersji modułu numpy
print(f”pandas version: {pd.__version__}”)sprawdzenie wersji modułu pandas
import matplotlib.pyplot as pltimport modułu pyplot z biblioteki matplotlib
import matplotlibimport całej biblioteki matplotlib
print(f”matplotlib version: {matplotlib.__version__}”)sprawdzenie wersji biblioteki matplotlib
import sklearnimport biblioteki sklearn
print(„scikit-learn version: {}”.format(sklearn.__version__))sprawdzenie wersji biblioteki sklearn

Polecenia w aplikacji Spyder:

Spyder import bibliotek

Uczenie maszynowe – klasyfikacja

Klasyfikacja w uczeniu maszynowym to problem modelowania predykcyjnego, w którym przewidujemy etykietę klasy dla danych wejściowych.

Najbardziej popularne algorytmy klasyfikacji to:

  • klasyfikacja binarna – możliwe są tylko dwa wyniki: prawda lub fałsz np. klient spłaci pożyczkę lub nie, klient złoży rezygnację lub nie.
  • klasyfikcja wieloklasowa – istnieje więcej niż jedna klasa np. kwalifkujemy książki do trzech klas: liryka, epika dramat lub kwalifkujemy recenzje do trzech klas: pozytywna, neutralna, negatywna.

Zbiór Iris – algorytm klasyfikacji

W przykładzie załadujemy zbiór Iris. Jest to zbiór często wykorzystywany z uczeniu maszynowym i statystyce. Mamy w nim zbiór danych zawierających informacje o kwiatach irys. Posiadamy zmierzone w centymetrach:

  • długość i szerokość płatków (ang. petal)
  • długość i szerokość łodygi płatka (ang. sepal)

Uczenie maszynowe - klasyfikacja kwiaty iris

W danych wejściowych posiadamy również pomiary irysów dla gatunków setosa, versicolor i virginica. Zakładamy, że są to jedyne gatunki, do których możemy zakwalifikować irysy.

Celem projektu jest zbudowanie modelu uczenia maszynowego, który może uczyć się na podstawie pomiarów irysów, dla których gatunek jest znany i przewidywać na tej podstawie gatunek dla nowych irysów.

W Spyder utwórz nową komórkę, wklej poniższy kod i uruchom go, aby załadować zbiór Iris z modułu sklearn.

from sklearn import datasets
iris = datasets.load_iris()
iris.keys() # klucze zawierające dane

import zbioru iris

Budujemy ramkę danych w Pandasie. Pierwsze cztery kolumny to cechy rośliny. Ostatnia kolumna to kolumna wynikowa (ang. target). W kolumnie target mamy informację, do której odmiany dany iris należy – setosa, versicolor, virginica.

df = pd.DataFrame(data=np.c_[iris['data'], iris['target']],
columns= iris['feature_names'] + ['target'])
df.head()
print(df.head())
sepal length (cm)sepal width (cm)petal length (cm)petal width (cm)target
05.13.51.40.20.0
14.93.01.40.20.0
24.73.21.30.20.0
34.63.11.50.20.0
45.03.61.40.20.0

W programie Spyder możemy odczytywać zawartość zmiennych. Aby to zrobić:

  • kliknij opcję Variable Explorer po prawej stronie okna
  • kliknij dwuklikiem lewego przyciku myszy na wierszu ze zmienną df. Wyświetli się wówczas okienko zawierające wartości znajdujące się w zmiennej df.

Pandas ramka danych

Za pomocą poniższego polecenia wyświetlamy wartości znajdujące się w kolumnie target.

print(df['target'].values)

Pandas zbiór Iris wyświetlenie kolumny target

Podział na zbiór treningowy i testowy

Za pomocą poniższego kodu:

  • importujemy z modułu sklearn.model_selection funkcję train_test_split, za pomocą której podzielimy zbiór na testowy i treningowy
  • do zmiennej X przypisujemy wszystkie dane ze zbioru Iris
  • do zmiennej y przypisujemy kolumnę target ze zbioru Iris
  • dzielimy dane ze zmiennej X na zbiór treningowy (X_train) i zbiór testowy (X_test)
  • dzielimy dane ze zmiennej y na zbiór treningowy (y_train) i zbiór testowy (y_test)
from sklearn.model_selection import train_test_split
X = iris['data']
y = iris['target']
X_train, X_test, y_train, y_test = train_test_split(X, y)

Za pomocą poniższego kodu wyświetlamy informację o zawartości zbioru treningowego X oraz y.

print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")

Pandas zbiór treningowy Iris

W zbiorze treningowym jest 112 wierszy i 4 kolumny.

Za pomocą poniższego kodu budujemy dataframe o nazwie df_iris, do którego przypisujemy dane ze zbioru X_train. W dataframe X_train nie ma nazw kolumn. Nazwy column są potrzebne do funkcji scatter_matrix.

Za pomocą funkcji pd.plotting.scatter_matrix rysujemy macierz punktową (wykres par), która przedstawia wszystkie zmienne numeryczne ze zbioru danych względem siebie.

Scatter_matrix (macierz punktowa, wykres par) służy do generowania grupy wykresów punktowych pomiędzy wszystkimi parami cech numerycznych w zbiorze. Tworzy wykres dla każdej cechy numerycznej w stosunku do każdej innej cechy numerycznej oraz histogram dla każdej z nich.

Argumenty funkcji pd.plotting.scatter_matrix:

  • c=y_train – kolory na wykresie
  • figsize=(15, 15) – kontroluje rozmiar wykresu
  • marker=’o’ – rysuje punkty dla wykresu punktowego
  • hist_kwds={’bins’: 20} – kontroluje rozmiar histogramu
  • s=60 – kontroluje rozmiar punktów dla wykresu punktowego
  • alpha=.8 – kontroluje przezroczystość dla wykresu punktowego
    df_iris = pd.DataFrame(X_train,columns=iris.feature_names)
    # create a scatter matrix from the dataframe
    # color by y_train
    pd.plotting.scatter_matrix(df_iris,
    c=y_train, 
    figsize=(15, 15),
    marker='o',
    hist_kwds={'bins': 20},
    s=60,
    alpha=.8)
    

    Zbiór Iris wykres par

    Model k-najbliższych sąsiadów

    Model budujemy z użyciem algorytmu k-najbliższych sąsiadów (k-Nearest Neighbors, k-NN).

    Algorytm k-najbliższych sąsiadów (KNN, k-NN) należy do algorytmów uczenia nadzorowanego. Możemy używać go do rozwiązywania problemów klasyfikacji i regresji.

    Budowanie modelu k-najbliższych sąsiadów polega jedynie na przechowywaniu zestawu uczącego. Aby dokonać prognozy dla nowego punktu danych, algorytm znajduje punkt w zbiorze uczącym, który jest najbliższy nowemu punktowi. Następnie przypisuje etykietę tego punktu treningowego do nowego punktu danych.

    Wartość k w k-najbliżsi sąsiedzi oznacza, że zamiast używać tylko najbliższego sąsiada nowego punktu danych, możemy wziąć pod uwagę dowolną stałą liczbę k sąsiadów w uczeniu (na przykład trzech lub pięciu najbliższych sąsiadów). Następnie możemy przewidzieć, używając klasy większości spośród tych sąsiadów.

    Wszystkie modele uczenia maszynowego w scikit-learn są zaimplementowane we własnych klasach, które nazywane są klasami estymatorami (ang. Estimator classes). Algorytm klasyfikacji k-Nearest Neighbors jest zaimplementowany w klasie KNeighborsClassifier w module neighbors. 

    Zanim będziemy mogli użyć modelu, musimy utworzyć instancję klasy w obiekcie. Wtedy ustawimy dowolne parametry modelu. Najważniejszy parametr KNeighborsClassifier to liczba sąsiadów, którą w przykładzie ustawimy na 1.

    Poniższy kod z biblioteki sklearn importuje klasyfikator KNeighborsClassifier, Przypisujemy go do obiektu knn i ustawiamy liczbę sąsiadów na 1.

    from sklearn.neighbors import KNeighborsClassifier
    knn = KNeighborsClassifier(n_neighbors=1)
    

    Obiekt knn zawiera algorytm, który zostanie użyty do zbudowania modelu z danych uczących, a także algorytm do przewidywania nowych punktów danych. Będzie również zawierał informacje, które algorytm wyodrębnił z danych treningowych. W przypadku KNeighborsClassifier przechowa zestaw treningowy.

    Aby zbudować model na zbiorze uczącym, wywołujemy metodę fit obiektu knn, która jako argumenty przyjmuje tablicę NumPy X_train zawierającą dane uczące oraz tablicę NumPy y_train odpowiednich etykiet uczących:

    knn.fit(X_train, y_train)
    

    Metoda fit zwraca sam obiekt knn (i modyfikuje go w miejscu), więc otrzymujemy ciąg znaków reprezentujący nasz klasyfikator. Reprezentacja pokazuje, jakie parametry zostały użyte przy tworzeniu modelu. Prawie wszystkie z nich są wartościami domyślnymi, ale można również znaleźć n_neighbors=1, który jest parametrem przez nas przekazanym.

    Większość modeli w scikit-learn ma wiele parametrów, ale większość z tych parametrów służy do optymalizacji szybkości działania lub do obsłużenia specjalnych przypadków użycia.

    KNN – wyliczanie predykcji

    Dokonujemy teraz prognoz przy użyciu modelu na nowych danych. W przykładzie w tablicy X_new umieszczamy poniższe dane irysa:

    • długość płatka 5 cm, szerokość płatka 2,9 cm
    • długość łodygi płatka 1 cm, szerokość łodygi płatka 0,2 cm

    Próbujemy przewidzieć, do jakiego gatunku iris o w/w cechach należy.

    Umieściliśmy pomiary w rzędzie w dwuwymiarowej tablicy NumPy, gdyż scikit-learn zawsze oczekuje dwuwymiarowych tablic dla danych.

    X_new = np.array([[5, 2.9, 1, 0.2]])
    

    Aby dokonać przewidywania, wywołujemy metodę przewidywania obiektu knn:

    prediction = knn.predict(X_new)
    print(f"Prediction: {prediction}")
    print(f"Predicted target name: {iris['target_names'][prediction]}")
    

    Model przewiduje, że ta nowy iris należy do klasy 0, co oznacza, że jest to gatunek setosa.

    Zbiór Iris KNN predykcja

    Ocena skuteczności modelu klasyfikacji

    Aby ocenić, czy model klasyfikacji działa prawidłowo, uruchamiamy go na danych testowych, których nie widział i sprawdzamy jak dużą część przypadków przewidział prawidłowo.

    y_pred = knn.predict(X_test)
    print(f"Test set predictions:\n{y_pred}")
    

    Zbiór Iris KNN test

    print("Test set score: {:.2f}".format(np.mean(y_pred == y_test)))
    

    Wynik:  Test set score: 0.97

    Możemy również użyć metody punktacji obiektu knn, która obliczy dla nas dokładność zestawu testowego:

    print("Test set score: {:.2f}".format(knn.score(X_test, y_test)))
    

    Wynik: Test set score: 0.97

    Dla tego modelu dokładność zestawu testowego wynosi około 0,97, co oznacza, że dokonaliśmy prawidłowej prognozy dla 97% irysów w zestawie testowym. Funkcja knn.score uruchomiona została na modelu w zmiennej knn.

    Jeśli nie mamy modelu, ale mamy jedynie predykcję, możemy wyliczyć dokładność tych predykcji za pomocą funkcji accuracy_score():

    from sklearn.metrics import accuracy_score
    print(f'Dokładność: {accuracy_score(y_test, y_pred):.2f}')
    

    Dokładność: 0.97

    Tak obliczona wartość dokładności może być jednak myląca, jeśli zbiór danych wejściowych jest niesymetryczny tzn. liczba obserwacji w poszczególnych klasach nie jest zbliżona. Na przykład jeśli mamy 90% obserwacji klasy 0 i 10% obserwacji klasy 1, dokładność na poziomie 90% można uzyskać przewidując same klasy 1. Jest to słabo działający model, ale uzyskuje złudnie wysoką dokładność. 

    W takiej sytuacji warto jest obliczyć macierz konfuzji (ang. confussion matrix), za pomocą której możemy zrobić wizualizację działania algorytmu. Macierz (tablica) zawiera dwa wymiary (rzeczywisty i przewidywany). Ułatwia ona sprawdzenie, czy algortym nie myli dwóch klas tzn. często błędnie oznacza jedną jako drugą.

    W przykładzie poniżej:

    • na przekątnej zawarte są poprawne predykcje dla poszczególnych klas
    • w pionie jest liczba obserwacji w poszczególnych klasach (ground truth)
    • w poziomie liczba przewidzianych
    from sklearn.metrics import ConfusionMatrixDisplay
    ConfusionMatrixDisplay.from_predictions(y_test, y_pred);
    

    Zbiór Iris knn predykcje confusion matrix

    Podstawowe informacje na temat przetwarzania danych i ich przygotowania do analizy oraz narzędzia Spyder znajdziesz w artykule Python podstawy analizy danych

    Rafał Lelusz

    Programista Python, C#
    Udostępnij wpis: udostępnij Facebook udostępnij Linkedin udostępnij e-mail
    Podobne artykuły z kategorii: Python

    Może Cię zainteresować