Verpass auch nicht unser Keras Cheat Sheet . Es zeigt dir die sechs Schritte, die du in Python zum Aufbau neuronaler Netze durchläufst – inklusive Codebeispielen!
Einführung in Künstliche Neuronale Netze
Bevor wir in Keras und den Einstieg in Deep Learning mit Python eintauchen, solltest du ein paar Dinge über neuronale Netze wissen. Wie oben kurz erwähnt, stammen die Ideen aus der Biologie, wo man mit „neural network“ auch das Geflecht aus Neuronen meint. Das menschliche Gehirn ist ein Beispiel für ein solches Netzwerk aus vielen Neuronen.
Wie du weißt, kann das Gehirn sehr komplexe Berechnungen durchführen – daher kommt die Inspiration für künstliche neuronale Netze. Das Netzwerk als Ganzes ist ein mächtiges Modellierungswerkzeug.
Perceptrons
Das einfachste neuronale Netz ist das „Perceptron“, das in seiner Grundform aus nur einem Neuron besteht. Ähnlich wie biologische Neuronen mit Dendriten und Axonen ist das künstliche Ein-Neuron-Netz eine Baumstruktur mit Eingangsknoten und einem einzelnen Ausgangsknoten, der mit allen Eingängen verbunden ist. Hier ist ein visueller Vergleich:
Wie du im Bild siehst, haben künstliche Neuronen sechs Komponenten. Von links nach rechts sind das:
Eingangsknoten . Jedem Eingang ist ein numerischer Wert zugeordnet – eine reelle Zahl, also positiv oder negativ, ganz oder dezimal.
Verbindungen . Jeder Verbindung vom Eingang ist ein Gewicht zugeordnet, ebenfalls eine reelle Zahl.
Alle Eingänge und Gewichte werden zusammengeführt als gewichtete Summe : \(y = f(\sum_{i=1}^{D} w_i*x_i)\) , also \(y = f(w_1*x_1 + w_2*x_2 + ... + w_D*x_D)\) .
Das Ergebnis fließt in eine Transfer- bzw. Aktivierungsfunktion . Trivial wäre die Identitätsfunktion \(f(x)=x\) bzw. \(y=x\) . Doch wie ein biologisches Neuron erst „feuert“, wenn ein Schwellwert überschritten ist, soll auch das künstliche Neuron erst auslösen, wenn die Summe einen Schwellwert, z. B. 0, übersteigt. Das leistet die Identitätsfunktion nicht. Eine einfache, aber unstetige Variante wäre:
\(f(x) = 0\) falls \(x<0\) \(f(x) = 0.5\) falls \(x=0\) \(f(x) = 1\) falls \(x>0\)
Da diese Funktion nicht glatt ist, verursacht sie Probleme in der Weiterverarbeitung. Daher nutzt man oft eine stetige Alternative wie die Sigmoidfunktion, z. B. die logistische Funktion – sie liefert glattere Ausgaben.
Am Ende steht der Ausgangsknoten , dessen Wert die Funktion (z. B. Sigmoid) der gewichteten Summe der Eingänge ist. Die Sigmoidfunktion erzeugt eine S-förmige Kurve – dazu später mehr.
Optional besitzt das Perceptron einen Bias als zusätzlichen Parameter. Er entspricht dem Gewicht eines stets auf 1 gesetzten zusätzlichen Eingangs und verschiebt die Aktivierungsfunktion nach links oder rechts – oft entscheidend für den Lernerfolg.
Logische Konsequenz: Perceptrons arbeiten nur mit numerischen Daten. Kategoriale Merkmale musst du also in Zahlen umwandeln.
Da Perceptrons mit Schwellwerten arbeiten, liegt die Klassifikation nahe: Werte oberhalb einer Schwelle gehören zu Klasse A, darunter zu Klasse B. Die Gerade bei Schwellenwert = Ausgabe bildet die Entscheidungsgrenze.
Multi-Layer-Perceptrons
Netze aus Perceptrons heißen Multi-Layer-Perceptrons – und genau die setzen wir mit Keras in Python um. Sie werden auch „Feedforward-Netze“ genannt. Sie sind komplexer als ein einzelnes Perceptron: Mehrere Neuronen sind in Schichten organisiert. Typisch sind zwei bis drei Schichten, theoretisch gibt es keine Grenze.
Die Schichten funktionieren wie oben beschrieben: Die Ausgaben einer Schicht sind die Eingaben der nächsten.
Man unterscheidet Eingabeschicht, verborgene Schichten und Ausgabeschicht. Häufig sind Multi-Layer-Perceptrons vollständig verbunden: Jeder Perceptron einer Schicht ist mit jedem der nächsten Schicht verbunden. Das ist nicht zwingend, aber üblich.
Während ein Perceptron nur lineare Trennungen darstellen kann, überwindet das Multi-Layer-Perceptron diese Grenze und bildet komplexe Entscheidungsflächen ab.
Weinsorten mit Keras in Python vorhersagen
Für dieses Tutorial nutzt du den Wine-Quality-Datensatz aus dem wine quality data set des UCI Machine Learning Repository. Deep Learning entfaltet seine Stärken bei großen Datensätzen, aber für den Einstieg reicht ein kleinerer. Ziel ist, Keras kennenzulernen und zu verstehen, wie neuronale Netze funktionieren.
Vielleicht kennst du den Datensatz bereits – er ist sehr beliebt, um ML-Probleme zu üben. Hier dient er als Einstieg in Deep Learning mit Keras.
Los geht’s!
Die Daten verstehen
Bevor du lädst, ein kurzer Check: Wie viel weißt du über Wein (bezogen auf den Datensatz)? Die meisten wissen, dass es grob zwei populäre Typen gibt: Rot und Weiß.
(Klar gibt es mehr, aber der Einfachheit halber – und weil mein Weinwissen begrenzt ist – bleiben wir dabei. Entschuldigt, ihr wahren Connaisseurs! :))
Für die Analyse brauchst du etwas mehr Kontext.
Sieh dir zuerst die Datenbeschreibung an, um die enthaltenen Variablen zu verstehen – das ist meist der erste Schritt. Geh zu dieser Seite oder lies hier weiter.
Es gibt zwei Datensätze zu Rot- und Weißweinen des portugiesischen „Vinho Verde“. Enthalten sind ausschließlich physikochemische und sensorische Variablen. Insgesamt gibt es 12 Variablen. Für alle, die – wie ich – keine Chemieexpert:innen sind, hier eine Kurzbeschreibung:
Fixed acidity : Säuren prägen den Geschmack. Man unterscheidet flüchtige und nichtflüchtige (fixe) Säuren. Zu den fixen zählen Weinsäure, Apfelsäure, Zitronensäure und Bernsteinsäure. Im Datensatz in g(\(tartaric acid\) )/\(dm^3\) .
Volatile acidity : Der Prozess, bei dem Wein zu Essig wird. In den USA liegen Grenzwerte bei 1,2 g/L (rot) und 1,1 g/L (weiß). Hier in g(\(acetic acid\) )/\(dm^3\) .
Citric acid : Eine der fixen Säuren, in g/\(dm^3\) .
Residual sugar : Übrig gebliebener Zucker nach (abgebrochener) Gärung, in g/\(dm^3\) in red und white.
Chlorides : Tragen zur Salzigkeit bei, hier in g(\(sodium chloride\) )/\(dm^3\) .
Free sulfur dioxide : Der aktive, ungebundene Teil des zugesetzten Schwefeldioxids, in mg/\(dm^3\) .
Total sulfur dioxide : Summe aus gebundenem und freiem SO2, in mg/\(dm^3\) . Gesetzliche Grenzwerte: EU 160 mg/L (rot), 210 mg/L (weiß/rosé), süß bis 400 mg/L; USA 350 mg/L; Australien 250 mg/L.
Density : Maß für die Umwandlung von Zucker zu Alkohol, in g/\(cm^3\) .
pH : Maß für Säure bzw. Basizität. pH < 7 sauer, > 7 basisch, 7 neutral. Wein liegt meist zwischen 2,9 und 3,9 und ist damit sauer.
Sulfates : Sulfite sind weltweit üblich und nötig, können aber Kopfschmerzen verursachen. Hier in g(\(potassium sulphate\) )/\(dm^3\) .
Alcohol : Alkoholgehalt in % vol.
Quality : Bewertung der Weinqualität von 0 (sehr schlecht) bis 10 (sehr gut). Der Wert ist der Median aus mindestens drei Verkostungen von Expert:innen.
Das ist das wichtigste Basiswissen für den Start. Wenn du Weinkenner:in bist, kennst du sicher noch viel mehr!
Jetzt hol dir die Daten!
Daten laden
Das geht bequem mit der Python-Bibliothek pandas. Du importierst sie konventionell als pd.
Dann liest du die CSV-Dateien mit read_csv() ein. Achte auf das Argument sep, hier ist das Trennzeichen ein Semikolon statt Komma.
Probier es im DataCamp-Light-Block unten aus:
# Import pandas
import pandas as pd
# Read in white wine data
white = ___________("http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-white.csv", sep=';')
# Read in red wine data
red = ___________("http://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv", sep=';')
Top! Das war doch einfach, oder?
Auch wenn du das schon oft gemacht hast – es ist ein essenzieller erster Schritt. Jetzt kannst du mit Exploration, Aufbereitung und Modeling starten.
Datenexploration
Mit den Daten zur Hand lernst du die Weine schnell besser kennen. Ein sinnvoller Start ist ein schneller Blick auf beide DataFrames:
# Print info on white wine
_____(white.____())
# Print info on red wine
_____(red.____())
Prüfe jetzt, ob der Import geklappt hat: Sind alle in der Beschreibung genannten Variablen vorhanden? Stimmen die Datentypen? Haben alle Zeilen geladen? Gibt es Nullwerte, die du beim Bereinigen beachten musst?
Du kannst noch mehr als nur info() nutzen:
# First rows of `red`
red.____()
# Last rows of `white`
white.____()
# Take a sample of 5 rows of `red`
red.______(5)
# Describe `white`
white.________()
# Double check for null values in `red`
pd.isnull(red)
Kurze Wiederholung: head(), tail() und sample() sind super, um schnell in die Daten zu schauen.
describe() liefert kompakte Kennzahlen zur Datenqualität. Du siehst, dass manche Variablen große Abstände zwischen min und max haben. Darum kümmern wir uns später – wichtig ist, es zu bemerken.
Außerdem hast du mit isnull() für red auf fehlende Werte geprüft – praktisch, wenn du nach info() noch unsicher bist.
Tipp : Prüfe auch für die Weißweindaten auf Nullwerte. Nutze die IPython-Shell des Blocks oben.
Jetzt geht’s etwas tiefer.
Daten visualisieren
Schau dir Verteilungen an und erstelle Scatterplots für mögliche Korrelationen. Für eigene Projekte kannst du natürlich deutlich weiter gehen.
Alkohol
Auffällig ist oft die Variable alcohol. Du kannst Verteilungen mit verschiedenen Bibliotheken plotten; hier nutzen wir matplotlib für einen schnellen Plot:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2)
ax[0].hist(red.alcohol, 10, facecolor='red', alpha=0.5, label="Red wine")
ax[1].hist(white.alcohol, 10, facecolor='white', ec="black", lw=0.5, alpha=0.5, label="White wine")
fig.subplots_adjust(left=0, right=1, bottom=0, top=0.5, hspace=0.05, wspace=1)
ax[0].set_ylim([0, 1000])
ax[0].set_xlabel("Alcohol in % Vol")
ax[0].set_ylabel("Frequency")
ax[1].set_xlabel("Alcohol in % Vol")
ax[1].set_ylabel("Frequency")
#ax[0].legend(loc='best')
#ax[1].legend(loc='best')
fig.suptitle("Distribution of Alcohol in % Vol")
plt.show()
Im Diagramm unten siehst du: Die Alkoholwerte von Rot- und Weißwein sind größtenteils ähnlich, meist um 9% vol. Es gibt auch viele Beobachtungen mit 10% oder 11% vol.
Du kannst das mit der histogram()-Funktion aus numpy gegenprüfen, z. B. so:
import numpy as np
print(np.histogram(red.alcohol, bins=[7,8,9,10,11,12,13,14,15]))
print(np.histogram(white.alcohol, bins=[7,8,9,10,11,12,13,14,15]))
Wenn dich matplotlib interessiert, sieh dir DataCamps Matplotlib -Tutorial für Einsteiger und das Tutorial 3D-Volumendaten visualisieren an – inklusive Event-Handler-API.
Sulfate
Mich interessiert der Zusammenhang zwischen Sulfaten und Qualität. Sulfite können Kopfschmerzen verursachen – wirkt sich das auf die Qualität aus? Oft hört man, dass insbesondere Frauen Wein wegen Kopfschmerzen meiden. Spiegelt sich das in den Rotwein-Bewertungen?
Schauen wir nach.
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, figsize=(8, 4))
ax[0].scatter(red['quality'], red["sulphates"], color="red")
ax[1].scatter(white['quality'], white['sulphates'], color="white", edgecolors="black", lw=0.5)
ax[0].set_title("Red Wine")
ax[1].set_title("White Wine")
ax[0].set_xlabel("Quality")
ax[1].set_xlabel("Quality")
ax[0].set_ylabel("Sulphates")
ax[1].set_ylabel("Sulphates")
ax[0].set_xlim([0,10])
ax[1].set_xlim([0,10])
ax[0].set_ylim([0,2.5])
ax[1].set_ylim([0,2.5])
fig.subplots_adjust(wspace=0.5)
fig.suptitle("Wine Quality by Amount of Sulphates")
plt.show()
Im Bild unten scheint Rotwein mehr Sulfate zu enthalten; bei Weißwein liegen nur wenige Beobachtungen knapp über 1 g/\(dm^3\) , bei Rotwein deutlich mehr. Das könnte das Sprichwort „Rotwein macht Kopfschmerzen“ untermauern – aber was ist mit der Qualität?
Es gibt Weißweine mit relativ wenig Sulfaten und einer 9 als Bewertung. Insgesamt ist die Interpretation hier aber schwierig.
Denk daran: Unterschiedliche Stichprobengrößen beeinflussen die Grafiken und deine Interpretation.
Säure
Neben Sulfaten ist die Säure zentral für die Weinqualität. Spitzenweine balancieren Säure, Tannin, Alkohol und Süße. In Mengen von 0,2 bis 0,4 g/L beeinflusst flüchtige Säure die Qualität kaum; bei höheren Werten vermittelt sie eine scharfe, essigartige Note – extreme Werte deuten auf fehlerhaften Wein.
Testen wir das: Erstelle einen Scatterplot Alkohol vs. flüchtige Säure, eingefärbt nach quality:
import matplotlib.pyplot as plt
import numpy as np
np.random.seed(570)
redlabels = np.unique(red['quality'])
whitelabels = np.unique(white['quality'])
import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 2, figsize=(8, 4))
redcolors = np.random.rand(6,4)
whitecolors = np.append(redcolors, np.random.rand(1,4), axis=0)
for i in range(len(redcolors)):
redy = red['alcohol'][red.quality == redlabels[i]]
redx = red['volatile acidity'][red.quality == redlabels[i]]
ax[0].scatter(redx, redy, c=redcolors[i])
for i in range(len(whitecolors)):
whitey = white['alcohol'][white.quality == whitelabels[i]]
whitex = white['volatile acidity'][white.quality == whitelabels[i]]
ax[1].scatter(whitex, whitey, c=whitecolors[i])
ax[0].set_title("Red Wine")
ax[1].set_title("White Wine")
ax[0].set_xlim([0,1.7])
ax[1].set_xlim([0,1.7])
ax[0].set_ylim([5,15.5])
ax[1].set_ylim([5,15.5])
ax[0].set_xlabel("Volatile Acidity")
ax[0].set_ylabel("Alcohol")
ax[1].set_xlabel("Volatile Acidity")
ax[1].set_ylabel("Alcohol")
#ax[0].legend(redlabels, loc='best', bbox_to_anchor-(1.3, 1))
ax[1].legend(whitelabels, loc='best', bbox_to_anchor=(1.3, 1))
#fig.suptitle("Alcohol - Volatile Acidity")
fig.subplots_adjust(top=0.85, wspace=0.7)
plt.show()
Die Farben wurden mit dem NumPy-random-Modul zufällig gewählt. Du kannst sie über Listen für redcolors bzw. whitecolors festlegen. Achte darauf, dass die Zuordnung passt (Weißwein hat einen quality-Wert mehr), sonst stimmen die Legenden nicht.
Sieh dir die komplette Grafik hier an:
Oben erkennst du: Die genannten Schwellen gelten besonders für Weißwein; viele Weine mit Label 8 haben flüchtige Säure ≤ 0,5. Ob das die Qualität beeinflusst, ist schwer zu sagen – die Punkte ballen sich stark auf einer Seite.
Das war eine kurze Exploration. Wenn du das vertiefen willst, sieh dir DataCamps Beiträge zu Exploratory Data Analysis in Python und Python Data Profiling an.
EDA zusammenfassen
Kurzer Recap der wichtigsten Punkte für den weiteren Verlauf:
Einige Variablen haben stark unterschiedliche Wertebereiche. Das adressieren wir gleich.
Es gibt keine Nullwerte in den Datensätzen.
Die meisten Weine liegen bei etwa 9% vol Alkohol.
Rotwein scheint mehr Sulfate zu enthalten; Weißwein hat seltener > 1 g/\(dm^3\) .
Die meisten Weine haben ≤ 0,5 flüchtige Säure. Ein direkter Zusammenhang zur Qualität ist aktuell nicht erkennbar.
Bisher hast du Rot- und Weißwein getrennt betrachtet. Manche Variablen unterscheiden sich, andere ähneln sich. Lässt sich anhand der Variablen in Weiß oder Rot klassifizieren?
Nur ein Weg führt zur Antwort: Daten vorverarbeiten und modellieren!
Daten vorverarbeiten
Jetzt setzt du die gewonnenen Insights um. Lass uns die Daten vorbereiten, damit du dein eigenes neuronales Netz bauen kannst.
# Add `type` column to `red` with value 1
___['type'] = 1
# Add `type` column to `white` with value 0
_____['type'] = 0
# Append `white` to `red`
wines = red.______(white, ignore_index=True)
ignore_index ist hier True, damit die Indexlabels von white beim Anhängen an red nicht erhalten bleiben. Die Indizes sollen sauber weiterlaufen, statt doppelt aufzutauchen.
Intermezzo: Korrelationsmatrix
Mit dem vollständigen Datensatz lohnt sich eine kurze Exploration. Du kennst schon einiges aus der getrennten Betrachtung – jetzt wollen wir belastbarere Insights.
Da Grafiken schwer zu deuten sein können, hilft eine Korrelationsmatrix. Sie zeigt schnell, welche Variablen zusammenhängen:
import seaborn as sns
corr = wines.corr()
sns.heatmap(corr,
xticklabels=corr.columns.values,
yticklabels=corr.columns.values)
sns.plt.show()
Wie erwartet, korrelieren z. B. density und residual sugar. Auch volatile acidity und type hängen enger zusammen als zunächst gedacht. Ebenfalls zu erwarten: free sulfur dioxide und total sulfur dioxide korrelieren.
Spannend!
Train- und Testsätze
Unausgeglichene Daten sind bei Klassifikationen häufig: Klassen sind ungleich vertreten. Ein kleiner Unterschied ist oft egal, aber du solltest sicherstellen, dass beide Weintypen im Training vorkommen und die Anteile nicht völlig kippen – sonst bevorzugt das Modell eine Klasse.
Hier gibt es ein Ungleichgewicht, wir gehen zunächst dennoch so vor. Später kannst du bei Bedarf unter- oder oversamplen.
Importiere train_test_split aus sklearn.model_selection, weise Daten und Zielvariablen X und y zu. Die Zielvariable musst du flach (1D) machen, damit train_test_split() sie akzeptiert. Los geht’s im Block:
# Import `train_test_split` from `sklearn.model_selection`
from sklearn.model_selection import train_test_split
# Specify the data
X=wines.ix[:,0:11]
# Specify the target labels and flatten the array
y=np.ravel(wines.type)
# Split the data up in train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
Du bist auf dem besten Weg zum ersten neuronalen Netz – ein Punkt fehlt noch: Erinnerst du dich an die sehr unterschiedlichen Wertebereiche in white und red?
Genau – wir sollten standardisieren.
Daten standardisieren
Standardisierung hilft bei stark unterschiedlichen Skalen. Scikit-learn bietet mit StandardScaler ein schnelles Werkzeug. Skaliere Trainings- und Testdaten wie folgt:
from sklearn. preprocessing import StandardScaler
scaler = StandardScaler( ) . fit( X_train)
X_train = scaler. transform( X_train)
X_test = scaler. transform( X_test) Bereitgestellt von
Jetzt ist dein Preprocessing erledigt. Weiter geht’s mit dem Herzstück: dem Klassifikationsnetz.
Daten modellieren
Zurück zur Ausgangsfrage: Kannst du anhand chemischer Eigenschaften wie flüchtiger Säure oder Sulfaten vorhersagen, ob ein Wein rot oder weiß ist?
Du hast zwei Klassen, also eine binäre Klassifikation. „Binär“ heißt 0 oder 1, ja oder nein. Da neuronale Netze numerische Eingaben erwarten, hast du Rot als 1 und Weiß als 0 kodiert.
Für solche Aufgaben eignet sich ein Multi-Layer-Perceptron. Meist sind diese Netze vollständig verbunden. Wir bauen also einen einfachen Stack aus Dense-Schichten. Als Aktivierungsfunktion nutzen wir zum Einstieg die verbreitete ReLU.
Baust du dein MLP am schnellsten mit dem Keras-Sequential-Modell: ein linearer Stapel von Schichten. Du initialisierst mit model = Sequential() und fügst Layer hinzu.
Denk an die Struktur: Eingabe-, verborgene und Ausgabeschicht. Die erste Schicht muss die Eingabeform kennen. Daher findest du in den Layer-Dokumentationen Argumente wie input_shape, input_dim, input_length oder batch_size.
Hier nutzt du eine Dense-Schicht (voll verbunden). Sie berechnet output = activation(dot(input, kernel) + bias). Ohne Aktivierung bliebe es bei zwei linearen Operationen.
In der ersten Schicht setzt du activation='relu' und definierst input_shape. Das Modell erwartet Eingaben der Form (12,) bzw. (*, 12). Außerdem hat die erste Schicht 12 units – also 12 verborgene Einheiten und damit eine Ausgabeform (*, 12). Mach dir noch keine Sorgen, wenn das abstrakt klingt – gleich wird es klarer.
Die units repräsentieren den Gewichts-„Kernel“ der obigen Formel, die Gewichtsmatrix der Eingaben. Im Beispiel wird kein Bias explizit gesetzt (du könntest use_bias=True verwenden).
Die mittlere Schicht nutzt ebenfalls ReLU und gibt (*, 8) aus.
Abschließend eine Dense-Schicht mit Größe 1 und Sigmoid-Aktivierung – damit wird die Ausgabe zur Wahrscheinlichkeit für Klasse „1“, also „rot“.
# Import `Sequential` from `keras.models`
from keras.models import Sequential
# Import `Dense` from `keras.layers`
from keras.layers import Dense
# Initialize the constructor
model = Sequential()
# Add an input layer
model.add(Dense(12, activation='relu', input_shape=(11,)))
# Add one hidden layer
model.add(Dense(8, activation='relu'))
# Add an output layer
model.add(Dense(1, activation='sigmoid'))
Es gibt zwei Schlüsselentscheidungen bei der Architektur: Wie viele Schichten nutzt du, und wie viele verborgene Einheiten pro Schicht?
Hier haben wir 12 Einheiten in der ersten Schicht gewählt. Damit legst du fest, wie viel Freiheitsgrade das Netz beim Lernen von Repräsentationen hat. Mehr Einheiten erlauben komplexere Muster, erhöhen aber Rechenaufwand und Overfitting-Risiko.
Overfitting entsteht, wenn das Modell zu komplex ist und Rauschen statt Strukturen lernt. Wenn du wenig Trainingsdaten hast, nutze eher kleine Netze mit wenigen Schichten (oft nur eine, wie hier).
Infos zum Modell bekommst du über output_shape oder summary() u. a. Probiere die folgenden Aufrufe aus, um ein Gefühl zu bekommen:
# Model output shape
model.___________
# Model summary
model.__________
# Model config
model.get_config()
# List all weight tensors
model.get_weights()
Kompilieren und Fitten
Jetzt kompilierst du das Modell und passt es an die Daten an: Nutze compile() und fit().
model. compile ( loss= 'binary_crossentropy' ,
optimizer= 'adam' ,
metrics= [ 'accuracy' ] )
model. fit( X_train, y_train, epochs= 20 , batch_size= 1 , verbose= 1 ) Bereitgestellt von
Beim Kompilieren wählst du den Optimierer adam und die Verlustfunktion binary_crossentropy. Über ['accuracy'] überwachst du die Genauigkeit während des Trainings.
optimizer und loss sind Pflichtargumente. Beliebte Optimierer sind Stochastic Gradient Descent (SGD), Adam und RMSprop. Je nach Algorithmus musst du Hyperparameter wie Lernrate oder Momentum abstimmen. Die Loss-Funktion hängt von der Aufgabe ab: Bei Regression oft Mean Squared Error (MSE), bei binärer Klassifikation wie hier binary_crossentropy, bei Multiklassen categorical_crossentropy.
Trainiere 20 Epochen über alle Samples in X_train und y_train mit Batchgröße 1. verbose=1 zeigt eine Fortschrittsanzeige.
Eine Epoche ist ein Durchlauf über den gesamten Trainingssatz, gefolgt von Validierung. Die Batchgröße legt fest, wie viele Samples pro Schritt durch das Netz gehen – das hilft, Speicher effizient zu nutzen.
Werte vorhersagen
Setz dein Modell ein: Sage die Labels für den Testsatz voraus. Nutze predict() und speichere in y_pred:
y_pred = model. predict( X_test) Bereitgestellt von
Vor der Evaluation kannst du die Genauigkeit grob prüfen, indem du y_pred und y_test vergleichst:
y_pred[ : 5 ] Bereitgestellt von
array( [ [ 0 ] ,
[ 1 ] ,
[ 0 ] ,
[ 0 ] ,
[ 0 ] ] , dtype= int32) Bereitgestellt von
y_test[ : 5 ] Bereitgestellt von
array( [ 0 , 1 , 0 , 0 , 0 ] ) Bereitgestellt von
Sieht passend aus – aber ohne harte Zahlen zählt das wenig.
Modell evaluieren
Nachdem du auf unbekannten Daten vorhergesagt hast, misst du die Leistung. Du kannst visuell mit y_test vergleichen oder Metriken verwenden. Hier nutzen wir evaluate() mit Testdaten und Labels; optional verbose=1 für Logs.
score = model. evaluate( X_test, y_test, verbose= 1 )
print ( score) Bereitgestellt von
[ 0.025217213829228164 , 0.99487179487179489 ] Bereitgestellt von
Der Score ist eine Liste aus Loss und Accuracy. Beides sieht sehr gut aus – denk jedoch an das Klassenungleichgewicht: Es gibt mehr Weißweine. Hohe Accuracy kann hier die Verteilung widerspiegeln, wenn das Modell oft „weiß“ tippt.
Bevor du Datenbalancing betreibst, probiere weitere Evaluationsmetriken – mit scikit-learn (sklearn) wie beim Splitten.
Wir testen grundlegende Klassifikationsmetriken:
Konfusionsmatrix: Zeigt korrekte und fehlerhafte Vorhersagen. Ideal: nur Diagonale belegt.
Precision misst Genauigkeit der positiven Vorhersagen.
Recall misst Vollständigkeit der Erkennung positiver Fälle.
F1-Score ist das gewichtete Mittel aus Precision und Recall.
Cohen’s Kappa normalisiert die Genauigkeit um die Klassenunwucht.
from sklearn. metrics import confusion_matrix, precision_score, recall_score, f1_score, cohen_kappa_score
confusion_matrix( y_test, y_pred) Bereitgestellt von
array( [ [ 1585 , 3 ] ,
[ 8 , 549 ] ] ) Bereitgestellt von
precision_score( y_test, y_pred) Bereitgestellt von
0.994565217391 Bereitgestellt von
recall_score( y_test, y_pred) Bereitgestellt von
0.98563734290843807 Bereitgestellt von
f1_score( y_test, y_pred) Bereitgestellt von
0.99008115419296661 Bereitgestellt von
cohen_kappa_score( y_test, y_pred) Bereitgestellt von
0.98662321692498967 Bereitgestellt von
Alle Werte sind sehr gut – starkes Modell trotz ungleicher Klassenverteilung.
Gute Arbeit!
Weitere Experimente
Dein erstes Modell steht. Jetzt kannst du es weiter ausreizen. Probier Folgendes und beobachte die Effekte – wie oben beschrieben, sind Schichten und Hidden Units die Stellhebel Nummer eins:
Du hast 1 verborgene Schicht genutzt. Teste 2 oder 3.
Variiere die Anzahl der Einheiten pro Schicht – mehr oder weniger.
Nimm quality als Target und den Rest (inkl. kodiertem type) als Features. Das ist dann Multiklassenklassifikation!
Wechsle auch die Aktivierung: Statt relu z. B. tanh – und vergleiche die Ergebnisse.
Weinqualität vorhersagen
Dein Klassifikationsmodell hat für den ersten Wurf überzeugt.
Aber da geht noch mehr – etwa ein Netz, das die Weinqualität vorhersagt.
Hier nehmen wir an, dass quality eine stetige Variable ist: keine binäre Klassifikation, sondern ordinale Regression. Du sagst einen Wert auf einer Skala mit sinnvoller Ordnung voraus (0–10 von „sehr schlecht“ bis „sehr gut“).
Alternativ könntest du die Qualitätswerte als Klassen behandeln und klassifizieren.
In jedem Fall sind die Zielwerte nun die quality-Spalte in red und white. Das erfordert zusätzliches Preprocessing.
Daten vorverarbeiten
Da quality jetzt das Target ist, trennst du es vom Rest der Daten. Lege wines.quality in y ab und die Weindaten ohne quality in X.
Statt eines einfachen Train-/Test-Splits verwenden wir hier k-fold-Validierung: Teile die Daten in K Folds (meist 4 oder 5), instanziiere identische Modelle, trainiere jeweils auf einem Fold und evaluiere auf den restlichen. Der Validierungsscore ist der Durchschnitt über die K Folds.
Das siehst du gleich. Zuvor standardisieren wir die Daten wieder mit StandardScaler, wie gehabt.
# Isolate target labels
y = wines.________
# Isolate data
X = wines.drop('quality', axis=_)
Denke daran: Wegen der unterschiedlichen Wertebereiche in red, white (und damit wines) brauchst du erneut Skalierung.
Probier’s im folgenden Block. Alle nötigen Bibliotheken sind geladen:
# Scale the data with `StandardScaler`
X = ________________.fit_transform(X)
Jetzt bist du wieder startklar fürs Modeling.
Architektur des neuronalen Netzes
Nach dem Preprocessing konstruierst du erneut ein Multi-Layer-Perceptron. Obwohl es sich um Regression handelt, kann die Architektur ähnlich sein: zwei Dense-Schichten.
Die erste Schicht ist die Eingabeschicht. Über input_dim übergibst du die Dimensionalität der Eingaben an Dense.
# Import `Sequential` from `keras.models`
from keras.models import Sequential
# Import `Dense` from `keras.layers`
from keras.layers import Dense
# Initialize the model
model = Sequential()
# Add input layer
model.add(Dense(64, input_dim=12, activation='relu'))
# Add output layer
model.add(Dense(1))
Noch mal zur Erinnerung: Die erste definierte Schicht ist die Eingabeschicht. Sie braucht die Eingabedimension – hier 12 (inklusive der zuvor generierten Type-Spalte). Du nutzt wieder ReLU; kein Bias ist angegeben. Anzahl der Hidden Units: 64.
Das Netz endet mit Dense(1) ohne Aktivierung. Das ist typisch für skalare Regression mit einem stetigen Zielwert.
Modell kompilieren, Daten fitten
Mit dem Modell in der Hand kompilierst du es und passt die Daten an – aber mit K-Fold-Validierung, wie angekündigt.
import numpy as np
from sklearn. model_selection import StratifiedKFold
seed = 7
np. random. seed( seed)
kfold = StratifiedKFold( n_splits= 5 , shuffle= True , random_state= seed)
for train, test in kfold. split( X, Y) :
model = Sequential( )
model. add( Dense( 64 , input_dim= 12 , activation= 'relu' ) )
model. add( Dense( 1 ) )
model. compile ( optimizer= 'rmsprop' , loss= 'mse' , metrics= [ 'mae' ] )
model. fit( X[ train] , Y[ train] , epochs= 10 , verbose= 1 ) Bereitgestellt von
Mit compile() setzt du mindestens optimizer und loss. Hier z. B. rmsprop (beliebt) und mse (typisch für Regression). Über metrics definierst du die Bewertungsfunktion – bei Regression oft Mean Absolute Error (MAE).
Über fit() übergibst du Trainingsdaten und -labels, Anzahl Epochen, Batchgröße und optional verbose=1 für Logs.
Modell evaluieren
Wie zuvor solltest du auch hier evaluieren. Zusätzlich zu y_pred = model.predict(X[test]) bieten sich Metriken aus sklearn an.
Nutze Mean Squared Error (MSE) und Mean Absolute Error (MAE). MSE misst den mittleren quadrierten Fehler (niedriger ist besser), MAE den mittleren absoluten Fehler.
Ergänze diese Zeilen (auf Einrückung achten):
mse_value, mae_value = model. evaluate( X[ test] , Y[ test] , verbose= 0 )
print ( mse_value)
0.522478731072
print ( mae_value)
0.561965950103 Bereitgestellt von
Neben MSE und MAE kannst du auch den R2-Score verwenden (Bestwert 1.0, kann auch negativ sein):
from sklearn. metrics import r2_score
r2_score( Y[ test] , y_pred)
0.3125092543 Bereitgestellt von
Auf den ersten Blick sehen die Werte nicht toll aus. Positiv: Jetzt kannst du gezielt optimieren.
Darum geht’s im letzten Abschnitt.
Modell-Fine-Tuning
Feinabstimmung gehört fast immer dazu – nicht alle Probleme sind so geradlinig wie die erste Aufgabe. Zwei Stellschrauben kennst du schon: Anzahl der Schichten und der Hidden Units.
Am Anfang ist das eine kleine Entdeckungsreise.
Weitere Schichten hinzufügen
Was passiert, wenn du eine Schicht ergänzt? Etwa so:
model = Sequential( )
model. add( Dense( 64 , input_dim= 12 , activation= 'relu' ) )
model. add( Dense( 64 , activation= 'relu' ) )
model. add( Dense( 1 ) ) Bereitgestellt von
Hidden Units
Probiere auch mehr Einheiten pro Schicht und beobachte die Metriken, z. B.:
model = Sequential( )
model. add( Dense( 128 , input_dim= 12 , activation= 'relu' ) )
model. add( Dense( 1 ) ) Bereitgestellt von
Denke daran: Bei wenig Daten steigt das Overfitting-Risiko. Halte die Netze eher klein.
Weitere Experimente: Optimierer-Parameter
Neben Schichten und Einheiten kannst du Parameter des Optimierers anpassen. Bisher haben wir Strings wie rmsprop übergeben.
Das geht auch explizit:
Importiere RMSprop und passe z. B. die Lernrate lr an. Andere Default-Werte lassen sich ebenfalls ändern (vorsichtig!). Mehr Infos hier .
from keras. optimizers import RMSprop
rmsprop = RMSprop( lr= 0.0001 )
model. compile ( optimizer= rmsprop, loss= 'mse' , metrics= [ 'mae' ] ) Bereitgestellt von
Teste auch andere Optimierer wie Stochastic Gradient Descent (SGD). Siehst du einen Effekt?
from keras. optimizers import SGD, RMSprop
sgd= SGD( lr= 0.1 )
model. compile ( optimizer= sgd, loss= 'mse' , metrics= [ 'mae' ] ) Bereitgestellt von
Mach weiter!
Dieses Tutorial ist dein Start in Deep Learning mit Python und Keras. Es gibt noch viel zu entdecken – zum Beispiel im DataCamp-Kurs Deep Learning in Python . Lies parallel unbedingt die Keras-Dokumentation , falls noch nicht geschehen. Dort findest du Beispiele, Funktionsreferenzen, Argumente, weitere Layer usw. – ein unverzichtbares Nachschlagewerk. Wenn du lieber ein Buch möchtest, das die Grundlagen von Deep Learning (mit Keras) und Praxis vereint, empfiehlt sich François Chollets Deep Learning in Python .
Wahrscheinlich kennst du bereits Machine Learning, einen Bereich der Informatik, der sich mit dem Design von Algorithmen befasst, die aus Daten lernen. Heute konzentrierst du dich auf Deep Learning, ein Teilgebiet des Machine Learnings mit Algorithmen, die von Struktur und Funktion des Gehirns inspiriert sind. Diese Algorithmen heißen meist Künstliche Neuronale Netze (ANN). Deep Learning zählt zu den dynamischsten Feldern der Data Science, mit beeindruckenden Ergebnissen in Robotik, Bilderkennung und Künstlicher Intelligenz (KI).
Einer der leistungsfähigsten und zugleich einfach zu bedienenden Python-Stacks für die Entwicklung und Evaluierung von Deep-Learning-Modellen ist Keras; Es kapselt die numerischen Bibliotheken Theano und TensorFlow. Der Vorteil: Du kannst auf einfache und motivierende Weise mit neuronalen Netzen loslegen.
Dieses Keras-Tutorial für Einsteiger führt dich in die Grundlagen von Deep Learning mit Python ein: