-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathNeuralNetwork.py
156 lines (129 loc) · 5.52 KB
/
NeuralNetwork.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import numpy as np
np.set_printoptions(linewidth = 200, precision = 10)
from scipy.special import expit
import numba
from cprofiler import profile
from p5 import *
import copy
class NeuralNetwork:
def __init__(self, settings, inputs):
self.settings = settings
self.num_input = settings.neutalNetworkDimensions["input"]
self.num_hidden = settings.neutalNetworkDimensions["hidden"]
self.num_output = settings.neutalNetworkDimensions["output"]
#self.in_neurons = []
#generate random starting weights for snake
#np.array([np.random.uniform(-1,1) for i in range(8)]).reshape(2,4)
self.whi = np.array([np.random.uniform(-1,1) for i in range(self.num_hidden*(self.num_input+1))]).reshape(self.num_hidden, self.num_input+1)
#self.whi = np.random.rand(self.num_hidden, self.num_input + 1)
self.whh = np.array([np.random.uniform(-1,1) for i in range(self.num_hidden*(self.num_hidden+1))]).reshape(self.num_hidden, self.num_hidden+1)
#self.whh = np.random.rand(self.num_hidden, self.num_hidden + 1)
self.woh = np.array([np.random.uniform(-1,1) for i in range(self.num_output*(self.num_hidden+1))]).reshape(self.num_output, self.num_hidden+1)
#self.woh = np.random.rand(self.num_output, self.num_hidden + 1)
self.dir_array = ["left", "right", "up", "down"]
self.outputArray = []
self.inputs = inputs
self.isBestBrain = False
def controlSnake(self, snake):
self.output(self.inputs.inputVector)
self.updateTurnDirection(snake)
def sigmoid(self,x):
# for i in range(len(x)):
# x[i] = (1 / 1+ np.exp(-x[i]))
# return(x)
return(1 / (1+ np.exp(-x)))
#calculate output by feeding forward through neural network
def output(self,inp):
res1 = self.feedForward(self.whi, inp)
res2 = self.feedForward(self.whh, res1)
res3 = self.feedForward(self.woh, res2)
self.outputArray = res3
#print(self.outputArray)
def feedForward(self, matrix, arr):
tempArr = np.append(arr, [1.0])
tempArr = np.matrix(tempArr).T
res = matrix * tempArr
res = self.sigmoid(res)
res = np.array(res).flatten()
return(res)
def updateTurnDirection(self, snake):
max = 0
maxIndex = 0
for i in range(len(self.outputArray)):
if(self.outputArray[i] > max):
max = self.outputArray[i]
maxIndex = i
if maxIndex == 0:
#left
snake.dir(-1, 0)
elif maxIndex == 1:
#right
snake.dir(1, 0)
elif maxIndex == 2:
#up
snake.dir(0, -1)
elif maxIndex == 3:
#down
snake.dir(0, 1)
def mutate(self):
for i in range(self.whi.shape[0]):
for j in range(self.whi.shape[1]):
if(np.random.random() < self.settings.mutationRate):
self.whi[i,j] += np.random.random()/5
self.whi[i,j] = constrain(self.whi[i,j], -1, 1)
for i in range(self.whh.shape[0]):
for j in range(self.whh.shape[1]):
if(np.random.random() < self.settings.mutationRate):
self.whh[i,j] += np.random.random()/5
self.whh[i,j] = constrain(self.whh[i,j], -1, 1)
for i in range(self.woh.shape[0]):
for j in range(self.woh.shape[1]):
if(np.random.random() < self.settings.mutationRate):
self.woh[i,j] += np.random.random()/5
self.woh[i,j] = constrain(self.woh[i,j], -1, 1)
return(self)
def crossover(self, parent1, parent2):
randC = np.random.randint(self.whi.shape[0])
randR = np.random.randint(self.whi.shape[1])
for i in range(self.whi.shape[0]):
for j in range(self.whi.shape[1]):
if i < randR or ( i == randR and j <= randC):
self.whi[i,j] = parent1.whi[i,j]
else:
self.whi[i,j] = parent2.whi[i,j]
randC = np.random.randint(self.whh.shape[0])
randR = np.random.randint(self.whh.shape[1])
for i in range(self.whh.shape[0]):
for j in range(self.whh.shape[1]):
if i < randR or ( i == randR and j <= randC):
self.whh[i,j] = parent1.whh[i,j]
else:
self.whh[i,j] = parent2.whh[i,j]
randC = np.random.randint(self.woh.shape[0])
randR = np.random.randint(self.woh.shape[1])
for i in range(self.woh.shape[0]):
for j in range(self.woh.shape[1]):
if i < randR or ( i == randR and j <= randC):
self.woh[i,j] = parent1.woh[i,j]
else:
self.woh[i,j] = parent2.woh[i,j]
return(self)
#used for testing, but might be useful for this NN class too
def whi_to_arr(self):
arr = []
for i in range(self.num_hidden):
for j in range(self.num_input+1):
arr.append(self.whi[i][j])
return(arr)
def whh_to_arr(self):
arr = []
for i in range(self.num_hidden):
for j in range(self.num_hidden+1):
arr.append(self.whh[i][j])
return(arr)
def woh_to_arr(self):
arr = []
for i in range(self.num_output):
for j in range(self.num_hidden+1):
arr.append(self.woh[i][j])
return(arr)