Basics with numerical time-series

  • Find this notebook at EpyNN/epynnlive/dummy_time/train.ipynb.

  • Regular python code at EpyNN/epynnlive/dummy_time/train.py.

Run the notebook online with Google Colab.

Level: Intermediate

In this notebook we will review:

  • Handling univariate time series data to proceed with Neural Network regression.

  • Training of Feed-Forward (FF) and Recurrent Neural Network (RNN) for binary classification tasks.

  • Overfitting of the model to the training data and the impact of Dropout regularization.

It is assumed that the following basics notebooks were already reviewed:

This notebook does not enhance, extend or replace EpyNN’s documentation.

Relevant documentation pages for the current notebook:

Environment and data

Follow this link for details about data preparation.

Briefly, sample features are univariate time series which may consist of only white noise (negative) or white noise supplemented with a pure sine-wave of random frequency (positive).

The goal of the game is to train a Neural Network which may be able to detect if sample features do or do not contain a true signal.

[1]:
# EpyNN/epynnlive/dummy_time/train.ipynb
# Install dependencies
!pip3 install --upgrade-strategy only-if-needed epynn

# Standard library imports
import random

# Related third party imports
import matplotlib.pyplot as plt
import numpy as np

# Local application/library specific imports
import epynn.initialize
from epynn.commons.maths import relu, softmax
from epynn.commons.library import (
    configure_directory,
    read_model,
)
from epynn.network.models import EpyNN
from epynn.dropout.models import Dropout
from epynn.embedding.models import Embedding
from epynn.flatten.models import Flatten
from epynn.rnn.models import RNN
from epynn.dense.models import Dense
from epynnlive.dummy_time.prepare_dataset import prepare_dataset
from epynnlive.dummy_time.settings import se_hPars


########################## CONFIGURE ##########################
random.seed(1)
np.random.seed(1)

np.set_printoptions(threshold=10)

np.seterr(all='warn')

configure_directory()


############################ DATASET ##########################
X_features, Y_label = prepare_dataset(N_SAMPLES=1024)

Let’s control what we retrieved.

[2]:
print(X_features[0].shape)
print(X_features[0])
(128, 1)
[[-0.35376783]
 [-0.17895082]
 [-0.29156932]
 ...
 [-0.25263271]
 [-0.74700792]
 [-0.16726332]]

This is called a univariate time series because it contains a single measurement per time step. Note we retrieved data with a sampling rate of 128 Hz and duration of 1 second for a total of 128 points.

[3]:
plt.plot(X_features[0], label='label: %s' % Y_label[0])
plt.plot(X_features[1], label='label: %s' % Y_label[1])
plt.legend()
plt.show()
plt.close()
../../_images/epynnlive_dummy_time_train_11_0.png

While sample features corresponding to label: 1 do not contain a true signal, sample features corresponding to label: 0 do contain a true signal of random frequency.

Feed-Forward (FF)

Feed-Forward Neural Networks are advantageous compared to other architectures because they are relatively fast to train, and most often less sensitive to parameters of training, also called hyperparameters. Therefore, they are most commonly a first choice when dealing with a new problem and prior to further insights.

Embedding

In EpyNN, sample features (X_features) and labels (Y_label) are passed to the corresponding arguments value when instantiating the embedding or input layer. It is required to use this layer in EpyNN, which is then always the first layer of the network architecture. The layer consists of a simple forward pass but contains several routines to prepare data according to user choices.

[4]:
embedding = Embedding(X_data=X_features,
                      Y_data=Y_label,
                      Y_encode=True,
                      relative_size=(2, 1, 0))

Herein, we instructed to the class constructor Embedding to one-hot encode the set of sample label Y_encode=True. We also instructed to split data in order to build a training set contraining 2/3 of the whole set while the validation set will contain 1/3.

The training procedure is exclusively driven by the training data. However, one may judge how general the model can be by comparing metrics with evaluation on the validation set.

Flatten-(Dense)n

As introduced before, sample features are univariate time series and as such the set of sample features has 3 dimensions.

[5]:
print(embedding.dtrain.X.shape)    # (m, s, v)
(683, 128, 1)

It contains 683 samples (m), each described by a sequence of 128 features (s) containing 1 element (v).

However, the fully-connected or dense layer can only process bi-dimensionnal input arrays. That is the reason why we need to invoke a flatten layer in between the embedding and dense layer.

[6]:
flatten = Flatten()

# Original shape (m, s, v)
print(embedding.dtrain.X.shape)

# Flatten on forward pass (m, s * v)
print (flatten.forward(embedding.dtrain.X).shape)

# Reverse on backward pass (m, s, v)
print (flatten.backward(flatten.forward(embedding.dtrain.X)).shape)
(683, 128, 1)
(683, 128)
(683, 128, 1)

In other words, the flatten layer is an adapter.

Let’s now build the network architecture.

[7]:
name = 'Flatten_Dense-64-relu_Dense-2-softmax'

# Tune defaults learning rate from 0.1 to 0.005
se_hPars['learning_rate'] = 0.005

flatten = Flatten()

hidden_dense = Dense(64, relu)

dense = Dense(2, softmax)

layers = [embedding, flatten, hidden_dense, dense]

model = EpyNN(layers=layers, name=name)

The network - or model - architecture is composed of the mandatory embedding input layer, one hidden_dense layer with 64 nodes and ReLU activation function and finally an output dense layer with 2 nodes - because we have two distinct one-hot encoded labels - and a softmax activation function.

We now initialize the model and instruct it to use a Mean Square Error cost function with network seeding for reproducibility and we provide our custom hyperparameters.

[8]:
model.initialize(loss='MSE', seed=1, se_hPars=se_hPars.copy(), end='\r')
--- EpyNN Check OK! ---                                                                             

The initialize method performs a dry epoch which includes all steps but omits parameters update.

We can now proceed with the training.

[9]:
model.train(epochs=100, init_logs=False)
Epoch 99 - Batch 0/0 - Accuracy: 1.0 Cost: 0.00075 - TIME: 7.75s RATE: 1.29e+01e/s TTC: 0s          

+-------+----------+----------+----------+-------+--------+-------+--------------------------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  MSE   |       |                    Experiment                    |
|       |  Dense   |  Dense   |  dtrain  | dval  | dtrain | dval  |                                                  |
+-------+----------+----------+----------+-------+--------+-------+--------------------------------------------------+
|   0   | 5.00e-03 | 5.00e-03 |  0.722   | 0.695 | 0.197  | 0.214 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  10   | 5.00e-03 | 5.00e-03 |  0.975   | 0.868 | 0.031  | 0.097 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  20   | 5.00e-03 | 5.00e-03 |  1.000   | 0.894 | 0.008  | 0.080 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  30   | 5.00e-03 | 5.00e-03 |  1.000   | 0.900 | 0.004  | 0.077 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  40   | 5.00e-03 | 5.00e-03 |  1.000   | 0.909 | 0.003  | 0.076 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  50   | 5.00e-03 | 5.00e-03 |  1.000   | 0.909 | 0.002  | 0.075 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  60   | 5.00e-03 | 5.00e-03 |  1.000   | 0.909 | 0.001  | 0.075 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  70   | 5.00e-03 | 5.00e-03 |  1.000   | 0.912 | 0.001  | 0.075 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  80   | 5.00e-03 | 5.00e-03 |  1.000   | 0.912 | 0.001  | 0.075 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  90   | 5.00e-03 | 5.00e-03 |  1.000   | 0.912 | 0.001  | 0.075 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
|  99   | 5.00e-03 | 5.00e-03 |  1.000   | 0.909 | 0.001  | 0.074 | 1635012768_Flatten_Dense-64-relu_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+--------------------------------------------------+

We can observe on the logs that an accuracy of 1 was reached after 40 iterations on the training set with a cost near zero. By contrast, we can observe that - although good - the metrics and cost computed on the validation set ran behind from the early epochs of the regression.

[10]:
model.plot(path=False)
../../_images/epynnlive_dummy_time_train_32_0.png

When plotting the accuracy and cost for training and validation sets, these differences are even more obvious.

This is called overfitting of the model to the training data. In other words, the model represents very well - and even exactly - the data from which it was trained, but lacks such performance on independant data.

There are many ways to limit such overfitting when designing or training a Neural Network. Herein we are going to experiment the dropout regularization method to see how it can impact such unwanted overfitting behavior.

For code, maths and pictures behind the Flatten and Dense layers, follow these links:

Flatten-(Dense)n with Dropout

You can follow `this link <>`__ for details on the dropout layer.

Briefly, the Dropout regularization layer randomly subsamples the output of the previous layer and forwards the product to the next layer. By introducing such instability in the network, the layer reduces the thinning capacity of the network which may be of interest to prevent overfitting, which happens when the model is too closely related to the training data.

In EpyNN, the class constructor Dropout() takes a single argument drop_prob which represents the probability of one element in the input array to be preserved in the output array.

For instance.

[11]:
test_array = np.random.standard_normal((5, 5))

D1 = (np.random.uniform(0, 1, test_array.shape) < 1)
D05 = (np.random.uniform(0, 1, test_array.shape) < 0.5)
D0 = (np.random.uniform(0, 1, test_array.shape) < 0)

print(test_array)
print(test_array * D1)    # drop_prob = 1 - No dropout
print(test_array * D05)   # drop_prob = 0.5 - Common value
print(test_array * D0)    # drop_prob = 0 - Output is null
[[-0.40461632  0.56992124 -0.188923   -1.92933133 -0.69195013]
 [ 1.04594288 -0.42813771  0.89180849  0.84383519  0.65651707]
 [-0.42446322 -1.20019422  2.12126642  0.27575357 -0.67915118]
 [-0.79589247 -0.40698592 -1.54560858  0.40910712 -0.89735926]
 [-1.02323887 -0.73387254 -0.17314366  0.50633278  2.35972254]]
[[-0.40461632  0.56992124 -0.188923   -1.92933133 -0.69195013]
 [ 1.04594288 -0.42813771  0.89180849  0.84383519  0.65651707]
 [-0.42446322 -1.20019422  2.12126642  0.27575357 -0.67915118]
 [-0.79589247 -0.40698592 -1.54560858  0.40910712 -0.89735926]
 [-1.02323887 -0.73387254 -0.17314366  0.50633278  2.35972254]]
[[-0.40461632  0.56992124 -0.         -1.92933133 -0.69195013]
 [ 0.         -0.          0.89180849  0.          0.        ]
 [-0.42446322 -1.20019422  2.12126642  0.27575357 -0.67915118]
 [-0.79589247 -0.40698592 -1.54560858  0.40910712 -0.89735926]
 [-0.         -0.         -0.          0.          2.35972254]]
[[-0.  0. -0. -0. -0.]
 [ 0. -0.  0.  0.  0.]
 [-0. -0.  0.  0. -0.]
 [-0. -0. -0.  0. -0.]
 [-0. -0. -0.  0.  0.]]

Usually, values for drop_prob are within 0-0.5.

Let’s build the same Feed-Forward network as above but with the implementation of two Dropout layers.

[12]:
name = 'Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax'

se_hPars['learning_rate'] = 0.005

flatten = Flatten()

dropout1 = Dropout(drop_prob=0.2)

hidden_dense = Dense(64, relu)

dropout2 = Dropout(drop_prob=0.5)

dense = Dense(2, softmax)

layers = [embedding, flatten, dropout1, hidden_dense, dropout2, dense]

model = EpyNN(layers=layers, name=name)

We have set up a first dropout1 between the flatten and hidden_dense layer as well as a second one between hidden_dense and dense.

Note the drop_prob values are different for the two dropout layers. We will dropt 0.2 of the input for the first, and 0.5 for the second. Those settings are quite empirical, better just to test and see.

Initialize with the same settings as is the no-dropout setup.

[13]:
model.initialize(loss='MSE', seed=1, se_hPars=se_hPars.copy(), end='\r')
--- EpyNN Check OK! ---                                                                             

You can see the dropout layers did appear in the check. Let’s proceed with training.

[14]:
model.train(epochs=100, init_logs=False)
Epoch 99 - Batch 0/0 - Accuracy: 0.993 Cost: 0.0111 - TIME: 8.1s RATE: 1.23e+01e/s TTC: 0s          

+-------+----------+----------+----------+-------+--------+-------+------------------------------------------------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  MSE   |       |                               Experiment                               |
|       |  Dense   |  Dense   |  dtrain  | dval  | dtrain | dval  |                                                                        |
+-------+----------+----------+----------+-------+--------+-------+------------------------------------------------------------------------+
|   0   | 5.00e-03 | 5.00e-03 |  0.518   | 0.510 | 0.303  | 0.305 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  10   | 5.00e-03 | 5.00e-03 |  0.791   | 0.736 | 0.143  | 0.173 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  20   | 5.00e-03 | 5.00e-03 |  0.922   | 0.891 | 0.061  | 0.085 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  30   | 5.00e-03 | 5.00e-03 |  0.952   | 0.897 | 0.044  | 0.079 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  40   | 5.00e-03 | 5.00e-03 |  0.971   | 0.924 | 0.030  | 0.066 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  50   | 5.00e-03 | 5.00e-03 |  0.977   | 0.927 | 0.026  | 0.068 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  60   | 5.00e-03 | 5.00e-03 |  0.980   | 0.915 | 0.022  | 0.065 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  70   | 5.00e-03 | 5.00e-03 |  0.987   | 0.918 | 0.017  | 0.061 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  80   | 5.00e-03 | 5.00e-03 |  0.985   | 0.921 | 0.014  | 0.058 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  90   | 5.00e-03 | 5.00e-03 |  0.988   | 0.891 | 0.012  | 0.073 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
|  99   | 5.00e-03 | 5.00e-03 |  0.974   | 0.938 | 0.021  | 0.055 | 1635012776_Flatten_Dropout-02_Dense-64-relu_Dropout-05_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+------------------------------------------------------------------------+

It is clear that the delta between training and validation set is much reduced now, both for accuracy metrics and MSE cost.

[15]:
model.plot(path=False)
../../_images/epynnlive_dummy_time_train_45_0.png

In brief, think about using dropout layers to reduce overfitting, alone or in combination with other methods.

For code, maths and pictures behind the Dropout layer, follow these links:

Recurrent Neural Network (RNN)

When dealing with any sort of sequential data, it is often suggested to use recurrent architectures because they can process three-dimensional input arrays and take advantage of the sequential nature of sample features.

Embedding

Let’s embed our data again, using the same settings as before, and proceed with a little refresh.

[16]:
embedding = Embedding(X_data=X_features,
                      Y_data=Y_label,
                      Y_encode=True,
                      relative_size=(2, 1, 0))

print(embedding.dtrain.X.shape)        # (m, s, v)
print(embedding.dtrain.X[:, 0].shape)  # Input shape at sequence step 0
(683, 128, 1)
(683, 1)

We have 683 samples (m) with sequential features of length 128 (s) which represents a univariate time series (v).

We recalled before that sample features may be white noise, or white noise combined with a pure sine-wave of random frequency. While there is no expected correlation through time within the white noise, we expect a periodic pattern to repeat in the case where a pure since-wave is also present in sample features.

Recurrent layers are said to have some internal memory of such periodic patterns because:

  • One recurrent layer is made of recurrent units or cells.

  • One unit processes every step in one sequence at time within a for loop.

  • The trick is: the output of every iteration - every step - is fed back in the unit for every step forward along the sequence.

Said differently, the output of one recurrent cell does not only depend of the input at a given sequence step.

This output of one iteration in sequence, called h for hidden cell state, becomes more and more “impregnated” by outputs of previous iterations along with the step forward in the sequence.

These statements may be hard to understand. See RNN - Forward for some graphical elements.

RNN-Dense

Below we will instantiate a simple RNN layer composed of 10 cells which forward the last (10th) hidden state to the output dense layer.

[17]:
name = 'RNN-10_Flatten_Dense-2-softmax'

se_hPars['learning_rate'] = 0.01
se_hPars['softmax_temperature'] = 5

rnn = RNN(10)

dense = Dense(2, softmax)

layers = [embedding, rnn, dense]

model = EpyNN(layers=layers, name=name)

In contrast to the Feed-Forward network seen above, the Flatten layer is absent herein. This is because RNN returns the last hidden state of shape (10,). The flatten operation is therefore unnecessary. Note that RNN in EpyNN may return all hidden states sequences (RNN(10, sequences=True)) which then would require the use of a flatten layer because the shape would be (128, 10).

Let’s give a try to this RNN-based network.

[18]:
model.initialize(loss='MSE', seed=1, se_hPars=se_hPars.copy(), end='\r')
--- EpyNN Check OK! ---                                                                             

Start training.

[19]:
model.train(epochs=100, init_logs=False)
Epoch 99 - Batch 0/0 - Accuracy: 0.693 Cost: 0.2105 - TIME: 30.35s RATE: 3.29e+00e/s TTC: 1s        

+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  MSE   |       |                Experiment                 |
|       |   RNN    |  Dense   |  dtrain  | dval  | dtrain | dval  |                                           |
+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+
|   0   | 1.00e-02 | 1.00e-02 |  0.533   | 0.499 | 0.248  | 0.251 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  10   | 1.00e-02 | 1.00e-02 |  0.561   | 0.507 | 0.247  | 0.249 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  20   | 1.00e-02 | 1.00e-02 |  0.564   | 0.510 | 0.245  | 0.248 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  30   | 1.00e-02 | 1.00e-02 |  0.581   | 0.513 | 0.242  | 0.246 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  40   | 1.00e-02 | 1.00e-02 |  0.599   | 0.528 | 0.239  | 0.244 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  50   | 1.00e-02 | 1.00e-02 |  0.609   | 0.548 | 0.236  | 0.241 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  60   | 1.00e-02 | 1.00e-02 |  0.625   | 0.589 | 0.231  | 0.237 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  70   | 1.00e-02 | 1.00e-02 |  0.638   | 0.622 | 0.226  | 0.232 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  80   | 1.00e-02 | 1.00e-02 |  0.657   | 0.628 | 0.221  | 0.227 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  90   | 1.00e-02 | 1.00e-02 |  0.673   | 0.651 | 0.215  | 0.222 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
|  99   | 1.00e-02 | 1.00e-02 |  0.694   | 0.663 | 0.210  | 0.216 | 1635012784_RNN-10_Flatten_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+

We observe that the model was still converging at the end of the training. Interestingly, there is no overfitting at all. Accuracy and cost (MSE) are even higher and lower, respectively, for the validation set.

[20]:
model.plot(path=False)
../../_images/epynnlive_dummy_time_train_62_0.png

It is clear that this model would need more training epochs to converge, but this would not fix the overfitting problem.

For code, maths and pictures behind the RNN layer, follow this link:

RNN-Dense with SGD

In the above-example we used Gradient Descent (GD) optimization, meaning that:

  • All training examples are in a single batch.

  • There is a single weight update by the training epoch.

Below we set batch_size to 32 to use Stochastic Gradient Descent (SGD), meaning that:

  • All training examples are divided into batches of size 32, yielding N_SAMPLES // 32 batches.

  • There are as many weight update by training epochs than training batches.

[21]:
embedding = Embedding(X_data=X_features,
                      Y_data=Y_label,
                      Y_encode=True,
                      batch_size=32,
                      relative_size=(2, 1, 0))

We use the same network as before.

[22]:
name = 'RNN-10_Flatten_Dense-2-softmax'

se_hPars['learning_rate'] = 0.01
se_hPars['softmax_temperature'] = 5

rnn = RNN(10)

dense = Dense(2, softmax)

layers = [embedding, rnn, dense]

model = EpyNN(layers=layers, name=name)

We initialize and train the nework.

[23]:
model.initialize(loss='MSE', seed=1, se_hPars=se_hPars.copy(), end='\r')

model.train(epochs=100, init_logs=False)
Epoch 99 - Batch 20/20 - Accuracy: 0.969 Cost: 0.02007 - TIME: 57.12s RATE: 1.75e+00e/s TTC: 1s     

+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+
| epoch |  lrate   |  lrate   | accuracy |       |  MSE   |       |                Experiment                 |
|       |   RNN    |  Dense   |  dtrain  | dval  | dtrain | dval  |                                           |
+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+
|   0   | 1.00e-02 | 1.00e-02 |  0.540   | 0.516 | 0.247  | 0.250 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  10   | 1.00e-02 | 1.00e-02 |  0.638   | 0.630 | 0.226  | 0.230 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  20   | 1.00e-02 | 1.00e-02 |  0.900   | 0.903 | 0.119  | 0.117 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  30   | 1.00e-02 | 1.00e-02 |  0.895   | 0.900 | 0.097  | 0.094 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  40   | 1.00e-02 | 1.00e-02 |  0.959   | 0.971 | 0.038  | 0.029 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  50   | 1.00e-02 | 1.00e-02 |  0.974   | 0.977 | 0.025  | 0.022 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  60   | 1.00e-02 | 1.00e-02 |  0.974   | 0.977 | 0.023  | 0.019 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  70   | 1.00e-02 | 1.00e-02 |  0.972   | 0.974 | 0.024  | 0.024 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  80   | 1.00e-02 | 1.00e-02 |  0.966   | 0.974 | 0.028  | 0.024 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  90   | 1.00e-02 | 1.00e-02 |  0.985   | 0.991 | 0.014  | 0.010 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
|  99   | 1.00e-02 | 1.00e-02 |  0.982   | 0.991 | 0.016  | 0.009 | 1635012814_RNN-10_Flatten_Dense-2-softmax |
+-------+----------+----------+----------+-------+--------+-------+-------------------------------------------+

For the same number of training epochs, accuracy is much higher.

[24]:
model.plot(path=False)
../../_images/epynnlive_dummy_time_train_73_0.png

And there is no overfitting, this is an excellent model.

For code, maths and pictures behind the RNN layer, follow this link:

Write, read & Predict

A trained model can be written on disk such as:

[25]:
model.write()

# model.write(path=/your/custom/path)
Make: /media/synthase/beta/EpyNN/epynnlive/dummy_time/models/1635012814_RNN-10_Flatten_Dense-2-softmax.pickle

A model can be read from disk such as:

[26]:
model = read_model()

# model = read_model(path=/your/custom/path)

We can retrieve new features and predict on them.

[27]:
X_features, _ = prepare_dataset(N_SAMPLES=10)

dset = model.predict(X_features)

Results can be extracted such as:

[28]:
for n, pred, probs in zip(dset.ids, dset.P, dset.A):
    print(n, pred, probs)
0 0 [0.98718813 0.01281187]
1 0 [0.94121987 0.05878013]
2 1 [0.02139625 0.97860375]
3 0 [0.95959614 0.04040386]
4 1 [0.02610764 0.97389236]
5 1 [0.01849713 0.98150287]
6 1 [0.018713 0.981287]
7 1 [0.01967183 0.98032817]
8 0 [0.96032797 0.03967203]
9 0 [0.93915586 0.06084414]