Hat mein neuronales Netzwerk tatsächlich etwas gelernt? – oder warum man sich nicht ausschließlich auf den MSE verlassen sollte
Von Dominik Thalmeier

Hat mein neuronales Netzwerk tatsächlich etwas gelernt? – oder warum man sich nicht ausschließlich auf den MSE verlassen sollte

Machine Learning ist durch Toolboxen wie PyTorch, Keras und scikit-learn zugänglicher geworden. Diese Tools sollte man jedoch mit Bedacht einsetzen, um häufige Fehlerquellen zu vermeiden. In diesem Artikel beleuchten wir einige dieser Fallstricke – und wie man ihnen aus dem Weg geht.

Ein Beispiel

Stellen wir uns eine Ingenieurin vor, die eine hochmoderne Maschine namens NiceDevice entwickelt hat. Diese Maschine ist mit 2.000 Sensoren ausgestattet und hat eine Qualitätskennzahl namens „mittlere Abweichung" – je näher sie an null liegt, desto besser. Um zu verhindern, dass die Maschine ausfällt, möchte die Ingenieurin die Qualität des NiceDevice für den nächsten Tag anhand der Sensordaten des aktuellen Tages vorhersagen.

Sie verfügt über Daten von 1.200 Tagen und möchte ein neuronales Netz für diese Vorhersage trainieren. Der erste wichtige Schritt ist, festzulegen, wie die Modellperformance getestet werden soll. Dazu legt sie einen Teil der Daten als Testdaten zurück, die nicht in das Training einfließen – damit das Netz die Daten nicht einfach auswendig lernt.

print(x_shape.train)
print(y_shape.train)

print(x_test_shape.train)
print(y_test_shape.train)

(1000, 550)
(1000, )
(200, 550)
(200, )

Um die „mittlere Abweichung" aus den Sensordaten vorherzusagen, setzen wir künstliche neuronale Netze (KNNs) ein. KNNs sind eine Machine-Learning-Technik, deren Architektur vom menschlichen Gehirn inspiriert ist und genutzt werden kann, um Werte auf Basis von Trainingsdaten vorherzusagen. Ähnlich wie das menschliche Gehirn besitzt ein neuronales Netz „Neuronen", die durch „Synapsen" verbunden sind. Wir verwenden hier ein Feedforward-Netz mit verschiedenen Schichten untereinander verbundener Neuronen.

Architektur eines neuronalen Netzes

65a102b436ea0801ee4148ec_Picture 1 1.png

Die erste Schicht ist die Eingabeschicht – hier werden mehrere Inputs (Features) eingespeist. Die zweite Schicht ist die versteckte Schicht (Hidden Layer), die den Input aus der Eingabeschicht mit synaptischen Gewichten multipliziert, aufsummiert und durch eine Aktivierungsfunktion transformiert. Die Aktivierung des versteckten Neurons h berechnet sich dabei wie folgt:

656f01eac9f5d86a382e0cc4_Neuralnetworks_actiationh.png

Dabei ist wᵢʰ das synaptische Gewicht der Verbindung von Eingabe-Neuron i mit dem versteckten Neuron h.

Die letzte Schicht ist die Ausgabeschicht, die ähnlich wie die versteckte Schicht arbeitet – diesmal mit den Aktivierungen der Hidden Layer als Input. Das ist eine sehr vereinfachte Darstellung. In der Praxis gibt es oft mehrere Inputs und mehrere Hidden Layers, was das Netz zu einem Deep Neural Network macht – dem Fundament von „Deep Learning".

Training neuronaler Netze

In unserem Fall trainieren wir ein einfaches neuronales Netz mit einer einzigen Hidden Layer, um die Qualität des NiceDevice vorherzusagen. Beim Training wird der Mean Squared Error (MSE) minimiert – er misst die Abweichung zwischen vorhergesagten und tatsächlichen Werten als durchschnittliche quadratische Differenz:

656f01ea7a87b1ea2406b44f_neuralnetwork_MSE.png

Dabei ist N die Anzahl der Datenpunkte und Σ die Summe über alle Datenpunkte i.

Da der vorhergesagte Wert der Output des neuronalen Netzes ist, ist der MSE eine Funktion der Netzgewichte. Training bedeutet im Wesentlichen: den MSE durch Ableitung und Gewichtsanpassung minimieren.

Wir nutzen dafür das scikit-learn¹-Paket in Python. Wir müssen uns nicht selbst um Ableitungen und Minimierung kümmern – ein einfaches fit reicht. Oder, wie wir es hier tun, partial_fit, das einen einzelnen Update-Schritt durchführt.

from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error

mse = []

regr = MLPRegressor(random_state=1)

for i in range(200):

    # select a random mini batch from the data
    index_range = range(X_train.shape[0])
    indexes = np.random.choice(index_range, size=200, replace=False)

    X_train_minibatch = X_train[indexes]
    y_train_minibatch = y_train[indexes]

    # do a training step of the neural network
    regr.partial_fit(X_train_minibatch, y_train_minibatch)
    y_predicted = regr.predict(X_test)

    # compute error measure
    test_error = mean_squared_error(y_predicted, y_test)
    mse.append(test_error)

Wir verwenden den MLPRegressor aus scikit-learn, der standardmäßig ein Feedforward-Netz mit einer Hidden Layer und 100 Knoten ist. Es ist ein Regressor (kein Classifier)², da wir einen kontinuierlichen Wert schätzen, keine diskreten Klassen.

Der MLPRegressor hat eine fit-Funktion, die das Modell in einem Befehl trainieren würde – intern führt sie eine Schleife über mehrere Update-Schritte aus. Wir schreiben die Schleife aber explizit über 200 Trainingsschritte, um den Verlauf des Fehlers besser beobachten zu können.

In jedem Durchlauf samplen wir zufällig 200 Datenpunkte aus unserem Trainingsset (sogenanntes Minibatch) und führen ein partial_fit durch – also eine einzelne Gewichtsanpassung. Nach jedem Update berechnen wir den MSE auf dem zurückgehaltenen Testset.

65a102c58076869654f54811_plot1.png

Wir sehen, dass der Fehler auf dem Testset tatsächlich sinkt und dann saturiert. Das Netz hat also etwas gelernt. Oder? Hat es das wirklich? Die Initialisierung erfolgt mit zufälligen Gewichten, was zu einem hohen Ausgangsfehler führt. Dieser Fehler ist zwar gesunken – aber ist die Vorhersagequalität wirklich „gut"? Wie klein muss der MSE sein, damit wir sagen können, dass das Netz sinnvoll vorhersagt?

Bewertung des trainierten neuronalen Netzes

Um diese Frage zu beantworten, betrachten wir einen Baseline-Schätzer: den Mean-Estimator – er nimmt einfach den Durchschnitt der Zielwerte aus dem Trainingsdatensatz als Vorhersage, unabhängig von den Sensordaten.

Der Fehler dieses Schätzers berechnet sich als:

656f023c39ff1e953143f985_neuralnetworks_meanestimator.png

Das ist nichts anderes als die Varianz der Zielwerte.

65a102d7f83d50cd5e426234_plot2.png

Die orange Linie markiert den Baseline-MSE. Und was sehen wir? Der Mean-Estimator ist besser als das neuronale Netz! Ein simpler Durchschnitt schlägt unseren komplexen ML-Algorithmus – ziemlich ernüchternd.

Es ist verlockend, beim Einsatz von Machine Learning einfach den MSE zu betrachten und daraus auf die Qualität des Netzes zu schließen, da er ja auch als Fehlerfunktion beim Training verwendet wird. Eine aussagekräftigere Kennzahl ist jedoch das Bestimmtheitsmaß, auch bekannt als R²-Wert:

656f023c9a36fcea50f5b868_neuralnetwork_coeffiencent.png

Im Grunde wird der MSE durch den MSE des Mean-Estimators normiert.

  • R² < 0: unser Schätzer ist schlechter als der Durchschnitt
  • R² = 0: er liegt gleichauf
  • R² = 1: er ist perfekt

Wenn wir den R²-Wert während des Trainings plotten, sehen wir sofort: er steigt zwar, saturiert aber auf einem Wert unter null. Das Netz lernt also nie, eine sinnvolle Vorhersage zu treffen – und ist damit schlicht nutzlos.

65a102e5ce16a6bedc76020f_plot3.png

Und so klappt es doch

Was ist schiefgelaufen? Warum versagt das neuronale Netz so deutlich?

Ein Blick auf die Daten hilft: Wir plotten die Sensorwerte jedes Tages gegen die mittlere Abweichung des nächsten Tages für die Sensoren 1–8.

65a102ef969a8d29f2ef240f_plot4.png

Wir sehen, dass zwischen den ersten drei Sensoren und dem Zielwert eine Korrelation besteht – am deutlichsten bei Sensor 3. Bei den anderen Sensoren ist keine erkennbare Korrelation vorhanden. Um das zu bestätigen, berechnen wir die Korrelationskoeffizienten für jeden Sensor.

65a102fa0bdfd0400d8f0f41_plot5.png

Tatsächlich: Während Sensoren 1, 2 und 3 stark mit dem Zielwert korrelieren, zeigen die übrigen kaum eine Korrelation³. Indem wir alle 550 Sensoren ins Netz eingespeist haben, haben wir überwiegend Rauschen und kaum Signal geliefert. Das Signal zu finden war wie die Suche nach der Nadel im Heuhaufen.

Vereinfachen wir die Aufgabe für das neuronale Netz, indem wir nur die korrelierten Features verwenden:

feature_selector = SelectKBest(r_regression, k=3) X_train_selected = feature_selector.fit_transform(X_train, y_train) X_test_selected = feature_selector.transform(X_test)

Wir nutzen den SelectKBest-Feature-Selector aus scikit-learn, der die Top-3-Features auswählt – nach dem r_regression-Maß, das den Pearson-Korrelationskoeffizienten zwischen Feature und Zielwert misst.

Nach der Featureauswahl trainieren wir das neuronale Netz erneut.

65a1031152abd76dbc940f84_plot6.png65a1031792d3a4947f1e2b62_plot7.png

Jetzt fällt der MSE deutlich unter den Baseline-MSE des Mean-Estimators – was sich im R²-Wert widerspiegelt, der nun auf einem Wert nahe 1 saturiert. Das Netz hat etwas gelernt. Da wir unseren Score auf einem zurückgehaltenen Testset berechnet haben, wissen wir: es hat nicht nur die Trainingsdaten auswendig gelernt, sondern kann auch auf neue Daten generalisieren.

Fazit

Aufgabe erledigt! Unsere Ingenieurin kann dieses neuronale Netz nutzen, um eine Warnlampe in den NiceDevice einzubauen, die einen Qualitätsabfall am nächsten Tag vorhersagt – damit die Maschine gewartet werden kann, bevor sie im Betrieb versagt.

Wenn man über ausreichend Daten verfügt und das Signal leicht zu finden ist, reicht der MSE als Kennzahl. Wie hier aber gezeigt: Dinge können schiefgehen – und ohne statistische Maßzahlen wie den R²-Wert bleibt schlechte Performance unbemerkt. Wie sind deine Erfahrungen? Hast du es von Anfang an richtig gemacht – oder auf die harte Tour gelernt?

Fußnoten

¹ Für komplexere Aufgaben wie Bilderkennung oder Natural Language Processing werden leistungsfähigere Tools wie PyTorch oder Keras benötigt. Für unser einfaches neuronales Netz ist scikit-learn jedoch ausreichend.

² Bei neuronalen Netzen gibt es wesentliche Unterschiede zwischen Klassifikations- und Regressionsnetzwerken. Bei einem Klassifikationsnetz wird der Output der letzten Schicht typischerweise in den Bereich 0–1 transformiert, um die Wahrscheinlichkeit jeder Klasse darzustellen. Außerdem verwendet es eine andere Fehlerfunktion: die logistische Verlustfunktion, die für Klassifikationsfehler besser geeignet ist als der MSE, der bei Regressionsnetzwerken zur Messung der Abweichung vom Zielwert verwendet wird.

³ In einem Korrelationsplot weist eine große positive Zahl auf eine positive Korrelation zwischen zwei Variablen hin – ein hoher Sensorwert geht dann wahrscheinlich mit einem hohen Qualitätswert einher. Eine große negative Zahl steht für eine negative Korrelation. Kleine Werte – positiv wie negativ – deuten auf keine lineare Korrelation hin, was bedeutet, dass das Feature als Prädiktor wenig nützlich ist. Nichtlineare Korrelationen können dennoch existieren, sprengen aber den Rahmen dieses Artikels.

Dominik Thalmeier

Dominik Thalmeier

Data Scientist

Dominik ist Data Scientist und Softwareentwickler und setzt sich leidenschaftlich dafür ein, eine Brücke zwischen Forschung und Industrie zu schlagen. Er hat sich mit Algorithmen des verstärkenden Lernens und des maschinellen Lernens befasst, um Krankheiten wie Demenz und genetisch bedingten Hörverlust zu diagnostizieren. In der Industrie ist er als Berater für Data Science Architektur und Governance tätig und arbeitet als KI-Entwickler und Data Scientist.

Alle Beiträge von Dominik Thalmeier

Kontakt aufnehmen

Wir freuen uns auf Ihre Anfrage.

Bitte akzeptieren Sie Marketing-Cookies, um das Anmeldeformular zu laden.