You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
393 lines
15 KiB
393 lines
15 KiB
<!--
|
|
CO_OP_TRANSLATOR_METADATA:
|
|
{
|
|
"original_hash": "482bccabe1df958496ea71a3667995cd",
|
|
"translation_date": "2025-09-04T23:54:49+00:00",
|
|
"source_file": "7-TimeSeries/3-SVR/README.md",
|
|
"language_code": "da"
|
|
}
|
|
-->
|
|
# Tidsserieforudsigelse med Support Vector Regressor
|
|
|
|
I den forrige lektion lærte du, hvordan man bruger ARIMA-modellen til at lave tidsserieforudsigelser. Nu skal du se på Support Vector Regressor-modellen, som er en regressionsmodel, der bruges til at forudsige kontinuerlige data.
|
|
|
|
## [Quiz før lektionen](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
## Introduktion
|
|
|
|
I denne lektion vil du opdage en specifik måde at bygge modeller med [**SVM**: **S**upport **V**ector **M**achine](https://en.wikipedia.org/wiki/Support-vector_machine) til regression, eller **SVR: Support Vector Regressor**.
|
|
|
|
### SVR i konteksten af tidsserier [^1]
|
|
|
|
Før du forstår vigtigheden af SVR i tidsserieforudsigelse, er her nogle af de vigtige begreber, du skal kende:
|
|
|
|
- **Regression:** En superviseret læringsteknik til at forudsige kontinuerlige værdier ud fra et givet sæt input. Ideen er at tilpasse en kurve (eller linje) i funktionsrummet, der har det maksimale antal datapunkter. [Klik her](https://en.wikipedia.org/wiki/Regression_analysis) for mere information.
|
|
- **Support Vector Machine (SVM):** En type superviseret maskinlæringsmodel, der bruges til klassifikation, regression og detektion af outliers. Modellen er et hyperplan i funktionsrummet, som i tilfælde af klassifikation fungerer som en grænse, og i tilfælde af regression fungerer som den bedst tilpassede linje. I SVM bruges en Kernel-funktion generelt til at transformere datasættet til et rum med et højere antal dimensioner, så de kan adskilles lettere. [Klik her](https://en.wikipedia.org/wiki/Support-vector_machine) for mere information om SVM'er.
|
|
- **Support Vector Regressor (SVR):** En type SVM, der finder den bedst tilpassede linje (som i SVM er et hyperplan), der har det maksimale antal datapunkter.
|
|
|
|
### Hvorfor SVR? [^1]
|
|
|
|
I den sidste lektion lærte du om ARIMA, som er en meget succesfuld statistisk lineær metode til at forudsige tidsseriedata. Men i mange tilfælde har tidsseriedata *ikke-linearitet*, som ikke kan kortlægges af lineære modeller. I sådanne tilfælde gør SVM's evne til at tage højde for ikke-linearitet i data til regression SVR succesfuld i tidsserieforudsigelse.
|
|
|
|
## Øvelse - byg en SVR-model
|
|
|
|
De første trin til datapreparation er de samme som i den forrige lektion om [ARIMA](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/2-ARIMA).
|
|
|
|
Åbn mappen [_/working_](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/3-SVR/working) i denne lektion og find filen [_notebook.ipynb_](https://github.com/microsoft/ML-For-Beginners/blob/main/7-TimeSeries/3-SVR/working/notebook.ipynb). [^2]
|
|
|
|
1. Kør notebooken og importer de nødvendige biblioteker: [^2]
|
|
|
|
```python
|
|
import sys
|
|
sys.path.append('../../')
|
|
```
|
|
|
|
```python
|
|
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
|
|
```
|
|
|
|
2. Indlæs data fra filen `/data/energy.csv` til en Pandas dataframe og kig på dem: [^2]
|
|
|
|
```python
|
|
energy = load_data('../../data')[['load']]
|
|
```
|
|
|
|
3. Plot alle de tilgængelige energidata fra januar 2012 til december 2014: [^2]
|
|
|
|
```python
|
|
energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12)
|
|
plt.xlabel('timestamp', fontsize=12)
|
|
plt.ylabel('load', fontsize=12)
|
|
plt.show()
|
|
```
|
|
|
|

|
|
|
|
Nu skal vi bygge vores SVR-model.
|
|
|
|
### Opret trænings- og testdatasæt
|
|
|
|
Nu er dine data indlæst, så du kan opdele dem i trænings- og testdatasæt. Derefter skal du omforme dataene for at skabe et tidsbaseret datasæt, som vil være nødvendigt for SVR. Du træner din model på træningssættet. Når modellen er færdig med at træne, evaluerer du dens nøjagtighed på træningssættet, testsættet og derefter det fulde datasæt for at se den samlede ydeevne. Du skal sikre dig, at testsættet dækker en senere periode end træningssættet for at sikre, at modellen ikke får information fra fremtidige tidsperioder [^2] (en situation kendt som *overfitting*).
|
|
|
|
1. Tildel en to-måneders periode fra 1. september til 31. oktober 2014 til træningssættet. Testsættet vil inkludere to-måneders perioden fra 1. november til 31. december 2014: [^2]
|
|
|
|
```python
|
|
train_start_dt = '2014-11-01 00:00:00'
|
|
test_start_dt = '2014-12-30 00:00:00'
|
|
```
|
|
|
|
2. Visualiser forskellene: [^2]
|
|
|
|
```python
|
|
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()
|
|
```
|
|
|
|

|
|
|
|
### Forbered dataene til træning
|
|
|
|
Nu skal du forberede dataene til træning ved at udføre filtrering og skalering af dine data. Filtrer dit datasæt, så det kun inkluderer de tidsperioder og kolonner, du har brug for, og skaler dataene for at sikre, at de projiceres i intervallet 0,1.
|
|
|
|
1. Filtrer det originale datasæt, så det kun inkluderer de nævnte tidsperioder pr. sæt og kun inkluderer den nødvendige kolonne 'load' plus datoen: [^2]
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
```output
|
|
Training data shape: (1416, 1)
|
|
Test data shape: (48, 1)
|
|
```
|
|
|
|
2. Skaler træningsdataene til at være i intervallet (0, 1): [^2]
|
|
|
|
```python
|
|
scaler = MinMaxScaler()
|
|
train['load'] = scaler.fit_transform(train)
|
|
```
|
|
|
|
4. Skaler nu testdataene: [^2]
|
|
|
|
```python
|
|
test['load'] = scaler.transform(test)
|
|
```
|
|
|
|
### Opret data med tidssteg [^1]
|
|
|
|
For SVR transformerer du inputdataene til formen `[batch, timesteps]`. Så du omformer de eksisterende `train_data` og `test_data`, så der er en ny dimension, der refererer til tidsstegene.
|
|
|
|
```python
|
|
# Converting to numpy arrays
|
|
train_data = train.values
|
|
test_data = test.values
|
|
```
|
|
|
|
I dette eksempel tager vi `timesteps = 5`. Så input til modellen er dataene for de første 4 tidssteg, og output vil være dataene for det 5. tidssteg.
|
|
|
|
```python
|
|
timesteps=5
|
|
```
|
|
|
|
Konvertering af træningsdata til 2D tensor ved hjælp af nested list comprehension:
|
|
|
|
```python
|
|
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
|
|
```
|
|
|
|
```output
|
|
(1412, 5)
|
|
```
|
|
|
|
Konvertering af testdata til 2D tensor:
|
|
|
|
```python
|
|
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
|
|
```
|
|
|
|
```output
|
|
(44, 5)
|
|
```
|
|
|
|
Udvælgelse af input og output fra trænings- og testdata:
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
```output
|
|
(1412, 4) (1412, 1)
|
|
(44, 4) (44, 1)
|
|
```
|
|
|
|
### Implementer SVR [^1]
|
|
|
|
Nu er det tid til at implementere SVR. For at læse mere om denne implementering kan du referere til [denne dokumentation](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVR.html). For vores implementering følger vi disse trin:
|
|
|
|
1. Definer modellen ved at kalde `SVR()` og angive modelhyperparametrene: kernel, gamma, c og epsilon
|
|
2. Forbered modellen til træningsdataene ved at kalde funktionen `fit()`
|
|
3. Lav forudsigelser ved at kalde funktionen `predict()`
|
|
|
|
Nu opretter vi en SVR-model. Her bruger vi [RBF kernel](https://scikit-learn.org/stable/modules/svm.html#parameters-of-the-rbf-kernel) og sætter hyperparametrene gamma, C og epsilon til henholdsvis 0.5, 10 og 0.05.
|
|
|
|
```python
|
|
model = SVR(kernel='rbf',gamma=0.5, C=10, epsilon = 0.05)
|
|
```
|
|
|
|
#### Tilpas modellen til træningsdata [^1]
|
|
|
|
```python
|
|
model.fit(x_train, y_train[:,0])
|
|
```
|
|
|
|
```output
|
|
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)
|
|
```
|
|
|
|
#### Lav model-forudsigelser [^1]
|
|
|
|
```python
|
|
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)
|
|
```
|
|
|
|
```output
|
|
(1412, 1) (44, 1)
|
|
```
|
|
|
|
Du har bygget din SVR! Nu skal vi evaluere den.
|
|
|
|
### Evaluer din model [^1]
|
|
|
|
For evaluering skal vi først skalere dataene tilbage til vores originale skala. Derefter, for at kontrollere ydeevnen, vil vi plotte den originale og forudsagte tidsserie og også udskrive MAPE-resultatet.
|
|
|
|
Skaler det forudsagte og originale output:
|
|
|
|
```python
|
|
# 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))
|
|
```
|
|
|
|
```python
|
|
# 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))
|
|
```
|
|
|
|
#### Kontroller modelens ydeevne på trænings- og testdata [^1]
|
|
|
|
Vi udtrækker tidsstemplerne fra datasættet for at vise dem på x-aksen i vores plot. Bemærk, at vi bruger de første ```timesteps-1``` værdier som input til det første output, så tidsstemplerne for output vil starte derefter.
|
|
|
|
```python
|
|
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))
|
|
```
|
|
|
|
```output
|
|
1412 44
|
|
```
|
|
|
|
Plot forudsigelserne for træningsdata:
|
|
|
|
```python
|
|
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()
|
|
```
|
|
|
|

|
|
|
|
Udskriv MAPE for træningsdata
|
|
|
|
```python
|
|
print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')
|
|
```
|
|
|
|
```output
|
|
MAPE for training data: 1.7195710200875551 %
|
|
```
|
|
|
|
Plot forudsigelserne for testdata
|
|
|
|
```python
|
|
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()
|
|
```
|
|
|
|

|
|
|
|
Udskriv MAPE for testdata
|
|
|
|
```python
|
|
print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')
|
|
```
|
|
|
|
```output
|
|
MAPE for testing data: 1.2623790187854018 %
|
|
```
|
|
|
|
🏆 Du har et meget godt resultat på testdatasættet!
|
|
|
|
### Kontroller modelens ydeevne på det fulde datasæt [^1]
|
|
|
|
```python
|
|
# 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)
|
|
```
|
|
|
|
```output
|
|
Tensor shape: (26300, 5)
|
|
X shape: (26300, 4)
|
|
Y shape: (26300, 1)
|
|
```
|
|
|
|
```python
|
|
# 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)
|
|
```
|
|
|
|
```python
|
|
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()
|
|
```
|
|
|
|

|
|
|
|
```python
|
|
print('MAPE: ', mape(Y_pred, Y)*100, '%')
|
|
```
|
|
|
|
```output
|
|
MAPE: 2.0572089029888656 %
|
|
```
|
|
|
|
🏆 Meget flotte plots, der viser en model med god nøjagtighed. Godt arbejde!
|
|
|
|
---
|
|
|
|
## 🚀Udfordring
|
|
|
|
- Prøv at justere hyperparametrene (gamma, C, epsilon) under oprettelsen af modellen og evaluer på dataene for at se, hvilket sæt hyperparametre giver de bedste resultater på testdataene. For at lære mere om disse hyperparametre kan du referere til dokumentet [her](https://scikit-learn.org/stable/modules/svm.html#parameters-of-the-rbf-kernel).
|
|
- Prøv at bruge forskellige kernel-funktioner til modellen og analyser deres ydeevne på datasættet. Et nyttigt dokument kan findes [her](https://scikit-learn.org/stable/modules/svm.html#kernel-functions).
|
|
- Prøv at bruge forskellige værdier for `timesteps` for modellen til at kigge tilbage for at lave forudsigelser.
|
|
|
|
## [Quiz efter lektionen](https://ff-quizzes.netlify.app/en/ml/)
|
|
|
|
## Gennemgang & Selvstudie
|
|
|
|
Denne lektion introducerede anvendelsen af SVR til tidsserieforudsigelse. For at læse mere om SVR kan du referere til [denne blog](https://www.analyticsvidhya.com/blog/2020/03/support-vector-regression-tutorial-for-machine-learning/). Denne [dokumentation om scikit-learn](https://scikit-learn.org/stable/modules/svm.html) giver en mere omfattende forklaring om SVM'er generelt, [SVR'er](https://scikit-learn.org/stable/modules/svm.html#regression) og også andre implementeringsdetaljer såsom de forskellige [kernel-funktioner](https://scikit-learn.org/stable/modules/svm.html#kernel-functions), der kan bruges, og deres parametre.
|
|
|
|
## Opgave
|
|
|
|
[En ny SVR-model](assignment.md)
|
|
|
|
## Credits
|
|
|
|
[^1]: Teksten, koden og output i dette afsnit blev bidraget af [@AnirbanMukherjeeXD](https://github.com/AnirbanMukherjeeXD)
|
|
[^2]: Teksten, koden og output i dette afsnit blev taget fra [ARIMA](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/2-ARIMA)
|
|
|
|
---
|
|
|
|
**Ansvarsfraskrivelse**:
|
|
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten [Co-op Translator](https://github.com/Azure/co-op-translator). Selvom vi bestræber os på nøjagtighed, skal du være opmærksom på, at automatiserede oversættelser kan indeholde fejl eller unøjagtigheder. Det originale dokument på dets oprindelige sprog bør betragtes som den autoritative kilde. For kritisk information anbefales professionel menneskelig oversættelse. Vi påtager os ikke ansvar for eventuelle misforståelser eller fejltolkninger, der opstår som følge af brugen af denne oversættelse. |