Multiple predictions

Viewed 1672

I have a df where I need to predict the dependent variable (numeric) for each day in the next 7 days. The train data is like:

df.head()
Date                   X1                X2             X3    Y
2004-11-20          453.0               654            989  716   # row 1
2004-11-21          716.0               878            886  605
2004-11-22          605.0               433            775  555
2004-11-23          555.0               453            564  680
2004-11-24          680.0               645            734  713

In specific, for date 2004-11-20 in row 1 I need a Y predicted value for each day of the next 7 days, not just the present day (variable Y), and considering that to predict the 5th day starting at 2004-11-20 I'm not going to have the data available of the next 4 days starting at 2004-11-20.

I have been thinking with the idea of creating 7 more variables ("Y+1day", "Y+2day" and so on) but I will need to create a training df for each day as machine learning techniques only return one variable as output. Is there an easier way?

I'm using skikit-learn library for modeling.

1 Answers

You absolutely can train a model to predict multiple outputs in sklearn. And pandas is very flexible. In the example below I convert your Date column into a datetime index, then use the shift utility to get more Y values.

import io
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

# Read from stackoverflow artifacts
s = """Date  X1  X2   X3   Y
2004-11-20          453.0               654            989  716  
2004-11-21          716.0               878            886  605
2004-11-22          605.0               433            775  555
2004-11-23          555.0               453            564  680
2004-11-24          680.0               645            734  713"""
text = io.StringIO(s)
df = pd.read_csv(text, sep='\\s+')

# Datetime index
df["Date"] = pd.to_datetime(df["Date"], format="%Y/%m/%d")
df = df.set_index("Date")

# Shifting for Y@Day+N   
df['Y1'] = df.shift(1)['Y'] # One day later
df['Y2'] = df.shift(2)['Y'] # Two...

We have to impute or drop the NaNs that result when we use shift. In a large dataset this hopefully only results in imputed or dropped data at the edge of the time range. For example if you want 7 days shifted you would lose 7 days from your dataset depending on how your data are structured and how you need to shift.

df.dropna(inplace=True) # Drop two rows

train, test = train_test_split(df)
# Get two training rows
trainX = train.drop(["Y", "Y1", "Y2"], axis=1)
trainY = train.drop(["X1", "X2", "X3"], axis=1)

# Get the test row
X = test.drop(["Y", "Y1", "Y2"], axis=1)
Y = test.drop(["X1", "X2", "X3"], axis=1)

Now we can instantiate a classifier from sklearn and do our predictions.

from sklearn.linear_model import LinearRegression

clf = LinearRegression()
model = clf.fit(trainX, trainY)
model.predict(X) # Array of three numbers
model.score(X, Y) # Predictably abysmal score

These all ran just fine for me with sklearn version 0.20.1. Now of course I got a terrible score result from this, but the model does train, and the predict method does return a prediction for each Y column, and the score method returns a score.

Related