Introduction: Neural Network for learning/processing time-series/historical data/signal

In this project, we'll build a neural network (NN) to learn and process historical/time-series signal data. The dataset, used in this project, is the smartwatch multisensor dataset acquired and collected by AnEAR app installed on a smartphone. This dataset is provided in the framework of ED-EAR project which is financially supported by NIH.


In [1]:
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

Load, explore, prepare, and preprocess the dataset

The first critical step is loading/downloading, exploring, and preparing the dataset correctly. Variables/values on different scales make it difficult for the NN to efficiently learn the correct parameters (e.g. weights and biases).


In [2]:
# The smartwatch historical/time-seris data to visualize
data_path_1xn = 'data/smartwatch_data/experimental_data_analysis/Basis_Watch_Data.csv'
watch_txn = pd.read_csv(data_path_1xn)

Downloading/ checking out the smartwatch dataset

Smartwatch dataset has the number of sensors time-seris data. The sensors data, recorded from the smartwatch, are following: GSR, heart rate, tempareture, lighting, contact, and ... Below is a plot showing the smartwatch multisensor dataset. Looking at the dataset, we can have information about different sensors modality and values.


In [3]:
# txn: time-space from the space-time theory
watch_txn.head()

# Exploring the data rows-t and cols-n
watch_txn[:20]

# Getting rid of NaN
watch_txn = watch_txn.fillna(value=0.0)
watch_txn[:100]


Out[3]:
date calories gsr heart-rate skin-temp steps
0 2014-08-08 15:18Z 0.4 0.000000 0.0 0.0000 0.0
1 2014-08-08 15:19Z 1.4 0.000000 0.0 0.0000 0.0
2 2014-08-08 15:20Z 1.4 0.000000 0.0 0.0000 0.0
3 2014-08-08 15:21Z 1.3 0.000000 0.0 0.0000 0.0
4 2014-08-08 15:22Z 1.4 0.000000 0.0 0.0000 0.0
5 2014-08-08 15:23Z 1.4 0.000000 0.0 0.0000 0.0
6 2014-08-08 15:24Z 1.4 0.000000 0.0 0.0000 0.0
7 2014-08-08 15:25Z 1.4 0.000000 0.0 0.0000 0.0
8 2014-08-08 15:26Z 1.4 0.000000 0.0 0.0000 0.0
9 2014-08-08 15:27Z 1.4 0.000000 0.0 0.0000 0.0
10 2014-08-08 15:28Z 1.3 0.000000 0.0 0.0000 0.0
11 2014-08-08 15:29Z 1.4 0.000000 0.0 0.0000 0.0
12 2014-08-08 15:30Z 1.4 0.000000 0.0 0.0000 0.0
13 2014-08-08 15:31Z 1.4 0.000000 0.0 0.0000 0.0
14 2014-08-08 15:32Z 1.4 0.000000 0.0 0.0000 0.0
15 2014-08-08 15:33Z 1.4 0.000000 0.0 0.0000 0.0
16 2014-08-08 15:34Z 1.4 0.000000 0.0 0.0000 0.0
17 2014-08-08 15:35Z 1.3 0.000000 0.0 0.0000 0.0
18 2014-08-08 15:36Z 1.4 0.000000 0.0 0.0000 0.0
19 2014-08-08 15:37Z 1.4 0.000000 0.0 0.0000 0.0
20 2014-08-08 15:38Z 1.4 0.000000 0.0 0.0000 0.0
21 2014-08-08 15:39Z 1.4 0.000000 0.0 0.0000 0.0
22 2014-08-08 15:40Z 1.4 0.000000 0.0 0.0000 0.0
23 2014-08-08 15:41Z 1.4 0.000000 0.0 0.0000 0.0
24 2014-08-08 15:42Z 1.3 0.000000 0.0 0.0000 0.0
25 2014-08-08 15:43Z 1.4 0.000000 0.0 0.0000 0.0
26 2014-08-08 15:44Z 1.4 0.000000 0.0 0.0000 0.0
27 2014-08-08 15:45Z 1.4 0.000000 0.0 0.0000 0.0
28 2014-08-08 15:46Z 1.4 0.000000 0.0 0.0000 0.0
29 2014-08-08 15:47Z 1.4 0.000000 0.0 0.0000 0.0
... ... ... ... ... ... ...
70 2014-08-08 16:28Z 1.2 0.001230 80.0 94.6813 0.0
71 2014-08-08 16:29Z 1.1 0.001349 80.0 94.7750 0.0
72 2014-08-08 16:30Z 1.2 0.001507 79.0 94.7750 0.0
73 2014-08-08 16:31Z 1.2 0.001553 78.0 94.9625 0.0
74 2014-08-08 16:32Z 0.9 0.001690 78.0 95.0000 0.0
75 2014-08-08 16:33Z 1.0 0.002012 79.0 95.0000 0.0
76 2014-08-08 16:34Z 1.0 0.002285 79.0 95.0563 0.0
77 2014-08-08 16:35Z 1.0 0.002313 79.0 95.2250 0.0
78 2014-08-08 16:36Z 1.0 0.002505 78.0 95.2250 0.0
79 2014-08-08 16:37Z 1.0 0.002391 79.0 95.2250 0.0
80 2014-08-08 16:38Z 1.0 0.002533 79.0 95.3000 0.0
81 2014-08-08 16:39Z 1.0 0.003178 79.0 95.4500 0.0
82 2014-08-08 16:40Z 1.0 0.004063 79.0 95.4500 0.0
83 2014-08-08 16:41Z 0.8 0.004169 78.0 95.4500 0.0
84 2014-08-08 16:42Z 1.1 0.006071 78.0 95.4500 0.0
85 2014-08-08 16:43Z 1.0 0.010282 78.0 95.4500 0.0
86 2014-08-08 16:44Z 1.1 0.016105 78.0 95.5625 0.0
87 2014-08-08 16:45Z 1.0 0.023378 77.0 95.6750 0.0
88 2014-08-08 16:46Z 1.0 0.048485 78.0 95.6750 0.0
89 2014-08-08 16:47Z 1.0 0.119621 77.0 95.6750 0.0
90 2014-08-08 16:48Z 1.1 0.220373 76.0 95.6750 0.0
91 2014-08-08 16:49Z 1.0 0.395007 76.0 95.6750 0.0
92 2014-08-08 16:50Z 1.0 0.564395 75.0 95.6750 0.0
93 2014-08-08 16:51Z 1.1 0.769779 75.0 95.6750 0.0
94 2014-08-08 16:52Z 1.2 1.276110 74.0 95.6937 0.0
95 2014-08-08 16:53Z 1.2 1.655600 71.0 95.7312 0.0
96 2014-08-08 16:54Z 1.2 1.667620 72.0 95.7125 0.0
97 2014-08-08 16:55Z 1.3 1.740780 75.0 95.7688 0.0
98 2014-08-08 16:56Z 1.2 2.195710 80.0 95.8063 0.0
99 2014-08-08 16:57Z 1.2 3.222840 81.0 95.9000 0.0

100 rows × 6 columns


In [4]:
# Plotting the smartwatch data
watch_txn[:100].plot() #x='dteday', y='cnt'


Out[4]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fbe4a9d39e8>

Batch normalization for standardizing the dataset using mean and variance/ scaling the data

For training NN easier and more efficiently on the dataset, we should normalize/standardize each of the continuous variables in the dataset. we'll shift/translate and scale the variables such that they have zero-mean and a standard deviation of 1. These scaling factors are saved to add up to the NN predictions eventually.


In [5]:
features_1x5 = ['calories', 'gsr', 'heart-rate', 'skin-temp', 'steps']

# Store scalings in a dictionary so we can convert back later
scaled_features_5x2 = {}
for each_name in features_1x5:
    mean_1x1_val, std_1x1_val = watch_txn[each_name].mean(), watch_txn[each_name].std() # std: standard dev. = square-root of MSE/Variance
    scaled_features_5x2[each_name] = [mean_1x1_val, std_1x1_val]
    watch_txn.loc[:, each_name] = (watch_txn[each_name] - mean_1x1_val)/std_1x1_val

# Drop date from the dataset
watch_txn = watch_txn.drop(labels='date', axis=1)

# Visualize the data again to double-check visually again
watch_txn[:100].plot()


Out[5]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fbe4a663550>

Splitting the dataset into training, validation, and testing sets

We'll use the last 1% of the dataset for testing the NN after training and validation to make predictions.


In [6]:
# Save 1% data for test
test_limit_1x1_value = watch_txn.shape[0]//100
test_data_txn = watch_txn[-test_limit_1x1_value:]

# Now remove the test data from the data set for the training data 
watch_txn = watch_txn[:-test_limit_1x1_value]

# Separate all the data into features and targets
target_fields_1x1 = ['steps']
features_txn, targets_txm = watch_txn.drop(target_fields_1x1, axis=1), watch_txn[target_fields_1x1]
test_features_txn, test_targets_txm = test_data_txn.drop(target_fields_1x1, axis=1), test_data_txn[target_fields_1x1]
test_features_txn.shape, test_targets_txm.shape, features_txn.shape, targets_txm.shape


Out[6]:
((10113, 4), (10113, 1), (1001234, 4), (1001234, 1))

Dividing the remaining data into training and validation sets to avoid overfitting and underfitting during the training

We'll split the remaining data into two sets: one for training and one for validating as NN is being trained. Since this is a time-series dataset, we'll train on historical data, then try to predict on future data (the validation set).


In [7]:
# For validation set, we use 10% the remaining datset
# txn: t is time/row (num of records) and n is space/col (input feature space dims)
# txm: t is time/row (num of records) and m is space/col (output feature space dims)
train_features_txn, train_targets_txm = features_txn[:-(features_txn.shape[0]//10)], targets_txm[:-(targets_txm.shape[0]//10)]
valid_features_txn, valid_targets_txm = features_txn[-(features_txn.shape[0]//10):], targets_txm[-(targets_txm.shape[0]//10):]
train_features_txn.shape, train_targets_txm.shape, valid_features_txn.shape, valid_targets_txm.shape


Out[7]:
((901111, 4), (901111, 1), (100123, 4), (100123, 1))

How to build the NN

Below we'll build NN architecture for learning and processing the time-series dataset. We've built NN architecture for the forward and the backward pass.

we'll set the hyperparameters: the momentum, the learning rate, the number of hidden units, the number of input units, the number of output units, and the number of epochs for training passes (updating the NN parameters such as weights and biases).

The NN has three layers in general and in our case: one input layer, one/multiple hidden layer/s, and one output layer. The hidden layer/s uses a non-linear function for activations/probability such as the sigmoid and tanh. The output layer, in our case, has one node and is used for the regression, i.e. the output of the node is the same as the input of the node. That is why the activation function is a linear unit (LU) $f(x)=x$.

A function that takes the input signal and generates an output signal, but takes into account a threshold, is called an activation function. We work through each layer of our network calculating the outputs for each neuron. All of the outputs from one layer become inputs to the neurons on the next layer. This process is called forward propagation which happens in forward pass.

We use the NN weights to propagate signals forward (in forward pass) from the input to the output layers in NN. We use the weights to also propagate error backwards (in backward pass) from the output all the way back into the NN to update our weights. This is called backpropagation.

Hint: We'll need the derivative of the output activation function ($f(x) = x$) for the backpropagation implementation. Based on calculus, the derivative of this function is equivalent to the equation $y = x$. In fact, the slope of this function is the derivative of $f(x)$.

Below, we'll build the NN as follows:

  1. Implement/apply an activation function such as sigmoid, tanh, or ReLU.
  2. Implement the forward pass in the train method for forward propagation of the input data.
  3. Implement the backpropagation algorithm in the train method in the backward pass by calculating the output error and the parameter gradients.
  4. Implement the forward pass again at the end in the run method for the actual prediction in validation data and test data.

In [8]:
class NN(object):
    # n: num_input_units in input layer, 
    # h: num_hidden_units in the hidden layer, 
    # m: num_out_units in the output layer, and 
    # lr: learning_rate
    def __init__(self, n, h, m, lr):
        # Initialize parameters: weights and biases
        self.w_nxh = np.random.normal(loc=0.0, scale=n**(-0.5), size=(n, h))
        self.b_1xh = np.zeros(shape=(1, h))

        self.w_hxm = np.random.normal(loc=0.0, scale=h**(-0.5), size=(h, m))
        self.b_1xm = np.zeros(shape=(1, m))

        self.lr = lr
    
    # Train to update NN paramteres (w, b) in each epoch using NN hyper-parameters
    def train(self, X_txn, Y_txm):
        ''' Train the network on batch of features (X_txn) and targets (Y_txm). 
        
            Arguments
            ---------
            
            features: X_txn is a 2D array, each row is one data record (t), each column is a feature (n)
            txn: ixj, rowxcol, and hxw
            targets: Y_txm is a 2D array as well.
        
        '''
        dw_nxh = np.zeros_like(self.w_nxh)
        db_1xh = np.zeros_like(self.b_1xh)
        dw_hxm = np.zeros_like(self.w_hxm)
        db_1xm = np.zeros_like(self.b_1xm)
        
        for each_X, each_Y in zip(X_txn, Y_txm):
            #### Implement the forward pass here ####
            ### Forward pass ###
            x_1xn = np.array(each_X, ndmin=2) # [[each]]
            y_1xm = np.array(each_Y, ndmin=2) # [[each]]
            
            # TODO: Hidden layer - Replace these values with your calculations.
            h_in_1xh = (x_1xn @ self.w_nxh) + self.b_1xh # signals into hidden layer
            h_out_1xh = np.tanh(h_in_1xh)

            # TODO: Output layer - Replace these values with your calculations.
            out_logits_1xm = (h_out_1xh @ self.w_hxm) + self.b_1xm # signals into final output layer
            y_pred_1xm = np.tanh(out_logits_1xm) # signals from final output layer
            
            #### Implement the backward pass here ####
            ### Backward pass ###
            dy_1xm = y_pred_1xm - y_1xm # Output layer error: difference between actual target and desired output.

            # TODO: Output error - Replace this value with your calculations.
            dout_logits_1xm = dy_1xm * (1-(np.tanh(out_logits_1xm)**2)) # dtanh= (1-(np.tanh(x))**2)
            dh_out_1xh = dout_logits_1xm @ self.w_hxm.T
            
            # TODO: Calculate the hidden layer's contribution to the error
            dh_in_1xh = dh_out_1xh * (1-(np.tanh(h_in_1xh)**2))
            dx_1xn = dh_in_1xh @ self.w_nxh.T # is dx_1xn USELESS?
            
            # TODO: Backpropagated error terms - Replace these values with your calculations.
            db_1xm += dout_logits_1xm
            dw_hxm += (dout_logits_1xm.T @ h_out_1xh).T
            db_1xh += dh_in_1xh
            dw_nxh += (dh_in_1xh.T @ x_1xn).T
            
        # TODO: Update the NN parameters (w, b) in each epoch of training
        self.w_hxm -= self.lr * dw_hxm # update hidden-to-output weights with gradient descent step
        self.b_1xm -= self.lr * db_1xm # output units/neurons/cells/nodes
        self.w_nxh -= self.lr * dw_nxh # update input-to-hidden weights with gradient descent step
        self.b_1xh -= self.lr * db_1xh # hidden units/cells/neurons/nodes
 
    def run(self, X_txn):
        ''' Run a forward pass through the network with input features 
        
            Arguments
            ---------
            features: X_txn is a 2D array of records (t as row) and their features (n as col)
        '''
        
        #### Implement the forward pass here ####
        ### Forward pass ###
        x_txn = X_txn

        # TODO: Hidden layer - Replace these values with your calculations.
        h_in_txh = (x_txn @ self.w_nxh) + self.b_1xh # signals into hidden layer
        h_out_txh = np.tanh(h_in_txh)

        # TODO: Output layer - Replace these values with your calculations.
        out_logits_txm = (h_out_txh @ self.w_hxm) + self.b_1xm # signals into final output layer
        y_pred_txm = np.tanh(out_logits_txm) # signals from final output layer
        
        return y_pred_txm

In [9]:
# Mean Squared-Error(MSE)
def MSE(Y_pred_1xt, Y_1xt):
    return np.mean((Y_pred_1xt-Y_1xt)**2)

Training the NN

At first, we'll set the hyperparameters for the NN. The strategy here is to find hyperparameters such that the error on the training set is the low enough, but you're not underfitting or overfitting to the training set.

If you train the NN too long or NN has too many hidden nodes, it can become overly specific to the training set and will fail to generalize to the validation set. That is, the loss on the validation set will start increasing as the training set loss drops.

We'll also be using a method known as Stochastic Gradient Descent (SGD) to train the NN using Backpropagation. The idea is that for each training pass, you grab a either a random minibatch of the data instead of using the whole data set/full batch.

We can also use bacth gradient descent (BGD), but with SGD, each pass is much faster than BGD. That is why as the data size grows in number of samples, BGD is not feasible for training the NN and we have to use SGD instead to consider our hardware limitation, specifically the memory size limits, i.e. RAM and Cache.

Epochs: choose the number of iterations for updating NN parameters

This is the number of times to update the NN parameters using the training dataset as we train the NN. The more iterations we use, the better the model might fit the data. However, if you use too many epoch iterations, then the model might not generalize well to the data but memorize the data which is called/known as overfitting. You want to find a number here where the network has a low training loss, and the validation loss is at a minimum. As you start overfitting, you'll see the training loss continue to decrease while the validation loss starts to increase.

Learning rate

This scales the size of the NN parameters updates. If it is too big, the weights tend to explode and the network fails to fit the data. A good choice to start at is 0.1. If the NN has problems fitting the data, try reducing the learning rate. Note that the lower the learning rate, the smaller the steps are in the weight updates and the longer it takes for the NN to converge.

Number of hidden nodes

The more hidden nodes you have, the more accurate predictions the model will make. Try a few different numbers and see how it affects the performance. You can look at the losses dictionary for a metric of the NN performance. If the number of hidden units is too low, then the model won't have enough space to learn and if it is too high there are too many options for the direction that the learning can take. The trick here is to find the right balance in number of hidden units you choose.


In [13]:
### Set the hyperparameters here ###
num_epochs = 100*2 # updating NN parameters (w, b)
learning_rate = 2 * 10/train_features_txn.shape[0] # train_features = x_txn, t: number of recorded samples/records
hidden_nodes = 10
output_nodes = 1 # y_tx1
input_nodes = train_features_txn.shape[1] # x_txn

# Buidlingthe NN by initializing/instantiating the NN class
nn = NN(h=hidden_nodes, lr=learning_rate, m=output_nodes, n=input_nodes)

# Training-validating the NN - learning process
losses_tx2 = {'train':[], 'valid':[]}
for each_epoch in range(num_epochs):
    
    # Go through a random minibatch of 128 records from the training data set
    random_minibatch = np.random.choice(train_features_txn.index, size=1024)
    x_txn, y_tx1 = train_features_txn.ix[random_minibatch].values, train_targets_txm.ix[random_minibatch].values #['cnt']
    
    #     # Go through the full batch of records in the training data set
    #     x_txn , y_tx1 = train_features_txn.values, train_targets_txm.values #['cnt']
    
    nn.train(X_txn=x_txn, Y_txm=y_tx1)
    
    # Printing out the training progress
    train_loss_1x1_value = MSE(Y_pred_1xt=nn.run(X_txn=train_features_txn).T, Y_1xt=train_targets_txm.values.T)
    valid_loss_1x1_value = MSE(Y_pred_1xt=nn.run(X_txn=valid_features_txn).T, Y_1xt=valid_targets_txm.values.T)
    print('each_epoch:', each_epoch, 'num_epochs:', num_epochs, 
          'train_loss:', train_loss_1x1_value, 'valid_loss:', valid_loss_1x1_value)
    
    losses_tx2['train'].append(train_loss_1x1_value)
    losses_tx2['valid'].append(valid_loss_1x1_value)


each_epoch: 0 num_epochs: 200 train_loss: 0.978365532452 valid_loss: 1.13290153322
each_epoch: 1 num_epochs: 200 train_loss: 0.976941679871 valid_loss: 1.13208449344
each_epoch: 2 num_epochs: 200 train_loss: 0.975100555383 valid_loss: 1.1310094727
each_epoch: 3 num_epochs: 200 train_loss: 0.973647895674 valid_loss: 1.12978582152
each_epoch: 4 num_epochs: 200 train_loss: 0.972150057872 valid_loss: 1.12875086867
each_epoch: 5 num_epochs: 200 train_loss: 0.970465517152 valid_loss: 1.12782864001
each_epoch: 6 num_epochs: 200 train_loss: 0.968759241715 valid_loss: 1.12709619887
each_epoch: 7 num_epochs: 200 train_loss: 0.967234547325 valid_loss: 1.12628810384
each_epoch: 8 num_epochs: 200 train_loss: 0.965866334052 valid_loss: 1.1253920888
each_epoch: 9 num_epochs: 200 train_loss: 0.964243180455 valid_loss: 1.12482000932
each_epoch: 10 num_epochs: 200 train_loss: 0.962661976304 valid_loss: 1.12401646486
each_epoch: 11 num_epochs: 200 train_loss: 0.961090842223 valid_loss: 1.1233575641
each_epoch: 12 num_epochs: 200 train_loss: 0.959635527139 valid_loss: 1.12266122813
each_epoch: 13 num_epochs: 200 train_loss: 0.958182410082 valid_loss: 1.12201222083
each_epoch: 14 num_epochs: 200 train_loss: 0.956433998711 valid_loss: 1.12152577774
each_epoch: 15 num_epochs: 200 train_loss: 0.954965853949 valid_loss: 1.12116931811
each_epoch: 16 num_epochs: 200 train_loss: 0.953608635368 valid_loss: 1.12018762095
each_epoch: 17 num_epochs: 200 train_loss: 0.952264078514 valid_loss: 1.11912628873
each_epoch: 18 num_epochs: 200 train_loss: 0.950638286989 valid_loss: 1.11840875234
each_epoch: 19 num_epochs: 200 train_loss: 0.949332853365 valid_loss: 1.11783210883
each_epoch: 20 num_epochs: 200 train_loss: 0.947986818708 valid_loss: 1.11651604987
each_epoch: 21 num_epochs: 200 train_loss: 0.946759055505 valid_loss: 1.11542596246
each_epoch: 22 num_epochs: 200 train_loss: 0.945795682529 valid_loss: 1.11498322734
each_epoch: 23 num_epochs: 200 train_loss: 0.944644745888 valid_loss: 1.11461341174
each_epoch: 24 num_epochs: 200 train_loss: 0.943386298649 valid_loss: 1.11430838735
each_epoch: 25 num_epochs: 200 train_loss: 0.9424824434 valid_loss: 1.11400096291
each_epoch: 26 num_epochs: 200 train_loss: 0.941165010838 valid_loss: 1.11294126812
each_epoch: 27 num_epochs: 200 train_loss: 0.939538562344 valid_loss: 1.11202351496
each_epoch: 28 num_epochs: 200 train_loss: 0.937876262665 valid_loss: 1.11140497749
each_epoch: 29 num_epochs: 200 train_loss: 0.936638729952 valid_loss: 1.11106787943
each_epoch: 30 num_epochs: 200 train_loss: 0.9351392151 valid_loss: 1.11041725392
each_epoch: 31 num_epochs: 200 train_loss: 0.934207079502 valid_loss: 1.10964430324
each_epoch: 32 num_epochs: 200 train_loss: 0.932858604406 valid_loss: 1.10892478281
each_epoch: 33 num_epochs: 200 train_loss: 0.931672453748 valid_loss: 1.10851100613
each_epoch: 34 num_epochs: 200 train_loss: 0.930563824638 valid_loss: 1.10768151216
each_epoch: 35 num_epochs: 200 train_loss: 0.929844087493 valid_loss: 1.10688820921
each_epoch: 36 num_epochs: 200 train_loss: 0.928661975611 valid_loss: 1.10596041366
each_epoch: 37 num_epochs: 200 train_loss: 0.927662322557 valid_loss: 1.10516418159
each_epoch: 38 num_epochs: 200 train_loss: 0.926560076967 valid_loss: 1.10492291746
each_epoch: 39 num_epochs: 200 train_loss: 0.92555267389 valid_loss: 1.10465331497
each_epoch: 40 num_epochs: 200 train_loss: 0.924461786658 valid_loss: 1.10416980196
each_epoch: 41 num_epochs: 200 train_loss: 0.923561850802 valid_loss: 1.10396403054
each_epoch: 42 num_epochs: 200 train_loss: 0.922383426694 valid_loss: 1.10327475235
each_epoch: 43 num_epochs: 200 train_loss: 0.921237218494 valid_loss: 1.10329266362
each_epoch: 44 num_epochs: 200 train_loss: 0.920500095237 valid_loss: 1.10300032157
each_epoch: 45 num_epochs: 200 train_loss: 0.919431136955 valid_loss: 1.10253211123
each_epoch: 46 num_epochs: 200 train_loss: 0.918704104088 valid_loss: 1.10129977805
each_epoch: 47 num_epochs: 200 train_loss: 0.917911747291 valid_loss: 1.10073566163
each_epoch: 48 num_epochs: 200 train_loss: 0.917020088915 valid_loss: 1.10056179215
each_epoch: 49 num_epochs: 200 train_loss: 0.916206315122 valid_loss: 1.09962702778
each_epoch: 50 num_epochs: 200 train_loss: 0.91494886241 valid_loss: 1.09946000859
each_epoch: 51 num_epochs: 200 train_loss: 0.914175036932 valid_loss: 1.09909994889
each_epoch: 52 num_epochs: 200 train_loss: 0.913349310297 valid_loss: 1.09861440208
each_epoch: 53 num_epochs: 200 train_loss: 0.912455799578 valid_loss: 1.09850428948
each_epoch: 54 num_epochs: 200 train_loss: 0.911968250953 valid_loss: 1.09827993935
each_epoch: 55 num_epochs: 200 train_loss: 0.910653100867 valid_loss: 1.09795957212
each_epoch: 56 num_epochs: 200 train_loss: 0.909811907666 valid_loss: 1.09805005666
each_epoch: 57 num_epochs: 200 train_loss: 0.909049341867 valid_loss: 1.09772662136
each_epoch: 58 num_epochs: 200 train_loss: 0.908260613993 valid_loss: 1.09695817571
each_epoch: 59 num_epochs: 200 train_loss: 0.907269751235 valid_loss: 1.09660235859
each_epoch: 60 num_epochs: 200 train_loss: 0.906395010277 valid_loss: 1.09603339279
each_epoch: 61 num_epochs: 200 train_loss: 0.905710204755 valid_loss: 1.09572809048
each_epoch: 62 num_epochs: 200 train_loss: 0.904753418309 valid_loss: 1.09503534411
each_epoch: 63 num_epochs: 200 train_loss: 0.903872959592 valid_loss: 1.09458114386
each_epoch: 64 num_epochs: 200 train_loss: 0.903215315819 valid_loss: 1.09406669645
each_epoch: 65 num_epochs: 200 train_loss: 0.902370938522 valid_loss: 1.09385697565
each_epoch: 66 num_epochs: 200 train_loss: 0.901427786615 valid_loss: 1.09365284643
each_epoch: 67 num_epochs: 200 train_loss: 0.900702675809 valid_loss: 1.0934406427
each_epoch: 68 num_epochs: 200 train_loss: 0.900223254595 valid_loss: 1.09316443019
each_epoch: 69 num_epochs: 200 train_loss: 0.89948821816 valid_loss: 1.09334446219
each_epoch: 70 num_epochs: 200 train_loss: 0.899015271484 valid_loss: 1.09303807217
each_epoch: 71 num_epochs: 200 train_loss: 0.898564215777 valid_loss: 1.0931530721
each_epoch: 72 num_epochs: 200 train_loss: 0.897963915546 valid_loss: 1.09290617769
each_epoch: 73 num_epochs: 200 train_loss: 0.897428325725 valid_loss: 1.09253612465
each_epoch: 74 num_epochs: 200 train_loss: 0.896712848131 valid_loss: 1.09217540215
each_epoch: 75 num_epochs: 200 train_loss: 0.896145316113 valid_loss: 1.09207001485
each_epoch: 76 num_epochs: 200 train_loss: 0.895564306212 valid_loss: 1.09209081608
each_epoch: 77 num_epochs: 200 train_loss: 0.895094498996 valid_loss: 1.09207040451
each_epoch: 78 num_epochs: 200 train_loss: 0.894195909879 valid_loss: 1.09197957453
each_epoch: 79 num_epochs: 200 train_loss: 0.893694878431 valid_loss: 1.09158760233
each_epoch: 80 num_epochs: 200 train_loss: 0.892883073228 valid_loss: 1.09096222566
each_epoch: 81 num_epochs: 200 train_loss: 0.892280623392 valid_loss: 1.09028792023
each_epoch: 82 num_epochs: 200 train_loss: 0.891563792515 valid_loss: 1.08954408921
each_epoch: 83 num_epochs: 200 train_loss: 0.890922013977 valid_loss: 1.08910813337
each_epoch: 84 num_epochs: 200 train_loss: 0.890199675852 valid_loss: 1.08861926817
each_epoch: 85 num_epochs: 200 train_loss: 0.889367776582 valid_loss: 1.08844572828
each_epoch: 86 num_epochs: 200 train_loss: 0.888848835705 valid_loss: 1.08818370845
each_epoch: 87 num_epochs: 200 train_loss: 0.888201062462 valid_loss: 1.08789843735
each_epoch: 88 num_epochs: 200 train_loss: 0.887702907991 valid_loss: 1.08743786364
each_epoch: 89 num_epochs: 200 train_loss: 0.887209951455 valid_loss: 1.08762950362
each_epoch: 90 num_epochs: 200 train_loss: 0.886862972774 valid_loss: 1.08725592323
each_epoch: 91 num_epochs: 200 train_loss: 0.886249741403 valid_loss: 1.08723363348
each_epoch: 92 num_epochs: 200 train_loss: 0.885816150336 valid_loss: 1.08711091868
each_epoch: 93 num_epochs: 200 train_loss: 0.88525248641 valid_loss: 1.08639194087
each_epoch: 94 num_epochs: 200 train_loss: 0.884625942873 valid_loss: 1.08578932001
each_epoch: 95 num_epochs: 200 train_loss: 0.883982047055 valid_loss: 1.08511533732
each_epoch: 96 num_epochs: 200 train_loss: 0.883365017774 valid_loss: 1.08475122072
each_epoch: 97 num_epochs: 200 train_loss: 0.882808769884 valid_loss: 1.08457714434
each_epoch: 98 num_epochs: 200 train_loss: 0.882254784671 valid_loss: 1.08440030123
each_epoch: 99 num_epochs: 200 train_loss: 0.881499913032 valid_loss: 1.08424485285
each_epoch: 100 num_epochs: 200 train_loss: 0.88098277499 valid_loss: 1.08404411655
each_epoch: 101 num_epochs: 200 train_loss: 0.880563392737 valid_loss: 1.08373963914
each_epoch: 102 num_epochs: 200 train_loss: 0.880025623799 valid_loss: 1.08355655913
each_epoch: 103 num_epochs: 200 train_loss: 0.87951248815 valid_loss: 1.08352960629
each_epoch: 104 num_epochs: 200 train_loss: 0.878917203832 valid_loss: 1.08312269553
each_epoch: 105 num_epochs: 200 train_loss: 0.878487971387 valid_loss: 1.08225645287
each_epoch: 106 num_epochs: 200 train_loss: 0.877982318553 valid_loss: 1.08172873126
each_epoch: 107 num_epochs: 200 train_loss: 0.877391549159 valid_loss: 1.08163396661
each_epoch: 108 num_epochs: 200 train_loss: 0.876900886029 valid_loss: 1.08103967008
each_epoch: 109 num_epochs: 200 train_loss: 0.876232769774 valid_loss: 1.08061231008
each_epoch: 110 num_epochs: 200 train_loss: 0.875778210619 valid_loss: 1.08007534507
each_epoch: 111 num_epochs: 200 train_loss: 0.875156019682 valid_loss: 1.07976463595
each_epoch: 112 num_epochs: 200 train_loss: 0.874912837943 valid_loss: 1.07961343444
each_epoch: 113 num_epochs: 200 train_loss: 0.874655276627 valid_loss: 1.0793374702
each_epoch: 114 num_epochs: 200 train_loss: 0.874127904992 valid_loss: 1.07879778797
each_epoch: 115 num_epochs: 200 train_loss: 0.873764883182 valid_loss: 1.07891104903
each_epoch: 116 num_epochs: 200 train_loss: 0.873312446151 valid_loss: 1.07875822741
each_epoch: 117 num_epochs: 200 train_loss: 0.873181056412 valid_loss: 1.07858870684
each_epoch: 118 num_epochs: 200 train_loss: 0.872963727765 valid_loss: 1.07825285853
each_epoch: 119 num_epochs: 200 train_loss: 0.872662316896 valid_loss: 1.07776365551
each_epoch: 120 num_epochs: 200 train_loss: 0.872244282288 valid_loss: 1.07732048837
each_epoch: 121 num_epochs: 200 train_loss: 0.871805774776 valid_loss: 1.07700774307
each_epoch: 122 num_epochs: 200 train_loss: 0.870971323938 valid_loss: 1.07670701453
each_epoch: 123 num_epochs: 200 train_loss: 0.87069393873 valid_loss: 1.07614035388
each_epoch: 124 num_epochs: 200 train_loss: 0.870289950184 valid_loss: 1.07558741284
each_epoch: 125 num_epochs: 200 train_loss: 0.869888230873 valid_loss: 1.07526822473
each_epoch: 126 num_epochs: 200 train_loss: 0.869706121452 valid_loss: 1.07504585502
each_epoch: 127 num_epochs: 200 train_loss: 0.8691373523 valid_loss: 1.07520844755
each_epoch: 128 num_epochs: 200 train_loss: 0.868598615022 valid_loss: 1.0751693254
each_epoch: 129 num_epochs: 200 train_loss: 0.868308237727 valid_loss: 1.0744892594
each_epoch: 130 num_epochs: 200 train_loss: 0.867725939452 valid_loss: 1.07415727286
each_epoch: 131 num_epochs: 200 train_loss: 0.867243121788 valid_loss: 1.07420262647
each_epoch: 132 num_epochs: 200 train_loss: 0.866732959023 valid_loss: 1.07429315376
each_epoch: 133 num_epochs: 200 train_loss: 0.866191484996 valid_loss: 1.07413201195
each_epoch: 134 num_epochs: 200 train_loss: 0.865669368075 valid_loss: 1.07400417803
each_epoch: 135 num_epochs: 200 train_loss: 0.865251135963 valid_loss: 1.0738797638
each_epoch: 136 num_epochs: 200 train_loss: 0.864969496157 valid_loss: 1.07354304079
each_epoch: 137 num_epochs: 200 train_loss: 0.864519266723 valid_loss: 1.07307468195
each_epoch: 138 num_epochs: 200 train_loss: 0.864116592814 valid_loss: 1.07274094578
each_epoch: 139 num_epochs: 200 train_loss: 0.863588649714 valid_loss: 1.07245752682
each_epoch: 140 num_epochs: 200 train_loss: 0.863342827982 valid_loss: 1.07206587115
each_epoch: 141 num_epochs: 200 train_loss: 0.862981409278 valid_loss: 1.07189829569
each_epoch: 142 num_epochs: 200 train_loss: 0.862676988689 valid_loss: 1.07139615685
each_epoch: 143 num_epochs: 200 train_loss: 0.862364005796 valid_loss: 1.07145136514
each_epoch: 144 num_epochs: 200 train_loss: 0.861869852785 valid_loss: 1.07113548685
each_epoch: 145 num_epochs: 200 train_loss: 0.86137799983 valid_loss: 1.07095492012
each_epoch: 146 num_epochs: 200 train_loss: 0.860977434505 valid_loss: 1.07085240883
each_epoch: 147 num_epochs: 200 train_loss: 0.860679984415 valid_loss: 1.07059044644
each_epoch: 148 num_epochs: 200 train_loss: 0.860351059232 valid_loss: 1.0701726287
each_epoch: 149 num_epochs: 200 train_loss: 0.860112448417 valid_loss: 1.07003598995
each_epoch: 150 num_epochs: 200 train_loss: 0.859728265229 valid_loss: 1.07004100412
each_epoch: 151 num_epochs: 200 train_loss: 0.859237452239 valid_loss: 1.06988765524
each_epoch: 152 num_epochs: 200 train_loss: 0.858983866782 valid_loss: 1.06969772863
each_epoch: 153 num_epochs: 200 train_loss: 0.858726627369 valid_loss: 1.06944953129
each_epoch: 154 num_epochs: 200 train_loss: 0.858407365189 valid_loss: 1.06924338856
each_epoch: 155 num_epochs: 200 train_loss: 0.858111648521 valid_loss: 1.0691899046
each_epoch: 156 num_epochs: 200 train_loss: 0.857725705555 valid_loss: 1.06892898452
each_epoch: 157 num_epochs: 200 train_loss: 0.857451337147 valid_loss: 1.06861434429
each_epoch: 158 num_epochs: 200 train_loss: 0.857084149922 valid_loss: 1.06852941731
each_epoch: 159 num_epochs: 200 train_loss: 0.856722403405 valid_loss: 1.06846031816
each_epoch: 160 num_epochs: 200 train_loss: 0.856394152943 valid_loss: 1.06828003854
each_epoch: 161 num_epochs: 200 train_loss: 0.856051525597 valid_loss: 1.068126415
each_epoch: 162 num_epochs: 200 train_loss: 0.855713909291 valid_loss: 1.06778942795
each_epoch: 163 num_epochs: 200 train_loss: 0.855471732315 valid_loss: 1.06747244456
each_epoch: 164 num_epochs: 200 train_loss: 0.85535904374 valid_loss: 1.06727243918
each_epoch: 165 num_epochs: 200 train_loss: 0.855011752977 valid_loss: 1.06703865594
each_epoch: 166 num_epochs: 200 train_loss: 0.854902451839 valid_loss: 1.06703953265
each_epoch: 167 num_epochs: 200 train_loss: 0.854526606077 valid_loss: 1.06690804326
each_epoch: 168 num_epochs: 200 train_loss: 0.854350365646 valid_loss: 1.06691075218
each_epoch: 169 num_epochs: 200 train_loss: 0.854126833344 valid_loss: 1.06657289655
each_epoch: 170 num_epochs: 200 train_loss: 0.853696231147 valid_loss: 1.0664310805
each_epoch: 171 num_epochs: 200 train_loss: 0.853461628971 valid_loss: 1.0661070536
each_epoch: 172 num_epochs: 200 train_loss: 0.853262073775 valid_loss: 1.06579261217
each_epoch: 173 num_epochs: 200 train_loss: 0.853019677311 valid_loss: 1.06574212097
each_epoch: 174 num_epochs: 200 train_loss: 0.852771486012 valid_loss: 1.06562604333
each_epoch: 175 num_epochs: 200 train_loss: 0.852505338826 valid_loss: 1.06557706856
each_epoch: 176 num_epochs: 200 train_loss: 0.852216674775 valid_loss: 1.06554093682
each_epoch: 177 num_epochs: 200 train_loss: 0.851938597955 valid_loss: 1.06533445774
each_epoch: 178 num_epochs: 200 train_loss: 0.851639563898 valid_loss: 1.06529358792
each_epoch: 179 num_epochs: 200 train_loss: 0.851413387582 valid_loss: 1.06534831332
each_epoch: 180 num_epochs: 200 train_loss: 0.851222426442 valid_loss: 1.0653488176
each_epoch: 181 num_epochs: 200 train_loss: 0.851041132433 valid_loss: 1.06510263069
each_epoch: 182 num_epochs: 200 train_loss: 0.850793695924 valid_loss: 1.06499921284
each_epoch: 183 num_epochs: 200 train_loss: 0.850546899654 valid_loss: 1.0649623615
each_epoch: 184 num_epochs: 200 train_loss: 0.850185969383 valid_loss: 1.06484290288
each_epoch: 185 num_epochs: 200 train_loss: 0.849931444886 valid_loss: 1.06461757706
each_epoch: 186 num_epochs: 200 train_loss: 0.849601715592 valid_loss: 1.06426409524
each_epoch: 187 num_epochs: 200 train_loss: 0.849369456967 valid_loss: 1.06385573154
each_epoch: 188 num_epochs: 200 train_loss: 0.849146852082 valid_loss: 1.06352645269
each_epoch: 189 num_epochs: 200 train_loss: 0.848801809485 valid_loss: 1.06331454479
each_epoch: 190 num_epochs: 200 train_loss: 0.848557427125 valid_loss: 1.06322162941
each_epoch: 191 num_epochs: 200 train_loss: 0.848256004157 valid_loss: 1.06299187388
each_epoch: 192 num_epochs: 200 train_loss: 0.848041838655 valid_loss: 1.06293653725
each_epoch: 193 num_epochs: 200 train_loss: 0.847841586307 valid_loss: 1.06261346394
each_epoch: 194 num_epochs: 200 train_loss: 0.8476012032 valid_loss: 1.06259983282
each_epoch: 195 num_epochs: 200 train_loss: 0.847376442642 valid_loss: 1.06220442091
each_epoch: 196 num_epochs: 200 train_loss: 0.84714421053 valid_loss: 1.06196783661
each_epoch: 197 num_epochs: 200 train_loss: 0.846984034483 valid_loss: 1.06192387254
each_epoch: 198 num_epochs: 200 train_loss: 0.846794267021 valid_loss: 1.0618049137
each_epoch: 199 num_epochs: 200 train_loss: 0.846592487652 valid_loss: 1.06185645216

In [14]:
plt.plot(losses_tx2['train'], label='Train loss')
plt.plot(losses_tx2['valid'], label='Valid loss')
plt.legend()
_ = plt.ylim()


Test predictions

Here, we test our NN on the test data to view how well the NN is modeling/predicting the test dataset. If something is wrong, the NN is NOT implemented correctly.


In [34]:
fig, ax = plt.subplots(figsize=(8,4))

mean, std = scaled_features_5x2['steps']
predictions_1xt = nn.run(X_txn=test_features_txn).T*std + mean
ax.plot(predictions_1xt[0], label='Prediction', color='b')
ax.plot((test_targets_txm*std + mean).values, label='Data', color='g')
ax.legend()


Out[34]:
<matplotlib.legend.Legend at 0x7fbdfd842710>

In [35]:
fig, ax_pred = plt.subplots(figsize=(8,4))
ax_pred.plot(predictions_1xt[0], label='Prediction', color='b')
ax_pred.legend()


Out[35]:
<matplotlib.legend.Legend at 0x7fbdfd7e7978>

In [36]:
fig, ax_data = plt.subplots(figsize=(8,4))
ax_data.plot((test_targets_txm*std + mean).values, label='Data', color='g')
ax_data.legend()


Out[36]:
<matplotlib.legend.Legend at 0x7fbdfd7054e0>

Discussion: Thinking about our results for conclusion and wrap-up.

Answer these questions concluding our results or for drawing conclusion out of the results: How well does the NN predict/model the data? Where does it fail? Why does it fail in the place it fails?