-
Notifications
You must be signed in to change notification settings - Fork 0
/
Perceptron.py
163 lines (120 loc) · 4.23 KB
/
Perceptron.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
153
154
155
156
157
158
159
160
161
162
163
import random, math
"""
Simple perceptron with backpropagation from scratch by Zack Beucler
"""
class Perceptron:
def __init__(self, numInputs, learningRate, epochs, isVerbose=False ):
self.numInputs = numInputs
self.weights = []
self.threshold = -1
self.thresholdWeight = None
self.learningRate = learningRate
self.epochs = epochs
self.isVerbose = isVerbose
def setWeights(self, value):
self.weights = value
def getWeights(self):
return self.weights
def setThresholdWeight(self, value):
self.thresholdWeight = value
def getThresholdWeight(self):
return self.thresholdWeight
def sigmoid(self, value):
return 1 / (1 + math.exp(-1 * value))
def activation(self, inputs, weights, threshold, thresholdWeight):
dotProduct = sum([i*j for (i, j) in zip(inputs, weights)]) # get the dot product of the weights and inputs
total = dotProduct + (threshold * thresholdWeight) # bias the dot product
return self.sigmoid(total)
def train(self, trainingData):
"""
Trains the perceptron using back propagation.
Data needs to be in this format [[inputs] output]
EX: [[1,1,1,1,0], 0]
"""
if self.weights == []:
self.setWeights([random.uniform(-0.5,0.5) for x in range(self.numInputs)]) # set the random weights
if self.thresholdWeight is None:
self.setThresholdWeight(random.uniform(-0.5, 0.5)) # set random threshold weight
for epoch in range(self.epochs):
if self.isVerbose: print(f"Epoch {epoch} out of {self.epochs}")
for indx,sample in enumerate(trainingData):
if self.isVerbose: print(f"\tSample {indx} out of {len(trainingData)}")
inputs = sample[0] # extract the inputs
desiredOutput = sample[1] # get the desired output
perceptronOutput = self.activation(inputs, self.weights, self.threshold, self.thresholdWeight) # get the perceptron's output
error = desiredOutput - perceptronOutput # calculate error
### threshold weight correction calculation ###
deltaThresholdWeight = self.learningRate * self.threshold * error
newThresholdWeight = self.thresholdWeight + deltaThresholdWeight
self.setThresholdWeight(newThresholdWeight) # update the threshold weight
### weights correction calculations ###
newWeights = []
for w_indx, currentWeight in enumerate(self.weights):
currentInput = inputs[w_indx]
deltaWeight = self.learningRate * currentInput * error
newWeight = currentWeight + deltaWeight
newWeights.append(newWeight)
self.setWeights(newWeights) # update the global weights
def test(self, testData, closeness=0.1):
"""
test the trained.
Data must be in format [[input], output]
"""
totalCorrect = 0
for indx,sample in enumerate(testData):
inputs = sample[0] # extract the inputs
desiredOutput = sample[1] # get the desired output
perceptronOutput = self.activation(inputs, self.weights, self.threshold, self.thresholdWeight) # get the perceptron's output
if abs(perceptronOutput-desiredOutput) <= closeness:
totalCorrect += 1
if self.isVerbose: print("Actual:", perceptronOutput, "\tDesired:", desiredOutput, "correct")
else:
if self.isVerbose: print("Actual:", perceptronOutput, "\tDesired:", desiredOutput)
print("Correct guesses:", totalCorrect, "out of", len(testData))
def predict(self, inputs):
"""
Use the perceptron to predict on inputs.
Data must be in an array
"""
return self.activation(inputs, self.weights, self.threshold, self.thresholdWeight)
def main():
trainingSample = [
[[0,0,0,0,0], 0],
[[0,0,0,0,1], 0],
[[0,0,0,1,0], 0],
[[0,0,1,0,0], 0],
[[0,1,0,0,0], 0],
[[1,0,0,0,0], 0],
[[0,0,0,1,1], 0],
[[0,0,1,0,1], 0],
[[0,1,0,0,1], 0],
[[1,0,0,0,1], 0],
[[0,0,1,1,0], 0],
[[0,1,0,1,0], 0],
[[1,0,0,1,0], 0],
[[0,1,1,0,0], 0],
[[1,0,1,0,0], 0],
[[1,1,0,0,0], 0],
[[0,0,1,1,1], 0],
[[0,1,0,1,1], 0],
[[1,0,0,1,1], 0],
[[0,1,1,0,1], 0],
[[1,0,1,0,1], 0],
[[1,1,0,0,1], 0],
[[0,1,1,1,0], 0],
[[1,0,1,1,0], 0],
[[1,1,0,1,0], 0],
[[1,1,1,0,0], 0],
[[0,1,1,1,1], 1],
[[1,0,1,1,1], 1],
[[1,1,0,1,1], 1],
[[1,1,1,0,1], 1],
[[1,1,1,1,0], 1],
[[1,1,1,1,1], 1]
]
p = Perceptron(5, 0.01, 50000, )
p.train(trainingSample)
#i = p.getWeights()
p.test(trainingSample)
print(p.predict([1,1,1,1,1]), "should be close to 1")
main()