Commit 9fc99616 authored by Marvin Kastner's avatar Marvin Kastner
Browse files

Merge Aenderungen, nummeriere JNs

parent 2a5f5722
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Repräsentation von Grauwertbildern\n",
"\n",
"Bilder werden häufig in Form von Rastergrafiken gespeichert.\n",
"Dies bedeutet, dass ein Bild mit einer Breite $m$ und einer Höhe $n$ dann $m \\times n$ Pixel groß ist.\n",
"Ein Pixel ist ein \"Picture Element\", also die Farbe an einer bestimmten Stelle.\n",
"Ein Bild kann somit als eine Matrix von Pixeln dargestellt werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import imageio\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Bibliothek `imageio` enthält eine Reihe von Beispielbildern.\n",
"Dies nimmt dem Entwickler Lizenzfragen ab."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gray_image = imageio.imread(\"imageio:camera.png\")\n",
"plt.imshow(gray_image, cmap=\"gray\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Ein Bild verfügt über eine Breite und eine Höhe.\n",
"Wie man oben an der X- und Y-Achse sieht, ist das Bild etwas über 500 Pixel hoch und breit.\n",
"Grauwertbilder haben nur einen Zahlenwert je darzustellenden Pixel, den Intensitätswert an der jeweiligen Position.\n",
"\n",
"Das Bild wird intern als eine zweidimensionale Matrix abgespeichert."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gray_image.ndim"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Es gibt viele Standards für die Intensitätswerte.\n",
"Deswegen sollte man jedes Mal überprüfen, in welchem Format ein Bild vorliegt.\n",
"Dafür werden die kleinsten und größten Intensitätswerte betrachtet."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gray_image.min(), gray_image.max()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Pixel rangieren zwischen 0 und 255, sprich insgesamt 256 verschiedene Werte."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Ausschneiden von Bildteilen\n",
"\n",
"Wir können auf die Matrix über die Standard-Operatoren von Python zugreifen.\n",
"Einer davon ist der Doppelpunkt zur Bestimmung von Abschnitten.\n",
"So können wir z. B. die Kamera ausschneiden.\n",
"Der Zugriff erfolgt über `BILD[Y-Achse, X-Achse]`."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(gray_image[100:200, 250:350], cmap=\"gray\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dieses Bild können wir nun auch invertieren."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(255 - gray_image[100:200, 250:350], cmap=\"gray\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nun betrachten wir das eine Kamera-Rohr weiter."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(gray_image[140:160, 320:340], cmap=\"gray\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Matrix von Pixelwerten lässt sich auch direkt einsehen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"gray_image[140:160, 320:340]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Was bedeuten hier die kleinen, was bedeuten hier die großen Zahlen?"
]
}
],
"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.6.7"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Erkennung von Ziffern\n",
"\n",
"Das Erkennen von Ziffern hat in dem Bereich Maschinelles Lernen Tradition.\n",
"Hiervon ausgehend kann mit Schrifterkennung gearbeitet werden, um z. B. automatisch Briefe der Adresse nach zu sortieren.\n",
"\n",
"In diesem Jupyter Notebook werden die Ziffern klassifziert, die mit scikit-learn bereits mit ausgeliefert werden."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from sklearn import datasets\n",
"from sklearn.ensemble import RandomForestClassifier\n",
"from sklearn.model_selection import train_test_split\n",
"from sklearn import metrics\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Zunächst wird der Datensatz mit den Ziffern geladen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"digits = datasets.load_digits()\n",
"print(digits.DESCR)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Darstellung einer Ziffer\n",
"\n",
"Nun wird exemplarisch die 0te Ziffer des Datensatzes dargestellt."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"digits.images[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Pixel werden anscheinend als Fließkommazahlen zwischen 0 und 16 dargestellt, wobei die Nachkommastellen nicht genutzt werden.\n",
"Eine Ziffer wird durch eine $8 \\times 8$-Matrix repräsentiert.\n",
"\n",
"Schauen wir uns mal das allererste Bild an."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(digits.images[0], cmap=\"gray\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Es handelt sich scheinbar um eine 0, wobei aus der Matrix eine 0 als schwarz und eine 16 als weiß dargestellt wird.\n",
"Die Zahlen repräsentieren Intensitätswerte."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Wir als Menschen erkennen, dass es sich um eine Null handelt, aber ist dies auch richtig im Datensatz hinterlegt?\n",
"Beim Überwachten Lernen brauchen wir für die Automatisierung bereits erkannte Ziffern."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"digits.target[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dies bestätigt, die oben dargestellte Ziffer eine 0 ist."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Eine alternative, uns eher geläufige Darstellung ist schwarz auf weiß.\n",
"Dafür können wir die Intensitätswerte einfach \"umdrehen\"."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"inverted = 16 - digits.images[0]\n",
"inverted"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plt.imshow(inverted, cmap=\"gray\")\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Dieser Schritt ist aber für den Menschen eher interessant und für weniger für das Maschinelle Lernen.\n",
"\n",
"Eine Möglichkeit, Ziffern zu analysieren, ist, einfach jeden Pixel wie ein eigenes Attribut zu behandeln.\n",
"Beim Aufruf von `flatten` werden die Reihen der Matrix aneinandergehängt, vgl. die [numpy-Dokumentation](https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.ndarray.flatten.html)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"flattened = digits.images[0].flatten()\n",
"flattened"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hier sind nun einfach alle Pixel aneinander gehängt worden.\n",
"So nimmt ein Bild nur eine Zeile ein."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"fig, ax = plt.subplots(figsize=(16, .2))\n",
"ax.imshow(np.expand_dims(flattened, axis=0), cmap=\"gray\", aspect=\"auto\")\n",
"plt.yticks([]) # verstecke Y-Achse\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Vorverarbeitung der Bilder"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Methode `flatten` erstellt aus einer 2d-Matrix einen 1d-Vektor.\n",
"Eine grafische Repräsentation dieses Formats ist oben zu sehen.\n",
"Dies ist notwendig, weil die bislang vorgestellten Klassifizierungs-Algorithmen nur einfache Attribute verstehen - die räumliche Nähe der Pixel kann von SVMs, Feedforward-NNs oder RandomForests so, wie sie bislang definiert worden sind, nicht ausgewertet werden.\n",
"Bei diesem Vorverarbeitungs-Schritt geht die Information über die räumliche Nähe im 2d-Bild verloren."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"images = [image.flatten() for image in digits.images]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nun liegt die Eingabe so vor, dass damit wie bislang auch verfahren werden kann.\n",
"Die Kategorie ist in `digits.target` vermerkt.\n",
"Also `digits.images[22]` ist das Bild und in `digits.target[22]` steht dann, dass es sich bei dem Bild um eine Zwei handelt."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X_train, X_test, y_train, y_test = train_test_split(images, digits.target, test_size=0.33, random_state=42)\n",
"\n",
"clf = RandomForestClassifier(\n",
" n_estimators=10,\n",
" max_depth=7,\n",
" n_jobs=-1,\n",
" max_features=\"auto\",\n",
" class_weight=None\n",
")\n",
"clf.fit(X_train, y_train)\n",
"accuracy = clf.score(X_test, y_test)\n",
"print(\"The accuracy reached {acc}%\".format(acc=accuracy * 100))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Nun lasssen wir uns eine Konfusionsmatrix anzeigen.\n",
"Damit kann man sehen, welche Ziffern mit welchen anderen Ziffern am häufigsten vertauscht worden sind."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"predicted = clf.predict(X_test)\n",
"confusion_matrix = metrics.confusion_matrix(\n",
" y_test,\n",
" predicted\n",
")\n",
"normalized_confusion_matrix = confusion_matrix.astype('float') / confusion_matrix.sum(axis=1)[:,]\n",
" \n",
"fig, ax = plt.subplots(figsize=(6, 6))\n",
"img = ax.imshow(normalized_confusion_matrix, interpolation='nearest', cmap=plt.cm.Blues)\n",
"plt.title(\"Konfusionsmatrix\")\n",
"plt.colorbar(img, shrink=0.5)\n",
"\n",
"plt.ylabel('Tatsächliche Ziffer')\n",
"plt.xlabel('Vorhergesagte Ziffer')\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Eigentlich ist die Vorhersage relativ gut: \n",
"Die tatsächliche und die vorhergesagte Ziffer stimmen ganz gut überein.\n",
"Man sieht nur, dass Fünfen häufiger für Neunen gehalten worden sind (in der Mitte rechts)\n",
"und dass Achten häufiger für eine Zwei gehalten worden sind (unten links).\n",
"\n",
"Die Literatur zur Erkennung von Ziffern ist sehr umfangreich, ein Startpunkt ist bspw. die Webseite http://yann.lecun.com/exdb/mnist/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"<a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\"><img alt=\"Creative Commons Lizenzvertrag\" style=\"border-width:0; display:inline\" src=\"https://i.creativecommons.org/l/by/4.0/88x31.png\" /></a> &nbsp;&nbsp;&nbsp;&nbsp;Dieses Werk von Marvin Kastner ist lizenziert unter einer <a rel=\"license\" href=\"http://creativecommons.org/licenses/by/4.0/\">Creative Commons Namensnennung 4.0 International Lizenz</a>."
]
}
],
"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.5"
},
"varInspector": {
"cols": {
"lenName": 16,
"lenType": 16,
"lenVar": 40
},
"kernels_config": {
"python": {
"delete_cmd_postfix": "",
"delete_cmd_prefix": "del ",
"library": "var_list.py",
"varRefreshCmd": "print(var_dic_list())"
},
"r": {
"delete_cmd_postfix": ") ",
"delete_cmd_prefix": "rm(",
"library": "var_list.r",
"varRefreshCmd": "cat(var_dic_list()) "
}
},
"types_to_exclude": [
"module",
"function",
"builtin_function_or_method",
"instance",
"_Feature"
],
"window_display": false
}
},
"nbformat": 4,
"nbformat_minor": 2
}
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Repräsentation von Farbbildern\n",
"\n",
"Bilder werden häufig in Form von Rastergrafiken gespeichert.\n",
"Dies bedeutet, dass ein Bild mit einer Breite $m$ und einer Höhe $n$ dann $m \\times n$ Pixel groß ist.\n",
"Ein Bild kann somit als eine Matrix von Pixeln dargestellt werden.\n",
"Soweit entsprechen Farbbildern den Grauwertbildern.\n",
"\n",
"Aber wie können Farben enkodiert werden?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"import imageio\n",
"import matplotlib.pyplot as plt\n",
"import skimage.transform\n",
"import skimage.color\n",
"import pandas as pd"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Zunächst wird ein Farbbild geladen."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"color_image = imageio.imread(\"imageio:chelsea.png\")\n",
"plt.imshow(color_image)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Das Bild verfügt, ebenso wie ein Grauwertbild, über eine Breite und eine Höhe.\n",
"Darüber hinaus gibt es noch eine Anzahl von Layers.\n",
"Grauwertbilder haben nur einen Layer, die Intensitätswerte.\n",
"Farbbilder verfügen über mehrere Layer:\n",
"Für die Farben Rot, Grün und Blau werden jeweils die Intensitätswerte angegeben."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"source": [
"height, width, dim = color_image.shape\n",
"height, width, dim"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Hier ist anhand der Variablen `dim` zu erkennen, dass es drei Layer gibt.\n",
"Im Handbuch von imageio ist nachlesbar, dass der erste Layer Rot, der zweite Grün und der dritte Blau darstellt.\n",
"Es gibt auch andere Bibliotheken, wie z. B. OpenCV, die eine andere Sortierung der Layer vornehmen."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"