commit 89ba3bbf1027cd26055df43be2a34750e2d337b0 Author: Paul Date: Mon Nov 2 17:26:31 2020 +0100 initial commit diff --git a/ML_U3_1_Perceptron.ipynb b/ML_U3_1_Perceptron.ipynb new file mode 100644 index 0000000..432d6e5 --- /dev/null +++ b/ML_U3_1_Perceptron.ipynb @@ -0,0 +1,328 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Maschinelles Lernen (ML) - Übung 3\n", + "# Perzeptronen und mehrschichtige Perzeptronen\n", + "## 3.1 Das einfache Perzeptron als linearer Klassifikator\n", + "\n", + "In dieser Übung wird ein einfaches Perzeptron (engl. perceptron) programmiert, trainiert und als linearer Klassifikator eingesetzt.\n", + "\n", + "![perceptron.pdf](Handout/fig/perceptron/perceptron.png)\n", + "\n", + "Weitere Informationen zur Wirkweise des einfachen Perzeptrons sind im PDF-Handout für diese Übung zu finden." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Aufgabe 1:** In dieser Übung sollen Sie ein Perzeptron objektorientiert erstellen. Dazu ist bereits eine vorstrukturierte Klasse *Perceptron* mit den Methoden *_init_* zur Initialisierung des Perzeptrons (z.B. Gewichte, Lernrate), *predict* zur Klassifizierung eines Datenpunktes und *fit* zum Trainieren des Perzeptrons vorbereitet.\t\tVervollständigen Sie diese Methoden." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# matplotlib: Modul zum Plotten von Daten\n", + "from matplotlib import pyplot as plt \n", + "# numpy: Mathematikbibliothek\n", + "import numpy as np \n", + "import pandas as pd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Hilfen für die Klasse Perzeptron\n", + "\n", + "##### Allgemein\n", + "Verwendete Variblenbezeichnungen:\n", + "- inputs $\\hat{=} \\textrm{ } \\lbrace x_1, \\ldots x_n \\rbrace$; Sollte als Numpy Array definiert werden.\n", + "- eta $\\hat{=} \\textrm{ } \\eta$\n", + "\n", + "##### Methode _init_(self, number_of_inputs, epochs, learning_rate):\n", + "In Python entspricht \\_\\_init\\_\\_ dem Konstruktor. Die \\_\\_init\\_\\_() Methode initialisiert die Klasse Perceptron. Definiere und initialisiere hier die folgenden Variablen: \n", + "- die zu lernenden Gewichte $\\textbf{w}$,\n", + "- die maximale Anzahl der Epochen (Lernzyklen), die der Lernalgorithmus durchlaufen darf und\n", + "- die Lernrate, die den Grad der Veränderung der Gewichte bei jedem Schritt durch die Trainingsdaten bestimmt.\n", + "\n", + "##### Methode predict(self, inputs):\n", + "Die predict(...) Methode enthält die Aktivierungsfunktion h(z) (hier: die Signum-Funktion):\n", + "\n", + "\\begin{equation}\n", + " h(z) =\n", + " \\begin{cases}\n", + "\t\t\t-1 \\textrm{ falls } z < 0 \\textrm{,} \\\\\t\n", + "\t\t\t0 \\textrm{ falls } z = 0 \\textrm{,} \\\\\t\n", + "\t\t\t1 \\textrm{ falls } z > 0 \\textrm{.} \\\\\n", + "\t\t\\end{cases}\n", + "\\end{equation} \n", + "Die Eingabe der Methode (inputs) sollte als NumPy Array/Vektor definiert werden.\n", + "\n", + "##### Methode fit(self, training_inputs, labels):\n", + "Die Methode fit(...) benötigt zwei Argumente:\n", + "- training_inputs ist eine Liste von numpy-Vektoren und\n", + "- labels ist ein Array von erwarteten Ausgabewerten.\n", + " \n", + "Beim Trainieren des Perzeptrons soll folgende Funktionalität implementiert werden: \n", + "Ein einzelner Trainingsdatenpunkt wird betrachtet und eine Vorhersage (Methode predict) getroffen. Auf Basis der Vorhersage $\\hat{y}$ werden die Gewichte nach folgender Regel aktualisiert (siehe auch Handout):\n", + "\\begin{equation}\n", + "\\textbf{w} \\leftarrow \\textbf{w} + \\eta \\cdot \\left( y - \\hat{y} \\right) \\cdot \\textbf{x} \\textrm{.} \n", + "\\end{equation}\n", + "\n", + "Der Block aus predict und update der Gewichte wird solange iterativ ausgeführt bis die maximale Anzahl der Epochen erreicht ist (oder optional bis die Fehlerfunktion konvergiert ist). \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "class Perceptron(object):\n", + " def __init__(self, number_of_inputs, epochs, eta):\n", + " \"\"\"\n", + " Beispielaufruf des Konstruktors:\n", + " >>> Perceptron(2, 100, 0.1)\n", + " \"\"\"\n", + " ### Dein Code kommt hierhin:\n", + " \n", + " ##########################\n", + " pass\n", + " \n", + " def predict(self, inputs):\n", + " \"\"\"\n", + " Beispiel des Funktionsaufrufes:\n", + " >>> inputs = np.array([0, 1])\n", + " >>> h = perceptron.predict(inputs) \n", + " \"\"\"\n", + " \n", + " # Dein Code kommt hierhin: \n", + " \n", + " ##########################\n", + " \n", + " pass\n", + "\n", + " def fit(self, training_inputs, labels):\n", + " \"\"\"\n", + " Beispiel des Funktionsaufrufs:\n", + " >>> perceptron.fit(train_input, labels)\n", + " \"\"\"\n", + " \n", + " # Dein Code kommt hierhin:\n", + "\n", + " ##########################\n", + " pass\n", + " \n", + " def status(self):\n", + " \"\"\"\n", + " Die Methode status(...) gibt die aktuellen Gewichte aus.\n", + "\n", + " Beispiel des Funktionsaufrufes und der Ausgabe:\n", + " >>> perceptron.status()\n", + " Perceptron weights: [0. 1. 1.]\n", + " \"\"\"\n", + " print(\"Perceptron weights: \", self.weights)\n", + " \n", + " def getWeights(self):\n", + " return self.weights" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Aufgabe 2:** Wenden Sie das implementierte Perzeptron auf das `AND`, `OR` und `XOR` Problem im zweidimensionalen Raum an. Berechnen Sie anhand der gelernten Gewichte $\\mathbf{w}$ des Perzeptrons die Geradengleichung der Diskriminanzgeraden und plotten Sie diese zusammen mit den Datenpunkten des jeweiligen Problems." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Beispiel mit AND\n", + "train_input_AND = np.array([\n", + " [0, 0],\n", + " [0, 1],\n", + " [1, 0],\n", + " [1, 1]\n", + " ])\n", + "\n", + "labels_AND = np.array([-1, -1, -1, 1])\n", + "\n", + "# Dein Code kommt hier hin:\n", + "# Perceptron anlegen und trainieren\n", + "\n", + "\n", + "# Geradengleichung berechnen und plotten\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Beispiel mit OR\n", + "train_input_OR = np.array([\n", + " [0, 0],\n", + " [0, 1],\n", + " [1, 0],\n", + " [1, 1]\n", + " ])\n", + "\n", + "labels_OR = np.array([-1, 1, 1, 1])\n", + "\n", + "# Dein Code kommt hier hin:\n", + "# Perceptron anlegen und trainieren\n", + "\n", + "\n", + "# Geradengleichung berechnen und plotten\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Beispiel mit XOR\n", + "train_input_XOR = np.array([\n", + " [0, 0],\n", + " [0, 1],\n", + " [1, 0],\n", + " [1, 1]\n", + " ])\n", + "\n", + "labels_XOR = np.array([-1, 1, 1, -1])\n", + "\n", + "# Dein Code kommt hier hin:\n", + "# Perceptron anlegen und trainieren\n", + "\n", + "\n", + "# Geradengleichung berechnen und plotten" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Aufgabe 3:** Warum wird im Perzeptron der Bias $x_0$ benötigt beziehungsweise wieso werden bei $n$ Merkmalen ($x_1, \\ldots, x_n$), $n+1$ Gewichte ($w_0, \\ldots, w_n$) benötigt? " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Antwort:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Aufgabe 4:** Wenden Sie das Perzeptron auf das Problem der Banknotenklassifizierung der letzten Übung an. Wählen und berechnen Sie dafür wieder zwei geeignete Merkmale der Trainingsbanknoten (Momentenberechnung auf den Farbkanälen mit `banknotes[i].compute_feature(moment, color)`). Mit welcher Genauigkeit (engl. *accuracy*) werden die Testbanknoten klassifiziert? Wie sind die erreichten Ergebnisse des Perzeptrons im Vergleich zum linearen Klassifikator der letzten Übung zu bewerten?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Hier wird der Iris-Datensatz geladen und vorbereitet (siehe letzte Übung)\n", + "\n", + "# Datensatz laden\n", + "names = [\"sepal-length\", \"sepal-width\", \"petal-length\", \"petal-width\", \"class\"]\n", + "iris_data = pd.read_csv(\"iris.csv\", names = names)\n", + "\n", + "# Klassen auswählen (Bei Bedarf ändern)\n", + "iris_data = iris_data.loc[lambda x: x['class'] != 'Iris-setosa']\n", + "\n", + "# Merkmale auswählen (Bei Bedarf ändern)\n", + "iris_features = ['petal-length', 'petal-width']\n", + "X = iris_data[iris_features]\n", + "\n", + "# Pandas-Datenformat in reine Liste umwandeln\n", + "X = X.values\n", + "\n", + "# Label vorbereiten\n", + "from sklearn.preprocessing import LabelEncoder\n", + "lb_make = LabelEncoder()\n", + "iris_data[\"class_code\"] = lb_make.fit_transform(iris_data[\"class\"])\n", + "y = iris_data.class_code\n", + "# Pandas-Datenformat in reine Liste umwandeln\n", + "y = y.values\n", + "# Die Signum-Funktion unseres Perzeptrons benötigt die Label -1, 1\n", + "y[y==0] = -1\n", + " \n", + "# Trainings- und Testdatensplit\n", + "from sklearn.model_selection import train_test_split\n", + "X_train, X_test, y_train, y_test = (\n", + " train_test_split(X, y, test_size=.2, random_state=np.random.seed(42)))\n", + "\n", + "# Scatterplot der ausgewählten Merkmale und Klassen\n", + "fig, ax = plt.subplots()\n", + "ax.scatter(X[(y==-1),0] , X[(y==-1),1])\n", + "ax.scatter(X[(y==1),0] , X[(y==1),1])\n", + "ax.set(xlabel = iris_features[0], ylabel = iris_features[1])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Perzeptron auf Iris-Datensatz trainieren und anwenden\n", + "# Dein Code kommt hierhin:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Aufgabe 5:** Welchen Einfluss haben die Hyperparameter *Epoche* und *Lernrate* auf die Klassifizierung der Banknoten? Lassen sich die vorherigen Ergebnisse noch verbessern?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Antwort:" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/iris.csv b/iris.csv new file mode 100644 index 0000000..5c4316c --- /dev/null +++ b/iris.csv @@ -0,0 +1,151 @@ +5.1,3.5,1.4,0.2,Iris-setosa +4.9,3.0,1.4,0.2,Iris-setosa +4.7,3.2,1.3,0.2,Iris-setosa +4.6,3.1,1.5,0.2,Iris-setosa +5.0,3.6,1.4,0.2,Iris-setosa +5.4,3.9,1.7,0.4,Iris-setosa +4.6,3.4,1.4,0.3,Iris-setosa +5.0,3.4,1.5,0.2,Iris-setosa +4.4,2.9,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.4,3.7,1.5,0.2,Iris-setosa +4.8,3.4,1.6,0.2,Iris-setosa +4.8,3.0,1.4,0.1,Iris-setosa +4.3,3.0,1.1,0.1,Iris-setosa +5.8,4.0,1.2,0.2,Iris-setosa +5.7,4.4,1.5,0.4,Iris-setosa +5.4,3.9,1.3,0.4,Iris-setosa +5.1,3.5,1.4,0.3,Iris-setosa +5.7,3.8,1.7,0.3,Iris-setosa +5.1,3.8,1.5,0.3,Iris-setosa +5.4,3.4,1.7,0.2,Iris-setosa +5.1,3.7,1.5,0.4,Iris-setosa +4.6,3.6,1.0,0.2,Iris-setosa +5.1,3.3,1.7,0.5,Iris-setosa +4.8,3.4,1.9,0.2,Iris-setosa +5.0,3.0,1.6,0.2,Iris-setosa +5.0,3.4,1.6,0.4,Iris-setosa +5.2,3.5,1.5,0.2,Iris-setosa +5.2,3.4,1.4,0.2,Iris-setosa +4.7,3.2,1.6,0.2,Iris-setosa +4.8,3.1,1.6,0.2,Iris-setosa +5.4,3.4,1.5,0.4,Iris-setosa +5.2,4.1,1.5,0.1,Iris-setosa +5.5,4.2,1.4,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +5.0,3.2,1.2,0.2,Iris-setosa +5.5,3.5,1.3,0.2,Iris-setosa +4.9,3.1,1.5,0.1,Iris-setosa +4.4,3.0,1.3,0.2,Iris-setosa +5.1,3.4,1.5,0.2,Iris-setosa +5.0,3.5,1.3,0.3,Iris-setosa +4.5,2.3,1.3,0.3,Iris-setosa +4.4,3.2,1.3,0.2,Iris-setosa +5.0,3.5,1.6,0.6,Iris-setosa +5.1,3.8,1.9,0.4,Iris-setosa +4.8,3.0,1.4,0.3,Iris-setosa +5.1,3.8,1.6,0.2,Iris-setosa +4.6,3.2,1.4,0.2,Iris-setosa +5.3,3.7,1.5,0.2,Iris-setosa +5.0,3.3,1.4,0.2,Iris-setosa +7.0,3.2,4.7,1.4,Iris-versicolor +6.4,3.2,4.5,1.5,Iris-versicolor +6.9,3.1,4.9,1.5,Iris-versicolor +5.5,2.3,4.0,1.3,Iris-versicolor +6.5,2.8,4.6,1.5,Iris-versicolor +5.7,2.8,4.5,1.3,Iris-versicolor +6.3,3.3,4.7,1.6,Iris-versicolor +4.9,2.4,3.3,1.0,Iris-versicolor +6.6,2.9,4.6,1.3,Iris-versicolor +5.2,2.7,3.9,1.4,Iris-versicolor +5.0,2.0,3.5,1.0,Iris-versicolor +5.9,3.0,4.2,1.5,Iris-versicolor +6.0,2.2,4.0,1.0,Iris-versicolor +6.1,2.9,4.7,1.4,Iris-versicolor +5.6,2.9,3.6,1.3,Iris-versicolor +6.7,3.1,4.4,1.4,Iris-versicolor +5.6,3.0,4.5,1.5,Iris-versicolor +5.8,2.7,4.1,1.0,Iris-versicolor +6.2,2.2,4.5,1.5,Iris-versicolor +5.6,2.5,3.9,1.1,Iris-versicolor +5.9,3.2,4.8,1.8,Iris-versicolor +6.1,2.8,4.0,1.3,Iris-versicolor +6.3,2.5,4.9,1.5,Iris-versicolor +6.1,2.8,4.7,1.2,Iris-versicolor +6.4,2.9,4.3,1.3,Iris-versicolor +6.6,3.0,4.4,1.4,Iris-versicolor +6.8,2.8,4.8,1.4,Iris-versicolor +6.7,3.0,5.0,1.7,Iris-versicolor +6.0,2.9,4.5,1.5,Iris-versicolor +5.7,2.6,3.5,1.0,Iris-versicolor +5.5,2.4,3.8,1.1,Iris-versicolor +5.5,2.4,3.7,1.0,Iris-versicolor +5.8,2.7,3.9,1.2,Iris-versicolor +6.0,2.7,5.1,1.6,Iris-versicolor +5.4,3.0,4.5,1.5,Iris-versicolor +6.0,3.4,4.5,1.6,Iris-versicolor +6.7,3.1,4.7,1.5,Iris-versicolor +6.3,2.3,4.4,1.3,Iris-versicolor +5.6,3.0,4.1,1.3,Iris-versicolor +5.5,2.5,4.0,1.3,Iris-versicolor +5.5,2.6,4.4,1.2,Iris-versicolor +6.1,3.0,4.6,1.4,Iris-versicolor +5.8,2.6,4.0,1.2,Iris-versicolor +5.0,2.3,3.3,1.0,Iris-versicolor +5.6,2.7,4.2,1.3,Iris-versicolor +5.7,3.0,4.2,1.2,Iris-versicolor +5.7,2.9,4.2,1.3,Iris-versicolor +6.2,2.9,4.3,1.3,Iris-versicolor +5.1,2.5,3.0,1.1,Iris-versicolor +5.7,2.8,4.1,1.3,Iris-versicolor +6.3,3.3,6.0,2.5,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +7.1,3.0,5.9,2.1,Iris-virginica +6.3,2.9,5.6,1.8,Iris-virginica +6.5,3.0,5.8,2.2,Iris-virginica +7.6,3.0,6.6,2.1,Iris-virginica +4.9,2.5,4.5,1.7,Iris-virginica +7.3,2.9,6.3,1.8,Iris-virginica +6.7,2.5,5.8,1.8,Iris-virginica +7.2,3.6,6.1,2.5,Iris-virginica +6.5,3.2,5.1,2.0,Iris-virginica +6.4,2.7,5.3,1.9,Iris-virginica +6.8,3.0,5.5,2.1,Iris-virginica +5.7,2.5,5.0,2.0,Iris-virginica +5.8,2.8,5.1,2.4,Iris-virginica +6.4,3.2,5.3,2.3,Iris-virginica +6.5,3.0,5.5,1.8,Iris-virginica +7.7,3.8,6.7,2.2,Iris-virginica +7.7,2.6,6.9,2.3,Iris-virginica +6.0,2.2,5.0,1.5,Iris-virginica +6.9,3.2,5.7,2.3,Iris-virginica +5.6,2.8,4.9,2.0,Iris-virginica +7.7,2.8,6.7,2.0,Iris-virginica +6.3,2.7,4.9,1.8,Iris-virginica +6.7,3.3,5.7,2.1,Iris-virginica +7.2,3.2,6.0,1.8,Iris-virginica +6.2,2.8,4.8,1.8,Iris-virginica +6.1,3.0,4.9,1.8,Iris-virginica +6.4,2.8,5.6,2.1,Iris-virginica +7.2,3.0,5.8,1.6,Iris-virginica +7.4,2.8,6.1,1.9,Iris-virginica +7.9,3.8,6.4,2.0,Iris-virginica +6.4,2.8,5.6,2.2,Iris-virginica +6.3,2.8,5.1,1.5,Iris-virginica +6.1,2.6,5.6,1.4,Iris-virginica +7.7,3.0,6.1,2.3,Iris-virginica +6.3,3.4,5.6,2.4,Iris-virginica +6.4,3.1,5.5,1.8,Iris-virginica +6.0,3.0,4.8,1.8,Iris-virginica +6.9,3.1,5.4,2.1,Iris-virginica +6.7,3.1,5.6,2.4,Iris-virginica +6.9,3.1,5.1,2.3,Iris-virginica +5.8,2.7,5.1,1.9,Iris-virginica +6.8,3.2,5.9,2.3,Iris-virginica +6.7,3.3,5.7,2.5,Iris-virginica +6.7,3.0,5.2,2.3,Iris-virginica +6.3,2.5,5.0,1.9,Iris-virginica +6.5,3.0,5.2,2.0,Iris-virginica +6.2,3.4,5.4,2.3,Iris-virginica +5.9,3.0,5.1,1.8,Iris-virginica +