- Preparing the data
- Defining and fitting the model
- Predicting and visualizing the results
- Source code listing
from keras.models import Sequential from keras.layers import Dense, SimpleRNN from numpy import array, sqrt, array from numpy.random import uniform from numpy import hstack import matplotlib.pyplot as plt from sklearn.metrics import mean_squared_error
Preparing the data
We'll create a multi-output dataset for this tutorial. It is randomly generated data with a simple rule. You can check the logic of data generation in a function below. There are three inputs and two outputs in this dataset.
def create_data(n): x1 = array([i/100-uniform()*10 for i in range(n)]).reshape(n,1) x2 = array([i/100+uniform()*5 for i in range(n)]).reshape(n,1) x3 = array([i/200+uniform()-5 for i in range(n)]).reshape(n,1) y1= [x1[i]/2+x2[i]+x3[i]+uniform() for i in range(n)] y2= [x1[i]-x2[i]*2-x3[i]/2-5-uniform() for i in range(n)] X = hstack((x1, x2, x3)) Y = hstack((y1, y2)) return X, Y
Now, we'll set N total number of samples and generate the dataset. You can draw X or Y data in a plot to check it visually.
N = 420 x, y = create_data(N)
plt.plot(y) plt.show()
Now, we'll split the dataset into the train and test parts. Here, we'll define n number of train samples.
n = 400 xtrain, xtest = x[0:n,:], x[n:N,:] ytrain, ytest = y[0:n,:], y[n:N,:]
Next, we'll define the function to prepare training data. It creates x and y data for a given step window.
def convertData(datax, datay, step): X, Y = [], [] for i in range(len(datax)-step): d = i+step X.append(datax[i:d,]) Y.append(datay[d]) return array(X), array(Y)
We'll define step value and create train and test data. You can check the dimensions of the data.
step = 2 testx,testy = convertData(xtest,ytest, step) trainx,trainy = convertData(xtrain,ytrain, step)
print("test-x:", testx.shape, "test-y:", testy.shape)
print("train-x:", trainx.shape, "trian-y:", trainy.shape)
test-x: (18, 2, 3) test-y: (18, 2)
train-x: (398, 2, 3) trian-y: (398, 2)
Defining and fitting the model
Input and output shapes can be extracted from the input and output training data.
in_dim = trainx.shape[1:3] out_dim = trainy.shape[1]
print(in_dim)
(2, 3) print(out_dim)
2
We'll define a sequential model and add the SimpleRNN layer by defining the input shapes. We'll add Dense layers with ReLU activations, set the output layer dimension, and compile the model with Adam optimizer.
model = Sequential() model.add(SimpleRNN(units=100, input_shape=in_dim, activation="relu")) model.add(Dense(16, activation="relu")) model.add(Dense(out_dim)) model.compile(loss='mse', optimizer='adam')
model.summary()
_________________________________________________________________ Layer (type) Output Shape Param # ================================================================= simple_rnn_1 (SimpleRNN) (None, 100) 10400 _________________________________________________________________ dense_2 (Dense) (None, 16) 1616 _________________________________________________________________ dense_3 (Dense) (None, 2) 34 ================================================================= Total params: 12,050 Trainable params: 12,050 Non-trainable params: 0 _________________________________________________________________
We'll fit the model with train data and check the training score.
model.fit(trainx,trainy, epochs=500, verbose=2) trainScore = model.evaluate(trainx, trainy, verbose=0) print(trainScore)
4.617212070292564
Predicting and visualizing the results
Finally, we'll predict test data and check to RMSE rate.
predtest= model.predict(testx) rmse_y1 = sqrt(mean_squared_error(testy[:,0], predtest[:,0])) rmse_y2 = sqrt(mean_squared_error(testy[:,1], predtest[:,1]))
print("RMSE y1: %.2f y2: %.2f" % (rmse_y1, rmse_y2))
RMSE y1: 3.12 y2: 6.54
We can visualize the y1 and y2 predicted and original values in a plot.
x_ax = range(len(testx)) plt.plot(x_ax, testy[:,0], label="y1-test",color="c") plt.plot(x_ax, predtest[:,0], label="y1-pred") plt.plot(x_ax, testy[:,1], label="y2-test",color="m") plt.plot(x_ax, predtest[:,1], label="y2-pred") plt.legend() plt.show()
In this tutorial, we've briefly learned how to fit and predict multi-output and multi-step regression data with Keras SimpleRNN model. The full source code is listed below.
Source code listing
from keras.models import Sequential from keras.layers import Dense, SimpleRNN from numpy import array, sqrt, array from numpy.random import uniform from numpy import hstack import matplotlib.pyplot as plt from sklearn.metrics import mean_squared_error def create_data(n): x1 = array([i/100-uniform()*10 for i in range(n)]).reshape(n,1) x2 = array([i/100+uniform()*5 for i in range(n)]).reshape(n,1) x3 = array([i/200+uniform()-5 for i in range(n)]).reshape(n,1) y1= [x1[i]/2+x2[i]+x3[i]+uniform() for i in range(n)] y2= [x1[i]-x2[i]*2-x3[i]/2-5-uniform() for i in range(n)] X = hstack((x1, x2, x3)) Y = hstack((y1, y2)) return X, Y N=420 n=400 x, y = create_data(N) plt.plot(y) plt.show() xtrain, xtest = x[0:n,:], x[n:N,:] ytrain, ytest = y[0:n,:], y[n:N,:] print("xtrain:", xtrain.shape, "ytrian:", ytrain.shape) def convertData(datax,datay,step): X, Y = [], [] for i in range(len(datax)-step): d = i+step X.append(datax[i:d,]) Y.append(datay[d]) return array(X), array(Y) step=2 testx,testy = convertData(xtest,ytest, step) trainx,trainy = convertData(xtrain,ytrain, step) print("test-x:", testx.shape, "test-y:", testy.shape) print("train-x:", trainx.shape, "trian-y:", trainy.shape) trainx[1:2,] test[1:3,1:2] in_dim = trainx.shape[1:3] out_dim = trainy.shape[1] model = Sequential() model.add(SimpleRNN(units=100, input_shape=in_dim, activation="relu")) model.add(Dense(16, activation="relu")) model.add(Dense(out_dim)) model.compile(loss='mse', optimizer='adam') model.summary() model.fit(trainx,trainy, epochs=500, verbose=2) trainScore = model.evaluate(trainx, trainy, verbose=0) print(trainScore) predtest= model.predict(testx) rmse_y1 = sqrt(mean_squared_error(testy[:,0], predtest[:,0])) rmse_y2 = sqrt(mean_squared_error(testy[:,1], predtest[:,1])) print("RMSE y1: %.2f y2: %.2f" % (rmse_y1, rmse_y2)) x_ax = range(len(testx)) plt.plot(x_ax, testy[:,0], label="y1-test",color="c") plt.plot(x_ax, predtest[:,0], label="y1-pred") plt.plot(x_ax, testy[:,1], label="y2-test",color="m") plt.plot(x_ax, predtest[:,1], label="y2-pred") plt.legend() plt.show()
Very helpful. Thanks a lot
ReplyDeletevery good and simple and easy to understand example
ReplyDelete