-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathplot_mlp.py
223 lines (197 loc) · 7.36 KB
/
plot_mlp.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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
from math import floor
from matplotlib.pyplot import Circle, subplots
from matplotlib.lines import Line2D
def plot_mlp(self):
"""
An ANN with up to three layers may be plotted.
Unfortunately, matplotlib is convoluted and far harder to
use than it should be.
"""
if self.hidden_layers > 3:
# If more than three layers, exit the function
print("Cannot plot this architecture")
return
# Define parameters
self.input_coord = {}
self.hidden_coord = {}
self.output_coord = {}
fig, ax = subplots(figsize=(40, 40))
ax.axis("off")
ax.set_xlim((0, 1))
ax.set_ylim((0, 1))
def set_final_syn_pos(self):
# Get final output synapses location ahead of time
if self.hidden_layers == 3:
self.final_syn_pos = 0.7
elif self.hidden_layers == 2:
self.final_syn_pos = 0.5
elif self.hidden_layers == 1:
self.final_syn_pos = 0.3
def add_input_layer(self):
# Generate input neuron coordinates
def gen_x_y_coords(self):
self.input_coord['x'] = [
0.1 for i in range(1, self.X.shape[1] + 1)
]
self.input_coord['y'] = [
0.1 + i * 0.1 for i in range(1, self.X.shape[1] + 1)
]
def gen_circles_coords(self):
# Add circles to input neuron coordinates
self.input_coord["circles"] = (Circle(
(x, y),
0.025,
color='r',
) for x, y in zip(
self.input_coord['x'],
self.input_coord['y'],
))
def gen_labels_coords(self):
# Add labels to input neuron coordinates
self.input_coord["labels"] = [
ax.annotate(
col,
xy=(x, y),
fontsize=15,
ha="center",
) for x, y, col in zip(
self.input_coord['x'],
self.input_coord['y'],
self.X.columns,
)
]
def add_circles(self):
# Plot the circles
for input_circle in self.input_coord["circles"]:
ax.add_artist(input_circle)
gen_x_y_coords(self)
gen_circles_coords(self)
gen_labels_coords(self)
add_circles(self)
def add_hidden_layers(self):
# Create list of tuples to reuse hidden layer plotting functions
def gen_hl_coord_list(self):
if self.hidden_layers >= 1:
self.hl_coord_list = [(0.1, 0.3, "HL1-Neuron ")]
if self.hidden_layers >= 2:
self.hl_coord_list.append((0.3, 0.5, "HL2-Neuron "))
if self.hidden_layers == 3:
self.hl_coord_list.append((0.5, 0.7, "HL3-Neuron "))
def gen_x_y_coords(self, coord):
# Generate hidden neuron coordinates
self.hidden_coord['x'] = [
coord[1] for i in range(1, self.X.shape[1] + 2)
]
self.hidden_coord['y'] = [
0.05 + i * 0.1 for i in range(1, self.X.shape[1] + 2)
]
def gen_circles_coords(self):
# Add circles to hidden neuron coordinates
self.hidden_coord["circles"] = (Circle(
(x, y),
0.025,
color='b',
) for x, y in zip(
self.hidden_coord['x'],
self.hidden_coord['y'],
))
def gen_labels_coords(self, coord):
# Add labels to hidden neuron coordinates
self.hidden_coord["labels"] = [
ax.annotate(
coord[2] + str(i),
xy=(x, y),
fontsize=15,
ha="center",
) for x, y, i in zip(
self.hidden_coord['x'],
self.hidden_coord['y'],
range(1, self.X.shape[1] + 2),
)
]
def gen_synapses_coords(self, coord, i):
# Add synapses to hidden neuron coordinates
if i == 0:
self.hidden_coord["hl-synapses"] = (
(y1, y2) for y2 in self.hidden_coord['y']
for y1 in self.input_coord['y'])
else:
self.hidden_coord["hl-synapses"] = (
(y1, y2) for y2 in self.hidden_coord['y']
for y1 in self.hidden_coord['y'])
def add_circles(self):
# Plot the circles
for hl_circle in self.hidden_coord["circles"]:
ax.add_artist(hl_circle)
def add_synapses(self, coord):
# Plot the synapses
for syn in self.hidden_coord["hl-synapses"]:
ax.add_line(Line2D(
(coord[0], coord[1]),
syn,
color='y',
))
def hl_iter(self):
# Iterate over the above functions for the appropriate
# number of hidden layers
for i, coord in enumerate(self.hl_coord_list):
gen_x_y_coords(self, coord)
gen_circles_coords(self)
gen_labels_coords(self, coord)
gen_synapses_coords(self, coord, i)
add_circles(self)
add_synapses(self, coord)
gen_hl_coord_list(self)
hl_iter(self)
def add_output_layer(self):
# Generate output neuron coordinates
def gen_x_y_coords(self):
# Generate output neuron coordinates
mode_hidden = floor(len(self.hidden_coord['y']) / 2)
self.output_coord['x'] = 0.9
self.output_coord['y'] = self.hidden_coord['y'][mode_hidden]
def gen_circle_coords(self):
# Add circles to output neuron coordinates
self.output_coord["circle"] = Circle(
(self.output_coord['x'], self.output_coord['y']),
0.025,
color='g',
)
def gen_label_coords(self):
# Add labels to output neuron coordinates
self.output_coord["label"] = ax.annotate(
"Output Neuron",
xy=(
self.output_coord['x'],
self.output_coord['y'],
),
fontsize=15,
ha="center",
)
def gen_synapses_coords(self):
# Add synapses to output neuron coordinates
self.output_coord["hl-output-synapses"] = (
(y, self.output_coord["y"]) for y in self.hidden_coord["y"]
for y1 in self.hidden_coord["y"])
def add_circle(self):
# Plot the circle
ax.add_artist(self.output_coord["circle"])
def add_synapses(self):
# Plot the synapses
for syn in self.output_coord["hl-output-synapses"]:
ax.add_line(
Line2D(
(self.final_syn_pos, 0.9),
syn,
color='y',
))
gen_x_y_coords(self)
gen_circle_coords(self)
gen_label_coords(self)
gen_synapses_coords(self)
add_circle(self)
add_synapses(self)
set_final_syn_pos(self)
add_input_layer(self)
add_hidden_layers(self)
add_output_layer(self)