angle-uparrow-clockwisearrow-counterclockwisearrow-down-uparrow-leftatcalendarcard-listchatcheckenvelopefolderhouseinfo-circlepencilpeoplepersonperson-fillperson-plusphoneplusquestion-circlesearchtagtrashx

Vorhersage von Werten mit Deep Learning und Keras

Mit Keras können wir eine Deep Learning Black Box erstellen, die zukünftige Werte vorhersagen kann

28 Januar 2022
post main image

Ich habe einen Datensatz, viele Zeilen mit N Eingaben und 1 Ausgabe, und möchte den Ausgabewert für jede neue Kombination von Eingabewerten vorhersagen. Ich bin auch ein Noob in Sachen Datenwissenschaft, aber die Geschichten im Internet über Deep Learning legen nahe, dass wir ganz einfach eine Art Blackbox mit einigen Neuronen, Knoten, darin erstellen und dann den Datensatz zum Trainieren der Blackbox verwenden können. Danach können wir beliebige Eingaben machen und unsere Blackbox liefert uns Ausgabewerte mit einer gewissen Fehlerspanne. Klingt zu schön, um wahr zu sein? Ist es wirklich so einfach?

Beginnen Sie mit KISS (Keep It Simple Stupid)

Wenn Sie im Internet nach "python data prediction" suchen, erhalten Sie natürlich eine Menge Treffer. Es gibt viele Beispiele, die mir gefallen, aber die meisten sind viel zu komplex für einen Anfänger. Aktienkurse anhand von Zeitreihen vorhersagen, zu komplex. Hauspreise vorhersagen, viel besser. Es gibt auch einen Datensatz zur Weinqualität. Ich mag Wein. kann gut sein, vielleicht ein anderes Mal.

In diesem Beitrag versuche ich, ein triviales Problem zu lösen. Ich ersetze die Funktion:

y = x0 + 2*x1

durch:

  • ein lineares Regressionsmodell, und,
  • ein Deep Learning, in der Tat ein neuronales Netz, eine Black Box

Ein großer Vorteil ist, dass ich den Datensatz selbst erstellen kann. Das bedeutet auch, dass ich die Vorhersagen mit den erwarteten Werten vergleichen kann.

Machine Learning: Regression vs. Klassifizierung

Um den richtigen Algorithmus zu wählen, ist es zunächst wichtig zu verstehen, ob es sich bei der Aufgabe Machine Learning um ein Regressions- oder ein Klassifikationsproblem handelt. Regression und Klassifizierung sind beides Arten von Supervised Machine Learning -Algorithmen. Supervised Machine Learning verwendet das Konzept der Verwendung von Datensätzen mit bekannten Ausgabewerten, um Vorhersagen zu treffen.

Die Regression ist ein Algorithmus, der mit einem Datensatz trainiert werden kann, um numerische Ausgabewerte, also Zahlen, vorherzusagen. Classification ist ein Algorithmus, der mit einem Datensatz trainiert werden kann, um Ausgaben vorherzusagen, bei denen es sich um Bezeichnungen, Kategorien, normalerweise 0 und 1, handelt.

Beispiel für Regression

Wir haben einen Datensatz, der aus Zeilen mit 2 Eingaben und einer Ausgabe von 1 besteht, wobei der Ausgabewert eine Zahl ist, die "jeden" Wert haben kann. Betrachten wir einen Datensatz für ein Haus, bei dem die Eingaben die Anzahl der Personen, die in dem Haus wohnen können, und die Anzahl der Zimmer sind, und die Ausgabe der Preis ist.

 persons | rooms | price
---------+-------+--------
  5      |  4    | 20.000
  3      |  2    | 24.000

Wenn wir einen ausreichend großen Datensatz haben, können wir einen Regressionsalgorithmus verwenden, um den Preis für jede Kombination von Personen und Zimmern vorherzusagen. Die Ausgabe ist dann 22.500, 18.100 usw.

Beispiel Classification

Wir haben einen Datensatz, der aus Zeilen mit 3 Eingaben und einer Ausgabe von 1 besteht. Der Ausgabewert ist eine Zahl, die 0 oder 1 ist. Die Eingaben sind die Anzahl der Personen, die in dem Haus wohnen können, die Anzahl der Zimmer und der Preis, und die Ausgabe ist 0 oder 1, je nachdem, ob das Haus von Personen, die auf einer Website nach einem Haus suchen, bevorzugt wird.

 persons | rooms | price   | liked
---------+-------+---------+--------
  5      |  4    | 20.000  | 0
  3      |  2    | 24.000  | 1

Wenn wir einen ausreichend großen Datensatz haben, können wir einen Klassifizierungsalgorithmus verwenden, um vorherzusagen, ob ein Haus für eine beliebige Kombination von Personen, Zimmern und Preis beliebt ist. Die Ausgabe ist dann 0 (nicht beliebt) oder 1 (beliebt).

Unteranpassung und Überanpassung

Unser Datensatz wird in einen Trainingsdatensatz und einen Testdatensatz aufgeteilt. Anhand dieser Daten können wir feststellen, wie gut oder schlecht unser Modell oder Algorithmus abschneidet.

Underfitting bedeutet, dass das Modell nicht in der Lage war, die relevanten Beziehungen zwischen den Daten zu bestimmen. Wahrscheinlich ist das Modell zu einfach. Ein Beispiel ist der Versuch, nichtlineare Beziehungen mit einem linearen Modell darzustellen.

Unteranpassung:

  • Funktioniert schlecht mit Trainingsdaten
  • Funktioniert schlecht mit Testdaten

Überanpassung bedeutet, dass das Modell auch Beziehungen zwischen Daten und zufälligen Schwankungen ermittelt. Wahrscheinlich ist das Modell zu komplex, es lernt zu gut.

Überanpassung:

  • Funktioniert gut mit Trainingsdaten
  • Funktioniert schlecht mit Testdaten

Beide Fälle können auch auftreten, wenn nicht genügend Daten in unserem Datensatz vorhanden sind.

Lineare Regression

Ich schlage vor, dass Sie die Beispiele in dem großartigen Tutorial 'Linear Regression in Python' durchlesen, siehe Links unten. Im Folgenden zeige ich meine Version mit zwei Eingaben, Trainings- und Testdaten und der Vorhersage eines Wertes. Da wir mit linearer Regression modellieren, ist es nicht überraschend, dass das Bestimmtheitsmaß 1,0 beträgt und wir nur eine sehr kleine Menge an Trainingsdaten benötigen.

# Linear regression: y = x0 + 2*x1
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

# generate dataset
X_items = []
y_items = []
for x0 in range(0, 3):
    for x1 in range(3, 5):
        y = x0 + 2*x1
        X_items.append([x0, x1])
        y_items.append(y)

X = np.array(X_items).reshape((-1, 2))
y = np.array(y_items)
print('X = {}'.format(X))
print('y = {}'.format(y))

# split dataset in training and test data
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
print('X_train = {}'.format(X_train))
print('y_train = {}'.format(y_train))
print('X_test = {}'.format(X_test))
print('y_test = {}'.format(y_test))

# create model
model = LinearRegression()

# mess up a training value
#X_train[0][0] += 2

# calculate optimal values of weights b0 and b1
model.fit(X_train, y_train)

# show results, mess up test data
print('model result:')
print('- intercept (b0) = {}'.format(model.intercept_))
print('- slope (b1) = {}'.format(model.coef_))
print('- coefficient of determination for training data = {}'.
    format(model.score(X_train, y_train)))
print('- coefficient of determination for test data = {}'.
    format(model.score(X_test, y_test)))

x = np.array([8, 9]).reshape((-1, 2))
y_pred = model.predict(x)
print('predicted response for x = {}: {}'.format(x, y_pred))

Das Skript liefert die folgende Ausgabe:

X = [[0 3]
 [0 4]
 [1 3]
 [1 4]
 [2 3]
 [2 4]]
y = [ 6  8  7  9  8 10]
X_train = [[2 3]
 [0 3]
 [1 4]
 [2 4]]
y_train = [ 8  6  9 10]
X_test = [[1 3]
 [0 4]]
y_test = [7 8]
model result:
- intercept (b0) = -3.552713678800501e-15
- slope (b1) = [1. 2.]
- coefficient of determination for training data = 1.0
- coefficient of determination for test data = 1.0
predicted response for x = [[8 9]]: [26.]

Um ein wenig Unruhe zu stiften, habe ich einen Trainingswert geändert, siehe oben. Dies ergibt das Ergebnis:

model result:
- intercept (b0) = -2.3529411764705817
- slope (b1) = [0.52941176 2.76470588]
- coefficient of determination for training data = 0.9865546218487395
- coefficient of determination for test data = -0.5570934256055304
predicted response for x = [[8 9]]: [26.76470588]

Wenn wir mehr Trainingsdaten hinzufügen, erhalten wir eine bessere Anpassung.

Deep Learning mit Keras

Dies sollte eher dem Blackbox-Ansatz entsprechen. Ich füge einfach ein paar Neuronen und Schichten hinzu und das sollte alles sein. Aber ist es das wirklich? Hier verwende ich Keras, weil es sehr populär zu sein scheint. Das folgende Beispiel war sehr hilfreich: 'Keras 101: A simple (and interpretable) Neural Network model for House Pricing regression', siehe Links unten. Die Darstellung des Verlusts und des mittleren Durchschnittsfehlers war sehr sinnvoll.

Wir werden die folgenden Schritte durchführen:

  • Laden der Daten
  • Definieren des Modells
  • Kompilieren des Modells
  • Trainieren (Anpassen) des Modells
  • Auswerten des Modells
  • Vorhersagen machen

Laden der Daten Hier erzeugen wir die Daten selbst, siehe auch oben.

Definieren des Modells Die erste dichte Schicht benötigt den Parametersatz input_shape . Ich habe mit 100 Neuronen in der ersten Schicht, 50 in der zweiten Schicht und 25 in der dritten Schicht begonnen. Und warum? Ich habe keine Ahnung, ich habe mir das noch nicht angesehen.

Kompilieren des Modells Dazu gibt es nicht viel zu sagen.

Trainieren (Anpassen) des Modells Wir verwenden den Parameter validation_split, ohne ihn können wir nicht plotten. Wenn validation_split angegeben ist, wird ein Teil der Trainingsdaten für die Validierung verwendet. Die für die Validierung verwendeten Daten können sich während der Anpassung ändern. Es ist wahrscheinlich besser, feste Daten zu verwenden, da wir sonst jedes Mal eine andere Anpassung erhalten.

Evaluieren des Modells Hier werden die Testdaten verwendet.

Vorhersagen Verwenden Sie einfach model.predict().

Natürlich brauchen wir hier mehr Trainingsdaten. Aber auch nicht wirklich viel mehr. Ich habe auch Code zum Speichern und Laden des Modells hinzugefügt. Unten ist der Code, den ich erstellt habe.

# Keras deep learning: y = x0 + 2*x1
from keras.models import Sequential, load_model
from keras.layers import Dense
import numpy as np
from plotly.subplots import make_subplots
import plotly.graph_objects as go
from sklearn.model_selection import train_test_split

use_saved_model = False
#use_saved_model = True

# create dataset
def fx(x0, x1):
    return x0 + 2*x1

X_items = []
y_items = []
for x0 in range(0, 18, 3):
    for x1 in range(2, 27, 3):
        y = fx(x0, x1)
        X_items.append([x0, x1])
        y_items.append(y)

X = np.array(X_items).reshape((-1, 2))
y = np.array(y_items)
print('X = {}'.format(X))
print('y = {}'.format(y))
X_data_shape = X.shape
print('X_data_shape = {}'.format(X_data_shape))

class DLM:
    
    def __init__(
        self,
        model_name='default_model',
    ):
        self.model_name = model_name
        self.dense_input_shape=(2, )
        self.dense_neurons = [100, 50, 25]
        self.fit_params = {
            'epochs': 100, 
            'validation_split': 0.1, 
            'verbose': 0,
        }

    def data_split_train_test(
        self,
        X,
        y,
    ):
        self.X_train, self.X_test, self.y_train, self.y_test = train_test_split(X, y, test_size=0.3, random_state=1)
        print('self.X_train = {}'.format(self.X_train))
        print('self.X_test = {}'.format(self.X_test))
        print('self.y_train = {}'.format(self.y_train))
        print('self.y_test = {}'.format(self.y_test))

        print('training data row count = {}'.format(len(self.y_train)))
        print('test data row count = {}'.format(len(self.y_test)))

        X_train_data_shape = self.X_train.shape
        print('X_train_data_shape = {}'.format(X_train_data_shape))

    def get_model(
        self,
    ):
        self.model = Sequential()
        self.model.add(Dense(self.dense_neurons[0], input_shape=self.dense_input_shape, activation='relu', name='dense_input'))
        for i, n in enumerate(self.dense_neurons[1:]):
            self.model.add(Dense(n, activation='relu', name='dense_hidden_' + str(i)))
        self.model.add(Dense(1, activation='linear', name='dense_output'))
        self.model.compile(optimizer='adam', loss='mse', metrics=['mean_absolute_error'])
        self.model_summary()
        return self.model

    def model_summary(
        self,
    ):
        self.model.summary()

    def train(
        self, 
        model,
        plot=False,
    ):
        history = model.fit(self.X_train, self.y_train, **self.fit_params)

        if plot:

            fig = go.Figure()
            fig.add_trace(go.Scattergl(y=history.history['loss'], name='Train'))
            fig.add_trace(go.Scattergl(y=history.history['val_loss'], name='Valid'))
            fig.update_layout(height=500, width=700, xaxis_title='Epoch', yaxis_title='Loss')
            fig.show()

            fig = go.Figure()
            fig.add_trace(go.Scattergl(y=history.history['mean_absolute_error'], name='Train'))
            fig.add_trace(go.Scattergl(y=history.history['val_mean_absolute_error'], name='Valid'))
            fig.update_layout(height=500, width=700, xaxis_title='Epoch', yaxis_title='Mean Absolute Error')
            fig.show() 

        return history

    def evaluate(
        self, 
        model,
    ):
        mse_nn, mae_nn = model.evaluate(self.X_test, self.y_test)
        print('Mean squared error on test data: ', mse_nn)
        print('Mean absolute error on test data: ', mae_nn)
        return mse_nn, mae_nn

    def predict(
        self,
        model,
        x0,
        x1,
        fx=None,
    ):
        x = np.array([[x0, x1]]).reshape((-1, 2))
        predictions = model.predict(x)
        expected = ''
        if fx is not None:
            expected = ', expected = {}'.format(fx(x0, x1))
        print('for x = {}, predictions = {}{}'.format(x, predictions, expected))
        return predictions

    def save_model(
        self,
        model,
    ):
        model.save(self.model_name)

    def load_saved_model(
        self,
    ):
        self.model = load_model(self.model_name)
        return self.model

# create & save or used saved
dlm = DLM()
if use_saved_model:
    model = dlm.load_saved_model()    
else:
    dlm.data_split_train_test(X, y)
    model = dlm.get_model()
    dlm.train(model, plot=True)
    dlm.evaluate(model)
    dlm.save_model(model)

# predict
dlm.predict(model, 4, 17, fx=fx)
dlm.predict(model, 23, 79, fx=fx)
dlm.predict(model, 40, 33, fx=fx)

Das Skript liefert die folgende Ausgabe, ohne die Eingabedaten:

training data row count = 37
test data row count = 17
X_train_data_shape = (37, 2)
2022-01-28 16:00:30.598860: W tensorflow/stream_executor/platform/default/dso_loader.cc:64] Could not load dynamic library 'libcuda.so.1'; dlerror: libcuda.so.1: cannot open shared object file: No such file or directory
2022-01-28 16:00:30.598886: W tensorflow/stream_executor/cuda/cuda_driver.cc:269] failed call to cuInit: UNKNOWN ERROR (303)
2022-01-28 16:00:30.598911: I tensorflow/stream_executor/cuda/cuda_diagnostics.cc:156] kernel driver does not appear to be running on this host (myra): /proc/driver/nvidia/version does not exist
2022-01-28 16:00:30.599110: I tensorflow/core/platform/cpu_feature_guard.cc:151] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 dense_input (Dense)         (None, 100)               300       
                                                                 
 dense_hidden_0 (Dense)      (None, 50)                5050      
                                                                 
 dense_hidden_1 (Dense)      (None, 25)                1275      
                                                                 
 dense_output (Dense)        (None, 1)                 26        
                                                                 
=================================================================
Total params: 6,651
Trainable params: 6,651
Non-trainable params: 0
_________________________________________________________________
1/1 [==============================] - 0s 25ms/step - loss: 0.1018 - mean_absolute_error: 0.2752
Mean squared error on test data:  0.10178931057453156
Mean absolute error on test data:  0.27519676089286804
2022-01-28 16:00:33.549267: W tensorflow/python/util/util.cc:368] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
for x = [[ 4 17]], predictions = [[38.0433]], expected = 38
for x = [[23 79]], predictions = [[177.94098]], expected = 181
for x = [[40 33]], predictions = [[103.54724]], expected = 106

Verbesserung der Leistung von Deep Learning

Während ich diesen Beitrag schrieb, änderte ich die Anzahl der Neuronen, die dichten Schichten und den Parameter validation_split. All das führte zu einigen Änderungen, manchmal gut, manchmal schlecht. Die größte Verbesserung besteht zweifellos darin, mehr Trainingsdaten hinzuzufügen, aber wie viel ist genug?

Zusammenfassung

Das Wichtigste, was ich gelernt habe, ist, dass Deep Learning einen großen Datensatz benötigt, je größer, desto besser. Mag ich die Blackbox? Ja, und bisher habe ich noch nicht wirklich hineingeschaut. Ich kann das jetzt als Ausgangspunkt für einige Projekte in der realen Welt verwenden. Es gibt auch Dinge wie die Normalisierung der Eingaben, das Hinzufügen von Gewichten zu den Eingaben. Viel mehr zu lesen ...

Links / Impressum

How to find the value for Keras input_shape/input_dim?
https://www.machinecurve.com/index.php/2020/04/05/how-to-find-the-value-for-keras-input_shape-input_dim

Keras 101: A simple (and interpretable) Neural Network model for House Pricing regression
https://towardsdatascience.com/keras-101-a-simple-and-interpretable-neural-network-model-for-house-pricing-regression-31b1a77f05ae

Keras examples
https://keras.io/examples

Linear Regression in Python
https://realpython.com/linear-regression-in-python

Predictive Analysis in Python
https://medium.com/my-data-camp-journey/predictive-analysis-in-python-97ca5b64e97f

Regression Tutorial with the Keras Deep Learning Library in Python
https://machinelearningmastery.com/regression-tutorial-keras-deep-learning-library-python

Einen Kommentar hinterlassen

Kommentieren Sie anonym oder melden Sie sich zum Kommentieren an.

Kommentare

Eine Antwort hinterlassen

Antworten Sie anonym oder melden Sie sich an, um zu antworten.