pyerualjetwork 4.3.8.dev15__py3-none-any.whl → 4.3.9b0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. pyerualjetwork/__init__.py +1 -1
  2. pyerualjetwork/activation_functions.py +2 -2
  3. pyerualjetwork/activation_functions_cuda.py +63 -114
  4. pyerualjetwork/data_operations_cuda.py +1 -1
  5. pyerualjetwork/model_operations.py +14 -14
  6. pyerualjetwork/model_operations_cuda.py +16 -17
  7. pyerualjetwork/plan.py +87 -268
  8. pyerualjetwork/plan_cuda.py +82 -276
  9. pyerualjetwork/planeat.py +12 -44
  10. pyerualjetwork/planeat_cuda.py +9 -45
  11. pyerualjetwork/visualizations.py +29 -26
  12. pyerualjetwork/visualizations_cuda.py +19 -20
  13. {pyerualjetwork-4.3.8.dev15.dist-info → pyerualjetwork-4.3.9b0.dist-info}/METADATA +2 -19
  14. pyerualjetwork-4.3.9b0.dist-info/RECORD +24 -0
  15. pyerualjetwork-4.3.9b0.dist-info/top_level.txt +1 -0
  16. pyerualjetwork-4.3.8.dev15.dist-info/RECORD +0 -45
  17. pyerualjetwork-4.3.8.dev15.dist-info/top_level.txt +0 -2
  18. pyerualjetwork_afterburner/__init__.py +0 -11
  19. pyerualjetwork_afterburner/activation_functions.py +0 -290
  20. pyerualjetwork_afterburner/activation_functions_cuda.py +0 -289
  21. pyerualjetwork_afterburner/data_operations.py +0 -406
  22. pyerualjetwork_afterburner/data_operations_cuda.py +0 -461
  23. pyerualjetwork_afterburner/help.py +0 -17
  24. pyerualjetwork_afterburner/loss_functions.py +0 -21
  25. pyerualjetwork_afterburner/loss_functions_cuda.py +0 -21
  26. pyerualjetwork_afterburner/memory_operations.py +0 -298
  27. pyerualjetwork_afterburner/metrics.py +0 -190
  28. pyerualjetwork_afterburner/metrics_cuda.py +0 -163
  29. pyerualjetwork_afterburner/model_operations.py +0 -408
  30. pyerualjetwork_afterburner/model_operations_cuda.py +0 -420
  31. pyerualjetwork_afterburner/parallel.py +0 -118
  32. pyerualjetwork_afterburner/plan.py +0 -432
  33. pyerualjetwork_afterburner/plan_cuda.py +0 -441
  34. pyerualjetwork_afterburner/planeat.py +0 -793
  35. pyerualjetwork_afterburner/planeat_cuda.py +0 -752
  36. pyerualjetwork_afterburner/ui.py +0 -22
  37. pyerualjetwork_afterburner/visualizations.py +0 -823
  38. pyerualjetwork_afterburner/visualizations_cuda.py +0 -825
  39. {pyerualjetwork-4.3.8.dev15.dist-info → pyerualjetwork-4.3.9b0.dist-info}/WHEEL +0 -0
@@ -1,823 +0,0 @@
1
- import networkx as nx
2
- import matplotlib.pyplot as plt
3
- import numpy as np
4
- from scipy.spatial import ConvexHull
5
- import seaborn as sns
6
- from matplotlib.animation import ArtistAnimation
7
-
8
- def draw_neural_web(W, ax, G, return_objs=False):
9
- """
10
- Visualizes a neural web by drawing the neural network structure.
11
-
12
- Parameters:
13
- W : numpy.ndarray
14
- A 2D array representing the connection weights of the neural network.
15
- ax : matplotlib.axes.Axes
16
- The matplotlib axes where the graph will be drawn.
17
- G : networkx.Graph
18
- The NetworkX graph representing the neural network structure.
19
- return_objs : bool, optional
20
- If True, returns the drawn objects (nodes and edges). Default is False.
21
-
22
- Returns:
23
- art1 : matplotlib.collections.PathCollection or None
24
- Returns the node collection if return_objs is True; otherwise, returns None.
25
- art2 : matplotlib.collections.LineCollection or None
26
- Returns the edge collection if return_objs is True; otherwise, returns None.
27
- art3 : matplotlib.collections.TextCollection or None
28
- Returns the label collection if return_objs is True; otherwise, returns None.
29
-
30
- Example:
31
- art1, art2, art3 = draw_neural_web(W, ax, G, return_objs=True)
32
- plt.show()
33
- """
34
-
35
- for i in range(W.shape[0]):
36
- for j in range(W.shape[1]):
37
- if W[i, j] != 0:
38
- G.add_edge(f'Output{i}', f'Input{j}', ltpw=W[i, j])
39
-
40
- edges = G.edges(data=True)
41
- weights = [edata['ltpw'] for _, _, edata in edges]
42
- pos = {}
43
- num_motor_neurons = W.shape[0]
44
- num_sensory_neurons = W.shape[1]
45
-
46
- for j in range(num_sensory_neurons):
47
- pos[f'Input{j}'] = (0, j)
48
-
49
- motor_y_start = (num_sensory_neurons - num_motor_neurons) / 2
50
- for i in range(num_motor_neurons):
51
- pos[f'Output{i}'] = (1, motor_y_start + i)
52
-
53
-
54
- art1 = nx.draw_networkx_nodes(G, pos, ax=ax, node_size=1000, node_color='lightblue')
55
- art2 = nx.draw_networkx_edges(G, pos, ax=ax, edge_color=weights, edge_cmap=plt.cm.Blues, width=2)
56
- art3 = nx.draw_networkx_labels(G, pos, ax=ax, font_size=10, font_weight='bold')
57
-
58
- ax.spines['top'].set_visible(False)
59
- ax.spines['right'].set_visible(False)
60
- ax.spines['left'].set_visible(False)
61
- ax.spines['bottom'].set_visible(False)
62
- ax.get_xaxis().set_visible(False)
63
- ax.get_yaxis().set_visible(False)
64
- ax.set_title('Neural Web')
65
-
66
- if return_objs == True:
67
-
68
- return art1, art2, art3
69
-
70
-
71
- def draw_model_architecture(model_name, model_path=''):
72
- """
73
- The `draw_model_architecture` function visualizes the architecture of a neural network model with
74
- multiple inputs based on activation functions.
75
-
76
- :param model_name: The `model_name` parameter in the `draw_model_architecture` function is used to
77
- specify the name of the neural network model whose architecture you want to visualize. This function
78
- visualizes the architecture of a neural network model with multiple inputs based on activation
79
- functions
80
- :param model_path: The `model_path` parameter in the `draw_model_architecture` function is used to
81
- specify the path where the neural network model is saved. If the model is saved in a specific
82
- directory or file location, you can provide that path as a string when calling the function. If the
83
- model is saved
84
- """
85
- """
86
- Visualizes the architecture of a neural network model with multiple inputs based on activation functions.
87
- """
88
-
89
- from .model_operations import load_model, get_scaler, get_act_pot, get_weights
90
-
91
- model = load_model(model_name=model_name, model_path=model_path)
92
-
93
- W = model[get_weights()]
94
- activation_potentiation = model[get_act_pot()]
95
- scaler_params = model[get_scaler()]
96
-
97
- # Calculate dimensions based on number of activation functions
98
- num_activations = len(activation_potentiation)
99
- input_groups = num_activations # Number of input groups equals number of activations
100
- num_inputs = W.shape[1]
101
-
102
- # Create figure
103
- fig = plt.figure(figsize=(15, 10))
104
-
105
- # Calculate positions for nodes
106
- def get_node_positions():
107
- positions = {}
108
-
109
- # Input layer positions
110
- total_height = 0.8 # Maksimum dikey alan
111
- group_height = total_height / input_groups # Her grup için ayrılan dikey alan
112
- input_spacing = min(group_height / (num_inputs + 1), 0.1) # Her girdi arasındaki mesafe
113
-
114
- for group in range(input_groups):
115
- group_start_y = 0.9 - (group * group_height) # Grubun başlangıç y koordinatı
116
- for i in range(num_inputs):
117
- y_pos = group_start_y - ((i + 1) * input_spacing)
118
- positions[f'input_{group}_{i}'] = (0.2, y_pos)
119
-
120
- # Aggregation layer positions
121
- agg_spacing = total_height / (num_inputs + 1)
122
- for i in range(num_inputs):
123
- positions[f'summed_{i}'] = (0.5, 0.9 - ((i + 1) * agg_spacing))
124
-
125
- # Output layer positions
126
- output_spacing = total_height / (W.shape[0] + 1)
127
- for i in range(W.shape[0]):
128
- positions[f'output_{i}'] = (0.8, 0.9 - ((i + 1) * output_spacing))
129
-
130
- return positions
131
-
132
- # Draw the network
133
- pos = get_node_positions()
134
-
135
- # Draw nodes
136
- for group in range(input_groups):
137
- # Draw input nodes
138
- for i in range(num_inputs):
139
- plt.plot(*pos[f'input_{group}_{i}'], 'o', color='lightgreen', markersize=20)
140
- plt.text(pos[f'input_{group}_{i}'][0] - 0.05, pos[f'input_{group}_{i}'][1],
141
- f'Input #{i+1} ({activation_potentiation[group]})', ha='right', va='center')
142
-
143
- # Draw connections from input to summed input directly
144
- plt.plot([pos[f'input_{group}_{i}'][0], pos[f'summed_{i}'][0]],
145
- [pos[f'input_{group}_{i}'][1], pos[f'summed_{i}'][1]], 'k-')
146
- # Draw aggregation nodes
147
- if group == 0:
148
- plt.plot(*pos[f'summed_{i}'], 'o', color='lightgreen', markersize=20)
149
- plt.text(pos[f'summed_{i}'][0], pos[f'summed_{i}'][1] + 0.02,
150
- f'Summed\nInput #{i+1}', ha='center', va='bottom')
151
-
152
- # Draw output nodes and connections
153
- for i in range(W.shape[0]):
154
- plt.plot(*pos[f'output_{i}'], 'o', color='gold', markersize=20)
155
- plt.text(pos[f'output_{i}'][0] + 0.05, pos[f'output_{i}'][1],
156
- f'Output #{i+1}', ha='left', va='center', color='purple')
157
-
158
- # Connect all aggregation nodes to each output
159
- for group in range(num_inputs):
160
- plt.plot([pos[f'summed_{group}'][0], pos[f'output_{i}'][0]],
161
- [pos[f'summed_{group}'][1], pos[f'output_{i}'][1]], 'k-')
162
-
163
- # Add labels and annotations
164
- plt.text(0.2, 0.95, 'Input Layer', ha='center', va='bottom', fontsize=12)
165
- plt.text(0.5, 0.95, 'Aggregation\nLayer', ha='center', va='bottom', fontsize=12)
166
- plt.text(0.8, 0.95, 'Output Layer', ha='center', va='bottom', fontsize=12)
167
-
168
- # Remove axes
169
- plt.axis('off')
170
-
171
- # Add model information
172
- if scaler_params is None:
173
- plt.text(0.95, 0.05, 'Standard Scaler=No', fontsize=10, ha='right', va='bottom')
174
- else:
175
- plt.text(0.95, 0.05, 'Standard Scaler=Yes', fontsize=10, ha='right', va='bottom')
176
-
177
- # Add model architecture title
178
- plt.text(0.95, 0.1, f"PLAN Model Architecture: {model_name}", fontsize=12, ha='right', va='bottom', fontweight='bold')
179
- plt.tight_layout()
180
- plt.show()
181
-
182
-
183
- def draw_activations(x_train, activation):
184
-
185
- from . import activation_functions as af
186
-
187
- if activation == 'sigmoid':
188
- result = af.Sigmoid(x_train)
189
-
190
- elif activation == 'swish':
191
- result = af.swish(x_train)
192
-
193
- elif activation == 'circular':
194
- result = af.circular_activation(x_train)
195
-
196
- elif activation == 'mod_circular':
197
- result = af.modular_circular_activation(x_train)
198
-
199
- elif activation == 'tanh_circular':
200
- result = af.tanh_circular_activation(x_train)
201
-
202
- elif activation == 'leaky_relu':
203
- result = af.leaky_relu(x_train)
204
-
205
- elif activation == 'relu':
206
- result = af.Relu(x_train)
207
-
208
- elif activation == 'softplus':
209
- result = af.softplus(x_train)
210
-
211
- elif activation == 'elu':
212
- result = af.elu(x_train)
213
-
214
- elif activation == 'gelu':
215
- result = af.gelu(x_train)
216
-
217
- elif activation == 'selu':
218
- result = af.selu(x_train)
219
-
220
- elif activation == 'softmax':
221
- result = af.Softmax(x_train)
222
-
223
- elif activation == 'tanh':
224
- result = af.tanh(x_train)
225
-
226
- elif activation == 'sinakt':
227
- result = af.sinakt(x_train)
228
-
229
- elif activation == 'p_squared':
230
- result = af.p_squared(x_train)
231
-
232
- elif activation == 'sglu':
233
- result = af.sglu(x_train, alpha=1.0)
234
-
235
- elif activation == 'dlrelu':
236
- result = af.dlrelu(x_train)
237
-
238
- elif activation == 'exsig':
239
- result = af.exsig(x_train)
240
-
241
- elif activation == 'sin_plus':
242
- result = af.sin_plus(x_train)
243
-
244
- elif activation == 'acos':
245
- result = af.acos(x_train, alpha=1.0, beta=0.0)
246
-
247
- elif activation == 'gla':
248
- result = af.gla(x_train, alpha=1.0, mu=0.0)
249
-
250
- elif activation == 'srelu':
251
- result = af.srelu(x_train)
252
-
253
- elif activation == 'qelu':
254
- result = af.qelu(x_train)
255
-
256
- elif activation == 'isra':
257
- result = af.isra(x_train)
258
-
259
- elif activation == 'waveakt':
260
- result = af.waveakt(x_train)
261
-
262
- elif activation == 'arctan':
263
- result = af.arctan(x_train)
264
-
265
- elif activation == 'bent_identity':
266
- result = af.bent_identity(x_train)
267
-
268
- elif activation == 'sech':
269
- result = af.sech(x_train)
270
-
271
- elif activation == 'softsign':
272
- result = af.softsign(x_train)
273
-
274
- elif activation == 'pwl':
275
- result = af.pwl(x_train)
276
-
277
- elif activation == 'cubic':
278
- result = af.cubic(x_train)
279
-
280
- elif activation == 'gaussian':
281
- result = af.gaussian(x_train)
282
-
283
- elif activation == 'sine':
284
- result = af.sine(x_train)
285
-
286
- elif activation == 'tanh_square':
287
- result = af.tanh_square(x_train)
288
-
289
- elif activation == 'mod_sigmoid':
290
- result = af.mod_sigmoid(x_train)
291
-
292
- elif activation == 'linear':
293
- result = x_train
294
-
295
- elif activation == 'quartic':
296
- result = af.quartic(x_train)
297
-
298
- elif activation == 'square_quartic':
299
- result = af.square_quartic(x_train)
300
-
301
- elif activation == 'cubic_quadratic':
302
- result = af.cubic_quadratic(x_train)
303
-
304
- elif activation == 'exp_cubic':
305
- result = af.exp_cubic(x_train)
306
-
307
- elif activation == 'sine_square':
308
- result = af.sine_square(x_train)
309
-
310
- elif activation == 'logarithmic':
311
- result = af.logarithmic(x_train)
312
-
313
- elif activation == 'scaled_cubic':
314
- result = af.scaled_cubic(x_train, 1.0)
315
-
316
- elif activation == 'sine_offset':
317
- result = af.sine_offset(x_train, 1.0)
318
-
319
- elif activation == 'spiral':
320
- result = af.spiral_activation(x_train)
321
-
322
- try: return result
323
- except:
324
- print('\rWARNING: error in drawing some activation.', end='')
325
- return x_train
326
-
327
- def plot_evaluate(x_test, y_test, y_preds, acc_list, W, activation_potentiation):
328
-
329
- from .metrics import metrics, confusion_matrix, roc_curve
330
- from .ui import loading_bars, initialize_loading_bar
331
- from .data_operations import decode_one_hot
332
- from .model_operations import predict_model_ram
333
-
334
- bar_format_normal = loading_bars()[0]
335
-
336
- acc = acc_list[len(acc_list) - 1]
337
- y_true = decode_one_hot(y_test)
338
-
339
- y_true = np.array(y_true)
340
- y_preds = np.array(y_preds)
341
- Class = np.unique(decode_one_hot(y_test))
342
-
343
- precision, recall, f1 = metrics(y_test, y_preds)
344
-
345
-
346
- cm = confusion_matrix(y_true, y_preds, len(Class))
347
- fig, axs = plt.subplots(2, 2, figsize=(16, 12))
348
-
349
- sns.heatmap(cm, annot=True, fmt='d', ax=axs[0, 0])
350
- axs[0, 0].set_title("Confusion Matrix")
351
- axs[0, 0].set_xlabel("Predicted Class")
352
- axs[0, 0].set_ylabel("Actual Class")
353
-
354
- if len(Class) == 2:
355
- fpr, tpr, thresholds = roc_curve(y_true, y_preds)
356
-
357
- roc_auc = np.trapz(tpr, fpr)
358
- axs[1, 0].plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
359
- axs[1, 0].plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
360
- axs[1, 0].set_xlim([0.0, 1.0])
361
- axs[1, 0].set_ylim([0.0, 1.05])
362
- axs[1, 0].set_xlabel('False Positive Rate')
363
- axs[1, 0].set_ylabel('True Positive Rate')
364
- axs[1, 0].set_title('Receiver Operating Characteristic (ROC) Curve')
365
- axs[1, 0].legend(loc="lower right")
366
- axs[1, 0].legend(loc="lower right")
367
- else:
368
-
369
- for i in range(len(Class)):
370
-
371
- y_true_copy = np.copy(y_true)
372
- y_preds_copy = np.copy(y_preds)
373
-
374
- y_true_copy[y_true_copy == i] = 0
375
- y_true_copy[y_true_copy != 0] = 1
376
-
377
- y_preds_copy[y_preds_copy == i] = 0
378
- y_preds_copy[y_preds_copy != 0] = 1
379
-
380
-
381
- fpr, tpr, thresholds = roc_curve(y_true_copy, y_preds_copy)
382
-
383
- roc_auc = np.trapz(tpr, fpr)
384
- axs[1, 0].plot(fpr, tpr, color='darkorange', lw=2, label=f'ROC curve (area = {roc_auc:.2f})')
385
- axs[1, 0].plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
386
- axs[1, 0].set_xlim([0.0, 1.0])
387
- axs[1, 0].set_ylim([0.0, 1.05])
388
- axs[1, 0].set_xlabel('False Positive Rate')
389
- axs[1, 0].set_ylabel('True Positive Rate')
390
- axs[1, 0].set_title('Receiver Operating Characteristic (ROC) Curve')
391
- axs[1, 0].legend(loc="lower right")
392
- axs[1, 0].legend(loc="lower right")
393
-
394
-
395
- metric = ['Precision', 'Recall', 'F1 Score', 'Accuracy']
396
- values = [precision, recall, f1, acc]
397
- colors = ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728']
398
-
399
-
400
- bars = axs[0, 1].bar(metric, values, color=colors)
401
-
402
-
403
- for bar, value in zip(bars, values):
404
- axs[0, 1].text(bar.get_x() + bar.get_width() / 2, bar.get_height() - 0.05, f'{value:.2f}',
405
- ha='center', va='bottom', fontsize=12, color='white', weight='bold')
406
-
407
- axs[0, 1].set_ylim(0, 1)
408
- axs[0, 1].set_xlabel('Metrics')
409
- axs[0, 1].set_ylabel('Score')
410
- axs[0, 1].set_title('Precision, Recall, F1 Score, and Accuracy (Weighted)')
411
- axs[0, 1].grid(True, axis='y', linestyle='--', alpha=0.7)
412
-
413
- feature_indices=[0, 1]
414
-
415
- h = .02
416
- x_min, x_max = x_test[:, feature_indices[0]].min() - 1, x_test[:, feature_indices[0]].max() + 1
417
- y_min, y_max = x_test[:, feature_indices[1]].min() - 1, x_test[:, feature_indices[1]].max() + 1
418
- xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
419
- np.arange(y_min, y_max, h))
420
-
421
- grid = np.c_[xx.ravel(), yy.ravel()]
422
-
423
- try:
424
-
425
- grid_full = np.zeros((grid.shape[0], x_test.shape[1]))
426
- grid_full[:, feature_indices] = grid
427
-
428
- Z = [None] * len(grid_full)
429
-
430
- predict_progress = initialize_loading_bar(total=len(grid_full),leave=False,
431
- bar_format=bar_format_normal ,desc="Predicts For Decision Boundary",ncols= 65)
432
-
433
- for i in range(len(grid_full)):
434
-
435
- Z[i] = np.argmax(predict_model_ram(grid_full[i], W=W, activation_potentiation=activation_potentiation))
436
- predict_progress.update(1)
437
-
438
- predict_progress.close()
439
-
440
- Z = np.array(Z)
441
- Z = Z.reshape(xx.shape)
442
-
443
- axs[1,1].contourf(xx, yy, Z, alpha=0.8)
444
- axs[1,1].scatter(x_test[:, feature_indices[0]], x_test[:, feature_indices[1]], c=decode_one_hot(y_test), edgecolors='k', marker='o', s=20, alpha=0.9)
445
- axs[1,1].set_xlabel(f'Feature {0 + 1}')
446
- axs[1,1].set_ylabel(f'Feature {1 + 1}')
447
- axs[1,1].set_title('Decision Boundary')
448
-
449
- except Exception as e:
450
- # Hata meydana geldiğinde yapılacak işlemler
451
- print(f"Hata oluştu: {e}")
452
-
453
- plt.show()
454
-
455
-
456
- def plot_decision_boundary(x, y, activation_potentiation, W, artist=None, ax=None):
457
-
458
- from .model_operations import predict_model_ram
459
- from .data_operations import decode_one_hot
460
-
461
- feature_indices = [0, 1]
462
-
463
- h = .02
464
- x_min, x_max = x[:, feature_indices[0]].min() - 1, x[:, feature_indices[0]].max() + 1
465
- y_min, y_max = x[:, feature_indices[1]].min() - 1, x[:, feature_indices[1]].max() + 1
466
- xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
467
- np.arange(y_min, y_max, h))
468
-
469
- grid = np.c_[xx.ravel(), yy.ravel()]
470
- grid_full = np.zeros((grid.shape[0], x.shape[1]), dtype=np.float32)
471
- grid_full[:, feature_indices] = grid
472
-
473
- Z = [None] * len(grid_full)
474
-
475
- for i in range(len(grid_full)):
476
- Z[i] = np.argmax(predict_model_ram(grid_full[i], W=W, activation_potentiation=activation_potentiation))
477
-
478
- Z = np.array(Z, dtype=np.int32)
479
- Z = Z.reshape(xx.shape)
480
-
481
- if ax is None:
482
-
483
- plt.contourf(xx, yy, Z, alpha=0.8)
484
- plt.scatter(x[:, feature_indices[0]], x[:, feature_indices[1]], c=decode_one_hot(y), edgecolors='k', marker='o', s=20, alpha=0.9)
485
- plt.xlabel(f'Feature {0 + 1}')
486
- plt.ylabel(f'Feature {1 + 1}')
487
- plt.title('Decision Boundary')
488
-
489
- plt.show()
490
-
491
- else:
492
-
493
- try:
494
- art1_1 = ax[1, 0].contourf(xx, yy, Z, alpha=0.8)
495
- art1_2 = ax[1, 0].scatter(x[:, feature_indices[0]], x[:, feature_indices[1]], c=decode_one_hot(y), edgecolors='k', marker='o', s=20, alpha=0.9)
496
- ax[1, 0].set_xlabel(f'Feature {0 + 1}')
497
- ax[1, 0].set_ylabel(f'Feature {1 + 1}')
498
- ax[1, 0].set_title('Decision Boundary')
499
-
500
- return art1_1, art1_2
501
-
502
- except:
503
-
504
- art1_1 = ax.contourf(xx, yy, Z, alpha=0.8)
505
- art1_2 = ax.scatter(x[:, feature_indices[0]], x[:, feature_indices[1]], c=decode_one_hot(y), edgecolors='k', marker='o', s=20, alpha=0.9)
506
- ax.set_xlabel(f'Feature {0 + 1}')
507
- ax.set_ylabel(f'Feature {1 + 1}')
508
- ax.set_title('Decision Boundary')
509
-
510
-
511
- return art1_1, art1_2
512
-
513
-
514
- def plot_decision_space(x, y, y_preds=None, s=100, color='tab20'):
515
-
516
- from .metrics import pca
517
- from .data_operations import decode_one_hot
518
-
519
- if x.shape[1] > 2:
520
-
521
- X_pca = pca(x, n_components=2)
522
- else:
523
- X_pca = x
524
-
525
- if y_preds == None:
526
- y_preds = decode_one_hot(y)
527
-
528
- y = decode_one_hot(y)
529
- num_classes = len(np.unique(y))
530
-
531
- cmap = plt.get_cmap(color)
532
-
533
-
534
- norm = plt.Normalize(vmin=0, vmax=num_classes - 1)
535
-
536
-
537
- plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, edgecolor='k', s=50, cmap=cmap, norm=norm)
538
-
539
-
540
- for cls in range(num_classes):
541
-
542
- class_points = []
543
-
544
-
545
- for i in range(len(y)):
546
- if y_preds[i] == cls:
547
- class_points.append(X_pca[i])
548
-
549
- class_points = np.array(class_points, dtype=y.dtype)
550
-
551
-
552
- if len(class_points) > 2:
553
- hull = ConvexHull(class_points)
554
- hull_points = class_points[hull.vertices]
555
-
556
- hull_points = np.vstack([hull_points, hull_points[0]])
557
-
558
- plt.fill(hull_points[:, 0], hull_points[:, 1], color=cmap(norm(cls)), alpha=0.3, edgecolor='k', label=f'Class {cls} Hull')
559
-
560
- plt.title("Decision Space (Data Distribution)")
561
-
562
- plt.draw()
563
-
564
-
565
- def update_neuron_history_for_learner(LTPW, ax1, row, col, class_count, artist5, data, fig1, acc=False, loss=False):
566
-
567
- for j in range(len(class_count)):
568
-
569
- if acc != False and loss != False:
570
- suptitle_info = data + ' Accuracy:' + str(acc) + '\n' + data + ' Loss:' + str(loss) + '\nNeurons Memory:'
571
- else:
572
- suptitle_info = 'Neurons Memory:'
573
-
574
- mat = LTPW[j,:].reshape(row, col)
575
-
576
- title_info = f'{j+1}. Neuron'
577
-
578
- art5 = ax1[j].imshow(mat, interpolation='sinc', cmap='viridis')
579
-
580
- ax1[j].set_aspect('equal')
581
- ax1[j].set_xticks([])
582
- ax1[j].set_yticks([])
583
- ax1[j].set_title(title_info)
584
-
585
-
586
- artist5.append([art5])
587
-
588
- fig1.suptitle(suptitle_info, fontsize=16)
589
-
590
- return artist5
591
-
592
- def update_neuron_history(LTPW, ax1, row, col, class_count, artist5, fig1, acc=False, loss=False):
593
-
594
- for j in range(class_count):
595
-
596
- if acc != False and loss != False:
597
- suptitle_info = ' Accuracy:' + str(acc) + '\n' + '\nNeurons Memory:'
598
- else:
599
- suptitle_info = 'Neurons Memory:'
600
-
601
- mat = LTPW[j,:].reshape(row, col)
602
-
603
- title_info = f'{j+1}. Neuron'
604
-
605
- art5 = ax1[j].imshow(mat, interpolation='sinc', cmap='viridis')
606
-
607
- ax1[j].set_aspect('equal')
608
- ax1[j].set_xticks([])
609
- ax1[j].set_yticks([])
610
- ax1[j].set_title(title_info)
611
-
612
-
613
- artist5.append([art5])
614
-
615
- fig1.suptitle(suptitle_info, fontsize=16)
616
-
617
-
618
- def initialize_visualization_for_fit(val, show_training, neurons_history, x_train, y_train):
619
- """Initializes the visualization setup based on the parameters."""
620
- from .data_operations import find_closest_factors
621
- visualization_objects = {}
622
-
623
- if show_training or neurons_history:
624
- if not val:
625
- raise ValueError("For showing training or neurons history, 'val' parameter must be True.")
626
-
627
- G = nx.Graph()
628
- fig, ax = plt.subplots(2, 2)
629
- fig.suptitle('Train History')
630
- visualization_objects.update({
631
- 'G': G,
632
- 'fig': fig,
633
- 'ax': ax,
634
- 'artist1': [],
635
- 'artist2': [],
636
- 'artist3': [],
637
- 'artist4': []
638
- })
639
-
640
- if neurons_history:
641
- row, col = find_closest_factors(len(x_train[0]))
642
- fig1, ax1 = plt.subplots(1, len(y_train[0]), figsize=(18, 14))
643
- visualization_objects.update({
644
- 'fig1': fig1,
645
- 'ax1': ax1,
646
- 'artist5': [],
647
- 'row': row,
648
- 'col': col
649
- })
650
-
651
- return visualization_objects
652
-
653
-
654
-
655
- def update_neural_web_for_fit(W, ax, G, artist):
656
- """
657
- The function `update_neural_web_for_fit` updates a neural web visualization for fitting.
658
- """
659
- art5_1, art5_2, art5_3 = draw_neural_web(W=W, ax=ax, G=G, return_objs=True)
660
- art5_list = [art5_1] + [art5_2] + list(art5_3.values())
661
- artist.append(art5_list)
662
-
663
-
664
- def update_weight_visualization_for_fit(ax, LTPW, artist2):
665
- """Updates the weight visualization plot."""
666
- art2 = ax.imshow(LTPW, interpolation='sinc', cmap='viridis')
667
- artist2.append([art2])
668
-
669
-
670
- def update_decision_boundary_for_fit(ax, x_val, y_val, activation_potentiation, LTPW, artist1):
671
- """Updates the decision boundary visualization."""
672
- art1_1, art1_2 = plot_decision_boundary(x_val, y_val, activation_potentiation, LTPW, artist=artist1, ax=ax)
673
- artist1.append([*art1_1.collections, art1_2])
674
-
675
-
676
- def update_validation_history_for_fit(ax, val_list, artist3):
677
- """Updates the validation accuracy history plot."""
678
- period = list(range(1, len(val_list) + 1))
679
- art3 = ax.plot(
680
- period,
681
- val_list,
682
- linestyle='--',
683
- color='g',
684
- marker='o',
685
- markersize=6,
686
- linewidth=2,
687
- label='Validation Accuracy'
688
- )
689
- ax.set_title('Validation History')
690
- ax.set_xlabel('Time')
691
- ax.set_ylabel('Validation Accuracy')
692
- ax.set_ylim([0, 1])
693
- artist3.append(art3)
694
-
695
-
696
- def display_visualization_for_fit(fig, artist_list, interval):
697
- """Displays the animation for the given artist list."""
698
- ani = ArtistAnimation(fig, artist_list, interval=interval, blit=True)
699
- return ani
700
-
701
- def show():
702
- plt.tight_layout()
703
- plt.show()
704
-
705
- def initialize_visualization_for_learner(show_history, neurons_history, neural_web_history, x_train, y_train):
706
- """Initialize all visualization components"""
707
- from .data_operations import find_closest_factors
708
- viz_objects = {}
709
-
710
- if show_history:
711
- fig, ax = plt.subplots(3, 1, figsize=(6, 8))
712
- fig.suptitle('Learner History')
713
- viz_objects['history'] = {
714
- 'fig': fig,
715
- 'ax': ax,
716
- 'artist1': [],
717
- 'artist2': [],
718
- 'artist3': []
719
- }
720
-
721
- if neurons_history:
722
- row, col = find_closest_factors(len(x_train[0]))
723
- if row != 0:
724
- fig1, ax1 = plt.subplots(1, len(y_train[0]), figsize=(18, 14))
725
- else:
726
- fig1, ax1 = plt.subplots(1, 1, figsize=(18, 14))
727
- viz_objects['neurons'] = {
728
- 'fig': fig1,
729
- 'ax': ax1,
730
- 'artists': [],
731
- 'row': row,
732
- 'col': col
733
- }
734
-
735
- if neural_web_history:
736
- G = nx.Graph()
737
- fig2, ax2 = plt.subplots(figsize=(18, 4))
738
- viz_objects['web'] = {
739
- 'fig': fig2,
740
- 'ax': ax2,
741
- 'G': G,
742
- 'artists': []
743
- }
744
-
745
- return viz_objects
746
-
747
- def update_history_plots_for_learner(viz_objects, depth_list, loss_list, best_acc_per_depth_list, x_train, final_activations):
748
- """Update history visualization plots"""
749
- if 'history' not in viz_objects:
750
- return
751
-
752
- hist = viz_objects['history']
753
-
754
- # Loss plot
755
- art1 = hist['ax'][0].plot(depth_list, loss_list, color='r', markersize=6, linewidth=2)
756
- hist['ax'][0].set_title('Train Loss Over Gen')
757
- hist['artist1'].append(art1)
758
-
759
- # Accuracy plot
760
- art2 = hist['ax'][1].plot(depth_list, best_acc_per_depth_list, color='g', markersize=6, linewidth=2)
761
- hist['ax'][1].set_title('Train Accuracy Over Gen')
762
- hist['artist2'].append(art2)
763
-
764
- # Activation shape plot
765
- x = np.linspace(np.min(x_train), np.max(x_train), len(x_train))
766
- translated_x_train = np.copy(x)
767
- for activation in final_activations:
768
- translated_x_train += draw_activations(x, activation)
769
-
770
- art3 = hist['ax'][2].plot(x, translated_x_train, color='b', markersize=6, linewidth=2)
771
- hist['ax'][2].set_title('Potentiation Shape Over Gen')
772
- hist['artist3'].append(art3)
773
-
774
- def display_visualizations_for_learner(viz_objects, best_weights, data, best_acc, test_loss, y_train, interval):
775
- """Display all final visualizations"""
776
- if 'history' in viz_objects:
777
- hist = viz_objects['history']
778
- for _ in range(30):
779
- hist['artist1'].append(hist['artist1'][-1])
780
- hist['artist2'].append(hist['artist2'][-1])
781
- hist['artist3'].append(hist['artist3'][-1])
782
-
783
- ani1 = ArtistAnimation(hist['fig'], hist['artist1'], interval=interval, blit=True)
784
- ani2 = ArtistAnimation(hist['fig'], hist['artist2'], interval=interval, blit=True)
785
- ani3 = ArtistAnimation(hist['fig'], hist['artist3'], interval=interval, blit=True)
786
- plt.tight_layout()
787
- plt.show()
788
-
789
- if 'neurons' in viz_objects:
790
- neurons = viz_objects['neurons']
791
- for _ in range(10):
792
- neurons['artists'] = update_neuron_history_for_learner(
793
- np.copy(best_weights),
794
- neurons['ax'],
795
- neurons['row'],
796
- neurons['col'],
797
- y_train[0],
798
- neurons['artists'],
799
- data=data,
800
- fig1=neurons['fig'],
801
- acc=best_acc,
802
- loss=test_loss
803
- )
804
-
805
- ani4 = ArtistAnimation(neurons['fig'], neurons['artists'], interval=interval, blit=True)
806
- plt.tight_layout()
807
- plt.show()
808
-
809
- if 'web' in viz_objects:
810
- web = viz_objects['web']
811
- for _ in range(30):
812
- art5_1, art5_2, art5_3 = draw_neural_web(
813
- W=best_weights,
814
- ax=web['ax'],
815
- G=web['G'],
816
- return_objs=True
817
- )
818
- art5_list = [art5_1] + [art5_2] + list(art5_3.values())
819
- web['artists'].append(art5_list)
820
-
821
- ani5 = ArtistAnimation(web['fig'], web['artists'], interval=interval, blit=True)
822
- plt.tight_layout()
823
- plt.show()