Grafik von Nicholas Cappello – https://unsplash.com/de/@bash__profile

Regression mittels neuronaler Netze

Es gibt eine Reihe von Möglichkeiten, eine Regressionsaufgabe zu lösen. In diesem Beitrag soll beschrieben werden, wie eine solche Regressionsaufgabe mit Hilfe eines neuronalen Netzes gelöst werden kann.

Henrik Bartsch

Henrik Bartsch

Die Texte in diesem Artikel wurden teilweise mit Hilfe künstlicher Intelligenz erarbeitet und von uns korrigiert und überarbeitet. Für die Generierung wurden folgende Dienste verwendet:

Einordnung

Neuronale Netze sind leistungsstarke Lernmodelle aus dem Machine Learning, die selbst komplexe Muster aus Daten lernen können. Sie werden häufig für verschiedene Klassifikationsaufgaben eingesetzt, z.B. zur Identifikation von Objekten in Bildern oder zur Vorhersage von Stimmungen in Texten. Aber was ist, wenn wir neuronale Netze für Regressionsaufgaben verwenden wollen, z.B. für die Schätzung von Hauspreisen oder für Umsatzprognosen von Unternehmen? Wie können wir neuronale Netze so anpassen, dass sie mit kontinuierlichen Ausgaben statt mit diskreten Ausgaben umgehen können? In diesem Blogeintrag werden wir uns mit diesen Fragen beschäftigen und einige der Optionen und Techniken vorstellen, die für die Verwendung von neuronalen Netzen für Regressionsaufgaben zur Verfügung stehen.

Regression als Aufgabe

Grundsätzlich geht es bei der Regression darum, eine Funktion möglichst genau durch eine andere Funktion zu approximieren. Dies kann verschiedene Gründe haben, z.B. kann die Auswertung der zu approximierenden Funktion zu lange dauern (dies ist bei der Leistung von neuronalen Netzen nach einem Training der Fall), die Funktion ist zu kompliziert oder eine Reihe anderer Gründe.

Regression wird laut Wikipedia auch als Regressionsanalyse bezeichnet. Im Weiteren wird hier allerdings nur der Begriff Regression verwendet. 1

Eine Regressionsmethode ist die Methode der kleinsten Quadrate 2, bei der an jedem Datenpunkt der Fehler zwischen der Originalfunktion ff und der Ersatzfunktion ff^* berechnet, quadriert und die Summe über alle Datenpunkte gebildet wird:

e:=i=1n(f(xi)f(xi))2.e := \sum_{i=1}^n \left( f(x_i) - f^*(x_i) \right)^2.

Der Gesamtfehler ist hier ee. In der Formel steht nNn \in \mathbb{N} für die Gesamtzahl der Datenpunkte. Die Aufgabe eines entsprechenden Regressionsalgorithmus ist es nun den entsprechenden Fehler zu minimieren:

min(i=1n(f(xi)f(xi))2).min \left( \sum_{i=1}^n \left( f(x_i) - f^*(x_i) \right)^2 \right).

Loss-Metrik

Es gibt viele verschiedene Loss-Metriken, um entsprechende Fehler in den Daten zu berechnen.

  1. Mean Absolute Error: Hierbei wird der Fehler klassisch durch

1ni=1n(f(xi)f(xi))\frac{1}{n} \sum_{i=1}^n \left( f(x_i) - f^*(x_i) \right)

berechnet.

  1. Mean Squared Error: Hierbei wird der Fehler berechnet und anschließend quadriert

1ni=1n(f(xi)f(xi))2.\frac{1}{n} \sum_{i=1}^n \left( f(x_i) - f^*(x_i) \right)^2.

  1. Mean Squared Logarithmic Error: Hierbei wird der Fehler logarithmiert und anschließend quadriert

1ni=1n(log(f(xi)+1)log(f(xi)+1))2.\frac{1}{n} \sum_{i=1}^n \left( log(f(x_i) + 1) - log(f^*(x_i) + 1) \right)^2.

Es gibt noch eine Reihe weiterer Loss-Metriken. Eine Auflistung kann hier gefunden werden.

Im Folgenden wird der Mean Squared Error verwendet. Dies ist eine gute Grundlage und führt oft zu guten Ergebnissen. Manchmal können andere Fehlerfunktionen bessere Endergebnisse liefern, dies hängt allerdings von der Problemstellung ab.

Implementierung mittels Tensorflow

Im Folgenden soll nun eine einfache Regressionsaufgabe gelöst werden. Hierbei soll eine Sinus-Funktion

f:RR:xsin(πx)f: R \rightarrow R: x \mapsto sin(\pi*x)

auf dem Bereich x[0,1]x \in [0, 1] durch ein neuronales Netz approximiert werden. Die Sinus-Funktion bietet sich für dieses Beispiel sehr gut an, da die Sinus-Funktion sich lediglich im Bereich

f(x)[0,1]x[0,1]f(x) \in [0, 1] \enspace \forall x \in [0, 1]

bewegt und somit normiert ist. Diese Sinus-Funktion ist im Folgenden visualisiert:

Generierung des Datensets

Bevor irgendein Datensatz generiert werden kann, sind Imports notwendig, um später arbeiten zu können:

regression.py
import numpy as np
import tensorflow as tf
import tensorflow.python.keras.metrics as tfm

import math

from tensorflow.python.keras import Sequential
from tensorflow.python.keras.optimizer_v2.adam import Adam
from tensorflow.python.keras.layers import InputLayer, Dense
from tensorflow.python.keras.losses import MeanSquaredError

Anschließend definieren wir uns eine Funktion, in welcher die Sinus-Funktion ausgewertet wird.

regression.py
def function_eval(x: float):
  return math.sin(2*math.pi*x)

Nun generieren wir als Trainingsdatensatz jeweils 100100 äquidistante Punkte auf dem Intervall [0,1][0, 1] und als Testdatensatz 200200 äquidistante Punkte auf dem identischen Intervall.

regression.py
## Trainingsdatensatz
x = np.linspace(0, 1, 100)

y = []
for i in range(x.shape[0]):
  y.append(function_eval(x[i]))

y = np.array(y)
regression.py
## Testdatensatz
x_eval = np.linspace(0, 1, 200)

y_eval = []
for i in range(x_eval.shape[0]):
  y_eval.append(function_eval(x_eval[i]))

y_eval = np.array(y_eval)

Hiermit haben wir alle notwendigen Daten, um ein entsprechendes Training mit einem neuronalen Netz durchführen zu können.

Training des Modells

Als nächstes definieren wir ein entsprechendes neuronales Netz:

regression.py
model = Sequential([
      InputLayer(input_shape=(1)),
      Dense(units=64, activation="relu"),
      Dense(units=192, activation="relu"),
      Dense(units=256, activation="relu"),
      Dense(units=256, activation="relu"),
      Dense(units=1, activation=None)
])

Dieses Konfiguration eines neuronalen Netzes entstand aus einer Hyperparameteroptimierung. Allerdings funktionieren auch kleinere oder geratene neuronale Netze sehr gut bei dieser Regressionsaufgabe.

Als nächstes müssen noch der jeweilige Optimizer, der Loss-Funktion und die Metrik definiert werden:

regression.py
optimizer = Adam(learning_rate=1e-4)
loss = MeanSquaredError()
model.compile(optimizer=optimizer, loss=loss, metrics=tfm.MeanSquaredError())

Nun kann das neuronale Netz trainiert werden.

regression.py
model.fit(x, y, epochs=100)

Als letzter Schritt kann das neuronale Netz noch evaluiert werden, um den Fehler und die Genauigkeit auf dem Testdatensatz herauszufinden:

regression.py
results = model.evaluate(x_eval, y_eval, verbose=0)
print("Test loss, test accuracy: ", results)

Hierbei werden zwei gleiche Ergebnisse bei herauskommen, da sowohl für den Fehler aus auch die Genauigkeit jeweils MeanSquaredError verwedet wurde. Als Alternative für die Genauigkeit wäre auch MeanAbsoluteError denkbar.

Visualisierung der Ergebnisse

Das neuronale Netz von oben wurde von uns für verschieden viele Epochen trainiert. Ein Vergleich zwischen der eigentlichen zu approximierenden Funktion und der Ausgabe des neuronalen Netzes ist im folgenden visualisiert:

Performance Plot

Weiterhin haben wir einmal den quadratischen Fehler an jeder Stelle für jede Epoche berechnet und einmal dargestellt:

Error Plot

Es ist relativ klar zu erkennen, das die Regression nicht an allen Punkten gleich schnell konvergiert. Dies ist ein häufiges Problem mit vielen Regressionsalgorithmen.

Dieses Beispiel war ein relativ simples Beispiel. Häufig sind sowohl die Dimensionen der Eingangs- als auch der Ausgangsdaten bedeutend höher. Entsprechend länger kann ein Lernprozess durch die höhere Komplexität des Datensatzes dauern.

Hinweise

Wie eben gezeigt, sind neuronale Netze für die Anwendung bei Regressionsproblemen gut geeignet. Es ist jedoch darauf zu achten, dass die Ergebnisse entsprechend genau getestet werden, damit nicht in kritischen Bereichen der Regression Fehler in der Auswertung auftreten und unerkannt bleiben.

Quellen

Footnotes

  1. wikipedia.org

  2. wikipedia.org