-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathperceptron.py
113 lines (87 loc) · 3.35 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
# -----------------------------------------------------------------------------
# Copyright (C) 2018 Nicolas P. Rougier
# Distributed under the terms of the BSD License.
# -----------------------------------------------------------------------------
import numpy as np
def f(x):
return x > 0
class Perceptron:
''' Perceptron class. '''
def __init__(self, n, m):
''' Initialization of the perceptron with given sizes. '''
self.input = np.ones(n+1)
self.output = np.ones(m)
self.weights= np.zeros((m,n+1))
self.reset()
def reset(self):
''' Reset weights '''
self.weights[...] = np.random.uniform(-.5, .5, self.weights.shape)
def propagate_forward(self, data):
''' Propagate data from input layer to output layer. '''
# Set input layer (but not bias)
self.input[1:] = data
self.output[...] = f(np.dot(self.weights,self.input))
# Return output
return self.output
def propagate_backward(self, target, lrate=0.1):
''' Back propagate error related to target using lrate. '''
error = np.atleast_2d(target-self.output)
input = np.atleast_2d(self.input)
self.weights += lrate*np.dot(error.T,input)
# Return error
return (error**2).sum()
# -----------------------------------------------------------------------------
if __name__ == '__main__':
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
np.random.seed(123)
samples = np.zeros(100, dtype=[('input', float, 2),
('output', float, 1)])
P = np.random.uniform(0.05,0.95,(len(samples),2))
samples["input"] = P
stars = np.where(P[:,0]+P[:,1] < 1)
discs = np.where(P[:,0]+P[:,1] > 1)
samples["output"][stars] = +1
samples["output"][discs] = 0
network = Perceptron(2,1)
network.reset()
lrate = 0.05
fig = plt.figure(figsize=(6,6))
ax = plt.subplot(1,1,1, aspect=1, frameon=False)
ax.scatter(P[stars,0], P[stars,1], color="red", marker="*", s=50, alpha=.5)
ax.scatter(P[discs,0], P[discs,1], color="blue", s=25, alpha=.5)
line, = ax.plot([], [], color="black", linewidth=2)
ax.set_xlim(0,1)
ax.set_xticks([])
ax.set_ylim(0,1)
ax.set_yticks([])
plt.tight_layout()
def animate(i):
global lrate
error = 0
count = 0
lrate *= 0.99
while error == 0 and count < 10:
n = np.random.randint(samples.size)
network.propagate_forward( samples['input'][n] )
error = network.propagate_backward( samples['output'][n], lrate )
count += 1
c,a,b = network.weights[0]
x0 = -2
x1 = +2
if a != 0:
y0 = (-c -b*x0)/a
y1 = (-c -b*x1)/a
else:
y0 = 0
y1 = 1
line.set_xdata([x0,x1])
line.set_ydata([y0,y1])
return line,
anim = animation.FuncAnimation(fig, animate, np.arange(1, 300))
#Writer = animation.writers['ffmpeg']
#writer = Writer(fps=30,
# metadata=dict(artist='Nicolas P. Rougier'), bitrate=1800)
# anim.save('perceptron.mp4', writer=writer)
plt.show()