16 KiB
Zeitreihenprognose mit Support Vector Regressor
In der vorherigen Lektion hast du gelernt, wie man das ARIMA-Modell zur Vorhersage von Zeitreihen verwendet. Jetzt wirst du das Support Vector Regressor-Modell kennenlernen, ein Regressionsmodell, das zur Vorhersage kontinuierlicher Daten verwendet wird.
Quiz vor der Lektion
Einführung
In dieser Lektion wirst du eine spezifische Methode entdecken, um Modelle mit SVM: Support Vector Machine für Regressionen zu erstellen, oder SVR: Support Vector Regressor.
SVR im Kontext von Zeitreihen 1
Bevor du die Bedeutung von SVR für die Vorhersage von Zeitreihen verstehst, hier einige wichtige Konzepte, die du kennen solltest:
- Regression: Überwachtes Lernverfahren zur Vorhersage kontinuierlicher Werte aus einem gegebenen Satz von Eingaben. Die Idee ist, eine Kurve (oder Linie) im Merkmalsraum zu finden, die die maximale Anzahl von Datenpunkten enthält. Hier klicken für weitere Informationen.
- Support Vector Machine (SVM): Ein Typ von überwachten Machine-Learning-Modellen, die für Klassifikation, Regression und Ausreißererkennung verwendet werden. Das Modell ist eine Hyperebene im Merkmalsraum, die im Fall der Klassifikation als Grenze und im Fall der Regression als Best-Fit-Linie fungiert. In SVM wird häufig eine Kernel-Funktion verwendet, um den Datensatz in einen Raum mit höherer Dimension zu transformieren, sodass sie leichter trennbar sind. Hier klicken für weitere Informationen zu SVMs.
- Support Vector Regressor (SVR): Ein Typ von SVM, der die Best-Fit-Linie (die im Fall von SVM eine Hyperebene ist) findet, die die maximale Anzahl von Datenpunkten enthält.
Warum SVR? 1
In der letzten Lektion hast du ARIMA kennengelernt, ein sehr erfolgreiches statistisches lineares Verfahren zur Vorhersage von Zeitreihendaten. In vielen Fällen weisen Zeitreihendaten jedoch Nichtlinearitäten auf, die von linearen Modellen nicht abgebildet werden können. In solchen Fällen macht die Fähigkeit von SVM, Nichtlinearitäten in den Daten für Regressionsaufgaben zu berücksichtigen, SVR erfolgreich bei der Vorhersage von Zeitreihen.
Übung - Erstelle ein SVR-Modell
Die ersten Schritte zur Datenvorbereitung sind dieselben wie in der vorherigen Lektion über ARIMA.
Öffne den /working-Ordner in dieser Lektion und finde die Datei notebook.ipynb. 2
-
Führe das Notebook aus und importiere die notwendigen Bibliotheken: 2
import sys sys.path.append('../../')
import os import warnings import matplotlib.pyplot as plt import numpy as np import pandas as pd import datetime as dt import math from sklearn.svm import SVR from sklearn.preprocessing import MinMaxScaler from common.utils import load_data, mape
-
Lade die Daten aus der Datei
/data/energy.csv
in ein Pandas-DataFrame und schaue sie dir an: 2energy = load_data('../../data')[['load']]
-
Plotte alle verfügbaren Energiedaten von Januar 2012 bis Dezember 2014: 2
energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12) plt.xlabel('timestamp', fontsize=12) plt.ylabel('load', fontsize=12) plt.show()
Jetzt lass uns unser SVR-Modell erstellen.
Erstelle Trainings- und Testdatensätze
Nachdem deine Daten geladen sind, kannst du sie in Trainings- und Testdatensätze aufteilen. Anschließend formst du die Daten um, um einen zeitbasierten Datensatz zu erstellen, der für das SVR benötigt wird. Du trainierst dein Modell mit dem Trainingsdatensatz. Nachdem das Modell trainiert wurde, bewertest du seine Genauigkeit anhand des Trainingsdatensatzes, des Testdatensatzes und dann des vollständigen Datensatzes, um die Gesamtleistung zu sehen. Du musst sicherstellen, dass der Testdatensatz einen späteren Zeitraum als der Trainingsdatensatz abdeckt, um sicherzustellen, dass das Modell keine Informationen aus zukünftigen Zeiträumen erhält 2 (eine Situation, die als Overfitting bekannt ist).
-
Weise dem Trainingsdatensatz einen Zeitraum von zwei Monaten vom 1. September bis 31. Oktober 2014 zu. Der Testdatensatz umfasst den Zeitraum vom 1. November bis 31. Dezember 2014: 2
train_start_dt = '2014-11-01 00:00:00' test_start_dt = '2014-12-30 00:00:00'
-
Visualisiere die Unterschiede: 2
energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \ .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \ .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12) plt.xlabel('timestamp', fontsize=12) plt.ylabel('load', fontsize=12) plt.show()
Bereite die Daten für das Training vor
Jetzt musst du die Daten für das Training vorbereiten, indem du die Daten filterst und skalierst. Filtere deinen Datensatz, um nur die benötigten Zeiträume und Spalten einzuschließen, und skaliere die Daten, um sicherzustellen, dass sie im Intervall 0,1 liegen.
-
Filtere den ursprünglichen Datensatz, um nur die oben genannten Zeiträume pro Satz und nur die benötigte Spalte 'load' sowie das Datum einzuschließen: 2
train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']] test = energy.copy()[energy.index >= test_start_dt][['load']] print('Training data shape: ', train.shape) print('Test data shape: ', test.shape)
Training data shape: (1416, 1) Test data shape: (48, 1)
-
Skaliere die Trainingsdaten, um sie in den Bereich (0, 1) zu bringen: 2
scaler = MinMaxScaler() train['load'] = scaler.fit_transform(train)
-
Skaliere nun die Testdaten: 2
test['load'] = scaler.transform(test)
Erstelle Daten mit Zeitschritten 1
Für das SVR transformierst du die Eingabedaten in die Form [batch, timesteps]
. Du formst also die vorhandenen train_data
und test_data
so um, dass eine neue Dimension entsteht, die sich auf die Zeitschritte bezieht.
# Converting to numpy arrays
train_data = train.values
test_data = test.values
Für dieses Beispiel nehmen wir timesteps = 5
. Die Eingaben für das Modell sind also die Daten der ersten 4 Zeitschritte, und die Ausgabe sind die Daten des 5. Zeitschritts.
timesteps=5
Umwandlung der Trainingsdaten in einen 2D-Tensor mithilfe von verschachtelten Listenkomprehensionen:
train_data_timesteps=np.array([[j for j in train_data[i:i+timesteps]] for i in range(0,len(train_data)-timesteps+1)])[:,:,0]
train_data_timesteps.shape
(1412, 5)
Umwandlung der Testdaten in einen 2D-Tensor:
test_data_timesteps=np.array([[j for j in test_data[i:i+timesteps]] for i in range(0,len(test_data)-timesteps+1)])[:,:,0]
test_data_timesteps.shape
(44, 5)
Auswahl von Eingaben und Ausgaben aus Trainings- und Testdaten:
x_train, y_train = train_data_timesteps[:,:timesteps-1],train_data_timesteps[:,[timesteps-1]]
x_test, y_test = test_data_timesteps[:,:timesteps-1],test_data_timesteps[:,[timesteps-1]]
print(x_train.shape, y_train.shape)
print(x_test.shape, y_test.shape)
(1412, 4) (1412, 1)
(44, 4) (44, 1)
Implementiere SVR 1
Jetzt ist es an der Zeit, SVR zu implementieren. Um mehr über diese Implementierung zu erfahren, kannst du diese Dokumentation lesen. Für unsere Implementierung folgen wir diesen Schritten:
- Definiere das Modell, indem du
SVR()
aufrufst und die Modell-Hyperparameter übergibst: Kernel, Gamma, C und Epsilon. - Bereite das Modell für die Trainingsdaten vor, indem du die Funktion
fit()
aufrufst. - Erstelle Vorhersagen, indem du die Funktion
predict()
aufrufst.
Jetzt erstellen wir ein SVR-Modell. Hier verwenden wir den RBF-Kernel und setzen die Hyperparameter Gamma, C und Epsilon auf 0,5, 10 bzw. 0,05.
model = SVR(kernel='rbf',gamma=0.5, C=10, epsilon = 0.05)
Trainiere das Modell mit den Trainingsdaten 1
model.fit(x_train, y_train[:,0])
SVR(C=10, cache_size=200, coef0=0.0, degree=3, epsilon=0.05, gamma=0.5,
kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
Erstelle Modellvorhersagen 1
y_train_pred = model.predict(x_train).reshape(-1,1)
y_test_pred = model.predict(x_test).reshape(-1,1)
print(y_train_pred.shape, y_test_pred.shape)
(1412, 1) (44, 1)
Du hast dein SVR erstellt! Jetzt müssen wir es bewerten.
Bewerte dein Modell 1
Für die Bewertung skalieren wir zuerst die Daten zurück auf unsere ursprüngliche Skala. Um die Leistung zu überprüfen, plotten wir die ursprüngliche und vorhergesagte Zeitreihe und geben auch das MAPE-Ergebnis aus.
Skaliere die vorhergesagten und ursprünglichen Ausgaben:
# Scaling the predictions
y_train_pred = scaler.inverse_transform(y_train_pred)
y_test_pred = scaler.inverse_transform(y_test_pred)
print(len(y_train_pred), len(y_test_pred))
# Scaling the original values
y_train = scaler.inverse_transform(y_train)
y_test = scaler.inverse_transform(y_test)
print(len(y_train), len(y_test))
Überprüfe die Modellleistung bei Trainings- und Testdaten 1
Wir extrahieren die Zeitstempel aus dem Datensatz, um sie auf der x-Achse unseres Plots anzuzeigen. Beachte, dass wir die ersten timesteps-1
Werte als Eingabe für die erste Ausgabe verwenden, sodass die Zeitstempel für die Ausgabe danach beginnen.
train_timestamps = energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)].index[timesteps-1:]
test_timestamps = energy[test_start_dt:].index[timesteps-1:]
print(len(train_timestamps), len(test_timestamps))
1412 44
Plotte die Vorhersagen für die Trainingsdaten:
plt.figure(figsize=(25,6))
plt.plot(train_timestamps, y_train, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(train_timestamps, y_train_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.title("Training data prediction")
plt.show()
Gib MAPE für die Trainingsdaten aus:
print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')
MAPE for training data: 1.7195710200875551 %
Plotte die Vorhersagen für die Testdaten:
plt.figure(figsize=(10,3))
plt.plot(test_timestamps, y_test, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(test_timestamps, y_test_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.show()
Gib MAPE für die Testdaten aus:
print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')
MAPE for testing data: 1.2623790187854018 %
🏆 Du hast ein sehr gutes Ergebnis auf dem Testdatensatz!
Überprüfe die Modellleistung auf dem vollständigen Datensatz 1
# Extracting load values as numpy array
data = energy.copy().values
# Scaling
data = scaler.transform(data)
# Transforming to 2D tensor as per model input requirement
data_timesteps=np.array([[j for j in data[i:i+timesteps]] for i in range(0,len(data)-timesteps+1)])[:,:,0]
print("Tensor shape: ", data_timesteps.shape)
# Selecting inputs and outputs from data
X, Y = data_timesteps[:,:timesteps-1],data_timesteps[:,[timesteps-1]]
print("X shape: ", X.shape,"\nY shape: ", Y.shape)
Tensor shape: (26300, 5)
X shape: (26300, 4)
Y shape: (26300, 1)
# Make model predictions
Y_pred = model.predict(X).reshape(-1,1)
# Inverse scale and reshape
Y_pred = scaler.inverse_transform(Y_pred)
Y = scaler.inverse_transform(Y)
plt.figure(figsize=(30,8))
plt.plot(Y, color = 'red', linewidth=2.0, alpha = 0.6)
plt.plot(Y_pred, color = 'blue', linewidth=0.8)
plt.legend(['Actual','Predicted'])
plt.xlabel('Timestamp')
plt.show()
print('MAPE: ', mape(Y_pred, Y)*100, '%')
MAPE: 2.0572089029888656 %
🏆 Sehr schöne Plots, die ein Modell mit guter Genauigkeit zeigen. Gut gemacht!
🚀Herausforderung
- Versuche, die Hyperparameter (Gamma, C, Epsilon) beim Erstellen des Modells anzupassen und die Daten zu bewerten, um herauszufinden, welche Hyperparameter die besten Ergebnisse auf den Testdaten liefern. Weitere Informationen zu diesen Hyperparametern findest du in der Dokumentation hier.
- Versuche, verschiedene Kernel-Funktionen für das Modell zu verwenden und analysiere deren Leistung auf dem Datensatz. Eine hilfreiche Dokumentation findest du hier.
- Versuche, verschiedene Werte für
timesteps
zu verwenden, damit das Modell zurückblicken kann, um Vorhersagen zu treffen.
Quiz nach der Lektion
Rückblick & Selbststudium
Diese Lektion sollte die Anwendung von SVR für die Zeitreihenprognose einführen. Um mehr über SVR zu erfahren, kannst du diesen Blog lesen. Diese Dokumentation zu scikit-learn bietet eine umfassendere Erklärung zu SVMs im Allgemeinen, SVRs und auch andere Implementierungsdetails wie die verschiedenen Kernel-Funktionen, die verwendet werden können, und deren Parameter.
Aufgabe
Credits
Haftungsausschluss:
Dieses Dokument wurde mit dem KI-Übersetzungsdienst Co-op Translator übersetzt. Obwohl wir uns um Genauigkeit bemühen, weisen wir darauf hin, dass automatisierte Übersetzungen Fehler oder Ungenauigkeiten enthalten können. Das Originaldokument in seiner ursprünglichen Sprache sollte als maßgebliche Quelle betrachtet werden. Für kritische Informationen wird eine professionelle menschliche Übersetzung empfohlen. Wir übernehmen keine Haftung für Missverständnisse oder Fehlinterpretationen, die aus der Nutzung dieser Übersetzung entstehen.
-
Der Text, Code und die Ausgabe in diesem Abschnitt wurden von @AnirbanMukherjeeXD beigetragen. ↩︎
-
Der Text, Code und die Ausgabe in diesem Abschnitt wurden aus ARIMA übernommen. ↩︎