Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision Next revision | Previous revision | ||
| efinf:blcks2017:bigdatab:start [2018/03/01 08:05] – [L7] Simon Knaus | efinf:blcks2017:bigdatab:start [2018/03/08 06:54] (current) – Simon Knaus | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | === Unterlagen | ||
| + | * {{efinf: | ||
| + | < | ||
| + | * Daten Ziffern | ||
| + | * Bildaten: {{efinf: | ||
| + | * Textdaten als CSV: {{efinf: | ||
| + | --> | ||
| + | === Lektionen === | ||
| + | * Woche 1 | ||
| + | * [[# | ||
| + | * Einführung Big Data / Machine Learning / Artificial Intelligence | ||
| + | * [[# | ||
| + | * Progammierung kNN | ||
| + | * Intelligente Transformationen: | ||
| + | * Woche 2 | ||
| + | * [[# | ||
| + | * Einführung Problematik Zahlenerkennung (Ziffernerkennung): | ||
| + | * Berechnnung Klassifikationsfehler in Abhängigkeit von $k$ | ||
| + | * [[# | ||
| + | * Aufbereitung Daten aus preprocessed 16x16 Bildern. | ||
| + | * Evtl. Einführung kNN in hohen Dimensionen | ||
| + | * Woche 3 | ||
| + | * [[# | ||
| + | * Einführung kNN in hohen Dimensionen: | ||
| + | * Test- und Trainings-Daten | ||
| + | * [[# | ||
| + | * Klassifizierung abschliessen | ||
| + | * Tuning: k, Konfusionsmatrix | ||
| + | * Python 2.7 installieren | ||
| + | * Woche 4 | ||
| + | * [[# | ||
| + | * Übersicht zentrale Begriffe und Ideen | ||
| + | * Implementierung Scikit | ||
| + | * Tour d' | ||
| + | * [[# | ||
| + | * Prüfung / Challenge auf ungesehenen Testdaten | ||
| + | * Neural Networks | ||
| + | |||
| + | |||
| + | ==== L1 ==== | ||
| + | |||
| + | {{efinf: | ||
| + | |||
| + | <file python readdata.py> | ||
| + | from gpanel import * | ||
| + | |||
| + | import csv #um Text-Dateien im CSV-Format zu lesen | ||
| + | import random | ||
| + | |||
| + | # CSV-File öffnen | ||
| + | csvfile = open(' | ||
| + | # CSV-File einlesen. | ||
| + | reader = csv.reader(csvfile, | ||
| + | # CSV-File in Liste umwandeln | ||
| + | datalist = list(reader) | ||
| + | |||
| + | # reader schliessen | ||
| + | reader.close() | ||
| + | # Liste anschauen: | ||
| + | # print(datalist) | ||
| + | |||
| + | # GPanel aufsetzen | ||
| + | makeGPanel(-20, | ||
| + | drawGrid(-15, | ||
| + | # Punkte zeichnen | ||
| + | # Alle Punkte in einer Schlaufen zeichnen, x-Koordinate: | ||
| + | # Mögliche hilfreiche Funktion move, if, setColor, fillCircle, etc. | ||
| + | </ | ||
| + | |||
| + | <hidden Lösung> | ||
| + | <file python readdata_sol.py> | ||
| + | from gpanel import * | ||
| + | |||
| + | import csv #um Text-Dateien im CSV-Format zu lesen | ||
| + | import random | ||
| + | |||
| + | # CSV-File öffnen | ||
| + | csvfile = open(' | ||
| + | # CSV-File einlesen. | ||
| + | reader = csv.reader(csvfile, | ||
| + | # CSV-File in Liste umwandeln | ||
| + | datalist = list(reader) | ||
| + | |||
| + | |||
| + | #GPanel aufsetzen | ||
| + | makeGPanel(-20, | ||
| + | drawGrid(-15, | ||
| + | # Punkte zeichnen | ||
| + | for i in range(len(datalist)): | ||
| + | move(datalist[i][0], | ||
| + | if int(datalist[i][2])==1: | ||
| + | setColor(" | ||
| + | else: | ||
| + | setColor(" | ||
| + | fillCircle(0.1) | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== L2 ==== | ||
| + | === Ziel === | ||
| + | * Den $k$-nearest-neighbour Algorithmus in $\mathbb{R}^2$ implementieren. | ||
| + | * Auf Grund einer Liste mit Kooordinaten '' | ||
| + | |||
| + | == Wichtige Zutaten == | ||
| + | * Liste mit Distanzen und Klassen, i.e. '' | ||
| + | * Sortieren dieser Liste um die $k$ nächsten Nachbarn resp. deren Klasse zu bestimmen: | ||
| + | * Sortieren von Listen kann mit Python mit [[https:// | ||
| + | * Auf Grund der sortierten Liste kann die Mehrheitsmeinung der $k$ nächsten Nachbarn bestimmt werden | ||
| + | <code python> | ||
| + | |||
| + | def computeDistances(xn, | ||
| + | # Funktion berechnet die Distanz von (xn,yn) zu den Punkten in datalist | ||
| + | return(distanceClassList) | ||
| + | | ||
| + | def assignClass(distClassList): | ||
| + | # die k nächsten nachbar raussuchen | ||
| + | # mehrheit herausfinden | ||
| + | # mehrheismeinung zurückgeben | ||
| + | | ||
| + | | ||
| + | </ | ||
| + | Empfehlung: Mindestens zwei Funktionen definieren. Eine zur Berechnung der Distanz-Klassen-Liste, | ||
| + | |||
| + | Testen des Algorithmus mit | ||
| + | * Einem fixen Punkt, z.B. (3,2) | ||
| + | * 100, 1000, 10'000 zufällig als Quadrat dargestellte eingefärbte Punkten. | ||
| + | |||
| + | |||
| + | Wer $k$-nearest-neighbour implementiert hat, kann sich überlegen, wie die untenstehende Daten klassifiziert werden sollen: | ||
| + | {{ : | ||
| + | Die Daten finden sich in einer neuen {{efinf: | ||
| + | |||
| + | <hidden Lösung> | ||
| + | <code python knn_classification.py> | ||
| + | from gpanel import * | ||
| + | import csv # um Text-Dateien im CSV-Format zu lesen | ||
| + | import random | ||
| + | |||
| + | # CSV-File oefffnen | ||
| + | |||
| + | csvfile = open(' | ||
| + | |||
| + | # CSV-File einlesen. | ||
| + | |||
| + | reader = csv.reader(csvfile, | ||
| + | quoting=csv.QUOTE_NONNUMERIC) | ||
| + | |||
| + | # CSV-File in Liste umwandeln | ||
| + | |||
| + | datalist = list(reader) | ||
| + | |||
| + | # GPanel aufsetzen | ||
| + | |||
| + | makeGPanel(-20, | ||
| + | drawGrid(-15, | ||
| + | |||
| + | # Punkte zeichnen | ||
| + | |||
| + | for i in range(len(datalist)): | ||
| + | move(datalist[i][0], | ||
| + | if int(datalist[i][2]) == 1: | ||
| + | setColor(' | ||
| + | else: | ||
| + | setColor(' | ||
| + | fillCircle(0.1) | ||
| + | |||
| + | # Funktion, die einem Punkt eine Klasse auf Grund der k naechsten Nachbarn zuweist. | ||
| + | def assignClass(point, | ||
| + | # Funktion die die Distanzen vom Punkt zu den exisitierenden Punkte berechnet | ||
| + | | ||
| + | |||
| + | # Liste um die Distanzen zu speichern. Achtung: Speicher!! | ||
| + | distlist = [] | ||
| + | |||
| + | # | ||
| + | for i in range(len(datalist)): | ||
| + | distlist.append([datalist[i][2], | ||
| + | - datalist[i][0]) ** 2 + (point[1] | ||
| + | - datalist[i][1]) ** 2)]) | ||
| + | |||
| + | |||
| + | | ||
| + | # das waere ein sehr Pythonesquer Weg mit Lambda-Funktionen | ||
| + | # nearest = sorted(distlist, | ||
| + | | ||
| + | # definiere eine Funktion, welche das zweite Element zurueckgibt. | ||
| + | def sortFunction(item): | ||
| + | return item[1] | ||
| + | |||
| + | # Sortiere die liste! Achtung: Man koennte auch ohne key Arbeiten, wenn Distanz an 1. Stelle waere | ||
| + | nearest = sorted(distlist, | ||
| + | | ||
| + | # Zaehle Klassennummern und entscheide ueber Klasse. Achtung: Laesst sich so nicht auf k>2 Klassen erweitern. | ||
| + | classsum = sum([nearest[i][0] for i in range(k)]) | ||
| + | if classsum > k / 2: | ||
| + | retclass = 1 | ||
| + | elif classsum < k / 2: | ||
| + | retclass = 0 | ||
| + | else: | ||
| + | retclass = random.randint(0, | ||
| + | return retclass | ||
| + | |||
| + | |||
| + | |||
| + | #Funktion um Pt zu zeichnen und mit Label auf Grund der k-naechsten Nachbarn zu versehen | ||
| + | def drawAndLablePoint(point, | ||
| + | guessedclass = assignClass(point, | ||
| + | move(point) | ||
| + | setColor(' | ||
| + | fillRectangle(0.02, | ||
| + | text(str(guessedclass)) | ||
| + | |||
| + | |||
| + | #Programm teseten | ||
| + | drawAndLablePoint([-0.5, | ||
| + | drawAndLablePoint([0.5, | ||
| + | print assignClass([-1, | ||
| + | print assignClass([-1, | ||
| + | print assignClass([1, | ||
| + | print assignClass([1, | ||
| + | print assignClass([-1, | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | |||
| + | ==== L3 ==== | ||
| + | === Ziele === | ||
| + | * Idee von Trainings- und Testdaten verstehen | ||
| + | * [[# | ||
| + | * Musterlösung verstehen | ||
| + | * Klassifizierungsfehler auf {{efinf: | ||
| + | | ||
| + | === Hinweise === | ||
| + | * **Klassifizierungsfehler**: | ||
| + | <hidden Lösung> | ||
| + | <file python knn_evaluate.py> | ||
| + | |||
| + | import time | ||
| + | import csv # um Text-Dateien im CSV-Format zu lesen | ||
| + | import random | ||
| + | from math import sqrt #ist bei Standard Python nicht dabei | ||
| + | |||
| + | # CSV-Files oefffnen | ||
| + | traindata = open(' | ||
| + | testdata = open(' | ||
| + | |||
| + | # CSV-Files oefffnen | ||
| + | trainreader = csv.reader(traindata, | ||
| + | testreader = csv.reader(testdata, | ||
| + | |||
| + | # CSV-Files in Liste umwandeln | ||
| + | datalist = list(trainreader) | ||
| + | testlist = list(testreader) | ||
| + | |||
| + | # File-handle schliessen | ||
| + | traindata.close() | ||
| + | testdata.close() | ||
| + | |||
| + | # Funktion, die einem Punkt eine Klasse auf Grund der k naechsten Nachbarn zuweist. | ||
| + | def assignClass(point, | ||
| + | # Liste um die Distanzen zu speichern. | ||
| + | distlist = [] | ||
| + | # Für jeden den Punkt point die Distanzen zu allen Punkten in datalist berechnen. | ||
| + | for i in range(len(datalist)): | ||
| + | distlist.append([datalist[i][2], | ||
| + | - datalist[i][0]) ** 2 + (point[1] | ||
| + | - datalist[i][1]) ** 2)]) | ||
| + | |||
| + | |||
| + | | ||
| + | # das waere ein sehr Pythonesquer Weg mit Lambda-Funktionen | ||
| + | # nearest = sorted(distlist, | ||
| + | | ||
| + | # definiere eine Funktion, welche das zweite Element zurueckgibt. | ||
| + | def sortFunction(item): | ||
| + | return item[1] | ||
| + | |||
| + | # Sortiere die liste! Achtung: Man koennte auch ohne key Arbeiten, wenn Distanz an 1. Stelle waere | ||
| + | nearest = sorted(distlist, | ||
| + | | ||
| + | # Zaehle Klassennummern und entscheide ueber Klasse. Achtung: Laesst sich so nicht auf k>2 Klassen erweitern. | ||
| + | classsum = sum([nearest[i][0] for i in range(k)]) | ||
| + | if classsum > k / 2: | ||
| + | retclass = 1 | ||
| + | elif classsum < k / 2: | ||
| + | retclass = 0 | ||
| + | else: | ||
| + | retclass = random.randint(0, | ||
| + | return retclass | ||
| + | |||
| + | |||
| + | ## Bereich zum Vergleichen: | ||
| + | |||
| + | testlength=len(testlist) | ||
| + | summary = [] | ||
| + | ## Iteriere über mehrere Anzahl Nachbarn. | ||
| + | for k in range(1, | ||
| + | correct = 0 | ||
| + | for i in range(testlength): | ||
| + | # teste ob korrekt klassifiziert: | ||
| + | if(abs(testlist[i][2]) - assignClass(testlist[i][0: | ||
| + | correct+=1 | ||
| + | # k und relative Anzahl korrekter ablegen | ||
| + | summary.append([k, | ||
| + | |||
| + | print(summary) | ||
| + | |||
| + | </ | ||
| + | |||
| + | </ | ||
| + | ==== L4 ==== | ||
| + | === Ziele === | ||
| + | * Musterlösung Klassifikationsfehler in Abhängigkeit von $k$ verstehen. | ||
| + | * ZIP-Code Problematik verstehen: ZIP-Code -> Ziffer -> 16x16 Bild -> Liste mit 256 Graustufen-Werten -> kNN in $\mathbb{R}^{256}$. | ||
| + | * Einzelne Ziffern als {{efinf: | ||
| + | * Eine Funktion schreiben, die als Argument einen Dateinamen hat und als Rückgabewert eine Liste mit 256 Elementen. | ||
| + | * Diese Funktion auf alle Dateien anwenden (siehe unten) und die Ziffer aus dem Dateinamen in eine Liste von Liste mit 256+1 Elementen speichern | ||
| + | === Hinweise === | ||
| + | * **Konvertierung der Bild-Dateien zu Zahlwerten** | ||
| + | * Bilder können in Tigerjython mit [[http:// | ||
| + | * Verzeichnisse können mit os.listdir() durchlaufen werden: <file python listdir.py> | ||
| + | for filename in os.listdir(" | ||
| + | print(filename) | ||
| + | |||
| + | </ | ||
| + | import os | ||
| + | for filename in [filename for filename in os.listdir(" | ||
| + | print(filename) | ||
| + | </ | ||
| + | * Mit '' | ||
| + | * Die Graustufenwerte von 0 bis 255 sollten auf Werte zwischen -1 und 1 " | ||
| + | * Ziel ist eine Liste mit 256 + 1 Einträgen pro Bilddatei. Diese Liste könnte dann wieder als [[https:// | ||
| + | * Speicherung als CSV passiert am einfachsten über CSV schreiben: <file python writecsv.py> | ||
| + | |||
| + | # CSV-writer konfigurieren. | ||
| + | writer = csv.writer(outcsv, | ||
| + | |||
| + | for item in datalist: | ||
| + | #Jeden Eintrag der Datalist als Zeile ausgeben | ||
| + | writer.writerow([item[0], | ||
| + | |||
| + | # Wrtier schliessen | ||
| + | outcsv.close() | ||
| + | </ | ||
| + | |||
| + | Die Anzahl Nachbarn $k$ ist ein sogenannter " | ||
| + | {{efinf: | ||
| + | |||
| + | ==== L5 ==== | ||
| + | === Ziele === | ||
| + | * Musterlösung zur Konvertierung von Bild -> Pixelliste verstehen / beenden. | ||
| + | * Implementierung kNN-Klassifizierer auf den Zeichendaten. Entweder die eigenen Zeichendaten oder die vorbereiteten {{efinf: | ||
| + | * Klassifizieren einer eigenen, handgeschriebenen Zahl | ||
| + | |||
| + | === Distanz in $n$ Dimensionen === | ||
| + | Beim kNN-Algorithmus geht es darum, den Abstand zu den Nachbarn zu berechnen. Bis jetzt war unser Problem $2$-dimensional. Neu ist es $256$-dimensional, | ||
| + | * Im eindimensionalen Fall ($\mathbb{R}^1$): | ||
| + | * Im zweidimensionalen Fall ($\mathbb{R}^2$): | ||
| + | * Im dreidimensionalen Fall ($\mathbb{R}^3$): | ||
| + | * Im vierdimensionalen Fall ($\mathbb{R}^4$): | ||
| + | * Im $n$-dimensionalen Fall ($\mathbb{R}^n$): | ||
| + | |||
| + | === Konvertierung Bild <-> Pixelliste === | ||
| + | Musterlösung um eine Pixelliste aus allen Dateien eines Verzeichnisses zu erstellen: | ||
| + | <code python pixelist_from_directory.py> | ||
| + | |||
| + | import gpanel | ||
| + | import os #um Verzeichnisse zu listen | ||
| + | import csv #um CSV-Dateien zu lesen. | ||
| + | |||
| + | # Pfad zu den Bilddateien | ||
| + | digitsdirectory = ' | ||
| + | |||
| + | |||
| + | def getPixeListFromFilePath(filepath): | ||
| + | img = gpanel.getImage(filepath) | ||
| + | w = img.getWidth() | ||
| + | h = img.getHeight() | ||
| + | pixellist = [] | ||
| + | for y in range(h): | ||
| + | for x in range(w): | ||
| + | # color is ein Objekt mit verschiedenen Attributen, u.a. red, green, blue. | ||
| + | # bei grau sind rot=gruen=blau, | ||
| + | # siehe auch https:// | ||
| + | color = img.getPixelColor(x, | ||
| + | |||
| + | # umlegen auf das Intervall [-1,1] zwecks Normalisierung | ||
| + | value = color.red / 255 * 2 - 1 | ||
| + | # an liste anhaengen | ||
| + | pixellist.append(value) | ||
| + | return pixellist | ||
| + | |||
| + | # Lese Ziffer aus Dateiname aus. | ||
| + | def getDigitFromFileName(filename): | ||
| + | return int(filename.split(' | ||
| + | |||
| + | # leere Liste fuer alle Trainingsdaten der Form [-0.93, | ||
| + | |||
| + | trainingset = [] | ||
| + | |||
| + | # durch alle files im Ziffernverzeichnis loopen | ||
| + | for filename in [filename for filename in os.listdir(digitsdirectory) if filename.endswith(" | ||
| + | # Ziffer auslesen | ||
| + | currdigit = getDigitFromFileName(filename) | ||
| + | |||
| + | # Pixelliste von Datei auslesen | ||
| + | currpixellist = getPixeListFromFilePath(digitsdirectory + filename) | ||
| + | |||
| + | # Der Pixelliste die Ziffer anhaengen | ||
| + | currpixellist.append(currdigit) | ||
| + | |||
| + | # Gesamte Liste dem trainingsset anhaengen. | ||
| + | trainingset.append(currpixellist) | ||
| + | |||
| + | # Das Trainingsset kann jetzt verwendet werden | ||
| + | # print(trainingsset) | ||
| + | |||
| + | </ | ||
| + | Der Code unten soll als Grundlage für den eigentlichen kNN Klassifizierer gelten. Es muss einizg noch die Funktion '' | ||
| + | |||
| + | <code python stub_knn_digits.py> | ||
| + | |||
| + | import csv #um CSV-Dateien zu lesen. | ||
| + | |||
| + | |||
| + | |||
| + | # Trainingsdaten | ||
| + | trainingset = list(csv.reader(open(digitsdirectory + ' | ||
| + | # Testdaten | ||
| + | testset = list(csv.reader(open(digitsdirectory + ' | ||
| + | |||
| + | |||
| + | def assignClass(point, | ||
| + | # Funktion die den Abstand von point zu den k naechsten | ||
| + | # Nachbarn im trainingset berechnet mit Pythagoras in | ||
| + | # 16x16=256 Dimensionen | ||
| + | | ||
| + | # über alle Trainingsdaten iterieren | ||
| + | for i in range(len(trainingsset)): | ||
| + | dist = 0; | ||
| + | # über alle 256 Pixel iterieren (für alle Trainingsdaten) | ||
| + | for j in range(255): | ||
| + | dist = dist + (point[j] - trainingsset[i][j])^2 | ||
| + | |||
| + | #etc. | ||
| + | # gibt die Mehrheitsklasse wieder. Tip: Liste mit Häufigkeiten zurückgeben. | ||
| + | return(assignedclass) | ||
| + | |||
| + | ## Funktion Testen auf ersten Testbild | ||
| + | print(assignClass(testset[0][0: | ||
| + | # Auf allen Testdaten | ||
| + | for i in range(len(testset)): | ||
| + | print(assignClass(testset[i][0: | ||
| + | print(testset[i][256]) | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== L6 ==== | ||
| + | === Ziele === | ||
| + | * kNN für Ziffern abschliessen / Musterlösung verstehen | ||
| + | * Klassifikationsgüte für verschiedene $k$ ausrechnen | ||
| + | * Konfusionsmatrix berechnen für ein bestimmtes $k$ | ||
| + | * Flaschenhals kNN verstehen: Dimensionen, | ||
| + | |||
| + | === Tipps === | ||
| + | * Algorithmus mit weniger Trainingsdaten / Testdaten testen. Laufzeit!! | ||
| + | * Klassifikationsgüte allenfalls mit eigener Schlaufe über verschiedene $k$ automatisiert ausrechnen | ||
| + | * Bild beschneiden, | ||
| + | |||
| + | === Zusatzinfos === | ||
| + | Sortieren ist kostspielig: | ||
| + | <hidden Lösung> | ||
| + | <code python knn_bilder.py> | ||
| + | |||
| + | import gpanel | ||
| + | import os #um Verzeichnisse zu listen | ||
| + | import csv #um CSV-Dateien zu lesen. | ||
| + | |||
| + | # Pfad zu den Bilddateien | ||
| + | digitsdirectory = ' | ||
| + | |||
| + | |||
| + | def getPixeListFromFilePath(filepath): | ||
| + | img = gpanel.getImage(filepath) | ||
| + | w = img.getWidth() | ||
| + | h = img.getHeight() | ||
| + | pixellist = [] | ||
| + | for y in range(h): | ||
| + | for x in range(w): | ||
| + | |||
| + | # color is ein Objekt mit verschiedenen Attributen, u.a. red, green, blue. | ||
| + | # bei grau sind rot=gruen=blau, | ||
| + | # siehe auch https:// | ||
| + | color = img.getPixelColor(x, | ||
| + | |||
| + | # umlegen auf das Intervall [-1,1] zwecks Normalisierung | ||
| + | value = color.red / 255 * 2 - 1 | ||
| + | # an liste anhaengen | ||
| + | pixellist.append(value) | ||
| + | | ||
| + | return pixellist | ||
| + | |||
| + | # Lese Ziffer aus Dateiname aus. | ||
| + | def getDigitFromFileName(filename): | ||
| + | return int(filename.split(' | ||
| + | |||
| + | |||
| + | # leere Liste fuer alle Trainingsdaten der Form [-0.93, | ||
| + | |||
| + | trainingset = [] | ||
| + | |||
| + | # durch alle files im Ziffernverzeichnis loopen | ||
| + | for filename in [filename for filename in os.listdir(digitsdirectory) if filename.endswith(" | ||
| + | |||
| + | |||
| + | # Ziffer auslesen | ||
| + | currdigit = getDigitFromFileName(filename) | ||
| + | |||
| + | # Pixelliste von Datei auslesen | ||
| + | currpixellist = getPixeListFromFilePath(digitsdirectory + filename) | ||
| + | |||
| + | # Der Pixelliste die Ziffer anhaengen | ||
| + | currpixellist.append(currdigit) | ||
| + | |||
| + | # Gesamte Liste dem trainingsset anhaengen. | ||
| + | trainingset.append(currpixellist) | ||
| + | |||
| + | # Das Trainingsset kann jetzt verwendet werden | ||
| + | # print(trainingsset) | ||
| + | |||
| + | # Alternative: | ||
| + | # trainingset = list(csv.reader(open(' | ||
| + | |||
| + | |||
| + | # Funktion, die einem Punkt eine Klasse auf Grund der k naechsten Nachbarn zuweist. | ||
| + | def assignClass(point, | ||
| + | |||
| + | # Liste um die Distanzen zu speichern. | ||
| + | distlist = [] | ||
| + | |||
| + | # Fuer jeden den Punkt point die Distanzen zu allen Punkten in datalist berechnen. | ||
| + | for i in range(len(trainingset)): | ||
| + | dist = 0 | ||
| + | |||
| + | # schlaufe ueber die 256 pixel | ||
| + | for j in range(255): | ||
| + | dist += (point[j] - trainingset[i][j]) ** 2 | ||
| + | | ||
| + | distlist.append([trainingset[i][256], | ||
| + | |||
| + | # das waere ein sehr Pythonesquer Weg mit Lambda-Funktionen | ||
| + | # nearest = sorted(distlist, | ||
| + | |||
| + | # definiere eine Funktion, welche das zweite Element zurueckgibt. | ||
| + | def sortFunction(item): | ||
| + | return item[1] | ||
| + | |||
| + | # Sortiere die liste! Achtung: Man koennte auch ohne key Arbeiten, wenn Distanz an 1. Stelle waere | ||
| + | nearest = sorted(distlist, | ||
| + | |||
| + | # Zaehle k naechsten Klassennummern und entscheide ueber Klasse. | ||
| + | # Liste die die Anzahl Vorkommen von 0,1,2,...,9 enthaelt. An Stelle 0 die Null, an Stelle 1 die Eins etc. | ||
| + | classcounts = [0] * 10 | ||
| + | |||
| + | # Loope durch die k naechsten Nachbarn und erhoehe den classcount jeweils um 1 | ||
| + | # wenn eine Ziffer (Klasse) der jeweiligen Ziffer gefunden worden ist. | ||
| + | for j in range(k): | ||
| + | classcounts[int(nearest[j][0])] += 1 | ||
| + | |||
| + | # Rueckggabe der Anzahl/ | ||
| + | # Wenn anstelle der Anzahl/ | ||
| + | # kann dies mit classcounts.index(max(classcounts)) passieren. | ||
| + | |||
| + | return classcounts | ||
| + | |||
| + | |||
| + | # Teste das Programm | ||
| + | |||
| + | testpoint = getPixeListFromFilePath(digitsdirectory + ' | ||
| + | print assignClass(testpoint, | ||
| + | testpoint = getPixeListFromFilePath(digitsdirectory + ' | ||
| + | print assignClass(testpoint, | ||
| + | testpoint = getPixeListFromFilePath(digitsdirectory + ' | ||
| + | print assignClass(testpoint, | ||
| + | testpoint = getPixeListFromFilePath(' | ||
| + | print assignClass(testpoint, | ||
| + | |||
| + | </ | ||
| + | </ | ||
| + | ==== L7 ==== | ||
| + | |||
| + | === Ziele === | ||
| + | * Jeder kann die zentralen Begriffen erklären / beschreiben (-> | ||
| + | * kNN mit Python und Scikit durchführen | ||
| + | * Eigene Ziffer als GIF klassifizieren oder Random Forests durchführen | ||
| + | |||
| + | === Aufträge === | ||
| + | * Bei installiertem Python 2.7. die notwendigen Module installieren (siehe [[# | ||
| + | * kNN in Python durchführen, | ||
| + | * Wer soweit durch: | ||
| + | * Eigene Ziffer als GIF klassifizieren mit der Funktion '' | ||
| + | * Random Forests durchführen und Klassifikationsgüte mit kNN vergleichen | ||
| + | * kNN für verschiedene '' | ||
| + | |||
| + | |||
| + | === Zusatzhintergrund Python === | ||
| + | Um mit bereits implementierten Methoden von [[http:// | ||
| + | |||
| + | == Navigation zu PIP == | ||
| + | * Pfad aus Explorer kopieren, üblicherweise '' | ||
| + | * Im DOS-Prompt (Windows + R -> cmd) zum Verzeichnis navigieren mit '' | ||
| + | * Dann '' | ||
| + | |||
| + | < | ||
| + | pip install numpy | ||
| + | pip install scipy | ||
| + | pip install sklearn | ||
| + | pip install imageio | ||
| + | </ | ||
| + | |||
| + | Ein wichtiges Konstrukt sind sogenannte numpy-Arrays: | ||
| + | |||
| + | <code python> | ||
| + | data = array([[2, | ||
| + | #zugriff via Zeile/ | ||
| + | data[0,1] | ||
| + | data[1,1] | ||
| + | # fuer trainingsdaten | ||
| + | trainingdata[0, | ||
| + | trainingdata[4, | ||
| + | trainingsdata[0,: | ||
| + | </ | ||
| + | === kNN in Python === | ||
| + | Nachher kann relativ einfach mit Python kNN implementiert werden: | ||
| + | <code python knn_scikit.py> | ||
| + | # | ||
| + | # -*- coding: utf-8 -*- | ||
| + | from sklearn.neighbors import KNeighborsClassifier | ||
| + | from sklearn.metrics import confusion_matrix | ||
| + | from numpy import genfromtxt, | ||
| + | from imageio import imread | ||
| + | # Trainingdaten einlesen | ||
| + | |||
| + | trainingdata = genfromtxt(' | ||
| + | |||
| + | # Testdaten einlesen | ||
| + | |||
| + | testdata = genfromtxt(' | ||
| + | |||
| + | # Trainingsfeatures und -klassen trennen. | ||
| + | # Kolonne 0:255: Features, Kolonne 256 Klasse | ||
| + | # Fuer Ekrlaerung der Syntax siehe: https:// | ||
| + | train_digits_features = trainingdata[:, | ||
| + | train_digits_class = trainingdata[:, | ||
| + | |||
| + | # Testfeatures und -klassen trennen. | ||
| + | test_digits_features = testdata[:, :-1] | ||
| + | test_digits_class = testdata[:, -1] | ||
| + | |||
| + | # kNN initilisieren mit 5 Nachbarn | ||
| + | knn = KNeighborsClassifier(n_neighbors=5) | ||
| + | |||
| + | # kNN traininieren | ||
| + | knn.fit(train_digits_features, | ||
| + | |||
| + | # Vorhersage | ||
| + | predicted_class = knn.predict(test_digits_features) | ||
| + | |||
| + | # Wahre Test digits ausgeben | ||
| + | print(test_digits_class) | ||
| + | |||
| + | # Predicted Test digits ausgeben | ||
| + | print(predicted_class) | ||
| + | |||
| + | ## Vergleichen und Klassifikationsguete berechnen. | ||
| + | ## Differenz muss = 0 sein wenn richtig klassifziert. Boolsche Variablen koennen summiert werden. | ||
| + | |||
| + | print sum(predicted_class - test_digits_class == 0) / float(len(predicted_class)) | ||
| + | |||
| + | ## Konfusionsmatrix berechnen | ||
| + | mat_knn = confusion_matrix(test_digits_class, | ||
| + | print(mat_knn) | ||
| + | |||
| + | # Aquivalent der Funktion getPixelListFromFilePath | ||
| + | def getPixelArrayFromFilePath(filepath): | ||
| + | img = imread(filepath) | ||
| + | return(asarray(((img.flatten()/ | ||
| + | |||
| + | |||
| + | |||
| + | getPixelArrayFromFilePath(" | ||
| + | print(knn.predict(getPixelArrayFromFilePath(" | ||
| + | |||
| + | </ | ||
| + | === Implementierung von Random Forests === | ||
| + | <code python knn_rf_scikit.py> | ||
| + | # | ||
| + | # -*- coding: utf-8 -*- | ||
| + | |||
| + | from sklearn.neighbors import KNeighborsClassifier | ||
| + | from numpy import genfromtxt, asarray, sum | ||
| + | from sklearn.metrics import confusion_matrix | ||
| + | from sklearn.ensemble import RandomForestClassifier | ||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # Daten einlesen. Für Random Forests (rf) und k-Nearest-Neighbors (knn) | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | |||
| + | # Trainingdaten einlesen | ||
| + | |||
| + | trainingdata = genfromtxt(' | ||
| + | |||
| + | # Testdaten einlesen | ||
| + | |||
| + | testdata = genfromtxt(' | ||
| + | |||
| + | # Trainingsfeatures und -klassen trennen. | ||
| + | # Kolonne 0:255: Features, Kolonne 256 Klasse | ||
| + | # Fuer Ekrlaerung der Syntax siehe: | ||
| + | # https:// | ||
| + | train_digits_features = trainingdata[: | ||
| + | train_digits_class = trainingdata[: | ||
| + | |||
| + | # Testfeatures und - klassen trennen. | ||
| + | test_digits_features = testdata[: , : -1] | ||
| + | test_digits_class = testdata[: , -1] | ||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # kNN trainieren, vorhersagen und evaluieren. | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | |||
| + | #kNN initilisieren mit 10 Nachbarn | ||
| + | knn = KNeighborsClassifier(n_neighbors = 10) | ||
| + | |||
| + | # kNN traininieren | ||
| + | knn.fit(train_digits_features, | ||
| + | |||
| + | # Vorhersage | ||
| + | predicted_class_knn = knn.predict(test_digits_features) | ||
| + | |||
| + | # Konfusionsmatrix | ||
| + | mat_knn = confusion_matrix(test_digits_class, | ||
| + | print(mat_knn)# | ||
| + | guete_knn = sum(mat_knn.diagonal()) / float(sum(mat_knn)) | ||
| + | print "Guete kNN:", guete_knn | ||
| + | |||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # Random Forests trainieren, vorhersagen und evaluieren. | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | rf = RandomForestClassifier(n_estimators = 200, random_state = 17) | ||
| + | rf.fit(train_digits_features, | ||
| + | predicted_class_rf = rf.predict(test_digits_features) | ||
| + | |||
| + | mat_rf = confusion_matrix(test_digits_class, | ||
| + | print(mat_rf) | ||
| + | |||
| + | # Güte | ||
| + | guete_rf = sum(mat_rf.diagonal()) / float(sum(mat_rf)) | ||
| + | print "Guete rf:", guete_rf | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | <!-- | ||
| + | ==== L6 - L7 ==== | ||
| + | === Ziele === | ||
| + | * kNN in TigerJython einmal durchführen: | ||
| + | * kNN in Python mit sklearn durchführen. | ||
| + | * Einfluss von $k$ und $n$ kennen / durchprobieren mit sklearn. | ||
| + | * Welches ist das optimale $k$ bei 100, 200, 500, 1000, 2000, 5000, 7000 Observationen? | ||
| + | * Wie stark hängt Klassifikationsgüte von Trainingsgrösse ab? | ||
| + | * ... | ||
| + | * Weiterführende Aspekte Computer Lernen kennenlernen: | ||
| + | * Künstliche Testsets | ||
| + | * Data Augmentation: | ||
| + | * Daten Qualität: Falsch klassifzierte Trainingsdaten. | ||
| + | |||
| + | === Zusatzhintergrund Python === | ||
| + | Um mit bereits implementierten Methoden von [[http:// | ||
| + | |||
| + | == Navigation zu PIP == | ||
| + | * Pfad aus Explorer kopieren, üblicherweise '' | ||
| + | * Im DOS-Prompt (Windows + R -> cmd) zum Verzeichnis navigieren mit '' | ||
| + | * Dann '' | ||
| + | |||
| + | < | ||
| + | pip install numpy | ||
| + | pip install scipy | ||
| + | pip install sklearn | ||
| + | pip install imageio | ||
| + | </ | ||
| + | |||
| + | Ein wichtiges Konstrukt sind sogenannte numpy-Arrays: | ||
| + | |||
| + | <code python> | ||
| + | data = array([[2, | ||
| + | #zugriff via Zeile/ | ||
| + | data[0,1] | ||
| + | data[1,1] | ||
| + | # fuer trainingsdaten | ||
| + | trainingdata[0, | ||
| + | trainingdata[4, | ||
| + | trainingsdata[0,: | ||
| + | </ | ||
| + | |||
| + | Nachher kann relativ einfach mit Python kNN implementiert werden: | ||
| + | <code python knn_scikit.py> | ||
| + | # | ||
| + | # -*- coding: utf-8 -*- | ||
| + | from sklearn.neighbors import KNeighborsClassifier | ||
| + | from numpy import genfromtxt, | ||
| + | from imageio import imread | ||
| + | # Trainingdaten einlesen | ||
| + | |||
| + | trainingdata = genfromtxt(' | ||
| + | |||
| + | # Testdaten einlesen | ||
| + | |||
| + | testdata = genfromtxt(' | ||
| + | |||
| + | # Trainingsfeatures und -klassen trennen. | ||
| + | # Kolonne 0:255: Features, Kolonne 256 Klasse | ||
| + | # Fuer Ekrlaerung der Syntax siehe: https:// | ||
| + | train_digits_features = trainingdata[:, | ||
| + | train_digits_class = trainingdata[:, | ||
| + | |||
| + | # Testfeatures und -klassen trennen. | ||
| + | test_digits_features = testdata[:, :-1] | ||
| + | test_digits_class = testdata[:, -1] | ||
| + | |||
| + | # kNN initilisieren mit 5 Nachbarn | ||
| + | knn = KNeighborsClassifier(n_neighbors=5) | ||
| + | |||
| + | # kNN traininieren | ||
| + | knn.fit(train_digits_features, | ||
| + | |||
| + | # Vorhersage | ||
| + | predicted_class = knn.predict(test_digits_features) | ||
| + | |||
| + | # Wahre Test digits ausgeben | ||
| + | print(test_digits_class) | ||
| + | |||
| + | # Predicted Test digits ausgeben | ||
| + | print(predicted_class) | ||
| + | |||
| + | ## Vergleichen und Klassifikationsguete berechnen. | ||
| + | ## Differenz muss = 0 sein wenn richtig klassifziert. Boolsche Variablen koennen summiert werden. | ||
| + | |||
| + | print sum(predicted_class - test_digits_class == 0) / float(len(predicted_class)) | ||
| + | |||
| + | # Aquivalent der Funktion getPixelListFromFilePath | ||
| + | def getPixelArrayFromFilePath(filepath): | ||
| + | img = imread(filepath) | ||
| + | return(asarray(((img.flatten()/ | ||
| + | |||
| + | |||
| + | |||
| + | getPixelArrayFromFilePath(" | ||
| + | print(knn.predict(getPixelArrayFromFilePath(" | ||
| + | |||
| + | </ | ||
| + | |||
| + | |||
| + | ==== L7 ==== | ||
| + | === Ziele === | ||
| + | * Jede/r kann die zentralen Begriffe der Slides erklären / berechnen / durchführen | ||
| + | * $k$-nearest neighbor und random forests in Python durchführen | ||
| + | * Vorbereitung Testcases Prüfung | ||
| + | |||
| + | Die Slides der Stunde finden sich {{efinf: | ||
| + | Eine Implementierung in Python, die '' | ||
| + | <code python knn_rf_scikit.py> | ||
| + | # | ||
| + | # -*- coding: utf-8 -*- | ||
| + | |||
| + | from sklearn.neighbors import KNeighborsClassifier | ||
| + | from numpy import genfromtxt, asarray, sum | ||
| + | from sklearn.metrics import confusion_matrix | ||
| + | from sklearn.ensemble import RandomForestClassifier | ||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # Daten einlesen. Für Random Forests (rf) und k-Nearest-Neighbors (knn) | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | |||
| + | # Trainingdaten einlesen | ||
| + | |||
| + | trainingdata = genfromtxt(' | ||
| + | |||
| + | # Testdaten einlesen | ||
| + | |||
| + | testdata = genfromtxt(' | ||
| + | |||
| + | # Trainingsfeatures und -klassen trennen. | ||
| + | # Kolonne 0:255: Features, Kolonne 256 Klasse | ||
| + | # Fuer Ekrlaerung der Syntax siehe: | ||
| + | # https:// | ||
| + | train_digits_features = trainingdata[: | ||
| + | train_digits_class = trainingdata[: | ||
| + | |||
| + | # Testfeatures und - klassen trennen. | ||
| + | test_digits_features = testdata[: , : -1] | ||
| + | test_digits_class = testdata[: , -1] | ||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # kNN trainieren, vorhersagen und evaluieren. | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | |||
| + | #kNN initilisieren mit 10 Nachbarn | ||
| + | knn = KNeighborsClassifier(n_neighbors = 10) | ||
| + | |||
| + | # kNN traininieren | ||
| + | knn.fit(train_digits_features, | ||
| + | |||
| + | # Vorhersage | ||
| + | predicted_class_knn = knn.predict(test_digits_features) | ||
| + | |||
| + | # Konfusionsmatrix | ||
| + | mat_knn = confusion_matrix(test_digits_class, | ||
| + | print(mat_knn)# | ||
| + | guete_knn = sum(mat_knn.diagonal()) / float(sum(mat_knn)) | ||
| + | print "Guete kNN:", guete_knn | ||
| + | |||
| + | |||
| + | ####################################################################### | ||
| + | # | ||
| + | # Random Forests trainieren, vorhersagen und evaluieren. | ||
| + | # | ||
| + | ####################################################################### | ||
| + | |||
| + | rf = RandomForestClassifier(n_estimators = 200, random_state = 17) | ||
| + | rf.fit(train_digits_features, | ||
| + | predicted_class_rf = rf.predict(test_digits_features) | ||
| + | |||
| + | mat_rf = confusion_matrix(test_digits_class, | ||
| + | print(mat_rf) | ||
| + | |||
| + | # Güte | ||
| + | guete_rf = sum(mat_rf.diagonal()) / float(sum(mat_rf)) | ||
| + | print "Guete rf:", guete_rf | ||
| + | </ | ||
| + | |||
| + | ==== L8 ==== | ||
| + | Prüfung und ANN | ||
| + | |||
| + | |||
| + | === Evaluation === | ||
| + | * {{efinf: | ||
| + | * [[https:// | ||
| + | |||
| + | |||
| + | === Artificial Neural Networks === | ||
| + | * [[https:// | ||
| + | * https:// | ||
| + | |||
| + | === Feedback === | ||
| + | https:// | ||