Folgend findest Du ein Tutorial, um KNN mit Python zu implementieren. Du darfst alleine oder zu zweit arbeiten.
Natürlich darfst Du auch versuchen, KNN ohne Hilfe des Tutorials zu implementieren. 🤩
Wir wollen mit dem Iris Dataset arbeiten.
Der Datensatz besteht aus jeweils 50 Proben von drei Irisarten (Iris setosa, Iris virginica und Iris versicolor). Bei jeder Probe wurden vier Merkmale gemessen: die Länge und die Breite der Kelch- und Blütenblätter in Zentimetern. Wir wollen versuchen, mit Hilfe von KNN, Blumen korrekt zu klassifizierenn.
Du brauchst die pandas library 🐼, um mit dem Dataset umgehen zu können. Pandas wir häufig beutzt, um Daten analysieren zu können. pandas ist eine Programmbibliothek für Python zur Verarbeitung, Analyse und Darstellung von Daten. Insbesondere enthält sie Datenstrukturen und Operatoren für den Zugriff auf numerische Tabellen und Zeitreihen
gehe auf Tools->manage packages…
suche nach pandas
installiere das Package...das dauert wahrscheinlich einen Augenblick ☕
Weiter brauchen wir noch die sklearn library. Dort gibt es verschiedene functions, auf welche wir zugreifen werden im Laufe der nächsten Lektionen.
gehe auf Tools->manage packages…
suche nach sklearn
installiere das Package...das dauert wahrscheinlich einen Augenblick ☕
Wenn das nicht geht, musst Du über die Konsole und mit pip sklearn herunterladen.
gehe dazu auf Tools->Open system shell…
pip install sklearn
das Package wird installiert...das dauert wahrscheinlich einen Augenblick ☕
Wir arbeiten mit dem Iris Dataset , um unseren KNN-Algorithmus zu testen. Du kannst das Dataset hier herunterladen: https://www.kaggle.com/datasets/arshid/iris-flower-dataset
import pandas as pd
iris = pd.read_csv('IRIS.csv')
Zuerst müssen wir unsere Daten einmal anschauen, mit was wir es zu tun haben.
Importiere das Dataset, wie oben und dann überprüfen wir folgende Angaben:
iris.shape (gibt uns zurück wie viele Zeilen und wie viele features (Spalten), unser dataset hat.
iris.head(5): gibt uns die fünf ersten Zeilen zurück, dann kannst Du dir anschauen, was für features alles das iris dataset abspeichert
iris.describe(): gibt uns den Durchschnitt (mean), Standardabweichung (std), sowie min und max Werte und die Quartile zurück.
mit iris.groupby('Species').size() können wir uns anschauen, wie viele Zeilen es gibt, pro Klasse. Die Klassen sind in der Spalte "Species".
Beschreibe, was Du alles rauslesen kannst aus den Daten.
Dein Code:
import pandas as pd
iris = pd.read_csv('IRIS.csv')
print(iris.shape) #(150,5) - 150 rows, 5 cols
print(iris.head(5))
print(iris.describe())
print(iris.groupby("species").size())
Wenn du iris.describe() aufrufst, wird Dir Folgendes ausgegeben:
sepal_length sepal_width petal_length petal_width
count 150.000000 150.000000 150.000000 150.000000
mean 5.843333 3.054000 3.758667 1.198667
std 0.828066 0.433594 1.764420 0.763161
min 4.300000 2.000000 1.000000 0.100000
25% 5.100000 2.800000 1.600000 0.300000
50% 5.800000 3.000000 4.350000 1.300000
75% 6.400000 3.300000 5.100000 1.800000
max 7.900000 4.400000 6.900000 2.500000
Du kannst die Durchschnittslänge, -breite der Sepals sowie der Petals auslesen. Diese vier Kategorien sind die features, die gemessen wurden in diesem dataset. Mit diesen features bauen wir dann unseren KNN - Algorithmus.
Mit iris.groupby("species").size() wird dir Folgendes (unsere target features, die unterschiedlichen Blumenarten) ausgegeben:
Iris-setosa 50
Iris-versicolor 50
Iris-virginica 50
Wir wollen nun unsere Daten in features and labels unterteilen. Features sind sepal_length sepal_width petal_length petal_width, das label (die Klassen), sind die Values in der Spalte species.
Versuche zwei Arrays zu coden. Eines mit Namen X (dort hinein kommen die Spalten der Features), eines mit Namen y (dort hinein kommt die Spalte species).
Du kannst die Spalten einfach wählen, indem Du Folgendes machst:
iris[["sepal_length", ...]]
damit die values ausgelesen werden, machst Du Folgendes:
iris[["sepal_length", ...]].values
X = iris[["sepal_length", "sepal_width", "petal_length", "petal_width"]].values
y = iris["species"].values
Mithilfe von StandardScaler(), wollen wir unsere Daten standardisieren. Die Standardisierung eines Datensatzes ist eine häufige Anforderung für viele Schätzer für maschinelles Lernen: Je nachdem verhalten sie sich ungünstig, wenn die einzelnen Merkmale nicht mehr oder weniger wie standardmäßige normalverteilte Daten aussehen (z. B. Gauß mit 0 Mittelwert und Einheitsvarianz).
from sklearn.preprocessing import StandardScaler
X = StandardScaler().fit_transform(X)
Wir wollen unser dataset in train und test data unterteilen.
Mit Hilfe von train_test_split, wird unser Array in random train und test subsets unterteilt. Per default werden 25% der Daten als Testdaten genutzt. Wir berechnen dann die Distanzen zwischen jedem Punkt im test_set zu jedem Punkt im train_set, um die Klassifizierung vorzunehmen.
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
Wir werden verschiedene Berechechnungen immer wieder brauchen, wenn wir KNN implementieren. Da macht es Sinn, diese in Funktionen auszulagern.
Wir müssen eine function definieren, welche das häufigste Element aus einer Liste ausgibt.
Wir müssen die euklidische Metrik implementieren, welche die Distanz zwischen einem Punkt und jedem Punkt aus dem Datensatz berechnet.
Implementiere diese beiden Funktionen:
import numpy as np #evt. musst Du numpy noch installieren.
def most_common(data_list):
return ❓
def euclidean(point, data):
return ❓
Erinnere Dich an die Formel der euklidischen Distanz.
Weiter gibt es die library numpy, welche viele Funktionen hat, die dir dabei behilflich sein kann, die Formel zu implementieren.
def most_common(data_list):
return max(set(data_list), key=data_list.count)
def euclidean(point, data):
'''Euclidean distance between a point & data'''
return np.sqrt(np.sum((point - data)**2, axis=1))
Wir brauchen eine prediction method. X_test wird Punkt für Punkt durchlaufen. Für jeden Datenpunkt werden die folgenden Schritte durchgeführt:
Entfernungen zu jedem Punkt im training dataset werden berechnet.
Die Klassen im training dataset sind nach Entfernung zum Datenpunkt zu sortieren.
Die ersten k Klassen werden beibehalten und in der Nachbarliste gespeichert. Nun ordnen wir einfach die Liste der nächsten Nachbarn unserer Funktion most_common zu und geben eine Liste mit Vorhersagen für jeden in X_test übergebenen Punkt zurück.
Ergänze dafür folgende function:
def predict(❓,k):
neighbors = ❓
for x in ❓:
distances = euclidean(x, ❓)
y_sorted = [y for _, y in sorted(zip(distances, ❓))]
neighbors.append(y_sorted[:k])
return list(map(most_common, neighbors))
zip function takes iterables (can be zero or more), aggregates them in a tuple, and returns it), ie:
languages = ['Java', 'Python', 'JavaScript']
versions = [14, 3, 6]
result = zip(languages, versions)
print(list(result))
# Output: [('Java', 14), ('Python', 3), ('JavaScript', 6)]
def predict(X_test,k):
neighbors = []
for x in X_test:
distances = euclidean(x, X_train)
y_sorted = [y for _, y in sorted(zip(distances, y_train))]
neighbors.append(y_sorted[:k])
return list(map(most_common, neighbors))
Jetzt wollen wir noch eine function hinzufügen, welche berechnet, wie gut unser KNNClassifier ist. Ein Datensatz von Attributen und ihren Klassen wird als X_test und y_test übergeben, und die Vorhersagen des Modells aus den Attributen werden mit den tatsächlichen Klassen verglichen.
Ergänze die function:
def evaluate(❓, ❓,k):
y_pred = predict(❓,k)
accuracy = sum(y_pred == ❓) / len(❓)
return accuracy
def evaluate(X_test, y_test,k):
y_pred = predict(X_test,k)
accuracy = sum(y_pred == y_test) / len(y_test)
return accuracy
Unser Classifier ist jetzt fertig. Wir wollen unseren KNN über unsere Daten laufen lassen.
Dabei wollen wir testen, wie die Accuracy ist bzgl. unseren gewählten Paramter k. Und welcher Parameter k optimal ist.
Ergänze folgenden Code-Ausschnitt:
accuracies = ❓
range_of_k = range(1,100)
for ❓ in range_of_k:
accuracy = evaluate(❓, ❓, ❓)
accuracies.append(accuracy)
Weiter wollen wir den Verlauf unserer Accuracy, je nachdem wie viele Nachbarn wir auswählen, auch darstellen können.
Ergänze:
fig, ax = plt.subplots()
ax.plot(❓, ❓)
ax.set(xlabel="k",
ylabel="Accuracy",
title="Performance of knn")
plt.show()
accuracies = []
range_of_k = range(1,30)
for k in range_of_k:
accuracy = evaluate(X_test, y_test,k)
accuracies.append(accuracy)
fig, ax = plt.subplots()
ax.plot(range_of_k, accuracies)
ax.set(xlabel="k",
ylabel="Accuracy",
title="Performance of knn")
plt.show()
# KNN
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
#from KNeighborsClassifier import KNeighborsClassifier
iris = pd.read_csv('IRIS.csv')
X = iris[["sepal_length", "sepal_width", "petal_length", "petal_width"]].values
y = iris["species"].values
X = StandardScaler().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
def most_common(data_list):
'''Returns the most common element in a list'''
return max(set(data_list), key=data_list.count)
def euclidean(point, data):
'''Euclidean distance between a point & data'''
return np.sqrt(np.sum((point - data)**2, axis=1))
def predict(X_test,k):
neighbors = []
for x in X_test:
distances = euclidean(x, X_train)
y_sorted = [y for _, y in sorted(zip(distances, y_train))]
neighbors.append(y_sorted[:k])
return list(map(most_common, neighbors))
def evaluate(X_test, y_test,k):
y_pred = predict(X_test,k)
accuracy = sum(y_pred == y_test) / len(y_test)
return accuracy
accuracies = []
range_of_k = range(1, 50)
for k in range_of_k:
accuracy = evaluate(X_test, y_test,k)
accuracies.append(accuracy)
fig, ax = plt.subplots()
ax.plot(range_of_k, accuracies)
ax.set(xlabel="k",
ylabel="Accuracy",
title="Performance of knn")
plt.show()