I am experiencing a weird offset in my Support Vector Regression prediction (code below).

A brief overview: I have a set of 10 .xls sheets as input data (each with 30 rows and 27 columns), and a 11th .xls sheet that I am using as my testing dataset.

I am working with an electricity dataset, and I am trying to predict the 11th month of electricity usage using the SVR. I am using the code written and released by Luke Benning on Github: https://github.com/lbenning/Load-Forecasting

All of my datasets are structured the same, but when I run the prediction model, I am receiving an offset (as shown in the photo below). The actual data versus the predicted data seem to follow a similar pattern, but the two plots are offset.

Does anyone know of what I may want to explore in order to try and understand the source of this offset?

enter image description here

#! /usr/bin/python

import math
import statistics
import visualizer
import numpy as np
from datagen import constructData
from sklearn import svm

# Applies Support Vector Regression to the electricity dataset,
# prints out the accuracy rate to the terminal and plots
# predictions against actual values
def suppVectorRegress():

    kernelList = ["linear","rbf",polyKernel]
    names = ["linear","radial basis","poly"]
    preds = []

    # Retrieve time series data & apply preprocessing
    data = constructData()

    cutoff = len(data)-30
    xTrain = data[0][0:cutoff]
    yTrain = data[1][0:cutoff]
    xTest = data[0][cutoff:]
    yTest = data[1][cutoff:]

    # Fill in missing values denoted by zeroes as an average of
    # both neighbors

    # Logarithmically scale the data
    xTrain = [[math.log(y) for y in x] for x in xTrain]
    xTest = [[math.log(y) for y in x] for x in xTest]
    yTrain = [math.log(x) for x in yTrain]

    # Detrend the time series
    indices = np.arange(len(data[1]))
    trainIndices = indices[0:cutoff]
    testIndices = indices[cutoff:]
    detrended,slope,intercept = statistics.detrend(trainIndices,yTrain)
    yTrain = detrended

    for gen in range(len(kernelList)):

        # Use SVR to predict test observations based upon training observations
        pred = svrPredictions(xTrain,yTrain,xTest,kernelList[gen])
        # Add the trend back into the predictions
        trendedPred = statistics.reapplyTrend(testIndices,pred,slope,intercept)
        # Reverse the normalization
        trendedPred = [math.exp(x) for x in trendedPred]
        # Compute the NRMSE
        err = statistics.normRmse(yTest,trendedPred)

        print ("The Normalized Root-Mean Square Error is " + str(err) + " using kernel " + names[gen] + "...")



    # Change the parameters 2017,2,1 based on the month you want to predict.
    visualizer.comparisonPlot(2017,2,1,preds,names,plotName="Support Vector Regression Load Predictions vs. Actual", 
        yAxisName="Predicted Kilowatts")

# Construct a support vector machine and get predictions
# for the test set
# Returns a 1-d vector of predictions
def svrPredictions(xTrain,yTrain,xTest,k):
    clf = svm.SVR(C=2.0,kernel=k)
    return clf.predict(xTest)

# A scale invariant kernel (note only conditionally semi-definite)
def polyKernel(x,y):
    return (np.dot(x,y.T)+1.0)**0.95

if __name__=="__main__":

I am generating the data as follows:

Functions for retrieving Elia dataset 
& forming training/testing datasets

# constructs dataset for simulations
# the last dataset in this file list, is the one used as the training set.
def constructData():
  files = ["data/jan_16_elec_scaled.xls", "data/feb_16_elec_scaled.xls", 
           "data/mar_16_elec_scaled.xls", "data/apr_16_elec_scaled.xls",
           "data/jul_16_elec_scaled.xls", "data/aug_16_elec_scaled.xls",
           "data/sep_16_elec_scaled.xls", "data/oct_16_elec_scaled.xls",

#  files = ["data/jan_16_elec_NOscaled.xls", "data/feb_16_elec_NOscaled.xls", 
#           "data/mar_16_elec_NOscaled.xls", "data/apr_16_elec_NOscaled.xls",
#           "data/may_16_elec_NOscaled.xls","data/jun_16_elec_NOscaled.xls",
#           "data/jul_16_elec_NOscaled.xls", "data/aug_16_elec_NOscaled.xls",
#           "data/sep_16_elec_NOscaled.xls", "data/oct_16_elec_NOscaled.xls",
#           "data/nov_16_elec_NOscaled.xls"]         
  return labelSeries(loadSeries(files))

# constructs labelled data from a
# univariate time series
sdef labelSeries(series):
  xData = []
  yData = []
  for x in range(len(series)-1):
    xData.append(series[x]) # xData contains all of the items up until the last item
    yData.append(np.mean(series[x+1])) # yData is the last item in the list
  return (xData,yData)

# arg1 : list of excel spreadsheets filenames
# returns : load univariate time series
def loadSeries(fileList):
  # Retrieve time series examples
  xData = []
  for fileName in fileList:
    book = xlrd.open_workbook(fileName)
    sheet = book.sheet_by_index(0)
    for rx in range(2,sheet.nrows):
      row = sheet.row(rx)[3:]
      row = [row[x].value for x in range(0,len(row)-4)]
  return xData

1 Answer 1


See this answer by Xu Cui. The reason, as he stated is simple: the model itself is very simple SVM. He suggests lagging 2 points behind to "improve" and get a more powerful model. Let me know what you think of it. We might be overthinking and he might be on point.

  • $\begingroup$ Based on my code given, do you know how to add this lag? $\endgroup$
    – Gary
    Commented Mar 22, 2017 at 22:32
  • $\begingroup$ Hi @Gary I am not sure whether your data is an matrix or a list. Assuming it is a matrix with the topmost row as the oldest observation then xTrain should be xTrain = xTrain[ 0:-2 , :] , and yTrain[2:,]. the svm can be kept as is. just adjust the training data such that you are calculating Yt in terms of Xt-2. hope this helps. $\endgroup$ Commented Mar 23, 2017 at 4:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.