pyerualjetwork 4.3.2.1__py3-none-any.whl → 4.3.3__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 (46) hide show
  1. {pyerualjetwork-afterburner → pyerualjetwork}/__init__.py +1 -1
  2. pyerualjetwork/activation_functions.py +343 -0
  3. pyerualjetwork/activation_functions_cuda.py +340 -0
  4. pyerualjetwork/model_operations.py +408 -0
  5. pyerualjetwork/model_operations_cuda.py +421 -0
  6. pyerualjetwork/plan.py +627 -0
  7. pyerualjetwork/plan_cuda.py +651 -0
  8. pyerualjetwork/planeat.py +825 -0
  9. pyerualjetwork/planeat_cuda.py +834 -0
  10. {pyerualjetwork-4.3.2.1.dist-info → pyerualjetwork-4.3.3.dist-info}/METADATA +17 -4
  11. pyerualjetwork-4.3.3.dist-info/RECORD +44 -0
  12. pyerualjetwork-4.3.3.dist-info/top_level.txt +2 -0
  13. pyerualjetwork_afterburner/__init__.py +11 -0
  14. pyerualjetwork_afterburner/data_operations.py +406 -0
  15. pyerualjetwork_afterburner/data_operations_cuda.py +461 -0
  16. pyerualjetwork_afterburner/help.py +17 -0
  17. pyerualjetwork_afterburner/loss_functions.py +21 -0
  18. pyerualjetwork_afterburner/loss_functions_cuda.py +21 -0
  19. pyerualjetwork_afterburner/memory_operations.py +298 -0
  20. pyerualjetwork_afterburner/metrics.py +190 -0
  21. pyerualjetwork_afterburner/metrics_cuda.py +163 -0
  22. pyerualjetwork_afterburner/ui.py +22 -0
  23. pyerualjetwork_afterburner/visualizations.py +823 -0
  24. pyerualjetwork_afterburner/visualizations_cuda.py +825 -0
  25. pyerualjetwork-4.3.2.1.dist-info/RECORD +0 -24
  26. pyerualjetwork-4.3.2.1.dist-info/top_level.txt +0 -1
  27. {pyerualjetwork-afterburner → pyerualjetwork}/data_operations.py +0 -0
  28. {pyerualjetwork-afterburner → pyerualjetwork}/data_operations_cuda.py +0 -0
  29. {pyerualjetwork-afterburner → pyerualjetwork}/help.py +0 -0
  30. {pyerualjetwork-afterburner → pyerualjetwork}/loss_functions.py +0 -0
  31. {pyerualjetwork-afterburner → pyerualjetwork}/loss_functions_cuda.py +0 -0
  32. {pyerualjetwork-afterburner → pyerualjetwork}/memory_operations.py +0 -0
  33. {pyerualjetwork-afterburner → pyerualjetwork}/metrics.py +0 -0
  34. {pyerualjetwork-afterburner → pyerualjetwork}/metrics_cuda.py +0 -0
  35. {pyerualjetwork-afterburner → pyerualjetwork}/ui.py +0 -0
  36. {pyerualjetwork-afterburner → pyerualjetwork}/visualizations.py +0 -0
  37. {pyerualjetwork-afterburner → pyerualjetwork}/visualizations_cuda.py +0 -0
  38. {pyerualjetwork-4.3.2.1.dist-info → pyerualjetwork-4.3.3.dist-info}/WHEEL +0 -0
  39. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/activation_functions.py +0 -0
  40. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/activation_functions_cuda.py +0 -0
  41. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/model_operations.py +0 -0
  42. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/model_operations_cuda.py +0 -0
  43. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/plan.py +0 -0
  44. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/plan_cuda.py +0 -0
  45. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/planeat.py +0 -0
  46. {pyerualjetwork-afterburner → pyerualjetwork_afterburner}/planeat_cuda.py +0 -0
pyerualjetwork/plan.py ADDED
@@ -0,0 +1,627 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+
4
+ MAIN MODULE FOR PLAN
5
+
6
+ Examples: https://github.com/HCB06/PyerualJetwork/tree/main/Welcome_to_PyerualJetwork/ExampleCodes
7
+
8
+ PLAN document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PLAN/PLAN.pdf
9
+ PYERUALJETWORK document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PyerualJetwork/PYERUALJETWORK_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf
10
+
11
+ @author: Hasan Can Beydili
12
+ @YouTube: https://www.youtube.com/@HasanCanBeydili
13
+ @Linkedin: https://www.linkedin.com/in/hasan-can-beydili-77a1b9270/
14
+ @Instagram: https://www.instagram.com/canbeydilj/
15
+ @contact: tchasancan@gmail.com
16
+ """
17
+
18
+ import numpy as np
19
+ import math
20
+
21
+ ### LIBRARY IMPORTS ###
22
+ from .ui import loading_bars, initialize_loading_bar
23
+ from .data_operations import normalization, decode_one_hot, batcher
24
+ from .loss_functions import binary_crossentropy, categorical_crossentropy
25
+ from .activation_functions import apply_activation, Softmax, all_activations
26
+ from .metrics import metrics
27
+ from .model_operations import get_acc, get_preds, get_preds_softmax
28
+ from .memory_operations import optimize_labels
29
+ from .visualizations import (
30
+ draw_neural_web,
31
+ update_neural_web_for_fit,
32
+ plot_evaluate,
33
+ update_neuron_history,
34
+ initialize_visualization_for_fit,
35
+ update_weight_visualization_for_fit,
36
+ update_decision_boundary_for_fit,
37
+ update_validation_history_for_fit,
38
+ display_visualization_for_fit,
39
+ display_visualizations_for_learner,
40
+ update_history_plots_for_learner,
41
+ initialize_visualization_for_learner,
42
+ update_neuron_history_for_learner,
43
+ show
44
+ )
45
+
46
+ ### GLOBAL VARIABLES ###
47
+ bar_format_normal = loading_bars()[0]
48
+ bar_format_learner = loading_bars()[1]
49
+
50
+ # BUILD -----
51
+
52
+ def fit(
53
+ x_train,
54
+ y_train,
55
+ val=False,
56
+ val_count=None,
57
+ activation_potentiation=['linear'],
58
+ x_val=None,
59
+ y_val=None,
60
+ show_training=None,
61
+ interval=100,
62
+ LTD=0,
63
+ decision_boundary_status=True,
64
+ train_bar=True,
65
+ auto_normalization=True,
66
+ neurons_history=False,
67
+ dtype=np.float32
68
+ ):
69
+ """
70
+ Creates a model to fitting data.
71
+
72
+ fit Args:
73
+
74
+ x_train (list[num]): List or numarray of input data.
75
+
76
+ y_train (list[num]): List or numarray of target labels. (one hot encoded)
77
+
78
+ val (None or True): validation in training process ? None or True default: None (optional)
79
+
80
+ val_count (None or int): After how many examples learned will an accuracy test be performed? default: 10=(%10) it means every approximately 10 step (optional)
81
+
82
+ activation_potentiation (list): For deeper PLAN networks, activation function parameters. For more information please run this code: plan.activations_list() default: [None] (optional)
83
+
84
+ x_val (list[num]): List of validation data. default: x_train (optional)
85
+
86
+ y_val (list[num]): (list[num]): List of target labels. (one hot encoded) default: y_train (optional)
87
+
88
+ show_training (bool, str): True or None default: None (optional)
89
+
90
+ LTD (int): Long Term Depression Hyperparameter for train PLAN neural network default: 0 (optional)
91
+
92
+ interval (float, int): frame delay (milisecond) parameter for Training Report (show_training=True) This parameter effects to your Training Report performance. Lower value is more diffucult for Low end PC's (33.33 = 30 FPS, 16.67 = 60 FPS) default: 100 (optional)
93
+
94
+ decision_boundary_status (bool): If the visualization of validation and training history is enabled during training, should the decision boundaries also be visualized? True or False. Default is True. (optional)
95
+
96
+ train_bar (bool): Training loading bar? True or False. Default is True. (optional)
97
+
98
+ auto_normalization(bool): Normalization process during training. May effect training time and model quality. True or False. Default is True. (optional)
99
+
100
+ neurons_history (bool, optional): Shows the history of changes that neurons undergo during the CL (Cumulative Learning) stages. True or False. Default is False. (optional)
101
+
102
+ dtype (numpy.dtype): Data type for the arrays. np.float32 by default. Example: np.float64 or np.float16. [fp32 for balanced devices, fp64 for strong devices, fp16 for weak devices: not reccomended!] (optional)
103
+
104
+ Returns:
105
+ numpyarray([num]): (Weight matrix).
106
+ """
107
+
108
+ # Pre-checks
109
+
110
+ x_train = x_train.astype(dtype, copy=False)
111
+
112
+ if train_bar and val:
113
+ train_progress = initialize_loading_bar(total=len(x_train), ncols=71, desc='Fitting', bar_format=bar_format_normal)
114
+ elif train_bar and val == False:
115
+ train_progress = initialize_loading_bar(total=len(x_train), ncols=44, desc='Fitting', bar_format=bar_format_normal)
116
+
117
+ if len(x_train) != len(y_train):
118
+ raise ValueError("x_train and y_train must have the same length.")
119
+
120
+ if val and (x_val is None and y_val is None):
121
+ x_val, y_val = x_train, y_train
122
+
123
+ elif val and (x_val is not None and y_val is not None):
124
+ x_val = x_val.astype(dtype, copy=False)
125
+ y_val = y_val.astype(dtype, copy=False)
126
+
127
+ val_list = [] if val else None
128
+ val_count = val_count or 10
129
+ # Defining weights
130
+ STPW = np.ones((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False) # STPW = SHORT TIME POTENTIATION WEIGHT
131
+ LTPW = np.zeros((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False) # LTPW = LONG TIME POTENTIATION WEIGHT
132
+ # Initialize visualization
133
+ vis_objects = initialize_visualization_for_fit(val, show_training, neurons_history, x_train, y_train)
134
+
135
+ # Training process
136
+ for index, inp in enumerate(x_train):
137
+ inp = np.array(inp, copy=False).ravel()
138
+ y_decoded = decode_one_hot(y_train[index])
139
+ # Weight updates
140
+ STPW = feed_forward(inp, STPW, is_training=True, Class=y_decoded, activation_potentiation=activation_potentiation, LTD=LTD)
141
+ LTPW += normalization(STPW, dtype=dtype) if auto_normalization else STPW
142
+ if val and index != 0:
143
+ if index % math.ceil((val_count / len(x_train)) * 100) == 0:
144
+ val_acc = evaluate(x_val, y_val, loading_bar_status=False, activation_potentiation=activation_potentiation, W=LTPW)[get_acc()]
145
+ val_list.append(val_acc)
146
+
147
+ # Visualization updates
148
+ if show_training:
149
+ update_weight_visualization_for_fit(vis_objects['ax'][0, 0], LTPW, vis_objects['artist2'])
150
+ if decision_boundary_status:
151
+ update_decision_boundary_for_fit(vis_objects['ax'][0, 1], x_val, y_val, activation_potentiation, LTPW, vis_objects['artist1'])
152
+ update_validation_history_for_fit(vis_objects['ax'][1, 1], val_list, vis_objects['artist3'])
153
+ update_neural_web_for_fit(W=LTPW, G=vis_objects['G'], ax=vis_objects['ax'][1, 0], artist=vis_objects['artist4'])
154
+ if neurons_history:
155
+ update_neuron_history(LTPW, row=vis_objects['row'], col=vis_objects['col'], class_count=len(y_train[0]), fig1=vis_objects['fig1'], ax1=vis_objects['ax1'], artist5=vis_objects['artist5'], acc=val_acc)
156
+ if train_bar:
157
+ train_progress.update(1)
158
+
159
+ STPW = np.ones((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False)
160
+
161
+ # Finalize visualization
162
+ if show_training:
163
+ ani1 = display_visualization_for_fit(vis_objects['fig'], vis_objects['artist1'], interval)
164
+ ani2 = display_visualization_for_fit(vis_objects['fig'], vis_objects['artist2'], interval)
165
+ ani3 = display_visualization_for_fit(vis_objects['fig'], vis_objects['artist3'], interval)
166
+ ani4 = display_visualization_for_fit(vis_objects['fig'], vis_objects['artist4'], interval)
167
+ show()
168
+
169
+ if neurons_history:
170
+ ani5 = display_visualization_for_fit(vis_objects['fig1'], vis_objects['artist5'], interval)
171
+ show()
172
+
173
+ return normalization(LTPW, dtype=dtype)
174
+
175
+
176
+ def learner(x_train, y_train, optimizer, fit_start, strategy='accuracy', gen=None, batch_size=1,
177
+ neural_web_history=False, show_current_activations=False, auto_normalization=True,
178
+ neurons_history=False, early_stop=False, loss='categorical_crossentropy', show_history=False,
179
+ interval=33.33, target_acc=None, target_loss=None,
180
+ start_this_act=None, start_this_W=None, dtype=np.float32):
181
+ """
182
+ Optimizes the activation functions for a neural network by leveraging train data to find
183
+ the most accurate combination of activation potentiation for the given dataset using genetic algorithm NEAT (Neuroevolution of Augmenting Topologies). But modifided for PLAN version. Created by me: PLANEAT.
184
+
185
+ Why genetic optimization and not backpropagation?
186
+ Because PLAN is different from other neural network architectures. In PLAN, the learnable parameters are not the weights; instead, the learnable parameters are the activation functions.
187
+ Since activation functions are not differentiable, we cannot use gradient descent or backpropagation. However, I developed a more powerful genetic optimization algorithm: PLANEAT.
188
+
189
+ Args:
190
+
191
+ x_train (array-like): Training input data.
192
+
193
+ y_train (array-like): Labels for training data. one-hot encoded.
194
+
195
+ optimizer (function): PLAN optimization technique with hyperparameters. (PLAN using NEAT(PLANEAT) for optimization.) Please use this: from pyerualjetwork import planeat (and) optimizer = lambda *args, **kwargs: planeat.evolve(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
196
+ ```python
197
+ genetic_optimizer = lambda *args, **kwargs: planeat.evolver(*args,
198
+ activation_add_prob=0.85,
199
+ strategy='aggressive',
200
+ **kwargs)
201
+
202
+ model = plan.learner(x_train,
203
+ y_train,
204
+ optimizer=genetic_optimizer,
205
+ fit_start=True,
206
+ strategy='accuracy',
207
+ show_history=True,
208
+ gen=15,
209
+ batch_size=0.05,
210
+ interval=16.67)
211
+ ```
212
+
213
+ fit_start (bool): If the fit_start parameter is set to True, the initial generation population undergoes a simple short training process using the PLAN algorithm. This allows for a very robust starting point, especially for large and complex datasets. However, for small or relatively simple datasets, it may result in unnecessary computational overhead. When fit_start is True, completing the first generation may take slightly longer (this increase in computational cost applies only to the first generation and does not affect subsequent generations). If fit_start is set to False, the initial population will be entirely random. Options: True or False. The fit_start parameter is MANDATORY and must be provided.
214
+
215
+ strategy (str, optional): Learning strategy. (options: 'accuracy', 'f1', 'precision', 'recall'): 'accuracy', Maximizes train (or test if given) accuracy during learning. 'f1', Maximizes train (or test if given) f1 score during learning. 'precision', Maximizes train (or test if given) precision score during learning. 'recall', Maximizes train (or test if given) recall during learning. Default is 'accuracy'.
216
+
217
+ gen (int, optional): The generation count for genetic optimization.
218
+
219
+ batch_size (float, optional): Batch size is used in the prediction process to receive train feedback by dividing the test data into chunks and selecting activations based on randomly chosen partitions. This process reduces computational cost and time while still covering the entire test set due to random selection, so it doesn't significantly impact accuracy. For example, a batch size of 0.08 means each train batch represents 8% of the train set. Default is 1. (%100 of train)
220
+
221
+ early_stop (bool, optional): If True, implements early stopping during training.(If accuracy not improves in two gen stops learning.) Default is False.
222
+
223
+ auto_normalization (bool, optional): IMPORTANT: auto_nomralization parameter works only if fit_start is True. Do not change this value if fit_start is False, because it doesnt matter.) If auto normalization=False this makes more faster training times and much better accuracy performance for some datasets. Default is True.
224
+
225
+ show_current_activations (bool, optional): Should it display the activations selected according to the current strategies during learning, or not? (True or False) This can be very useful if you want to cancel the learning process and resume from where you left off later. After canceling, you will need to view the live training activations in order to choose the activations to be given to the 'start_this' parameter. Default is False
226
+
227
+ show_history (bool, optional): If True, displays the training history after optimization. Default is False.
228
+
229
+ loss (str, optional): For visualizing and monitoring. PLAN neural networks doesn't need any loss function in training. options: ('categorical_crossentropy' or 'binary_crossentropy') Default is 'categorical_crossentropy'.
230
+
231
+ interval (int, optional): The interval at which evaluations are conducted during training. (33.33 = 30 FPS, 16.67 = 60 FPS) Default is 100.
232
+
233
+ target_acc (int, optional): The target accuracy to stop training early when achieved. Default is None.
234
+
235
+ target_loss (float, optional): The target loss to stop training early when achieved. Default is None.
236
+
237
+ start_this_act (list, optional): To resume a previously canceled or interrupted training from where it left off, or to continue from that point with a different strategy, provide the list of activation functions selected up to the learned portion to this parameter. Default is None
238
+
239
+ start_this_W (numpy.array, optional): To resume a previously canceled or interrupted training from where it left off, or to continue from that point with a different strategy, provide the weight matrix of this genome. Default is None
240
+
241
+ neurons_history (bool, optional): Shows the history of changes that neurons undergo during the TFL (Test or Train Feedback Learning) stages. True or False. Default is False.
242
+
243
+ neural_web_history (bool, optional): Draws history of neural web. Default is False.
244
+
245
+ dtype (numpy.dtype): Data type for the arrays. np.float32 by default. Example: np.float64 or np.float16. [fp32 for balanced devices, fp64 for strong devices, fp16 for weak devices: not reccomended!] (optional)
246
+
247
+ Returns:
248
+ tuple: A list for model parameters: [Weight matrix, Test loss, Test Accuracy, [Activations functions]].
249
+
250
+ """
251
+
252
+ from .planeat import define_genomes
253
+
254
+ data = 'Train'
255
+
256
+ activation_potentiation = all_activations()
257
+ activation_potentiation_len = len(activation_potentiation)
258
+
259
+ # Pre-checks
260
+
261
+ x_train = x_train.astype(dtype, copy=False)
262
+ y_train = optimize_labels(y_train, cuda=False)
263
+
264
+ if gen is None:
265
+ gen = activation_potentiation_len
266
+
267
+ if strategy != 'accuracy' and strategy != 'f1' and strategy != 'recall' and strategy != 'precision': raise ValueError("Strategy parameter only be 'accuracy' or 'f1' or 'recall' or 'precision'.")
268
+ if target_acc is not None and (target_acc < 0 or target_acc > 1): raise ValueError('target_acc must be in range 0 and 1')
269
+ if fit_start is not True and fit_start is not False: raise ValueError('fit_start parameter only be True or False. Please read doc-string')
270
+
271
+ # Initialize visualization components
272
+ viz_objects = initialize_visualization_for_learner(show_history, neurons_history, neural_web_history, x_train, y_train)
273
+
274
+ # Initialize progress bar
275
+ if batch_size == 1:
276
+ ncols = 76
277
+ else:
278
+ ncols = 89
279
+
280
+ # Initialize variables
281
+ best_acc = 0
282
+ best_f1 = 0
283
+ best_recall = 0
284
+ best_precision = 0
285
+ best_acc_per_gen_list = []
286
+ postfix_dict = {}
287
+ loss_list = []
288
+ target_pop = []
289
+
290
+ progress = initialize_loading_bar(total=activation_potentiation_len, desc="", ncols=ncols, bar_format=bar_format_learner)
291
+
292
+ if fit_start is False:
293
+ weight_pop, act_pop = define_genomes(input_shape=len(x_train[0]), output_shape=len(y_train[0]), population_size=activation_potentiation_len, dtype=dtype)
294
+
295
+ if start_this_act is not None and start_this_W is not None:
296
+ weight_pop[0] = start_this_W
297
+ act_pop[0] = start_this_act
298
+
299
+ else:
300
+ weight_pop = []
301
+ act_pop = []
302
+
303
+ for i in range(gen):
304
+ postfix_dict["Gen"] = str(i+1) + '/' + str(gen)
305
+ progress.set_postfix(postfix_dict)
306
+
307
+ progress.n = 0
308
+ progress.last_print_n = 0
309
+ progress.update(0)
310
+
311
+ for j in range(activation_potentiation_len):
312
+
313
+ x_train_batch, y_train_batch = batcher(x_train, y_train, batch_size=batch_size)
314
+
315
+ if fit_start is True and i == 0:
316
+ act_pop.append(activation_potentiation[j])
317
+ W = fit(x_train_batch, y_train_batch, activation_potentiation=act_pop[-1], train_bar=False, auto_normalization=auto_normalization, dtype=dtype)
318
+ weight_pop.append(W)
319
+
320
+ model = evaluate(x_train_batch, y_train_batch, W=weight_pop[j], loading_bar_status=False, activation_potentiation=act_pop[j], dtype=dtype)
321
+ acc = model[get_acc()]
322
+
323
+ if strategy == 'accuracy': target_pop.append(acc)
324
+
325
+ elif strategy == 'f1' or strategy == 'precision' or strategy == 'recall':
326
+ precision_score, recall_score, f1_score = metrics(y_train_batch, model[get_preds()])
327
+
328
+ if strategy == 'precision':
329
+ target_pop.append(precision_score)
330
+
331
+ if i == 0 and j == 0:
332
+ best_precision = precision_score
333
+
334
+ if strategy == 'recall':
335
+ target_pop.append(recall_score)
336
+
337
+ if i == 0 and j == 0:
338
+ best_recall = recall_score
339
+
340
+ if strategy == 'f1':
341
+ target_pop.append(f1_score)
342
+
343
+ if i == 0 and j == 0:
344
+ best_f1 = f1_score
345
+
346
+ if ((strategy == 'accuracy' and acc >= best_acc) or
347
+ (strategy == 'f1' and f1_score >= best_f1) or
348
+ (strategy == 'precision' and precision_score >= best_precision) or
349
+ (strategy == 'recall' and recall_score >= best_recall)):
350
+
351
+ best_acc = acc
352
+ best_weights = np.copy(weight_pop[j])
353
+ final_activations = act_pop[j].copy() if isinstance(act_pop[j], list) else act_pop[j]
354
+ best_model = model
355
+
356
+ final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
357
+
358
+ if batch_size == 1:
359
+ postfix_dict[f"{data} Accuracy"] = best_acc
360
+ else:
361
+ postfix_dict[f"{data} Batch Accuracy"] = acc
362
+ progress.set_postfix(postfix_dict)
363
+
364
+ if show_current_activations:
365
+ print(f", Current Activations={final_activations}", end='')
366
+
367
+ if loss == 'categorical_crossentropy':
368
+ train_loss = categorical_crossentropy(y_true_batch=y_train_batch, y_pred_batch=model[get_preds_softmax()])
369
+ else:
370
+ train_loss = binary_crossentropy(y_true_batch=y_train_batch, y_pred_batch=model[get_preds_softmax()])
371
+
372
+ if batch_size == 1:
373
+ postfix_dict[f"{data} Loss"] = train_loss
374
+ best_loss = train_loss
375
+ else:
376
+ postfix_dict[f"{data} Batch Loss"] = train_loss
377
+ progress.set_postfix(postfix_dict)
378
+ best_loss = train_loss
379
+
380
+ # Update visualizations during training
381
+ if show_history:
382
+ gen_list = range(1, len(best_acc_per_gen_list) + 2)
383
+ update_history_plots_for_learner(viz_objects, gen_list, loss_list + [train_loss],
384
+ best_acc_per_gen_list + [best_acc], x_train, final_activations)
385
+
386
+ if neurons_history:
387
+ viz_objects['neurons']['artists'] = (
388
+ update_neuron_history_for_learner(np.copy(best_weights), viz_objects['neurons']['ax'],
389
+ viz_objects['neurons']['row'], viz_objects['neurons']['col'],
390
+ y_train[0], viz_objects['neurons']['artists'],
391
+ data=data, fig1=viz_objects['neurons']['fig'],
392
+ acc=best_acc, loss=train_loss)
393
+ )
394
+
395
+ if neural_web_history:
396
+ art5_1, art5_2, art5_3 = draw_neural_web(W=best_weights, ax=viz_objects['web']['ax'],
397
+ G=viz_objects['web']['G'], return_objs=True)
398
+ art5_list = [art5_1] + [art5_2] + list(art5_3.values())
399
+ viz_objects['web']['artists'].append(art5_list)
400
+
401
+ # Check target accuracy
402
+ if target_acc is not None and best_acc >= target_acc:
403
+ progress.close()
404
+ train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
405
+ activation_potentiation=final_activations, dtype=dtype)
406
+
407
+ if loss == 'categorical_crossentropy':
408
+ train_loss = categorical_crossentropy(y_true_batch=y_train,
409
+ y_pred_batch=train_model[get_preds_softmax()])
410
+ else:
411
+ train_loss = binary_crossentropy(y_true_batch=y_train,
412
+ y_pred_batch=train_model[get_preds_softmax()])
413
+
414
+ print('\nActivations: ', final_activations)
415
+ print(f'Train Accuracy :', train_model[get_acc()])
416
+ print(f'Train Loss : ', train_loss, '\n')
417
+
418
+ # Display final visualizations
419
+ display_visualizations_for_learner(viz_objects, best_weights, data, best_acc,
420
+ train_loss, y_train, interval)
421
+ return best_weights, best_model[get_preds()], best_acc, final_activations
422
+
423
+ # Check target loss
424
+ if target_loss is not None and best_loss <= target_loss:
425
+ progress.close()
426
+ train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
427
+ activation_potentiation=final_activations, dtype=dtype)
428
+
429
+ if loss == 'categorical_crossentropy':
430
+ train_loss = categorical_crossentropy(y_true_batch=y_train,
431
+ y_pred_batch=train_model[get_preds_softmax()])
432
+ else:
433
+ train_loss = binary_crossentropy(y_true_batch=y_train,
434
+ y_pred_batch=train_model[get_preds_softmax()])
435
+
436
+ print('\nActivations: ', final_activations)
437
+ print(f'Train Accuracy :', train_model[get_acc()])
438
+ print(f'Train Loss : ', train_loss, '\n')
439
+
440
+ # Display final visualizations
441
+ display_visualizations_for_learner(viz_objects, best_weights, data, best_acc,
442
+ train_loss, y_train, interval)
443
+ return best_weights, best_model[get_preds()], best_acc, final_activations
444
+
445
+ progress.update(1)
446
+
447
+ best_acc_per_gen_list.append(best_acc)
448
+ loss_list.append(best_loss)
449
+
450
+ weight_pop, act_pop = optimizer(np.array(weight_pop, copy=False, dtype=dtype), act_pop, i, np.array(target_pop, dtype=dtype, copy=False), bar_status=False)
451
+ target_pop = []
452
+
453
+ # Early stopping check
454
+ if early_stop == True and i > 0:
455
+ if best_acc_per_gen_list[i] == best_acc_per_gen_list[i-1]:
456
+ progress.close()
457
+ train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
458
+ activation_potentiation=final_activations, dtype=dtype)
459
+
460
+ if loss == 'categorical_crossentropy':
461
+ train_loss = categorical_crossentropy(y_true_batch=y_train,
462
+ y_pred_batch=train_model[get_preds_softmax()])
463
+ else:
464
+ train_loss = binary_crossentropy(y_true_batch=y_train,
465
+ y_pred_batch=train_model[get_preds_softmax()])
466
+
467
+ print('\nActivations: ', final_activations)
468
+ print(f'Train Accuracy :', train_model[get_acc()])
469
+ print(f'Train Loss : ', train_loss, '\n')
470
+
471
+ # Display final visualizations
472
+ display_visualizations_for_learner(viz_objects, best_weights, data, best_acc,
473
+ train_loss, y_train, interval)
474
+ return best_weights, best_model[get_preds()], best_acc, final_activations
475
+
476
+ # Final evaluation
477
+ progress.close()
478
+ train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
479
+ activation_potentiation=final_activations, dtype=dtype)
480
+
481
+ if loss == 'categorical_crossentropy':
482
+ train_loss = categorical_crossentropy(y_true_batch=y_train, y_pred_batch=train_model[get_preds_softmax()])
483
+ else:
484
+ train_loss = binary_crossentropy(y_true_batch=y_train, y_pred_batch=train_model[get_preds_softmax()])
485
+
486
+ print('\nActivations: ', final_activations)
487
+ print(f'Train Accuracy :', train_model[get_acc()])
488
+ print(f'Train Loss : ', train_loss, '\n')
489
+
490
+ # Display final visualizations
491
+ display_visualizations_for_learner(viz_objects, best_weights, data, best_acc, train_loss, y_train, interval)
492
+ return best_weights, best_model[get_preds()], best_acc, final_activations
493
+
494
+
495
+
496
+ def feed_forward(
497
+ Input, # list[num]: Input data.
498
+ w, # num: Weight matrix of the neural network.
499
+ is_training, # bool: Flag indicating if the function is called during training (True or False).
500
+ activation_potentiation,
501
+ Class='?', # int: Which class is, if training. # (list): Activation potentiation list for deep PLAN. (optional)
502
+ LTD=0
503
+ ) -> tuple:
504
+ """
505
+ Applies feature extraction process to the input data using synaptic potentiation.
506
+
507
+ Args:
508
+ Input (num): Input data.
509
+ w (num): Weight matrix of the neural network.
510
+ is_training (bool): Flag indicating if the function is called during training (True or False).
511
+ Class (int): if is during training then which class(label) ? is isnt then put None.
512
+ # activation_potentiation (list): ac list for deep PLAN. default: [None] ('linear') (optional)
513
+
514
+ Returns:
515
+ tuple: A tuple (vector) containing the neural layer result and the updated weight matrix.
516
+ or
517
+ num: neural network output
518
+ """
519
+
520
+ Output = apply_activation(Input, activation_potentiation)
521
+
522
+ Input = Output
523
+
524
+ if is_training == True:
525
+
526
+ for _ in range(LTD):
527
+
528
+ depression_vector = np.random.rand(*Input.shape)
529
+
530
+ Input -= depression_vector
531
+
532
+ w[Class, :] = Input
533
+ return w
534
+
535
+ else:
536
+
537
+ neural_layer = np.dot(w, Input)
538
+
539
+ return neural_layer
540
+
541
+
542
+ def evaluate(
543
+ x_test, # NumPy array: Test input data.
544
+ y_test, # NumPy array: Test labels.
545
+ W, # List of NumPy arrays: Neural network weight matrices.
546
+ activation_potentiation=['linear'], # List of activation functions.
547
+ loading_bar_status=True, # Optionally show loading bar.
548
+ show_metrics=None, # Optionally show metrics.
549
+ dtype=np.float32
550
+ ) -> tuple:
551
+ """
552
+ Evaluates the neural network model using the given test data.
553
+
554
+ Args:
555
+ x_test (np.ndarray): Test input data.
556
+
557
+ y_test (np.ndarray): Test labels. one-hot encoded.
558
+
559
+ W (list[np.ndarray]): List of neural network weight matrices.
560
+
561
+ activation_potentiation (list): List of activation functions.
562
+
563
+ loading_bar_status (bool): Option to show a loading bar (optional).
564
+
565
+ show_metrics (bool): Option to show metrics (optional).
566
+
567
+ dtype (numpy.dtype): Data type for the arrays. np.float32 by default. Example: np.float64 or np.float16. [fp32 for balanced devices, fp64 for strong devices, fp16 for weak devices: not reccomended!]
568
+
569
+ Returns:
570
+ tuple: Predicted labels, model accuracy, and other evaluation metrics.
571
+ """
572
+ # Pre-checks
573
+
574
+ x_test = x_test.astype(dtype, copy=False)
575
+
576
+ if len(y_test[0]) < 256:
577
+ if y_test.dtype != np.uint8:
578
+ y_test = np.array(y_test, copy=False).astype(np.uint8, copy=False)
579
+ elif len(y_test[0]) <= 32767:
580
+ if y_test.dtype != np.uint16:
581
+ y_test = np.array(y_test, copy=False).astype(np.uint16, copy=False)
582
+ else:
583
+ if y_test.dtype != np.uint32:
584
+ y_test = np.array(y_test, copy=False).astype(np.uint32, copy=False)
585
+
586
+ predict_probabilitys = np.empty((len(x_test), W.shape[0]), dtype=dtype)
587
+ real_classes = np.empty(len(x_test), dtype=y_test.dtype)
588
+ predict_classes = np.empty(len(x_test), dtype=y_test.dtype)
589
+
590
+ true_predict = 0
591
+ acc_list = np.empty(len(x_test), dtype=dtype)
592
+
593
+ if loading_bar_status:
594
+ loading_bar = initialize_loading_bar(total=len(x_test), ncols=64, desc='Testing', bar_format=bar_format_normal)
595
+
596
+ for inpIndex in range(len(x_test)):
597
+ Input = x_test[inpIndex].ravel()
598
+
599
+ neural_layer = Input
600
+
601
+ neural_layer = feed_forward(neural_layer, np.copy(W), is_training=False, Class='?', activation_potentiation=activation_potentiation)
602
+
603
+ predict_probabilitys[inpIndex] = Softmax(neural_layer)
604
+
605
+ RealOutput = np.argmax(y_test[inpIndex])
606
+ real_classes[inpIndex] = RealOutput
607
+ PredictedOutput = np.argmax(neural_layer)
608
+ predict_classes[inpIndex] = PredictedOutput
609
+
610
+ if RealOutput == PredictedOutput:
611
+ true_predict += 1
612
+
613
+ acc = true_predict / (inpIndex + 1)
614
+ acc_list[inpIndex] = acc
615
+
616
+ if loading_bar_status:
617
+ loading_bar.update(1)
618
+ loading_bar.set_postfix({"Test Accuracy": acc})
619
+
620
+ if loading_bar_status:
621
+ loading_bar.close()
622
+
623
+ if show_metrics:
624
+ # Plot the evaluation metrics
625
+ plot_evaluate(x_test, y_test, predict_classes, acc_list, W=np.copy(W), activation_potentiation=activation_potentiation)
626
+
627
+ return W, predict_classes, acc_list[-1], None, None, predict_probabilitys