-
Notifications
You must be signed in to change notification settings - Fork 0
/
ann.py
82 lines (82 loc) · 3.22 KB
/
ann.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
import numpy as np
class NeuralNetwork(object):
def __init__(self, layers = [2 , 10, 1], activations=['sigmoid', 'sigmoid']):
assert(len(layers) == len(activations)+1)
self.layers = layers
self.activations = activations
self.weights = []
self.biases = []
self.temp_z_s = []
self.temp_a_s = []
for i in range(len(layers)-1):
self.weights.append(np.random.randn(layers[i+1], layers[i]))
self.biases.append(np.random.randn(layers[i+1], 1))
def forward_pass(self, x):
a = np.copy(x)
z_s = []
a_s = [a]
for i in range(len(self.weights)):
activation_function = self.getActivationFunction(self.activations[i])
z_s.append(self.weights[i].dot(a) + self.biases[i])
a = activation_function(z_s[-1])
a_s.append(a)
self.temp_z_s = z_s
self.temp_a_s = a_s
return (z_s, a_s)
def backward_pass(self,y):
z_s=self.temp_z_s
a_s=self.temp_a_s
dw = [] # dC/dW
db = [] # dC/dB
deltas = [None] * len(self.weights) # delta = dC/dZ known as error for each layer
# insert the last layer error
deltas[-1] = ((y-a_s[-1])*(self.getDerivitiveActivationFunction(self.activations[-1]))(z_s[-1]))
# Perform BackPropagation
for i in reversed(range(len(deltas)-1)):
deltas[i] = self.weights[i+1].T.dot(deltas[i+1])*(self.getDerivitiveActivationFunction(self.activations[i])(z_s[i]))
#a= [print(d.shape) for d in deltas]
batch_size = 1
db = [d.dot(np.ones((batch_size,1)))/float(batch_size) for d in deltas]
dw = [d.dot(a_s[i].T)/float(batch_size) for i,d in enumerate(deltas)]
# return the derivitives respect to weight matrix and biases
return dw, db, 1/2*(y-a_s[-1])*(y-a_s[-1])
def update(self,dw,db,lr):
self.weights = [w+lr*dweight for w,dweight in zip(self.weights, dw)]
self.biases = [w+lr*dbias for w,dbias in zip(self.biases, db)]
@staticmethod
def getActivationFunction(name):
if(name == 'sigmoid'):
return lambda x : 1/(1+np.exp(-x))
elif(name == 'linear'):
return lambda x : x
elif(name == 'tanh'):
return lambda x : np.tanh(x)
elif(name == 'relu'):
def relu(x):
y = np.copy(x)
y[y<0] = 0
return y
return relu
else:
print('Unknown activation function. linear is used')
return lambda x: x
@staticmethod
def getDerivitiveActivationFunction(name):
if(name == 'sigmoid'):
sig = lambda x : 1/(1+np.exp(-x))
return lambda x :sig(x)*(1-sig(x))
elif(name == 'linear'):
return lambda x: 1
elif(name == 'tanh'):
tanh = lambda x : np.tanh(x)
return lambda x : 1-tanh(x)*tanh(x)
elif(name == 'relu'):
def relu_diff(x):
y = np.copy(x)
y[y>=0] = 1
y[y<0] = 0
return y
return relu_diff
else:
print('Unknown activation function. linear is used')
return lambda x: 1