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!!

No comments:

Post a Comment