Saturday, 23 January 2021

Tensorflow and predicting votes in Northern Ireland

Using the data from 

 SF Westinster election results

a neural network was trained with number of candidates in an election as input, and number of votes as output. Here is the python code:


import tensorflow as tf



x_train = [0.102, 0.005, 0.002, 0.012, 0.012, 0.014, 0.014, 0.014, 0.017, 0.018, 0.018, 0.017, 0.018, 0.018, 0.015]
y_train = [0.417211, 0.34181, 0.23362, 0.15231, 0.63415, 0.10270, 0.83389, 0.78291, 0.126921, 0.175933, 0.17453, 0.171942, 0.176232, 0.238915, 0.181853]


m = tf.Variable(0.)
c = tf.Variable(0.)

x = tf.placeholder(dtype = tf.float32)
y = tf.placeholder(dtype=tf.float32)



# using sigmoid function y = mx + c
model = tf.nn.sigmoid(tf.add(tf.multiply(x, m),c))

pred = tf.add(tf.multiply(x, m),c)
error = pred - y
loss = tf.reduce_mean(tf.square(error))

learn_rate = 0.005
num_epochs = 350

#using Gradient Descent with learning rate 0.005
train = tf.train.GradientDescentOptimizer(learn_rate).minimize(loss)
session = tf.Session()
init = tf.global_variables_initializer()

loss_trace = []


session.run(init)

#training model for 350 iterations
for epoch in range(num_epochs):
    session.run([train], {x:x_train, y:y_train})
#   lossval = session.run([loss], {x:x_train, y:y_train})
    loss_trace.append(session.run([loss], {x:x_train, y:y_train}))
    pred = tf.add(tf.multiply(x, m),c)
    error = pred - y
    error = session.run([error], {x:x_train, y:y_train})
    prediction = session.run([pred],{x:x_train, y:y_train})
    print('Iter: ', epoch, 'MSE in training: ', loss_trace[-1])
 
#final values of m and c
print('')
print('m =', session.run(m))
print('c =', session.run(c))
print('Final loss: ', loss_trace[-1])
print('Prediction :' , prediction)
print('Error: ', error)

import matplotlib.pyplot as plt
plt.xlabel('Number of epochs --------->')
plt.ylabel('Error (MSE) --------->')
plt.plot(loss_trace)
plt.show()


(virtualenvironment.) david@debian:~/pythonvirenv$ python3 sfseats.py
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:455: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint8 = np.dtype([("qint8", np.int8, 1)])
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:456: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_quint8 = np.dtype([("quint8", np.uint8, 1)])
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:457: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint16 = np.dtype([("qint16", np.int16, 1)])
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:458: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_quint16 = np.dtype([("quint16", np.uint16, 1)])
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:459: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  _np_qint32 = np.dtype([("qint32", np.int32, 1)])
/home/david/pythonvirenv/virtualenvironment./lib/python3.5/site-packages/tensorflow/python/framework/dtypes.py:462: FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated; in a future version of numpy, it will be understood as (type, (1,)) / '(1,)type'.
  np_resource = np.dtype([("resource", np.ubyte, 1)])
2021-01-23 19:45:45.073012: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.1 instructions, but these are available on your machine and could speed up CPU computations.
2021-01-23 19:45:45.073108: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.
2021-01-23 19:45:45.073137: W tensorflow/core/platform/cpu_feature_guard.cc:45] The TensorFlow library wasn't compiled to use AVX instructions, but these are available on your machine and could speed up CPU computations.
Iter:  0 MSE in training:  [0.15254016]
Iter:  1 MSE in training:  [0.15058766]
Iter:  2 MSE in training:  [0.14867406]
Iter:  3 MSE in training:  [0.14679854]
Iter:  4 MSE in training:  [0.14496036]
Iter:  5 MSE in training:  [0.14315876]
.

.

'

Iter:  345 MSE in training:  [0.054557513]
Iter:  346 MSE in training:  [0.054555614]
Iter:  347 MSE in training:  [0.05455375]
Iter:  348 MSE in training:  [0.054551926]
Iter:  349 MSE in training:  [0.054550137]

m = 0.0074915974
c = 0.30681604
Final loss:  [0.054550137]
Prediction : [array([0.30758017, 0.3068535 , 0.30683103, 0.30690596, 0.30690596,
       0.30692092, 0.30692092, 0.30692092, 0.3069434 , 0.3069509 ,
       0.3069509 , 0.3069434 , 0.3069509 , 0.3069509 , 0.30692843],
      dtype=float32)]
Error:  [array([-0.10963082, -0.03495649,  0.07321103,  0.15459596, -0.32724407,
        0.20422092, -0.5269691 , -0.47598907,  0.18002239,  0.1310179 ,
        0.1324209 ,  0.13500139,  0.1307189 ,  0.0680359 ,  0.12507543],
      dtype=float32)]


From y = mx + c

The votes for Westminster start to change when  x is 0 for y = mx + c 

When x is 0 on the sigmoid curve it is going from a negative value to a positive one indicating that the neural network has started to learn and has identified a pattern. 

Where y is the number of votes 

y = 0.0074915974x + 0.30681604

When x = 0   

y = 0.0074915974*0 + 0.30681604

 y = 0 + 0.30681604

y = 0.30681604

To scale up by a thousand as the input vectors were normalised to fall between 0 and 1 by dividing them by a thousand,

y = 306.81604 

we get there must be 306 to 307 supporters or potential voters for the number of seats, or, the voting situation for Westminster to change in a general election.


No comments:

Post a Comment