-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnn.py
107 lines (93 loc) · 3.34 KB
/
nn.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
'neural network'
import warnings
import numpy as np
warnings.filterwarnings('ignore')
BOARD_LENGTH = 3
INPUT_LAYER_AMT = BOARD_LENGTH ** 2
HIDDEN_LAYER_AMT = INPUT_LAYER_AMT + BOARD_LENGTH
OUTPUT_LAYER_AMT = INPUT_LAYER_AMT
EPOCHS = 100
LEARNING_RATE = 1
def sigmoid(z):
'returns sigmoid of z'
return 1/(1+np.exp(-z))
def deriv_sigmoid(z):
'returns the derivative of the sigmoid of z'
return sigmoid(z)*(1-sigmoid(z))
def rand(shape):
'returns a numpy array of values -1 to 1 with the given shape'
return np.random.uniform(-1, 1, shape)
def gradient_descent(layer, prev_layer, y=None, cost=None, learning_rate=1): # i give up
'performs gradient descent on the layer'
if cost is None:
cost = layer.input-y
dy_yhat = cost
dz_y = deriv_sigmoid(layer.input)
dw_z = prev_layer.input.T
dw_yhat = dy_yhat * dz_y * dw_z
da_yhat = dy_yhat * dz_y * layer.array.sum(axis=1)[:, np.newaxis]
da_yhat = da_yhat.sum(axis=1)[:, np.newaxis].T
layer.array -= (dw_yhat*learning_rate)
db_yhat = dy_yhat * dz_y
layer.biases -= (db_yhat.T*learning_rate)
return da_yhat
class NetworkLayer:
'layer for NeuralNetwork class'
def __init__(self, nparray=None, biases=None):
self.array = nparray
self.input = None
self.biases = biases
def __len__(self):
return len(self.array)
class NeuralNetwork:
'makes a neural network'
def __init__(self, hidden_layers, output_layer, board_length):
self.input_layer = NetworkLayer(np.array(0))
self.hidden_layers = [NetworkLayer(hidden[0], hidden[1]) for hidden in hidden_layers]
self.output_layer = NetworkLayer(output_layer[0], output_layer[1])
self.layers = [self.input_layer]
self.value = None
self.board_length = board_length
for hidden_layer in self.hidden_layers:
self.layers.append(hidden_layer)
self.layers.append(self.output_layer)
def output(self):
'outputs the network weights'
for a in self.layers:
print(a.array)
def forward_prop(self, x) -> np.ndarray:
'Forward propagates the network'
mult1 = x[:, np.newaxis].T
mult2 = self.hidden_layers[0].array
self.input_layer.input = mult1
for index, network_layer in enumerate(self.layers[1:]):
dot = mult2 * mult1.T
add_bias = dot.T.sum(axis=1) + network_layer.biases.T
mult1 = sigmoid(add_bias)
network_layer.input = mult1
if index == len(self.layers)-2:
break
mult2 = self.layers[index+2].array
return mult1
def back_prop(self, y, learning_rate, da_yhat=None):
'Back propagates the network'
if da_yhat is None:
da_yhat = gradient_descent(
self.output_layer,
self.hidden_layers[-1],
y,
learning_rate=learning_rate
)
for index, layer in reversed(list(enumerate(self.layers[1:-1]))):
index += 1
da_yhat = gradient_descent(
layer,
self.layers[index-1],
None,
da_yhat,
learning_rate=learning_rate
)
def clear_input(self):
'clears the input from all the layers'
for layer in self.layers:
layer.input = None