Sunday, 30 June 2019

Predicting time with a neural network

The following network was trained with the available bank balance at the time of going to a cafe, and the time spent there on that available balance.
The balance was normalised by dividing by 1000 so that the values fell between 0 and 1. Similarly the time (minutes) was divided by 100.

The code from this program can be saved as filename.py

The network can be run from a terminal by typing:
python filename.py

Here is the code:

from numpy import exp, array, random, dot
import numpy as np


class NeuralNetwork():
    def __init__(self):
        # Seed the random number generator, so it generates the same numbers
        # every time the program runs.
        np.random.seed(1)

        # We model a single neuron, with 1 input connection and 1 output connection.
        # We assign random weights to a 1 x 1 matrix, with values in the range -1 to 1
        # and mean 0.
        self.synaptic_weights =   np.random.random((1, 1)) - 1

    # The Sigmoid function, which describes an S shaped curve.
    # We pass the weighted sum of the inputs through this function to
    # normalise them between 0 and 1.
    def sigmoid(self, x):
        return 1 / (1 + exp(-x))

    # The derivative of the Sigmoid function.
    # This is the gradient of the Sigmoid curve.
    # It indicates how confident we are about the existing weight.
    def sigmoid_derivative(self, x):
        return x * (1 - x)

    # We train the neural network through a process of trial and error.
    # Adjusting the synaptic weights each time.
    def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations):
        for iteration in xrange(number_of_training_iterations):
            # Pass the training set through our neural network (a single neuron).
            output = self.think(training_set_inputs)

            # Calculate the error (The difference between the desired output
            # and the predicted output).
            error = training_set_outputs - output

            # Multiply the error by the input and again by the gradient of the Sigmoid curve.
            # This means less confident weights are adjusted more.
            # This means inputs, which are zero, do not cause changes to the weights.
            adjustment = np.dot(training_set_inputs.T, error * self.sigmoid_derivative(output))

            # Adjust the weights.
            self.synaptic_weights += adjustment

    # The neural network thinks.
    def think(self, inputs):
        inputs = inputs.astype(float)       
    # Pass inputs through our neural network (our single neuron).
        output = self.sigmoid(np.dot(inputs, self.synaptic_weights))
        return output

#        return self.__sigmoid(np.dot(training_set_inputs, self.synaptic_weights))


if __name__ == "__main__":

    #Intialise a single neuron neural network.
    neural_network = NeuralNetwork()

training_set_inputs = np.array([[0.14569],
[0.17944],
[0.15496],
[0.07607],
[0.01223],
[0.00873],
[0.26456],
[0.19928],
[0.01417],
[0.00220],
[0.16451],
[0.09408],
[0.23073],
[0.13403],
[0.11177],
[0.29657],
[0.21266],
[0.11302],
[0.29185],
[0.24873],
[0.15997],
[0.09582],
[0.30616],
[0.11861],
[0.18292],
[0.12121],
[0.08206 ]])

#training_set_inputs = np.array(training_set_inputs, ndmin = 2).T

print(training_set_inputs, training_set_inputs.shape)

#training_set_outputs = np.array([[0.51050, 0.50950, 0.50750, 0.510, 0.5110, 0.50250, 0.50450, 0.5090, 0.50750, 0.5050, 0.503, 0.5065, 0.50750, 0.505, 0.503, 0.50650, 0.507, 0.5050, 0.49420, 0.5070, 0.499, 0.49330, 0.5095, 0.51650, 0.501, 0.51150]]).T

training_set_outputs = np.array([[0.381, 0.96, 0.385, 0.369, 0.3225, 0.28, 0.2776, 0.2641, 0.3415, 0.6881, 0.4925, 0.5263, 0.2965, 0.8622, 0.4678, 0.3493, 0.3008, 0.2553, 0.178, 0.3826, 0.3378, 0.4217, 0.42, 0.4197, 0.3938, 0.5988, 0.5358]]).T

#training_set_outputs = np.array(training_set_outputs, ndmin = 1).T

print(training_set_outputs, training_set_outputs.shape)


print "Random starting synaptic weights: "
print neural_network.synaptic_weights


    # Train the neural network using a training set.
    # Do it 10,000 times and make small adjustments each time.
neural_network.train(training_set_inputs, training_set_outputs, 10000)

print "New synaptic weights after training: "
print neural_network.synaptic_weights
user_input_one = str(input("User Input: "))
    # Test the neural network with a new situation.
print("Considering new situation of available balance [input value] -> ?: ", user_input_one)
print(neural_network.think(np.array([user_input_one])))# enter some input value inside brackets



The screen output is as follows:

david@debian:~/neuralnetworks/Scikitnumpy$ python hobtimepredict.py
(array([[ 0.14569],
       [ 0.17944],
       [ 0.15496],
       [ 0.07607],
       [ 0.01223],
       [ 0.00873],
       [ 0.26456],
       [ 0.19928],
       [ 0.01417],
       [ 0.0022 ],
       [ 0.16451],
       [ 0.09408],
       [ 0.23073],
       [ 0.13403],
       [ 0.11177],
       [ 0.29657],
       [ 0.21266],
       [ 0.11302],
       [ 0.29185],
       [ 0.24873],
       [ 0.15997],
       [ 0.09582],
       [ 0.30616],
       [ 0.11861],
       [ 0.18292],
       [ 0.12121],
       [ 0.08206]]), (27, 1))
(array([[ 0.381 ],
       [ 0.96  ],
       [ 0.385 ],
       [ 0.369 ],
       [ 0.3225],
       [ 0.28  ],
       [ 0.2776],
       [ 0.2641],
       [ 0.3415],
       [ 0.6881],
       [ 0.4925],
       [ 0.5263],
       [ 0.2965],
       [ 0.8622],
       [ 0.4678],
       [ 0.3493],
       [ 0.3008],
       [ 0.2553],
       [ 0.178 ],
       [ 0.3826],
       [ 0.3378],
       [ 0.4217],
       [ 0.42  ],
       [ 0.4197],
       [ 0.3938],
       [ 0.5988],
       [ 0.5358]]), (27, 1))
Random starting synaptic weights:
[[-0.582978]]
New synaptic weights after training:
[[-1.93043177]]
User Input: 0.23223
('Considering new situation of available balance [input value] -> ?: ', '0.23223')
[ 0.38976404]
david@debian:~/neuralnetworks/Scikitnumpy$


The new case of available balance to input is first divided by 1000, so £232.22 becomes 0.23223 to input.
The resulting output time is multiplied by 100 to give 38.976404 minutes.

Enjoy!!

Wednesday, 26 June 2019

Neural network to work out cashflow and timeflow

The following neural network in Python was trained on available cashflow in my bank account prior to the time of purchase of a coffee and snack at a set location. The time spent at this activity at the cafe was measured using a stopwatch. To normalise the data used in training, the available balances were divided by a 1000 and minutes were divided by 100 so all the values fell between 0 and 1. So after running the network, the predicted output for cashflow is multiplied by 1000 and the minutes multiplied by 100. Predicted X for this example is 0.369 * 1000 = £369 predicted available cashflow on approach to the cafe, and the predicted Y  is  0.42 * 100 = 42 minutes predicted time spent there.

After saving the code to a file filename.py it can be run from a terminal by typing python filename.py   

Here is the code:


import numpy as np
from numpy import  array
from sklearn import svm

clf = svm.SVC(gamma=0.001, C=100)

y = np.array([0.381, 0.96, 0.385, 0.369, 0.3225, 0.28, 0.2776, 0.2641, 0.3415,
0.6881, 0.4925, 0.5263, 0.2965, 0.8622, 0.4678, 0.3493, 0.3008, 0.2553, 0.178,
0.3826, 0.3378, 0.4217, 0.42, 0.4197, 0.3938, 0.5988, 0.5358]).T

y = np.array(y, ndmin = 1).T
print(y, y.shape)

x = np.array([0.14569, 0.17944, 0.15496, 0.07607, 0.01223, 0.00873, 0.26456, 0.19928, 0.01417, 0.00220, 0.16451, 0.09408, 0.23073, 0.13403, 0.11177, 0.29657, 0.21266,
0.11302, 0.29185, 0.24873, 0.15997, 0.09582, 0.30616, 0.11861, 0.18292, 0.12121, 0.08206 ]).T

x = np.array(x, ndmin = 2).T
print(x, x.shape)  

xtrain, ytrain =  x[:-1], y[:-1]  

clf.fit(xtrain, ytrain) #train the data

print('Prediction for x:', clf.predict(x[-1])) #predict the data
print('Prediction for y:', clf.predict(y[-1])) #predict the data



Here is the screen / terminal output:

david@debian:~/Timecfnn$ python cashflowtime+time.py
(array([ 0.381 ,  0.96  ,  0.385 ,  0.369 ,  0.3225,  0.28  ,  0.2776,
        0.2641,  0.3415,  0.6881,  0.4925,  0.5263,  0.2965,  0.8622,
        0.4678,  0.3493,  0.3008,  0.2553,  0.178 ,  0.3826,  0.3378,
        0.4217,  0.42  ,  0.4197,  0.3938,  0.5988,  0.5358]), (27,))
(array([[ 0.14569],
       [ 0.17944],
       [ 0.15496],
       [ 0.07607],
       [ 0.01223],
       [ 0.00873],
       [ 0.26456],
       [ 0.19928],
       [ 0.01417],
       [ 0.0022 ],
       [ 0.16451],
       [ 0.09408],
       [ 0.23073],
       [ 0.13403],
       [ 0.11177],
       [ 0.29657],
       [ 0.21266],
       [ 0.11302],
       [ 0.29185],
       [ 0.24873],
       [ 0.15997],
       [ 0.09582],
       [ 0.30616],
       [ 0.11861],
       [ 0.18292],
       [ 0.12121],
       [ 0.08206]]), (27, 1))
('Prediction for x:', array([ 0.369]))
('Prediction for y:', array([ 0.42]))
david@debian:~/Timecfnn$


Acknowledgements: I  would like to thank Jack's Snax of Barum Arcade in Barnstaple for the endless supply of coffee, and houmous and haloumi wraps with lettuce and tomato and pleasant conversation.

Picture: me outside Jack's Snax