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.
ML-For-Beginners/translations/da/7-TimeSeries/3-SVR/README.md

15 KiB

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

Introduktion

I denne lektion vil du opdage en specifik måde at bygge modeller med SVM: 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 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 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.

Åbn mappen /working i denne lektion og find filen notebook.ipynb. 2

  1. Kør notebooken og importer de nødvendige biblioteker: 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
    
  2. Indlæs data fra filen /data/energy.csv til en Pandas dataframe og kig på dem: 2

    energy = load_data('../../data')[['load']]
    
  3. Plot alle de tilgængelige energidata fra januar 2012 til december 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()
    

    fulde data

    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

    train_start_dt = '2014-11-01 00:00:00'
    test_start_dt = '2014-12-30 00:00:00'
    
  2. Visualiser forskellene: 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()
    

    trænings- og testdata

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

    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)
    
  2. Skaler træningsdataene til at være i intervallet (0, 1): 2

    scaler = MinMaxScaler()
    train['load'] = scaler.fit_transform(train)
    
  3. Skaler nu testdataene: 2

    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.

# 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.

timesteps=5

Konvertering af træningsdata til 2D tensor ved hjælp af nested list comprehension:

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)

Konvertering af testdata til 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)

Udvælgelse af input og output fra trænings- og testdata:

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)

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. 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 og sætter hyperparametrene gamma, C og epsilon til henholdsvis 0.5, 10 og 0.05.

model = SVR(kernel='rbf',gamma=0.5, C=10, epsilon = 0.05)

Tilpas modellen til træningsdata 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)

Lav model-forudsigelser 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 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:

# 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))

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.

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

Plot forudsigelserne for træningsdata:

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()

forudsigelse af træningsdata

Udskriv MAPE for træningsdata

print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')
MAPE for training data: 1.7195710200875551 %

Plot forudsigelserne for testdata

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()

forudsigelse af testdata

Udskriv MAPE for testdata

print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')
MAPE for testing data:  1.2623790187854018 %

🏆 Du har et meget godt resultat på testdatasættet!

Kontroller modelens ydeevne på det fulde datasæt 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()

forudsigelse af fulde data

print('MAPE: ', mape(Y_pred, Y)*100, '%')
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.
  • Prøv at bruge forskellige kernel-funktioner til modellen og analyser deres ydeevne på datasættet. Et nyttigt dokument kan findes her.
  • Prøv at bruge forskellige værdier for timesteps for modellen til at kigge tilbage for at lave forudsigelser.

Quiz efter lektionen

Gennemgang & Selvstudie

Denne lektion introducerede anvendelsen af SVR til tidsserieforudsigelse. For at læse mere om SVR kan du referere til denne blog. Denne dokumentation om scikit-learn giver en mere omfattende forklaring om SVM'er generelt, SVR'er og også andre implementeringsdetaljer såsom de forskellige kernel-funktioner, der kan bruges, og deres parametre.

Opgave

En ny SVR-model

Credits


Ansvarsfraskrivelse:
Dette dokument er blevet oversat ved hjælp af AI-oversættelsestjenesten 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.


  1. Teksten, koden og output i dette afsnit blev bidraget af @AnirbanMukherjeeXD ↩︎

  2. Teksten, koden og output i dette afsnit blev taget fra ARIMA ↩︎