pyerualjetwork 3.3.4__py3-none-any.whl → 4.1.9__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.
pyerualjetwork/plan.py CHANGED
@@ -3,8 +3,8 @@
3
3
 
4
4
  MAIN MODULE FOR PLAN
5
5
 
6
- PLAN document: https://github.com/HCB06/Anaplan/blob/main/Welcome_to_PLAN/PLAN.pdf
7
- ANAPLAN document: https://github.com/HCB06/Anaplan/blob/main/Welcome_to_Anaplan/ANAPLAN_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf
6
+ PLAN document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PLAN/PLAN.pdf
7
+ PYERUALJETWORK document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PyerualJetwork/PYERUALJETWORK_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf
8
8
 
9
9
  @author: Hasan Can Beydili
10
10
  @YouTube: https://www.youtube.com/@HasanCanBeydili
@@ -14,8 +14,9 @@ ANAPLAN document: https://github.com/HCB06/Anaplan/blob/main/Welcome_to_Anaplan/
14
14
  """
15
15
 
16
16
  import numpy as np
17
- from colorama import Fore, Style
18
- import sys
17
+ from colorama import Fore
18
+ import math
19
+ import random
19
20
 
20
21
  ### LIBRARY IMPORTS ###
21
22
  from .ui import loading_bars, initialize_loading_bar
@@ -23,11 +24,13 @@ from .data_operations import normalization, decode_one_hot, batcher
23
24
  from .loss_functions import binary_crossentropy, categorical_crossentropy
24
25
  from .activation_functions import apply_activation, Softmax, all_activations
25
26
  from .metrics import metrics
26
- from.model_operations import get_acc, get_preds, get_preds_softmax
27
+ from .model_operations import get_acc, get_preds, get_preds_softmax
28
+ from .memory_operations import optimize_labels
27
29
  from .visualizations import (
28
30
  draw_neural_web,
31
+ update_neural_web_for_fit,
29
32
  plot_evaluate,
30
- neuron_history,
33
+ update_neuron_history,
31
34
  initialize_visualization_for_fit,
32
35
  update_weight_visualization_for_fit,
33
36
  update_decision_boundary_for_fit,
@@ -35,7 +38,9 @@ from .visualizations import (
35
38
  display_visualization_for_fit,
36
39
  display_visualizations_for_learner,
37
40
  update_history_plots_for_learner,
38
- initialize_visualization_for_learner
41
+ initialize_visualization_for_learner,
42
+ update_neuron_history_for_learner,
43
+ show
39
44
  )
40
45
 
41
46
  ### GLOBAL VARIABLES ###
@@ -47,7 +52,7 @@ bar_format_learner = loading_bars()[1]
47
52
  def fit(
48
53
  x_train,
49
54
  y_train,
50
- val=None,
55
+ val=False,
51
56
  val_count=None,
52
57
  activation_potentiation=['linear'],
53
58
  x_val=None,
@@ -58,7 +63,8 @@ def fit(
58
63
  decision_boundary_status=True,
59
64
  train_bar=True,
60
65
  auto_normalization=True,
61
- neurons_history=False
66
+ neurons_history=False,
67
+ dtype=np.float32
62
68
  ):
63
69
  """
64
70
  Creates a model to fitting data.
@@ -93,11 +99,16 @@ def fit(
93
99
 
94
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)
95
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
+
96
104
  Returns:
97
105
  numpyarray([num]): (Weight matrix).
98
106
  """
107
+
99
108
  # Pre-checks
100
109
 
110
+ x_train = x_train.astype(dtype, copy=False)
111
+
101
112
  if train_bar and val:
102
113
  train_progress = initialize_loading_bar(total=len(x_train), ncols=71, desc='Fitting', bar_format=bar_format_normal)
103
114
  elif train_bar and val == False:
@@ -106,82 +117,117 @@ def fit(
106
117
  if len(x_train) != len(y_train):
107
118
  raise ValueError("x_train and y_train must have the same length.")
108
119
 
109
- if val and (x_val is None or y_val is None):
120
+ if val and (x_val is None and y_val is None):
110
121
  x_val, y_val = x_train, y_train
111
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
+
112
127
  val_list = [] if val else None
113
128
  val_count = val_count or 10
114
129
  # Defining weights
115
- STPW = np.ones((len(y_train[0]), len(x_train[0].ravel()))) # STPW = SHORT TIME POTENTIATION WEIGHT
116
- LTPW = np.zeros((len(y_train[0]), len(x_train[0].ravel()))) # LTPW = LONG TIME POTENTIATION WEIGHT
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
117
132
  # Initialize visualization
118
133
  vis_objects = initialize_visualization_for_fit(val, show_training, neurons_history, x_train, y_train)
119
134
 
120
135
  # Training process
121
136
  for index, inp in enumerate(x_train):
122
- inp = np.array(inp).ravel()
137
+ inp = np.array(inp, copy=False).ravel()
123
138
  y_decoded = decode_one_hot(y_train)
124
139
  # Weight updates
125
140
  STPW = feed_forward(inp, STPW, is_training=True, Class=y_decoded[index], activation_potentiation=activation_potentiation, LTD=LTD)
126
- LTPW += normalization(STPW) if auto_normalization else STPW
127
-
128
- # Visualization updates
129
- if show_training:
130
- update_weight_visualization_for_fit(vis_objects['ax'][0, 0], LTPW, vis_objects['artist2'])
131
- if decision_boundary_status:
132
- update_decision_boundary_for_fit(vis_objects['ax'][0, 1], x_val, y_val, activation_potentiation, LTPW, vis_objects['artist1'])
133
- update_validation_history_for_fit(vis_objects['ax'][1, 1], val_list, vis_objects['artist3'])
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)
134
156
  if train_bar:
135
157
  train_progress.update(1)
136
158
 
137
- STPW = np.ones((len(y_train[0]), len(x_train[0].ravel())))
159
+ STPW = np.ones((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False)
138
160
 
139
161
  # Finalize visualization
140
162
  if show_training:
141
- display_visualization_for_fit(vis_objects['fig'], vis_objects['artist1'], interval)
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()
142
172
 
143
- return normalization(LTPW)
173
+ return normalization(LTPW, dtype=dtype)
144
174
 
145
175
 
146
- def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', batch_size=1,
176
+ def learner(x_train, y_train, optimizer, x_test=None, y_test=None, strategy='accuracy', gen=None, batch_size=1,
147
177
  neural_web_history=False, show_current_activations=False, auto_normalization=True,
148
- neurons_history=False, patience=None, depth=None, early_shifting=False,
149
- early_stop=False, loss='categorical_crossentropy', show_history=False,
178
+ neurons_history=False, early_stop=False, loss='categorical_crossentropy', show_history=False,
150
179
  interval=33.33, target_acc=None, target_loss=None, except_this=None,
151
- only_this=None, start_this=None):
180
+ only_this=None, start_this_act=None, start_this_W=None, target_fitness='max', dtype=np.float32):
152
181
  """
153
182
  Optimizes the activation functions for a neural network by leveraging train data to find
154
- the most accurate combination of activation potentiation for the given dataset.
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.
155
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
+
156
189
  Args:
157
190
 
158
191
  x_train (array-like): Training input data.
159
192
 
160
- y_train (array-like): Labels for training data.
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.evolve(*args,
198
+ activation_add_prob=0.85,
199
+ mutations=False,
200
+ strategy='cross_over',
201
+ **kwargs)
202
+
203
+ model = plan.learner(x_train,
204
+ y_train,
205
+ optimizer=genetic_optimizer,
206
+ strategy='accuracy',
207
+ show_history=True,
208
+ target_acc=0.94,
209
+ interval=16.67)
210
+ ```
161
211
 
162
212
  x_test (array-like, optional): Test input data (for improve next gen generilization). If test data is not given then train feedback learning active
163
213
 
164
214
  y_test (array-like, optional): Test Labels (for improve next gen generilization). If test data is not given then train feedback learning active
165
215
 
166
- strategy (str, optional): Learning strategy. (options: 'accuracy', 'loss', 'f1', 'precision', 'recall', 'adaptive_accuracy', 'adaptive_loss', 'all'): 'accuracy', Maximizes test accuracy during learning. 'f1', Maximizes test f1 score during learning. 'precision', Maximizes test preciison score during learning. 'recall', Maximizes test recall during learning. loss', Minimizes test loss during learning. 'adaptive_accuracy', The model compares the current accuracy with the accuracy from the past based on the number specified by the patience value. If no improvement is observed it adapts to the condition by switching to the 'loss' strategy quickly starts minimizing loss and continues learning. 'adaptive_loss',The model adopts the 'loss' strategy until the loss reaches or falls below the value specified by the patience parameter. However, when the patience threshold is reached, it automatically switches to the 'accuracy' strategy and begins to maximize accuracy. 'all', Maximizes all test scores and minimizes test loss, 'all' strategy most strong and most robust strategy. Default is 'accuracy'.
167
-
168
- patience ((int, float), optional): patience value for adaptive strategies. For 'adaptive_accuracy' Default value: 5. For 'adaptive_loss' Default value: 0.150.
216
+ 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'.
169
217
 
170
- depth (int, optional): The depth of the PLAN neural networks Aggreagation layers.
218
+ gen (int, optional): The generation count for genetic optimization.
171
219
 
172
220
  batch_size (float, optional): Batch size is used in the prediction process to receive test 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 test batch represents 8% of the test set. Default is 1. (%100 of test)
173
221
 
174
222
  auto_normalization (bool, optional): If auto normalization=False this makes more faster training times and much better accuracy performance for some datasets. Default is True.
175
223
 
176
- early_shifting (int, optional): Early shifting checks if the test accuracy improves after a given number of activation attempts while inside a depth. If there's no improvement, it automatically shifts to the next depth. Basically, if no progress, it’s like, “Alright, let’s move on!” Default is False
177
-
178
- early_stop (bool, optional): If True, implements early stopping during training.(If test accuracy not improves in two depth stops learning.) Default is False.
224
+ early_stop (bool, optional): If True, implements early stopping during training.(If test accuracy not improves in two gen stops learning.) Default is False.
179
225
 
180
226
  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
181
227
 
182
228
  show_history (bool, optional): If True, displays the training history after optimization. Default is False.
183
229
 
184
- loss (str, optional): For visualizing and monitoring. PLAN neural networks doesn't need any loss function in training(if strategy not 'loss'). options: ('categorical_crossentropy' or 'binary_crossentropy') Default is 'categorical_crossentropy'.
230
+ 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'.
185
231
 
186
232
  interval (int, optional): The interval at which evaluations are conducted during training. (33.33 = 30 FPS, 16.67 = 60 FPS) Default is 100.
187
233
 
@@ -193,52 +239,54 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
193
239
 
194
240
  only_this (list, optional): A list of activations to focus on during optimization. Default is None. (For avaliable activation functions, run this code: plan.activations_list())
195
241
 
196
- start_this (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
242
+ 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
243
+
244
+ 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
197
245
 
198
246
  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.
199
247
 
200
248
  neural_web_history (bool, optional): Draws history of neural web. Default is False.
201
249
 
250
+ target_fitness (str, optional): Target fitness strategy for PLANEAT optimization. ('max' for machine learning, 'min' for machine unlearning.) Default: 'max'
251
+
252
+ 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)
253
+
202
254
  Returns:
203
255
  tuple: A list for model parameters: [Weight matrix, Test loss, Test Accuracy, [Activations functions]].
204
256
 
205
257
  """
206
- print(Fore.WHITE + "\nRemember, optimization on large datasets can be very time-consuming and computationally expensive. Therefore, if you are working with such a dataset, our recommendation is to include activation function: ['circular'] in the 'except_this' parameter unless absolutely necessary, as they can significantly prolong the process. from: learner\n" + Fore.RESET)
258
+
259
+ print(Fore.WHITE + "\nRemember, optimization on large datasets can be very time-consuming and computationally expensive. Therefore, if you are working with such a dataset, our recommendation is to include activation function: ['circular', 'spiral'] in the 'except_this' parameter unless absolutely necessary, as they can significantly prolong the process. from: learner\n" + Fore.RESET)
207
260
 
208
261
  activation_potentiation = all_activations()
209
262
 
263
+ # Pre-checks
264
+
265
+ x_train = x_train.astype(dtype, copy=False)
266
+ y_train = optimize_labels(y_train, cuda=False)
267
+
210
268
  if x_test is None and y_test is None:
211
269
  x_test = x_train
212
270
  y_test = y_train
213
271
  data = 'Train'
214
272
  else:
273
+ x_test = x_test.astype(dtype, copy=False)
274
+ y_test = optimize_labels(y_test, cuda=False)
215
275
  data = 'Test'
216
276
 
217
- if early_shifting != False:
218
- shift_patience = early_shifting
219
-
220
- # Strategy initialization
221
- if strategy == 'adaptive_accuracy':
222
- strategy = 'accuracy'
223
- adaptive = True
224
- if patience == None:
225
- patience = 5
226
- elif strategy == 'adaptive_loss':
227
- strategy = 'loss'
228
- adaptive = True
229
- if patience == None:
230
- patience = 0.150
231
- else:
232
- adaptive = False
233
-
234
277
  # Filter activation functions
235
- if only_this != None:
278
+ if only_this is not None:
236
279
  activation_potentiation = only_this
237
- if except_this != None:
280
+ if except_this is not None:
238
281
  activation_potentiation = [item for item in activation_potentiation if item not in except_this]
239
- if depth is None:
240
- depth = len(activation_potentiation)
282
+ if gen is None:
283
+ gen = len(activation_potentiation)
284
+
285
+ 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'.")
241
286
 
287
+ if start_this_act is None and len(activation_potentiation) % 2 != 0: raise ValueError("Activation length must be even number. Please use 'except_this' parameter and except some activation. For example: except_this=['linear']")
288
+ if start_this_act is not None and len(activation_potentiation) + 1 % 2 != 0: raise ValueError("You are using start_this parameter, activation length still must be even number. Please use 'except_this' parameter and except some activation. For example: except_this=['linear']")
289
+
242
290
  # Initialize visualization components
243
291
  viz_objects = initialize_visualization_for_learner(show_history, neurons_history, neural_web_history, x_train, y_train)
244
292
 
@@ -247,18 +295,20 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
247
295
  ncols = 76
248
296
  else:
249
297
  ncols = 89
250
- progress = initialize_loading_bar(total=len(activation_potentiation), desc="", ncols=ncols, bar_format=bar_format_learner)
251
298
 
252
299
  # Initialize variables
253
- activations = []
254
- if start_this is None:
255
- best_activations = []
300
+ act_pop = []
301
+ weight_pop = []
302
+
303
+ if start_this_act is None and start_this_W is None:
256
304
  best_acc = 0
257
305
  else:
258
- best_activations = start_this
306
+ act_pop.append(start_this_act)
307
+ weight_pop.append(start_this_W)
308
+
259
309
  x_test_batch, y_test_batch = batcher(x_test, y_test, batch_size=batch_size)
260
- W = fit(x_train, y_train, activation_potentiation=best_activations, train_bar=False, auto_normalization=auto_normalization)
261
- model = evaluate(x_test_batch, y_test_batch, W=W, loading_bar_status=False, activation_potentiation=activations)
310
+
311
+ model = evaluate(x_test_batch, y_test_batch, W=start_this_W, loading_bar_status=False, activation_potentiation=act_pop, dtype=dtype)
262
312
 
263
313
  if loss == 'categorical_crossentropy':
264
314
  test_loss = categorical_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
@@ -268,12 +318,15 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
268
318
  best_acc = model[get_acc()]
269
319
  best_loss = test_loss
270
320
 
271
- best_acc_per_depth_list = []
321
+ best_acc_per_gen_list = []
272
322
  postfix_dict = {}
273
323
  loss_list = []
274
-
275
- for i in range(depth):
276
- postfix_dict["Depth"] = str(i+1) + '/' + str(depth)
324
+ target_pop = []
325
+
326
+ progress = initialize_loading_bar(total=len(activation_potentiation), desc="", ncols=ncols, bar_format=bar_format_learner)
327
+
328
+ for i in range(gen):
329
+ postfix_dict["Gen"] = str(i+1) + '/' + str(gen)
277
330
  progress.set_postfix(postfix_dict)
278
331
 
279
332
  progress.n = 0
@@ -281,79 +334,65 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
281
334
  progress.update(0)
282
335
 
283
336
  for j in range(len(activation_potentiation)):
284
- for k in range(len(best_activations)):
285
- activations.append(best_activations[k])
286
-
287
- activations.append(activation_potentiation[j])
288
337
 
289
338
  x_test_batch, y_test_batch = batcher(x_test, y_test, batch_size=batch_size)
290
- W = fit(x_train, y_train, activation_potentiation=activations, train_bar=False, auto_normalization=auto_normalization)
291
- model = evaluate(x_test_batch, y_test_batch, W=W, loading_bar_status=False, activation_potentiation=activations)
339
+
340
+ if i == 0:
341
+ act_pop.append(activation_potentiation[j])
342
+ W = fit(x_train, y_train, activation_potentiation=act_pop[-1], train_bar=False, auto_normalization=auto_normalization, dtype=dtype)
343
+ weight_pop.append(W)
292
344
 
345
+ model = evaluate(x_test_batch, y_test_batch, W=weight_pop[j], loading_bar_status=False, activation_potentiation=act_pop[j], dtype=dtype)
293
346
  acc = model[get_acc()]
347
+
348
+ if strategy == 'accuracy': target_pop.append(acc)
294
349
 
295
- if strategy == 'loss' or strategy == 'all':
296
- if loss == 'categorical_crossentropy':
297
- test_loss = categorical_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
298
- else:
299
- test_loss = binary_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
300
-
301
- if i == 0 and j == 0 and start_this is None:
302
- best_loss = test_loss
303
-
304
- if strategy == 'f1' or strategy == 'precision' or strategy == 'recall' or strategy == 'all':
350
+ elif strategy == 'f1' or strategy == 'precision' or strategy == 'recall':
305
351
  precision_score, recall_score, f1_score = metrics(y_test_batch, model[get_preds()])
306
352
 
307
- if strategy == 'precision' or strategy == 'all':
353
+ if strategy == 'precision':
354
+ target_pop.append(precision_score)
355
+
308
356
  if i == 0 and j == 0:
309
357
  best_precision = precision_score
310
358
 
311
- if strategy == 'recall' or strategy == 'all':
359
+ if strategy == 'recall':
360
+ target_pop.append(recall_score)
361
+
312
362
  if i == 0 and j == 0:
313
363
  best_recall = recall_score
314
364
 
315
- if strategy == 'f1' or strategy == 'all':
365
+ if strategy == 'f1':
366
+ target_pop.append(f1_score)
367
+
316
368
  if i == 0 and j == 0:
317
369
  best_f1 = f1_score
318
370
 
319
- if early_shifting != False:
320
- if acc <= best_acc:
321
- early_shifting -= 1
322
- if early_shifting == 0:
323
- early_shifting = shift_patience
324
- break
325
-
326
371
  if ((strategy == 'accuracy' and acc >= best_acc) or
327
- (strategy == 'loss' and test_loss <= best_loss) or
328
372
  (strategy == 'f1' and f1_score >= best_f1) or
329
- (strategy == 'precision' and precision_score >= best_precision) or
330
- (strategy == 'recall' and recall_score >= best_recall) or
331
- (strategy == 'all' and f1_score >= best_f1 and acc >= best_acc and
332
- test_loss <= best_loss and precision_score >= best_precision and
333
- recall_score >= best_recall)):
373
+ (strategy == 'precision' and precision_score >= best_precision) or
374
+ (strategy == 'recall' and recall_score >= best_recall)):
334
375
 
335
- current_best_activation = activation_potentiation[j]
336
376
  best_acc = acc
337
-
377
+ best_weights = weight_pop[j]
378
+ final_activations = act_pop[j]
379
+ best_model = model
380
+
381
+ final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
382
+
338
383
  if batch_size == 1:
339
384
  postfix_dict[f"{data} Accuracy"] = best_acc
340
385
  else:
341
386
  postfix_dict[f"{data} Batch Accuracy"] = acc
342
387
  progress.set_postfix(postfix_dict)
343
-
344
- final_activations = activations
345
388
 
346
389
  if show_current_activations:
347
390
  print(f", Current Activations={final_activations}", end='')
348
391
 
349
- best_weights = W
350
- best_model = model
351
-
352
- if strategy != 'loss':
353
- if loss == 'categorical_crossentropy':
354
- test_loss = categorical_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
355
- else:
356
- test_loss = binary_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
392
+ if loss == 'categorical_crossentropy':
393
+ test_loss = categorical_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
394
+ else:
395
+ test_loss = binary_crossentropy(y_true_batch=y_test_batch, y_pred_batch=model[get_preds_softmax()])
357
396
 
358
397
  if batch_size == 1:
359
398
  postfix_dict[f"{data} Loss"] = test_loss
@@ -365,13 +404,13 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
365
404
 
366
405
  # Update visualizations during training
367
406
  if show_history:
368
- depth_list = range(1, len(best_acc_per_depth_list) + 2)
369
- update_history_plots_for_learner(viz_objects, depth_list, loss_list + [test_loss],
370
- best_acc_per_depth_list + [best_acc], x_train, final_activations)
407
+ gen_list = range(1, len(best_acc_per_gen_list) + 2)
408
+ update_history_plots_for_learner(viz_objects, gen_list, loss_list + [test_loss],
409
+ best_acc_per_gen_list + [best_acc], x_train, final_activations)
371
410
 
372
411
  if neurons_history:
373
412
  viz_objects['neurons']['artists'] = (
374
- neuron_history(np.copy(best_weights), viz_objects['neurons']['ax'],
413
+ update_neuron_history_for_learner(np.copy(best_weights), viz_objects['neurons']['ax'],
375
414
  viz_objects['neurons']['row'], viz_objects['neurons']['col'],
376
415
  y_train[0], viz_objects['neurons']['artists'],
377
416
  data=data, fig1=viz_objects['neurons']['fig'],
@@ -388,7 +427,7 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
388
427
  if target_acc is not None and best_acc >= target_acc:
389
428
  progress.close()
390
429
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
391
- activation_potentiation=final_activations)
430
+ activation_potentiation=final_activations, dtype=dtype)
392
431
 
393
432
  if loss == 'categorical_crossentropy':
394
433
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -413,7 +452,7 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
413
452
  if target_loss is not None and best_loss <= target_loss:
414
453
  progress.close()
415
454
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
416
- activation_potentiation=final_activations)
455
+ activation_potentiation=final_activations, dtype=dtype)
417
456
 
418
457
  if loss == 'categorical_crossentropy':
419
458
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -435,28 +474,19 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
435
474
  return best_weights, best_model[get_preds()], best_acc, final_activations
436
475
 
437
476
  progress.update(1)
438
- activations = []
439
477
 
440
- best_activations.append(current_best_activation)
441
- best_acc_per_depth_list.append(best_acc)
478
+ best_acc_per_gen_list.append(best_acc)
442
479
  loss_list.append(best_loss)
443
480
 
444
- # Check adaptive strategy conditions
445
- if adaptive == True and strategy == 'accuracy' and i + 1 >= patience:
446
- check = best_acc_per_depth_list[-patience:]
447
- if all(x == check[0] for x in check):
448
- strategy = 'loss'
449
- adaptive = False
450
- elif adaptive == True and strategy == 'loss' and best_loss <= patience:
451
- strategy = 'accuracy'
452
- adaptive = False
481
+ weight_pop, act_pop = optimizer(np.array(weight_pop, dtype=dtype), act_pop, i, np.array(target_pop, dtype=dtype, copy=False), target_fitness=target_fitness, bar_status=False)
482
+ target_pop = []
453
483
 
454
484
  # Early stopping check
455
485
  if early_stop == True and i > 0:
456
- if best_acc_per_depth_list[i] == best_acc_per_depth_list[i-1]:
486
+ if best_acc_per_gen_list[i] == best_acc_per_gen_list[i-1]:
457
487
  progress.close()
458
488
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
459
- activation_potentiation=final_activations)
489
+ activation_potentiation=final_activations, dtype=dtype)
460
490
 
461
491
  if loss == 'categorical_crossentropy':
462
492
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -480,14 +510,14 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
480
510
  # Final evaluation
481
511
  progress.close()
482
512
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
483
- activation_potentiation=final_activations)
513
+ activation_potentiation=final_activations, dtype=dtype)
484
514
 
485
515
  if loss == 'categorical_crossentropy':
486
516
  train_loss = categorical_crossentropy(y_true_batch=y_train, y_pred_batch=train_model[get_preds_softmax()])
487
517
  else:
488
518
  train_loss = binary_crossentropy(y_true_batch=y_train, y_pred_batch=train_model[get_preds_softmax()])
489
519
 
490
- print('\nActivations: ', final_activations)
520
+ print('\nActivations: ', act_pop[-1])
491
521
  print(f'Train Accuracy (%{batch_size * 100} of train samples):', train_model[get_acc()])
492
522
  print(f'Train Loss (%{batch_size * 100} of train samples): ', train_loss, '\n')
493
523
  if data == 'Test':
@@ -547,99 +577,88 @@ def feed_forward(
547
577
 
548
578
 
549
579
  def evaluate(
550
- x_test, # list[num]: Test input data.
551
- y_test, # list[num]: Test labels.
552
- W, # list[num]: Weight matrix list of the neural network.
553
- activation_potentiation=['linear'], # (list): Activation potentiation list for deep PLAN. (optional)
554
- loading_bar_status=True, # bar_status (bool): Loading bar for accuracy (True or None) (optional) Default: True
555
- show_metrics=None, # show_metrices (bool): (True or None) (optional) Default: None
580
+ x_test, # NumPy array: Test input data.
581
+ y_test, # NumPy array: Test labels.
582
+ W, # List of NumPy arrays: Neural network weight matrices.
583
+ activation_potentiation=['linear'], # List of activation functions.
584
+ loading_bar_status=True, # Optionally show loading bar.
585
+ show_metrics=None, # Optionally show metrics.
586
+ dtype=np.float32
556
587
  ) -> tuple:
557
588
  """
558
- Tests the neural network model with the given test data.
589
+ Evaluates the neural network model using the given test data.
559
590
 
560
591
  Args:
561
-
562
- x_test (list[num]): Test input data.
563
-
564
- y_test (list[num]): Test labels.
565
-
566
- W (list[num]): Weight matrix list of the neural network.
567
-
568
- activation_potentiation (list): For deeper PLAN networks, activation function parameters. For more information please run this code: plan.activations_list() default: [None]
569
-
570
- loading_bar_status: Evaluate progress have a loading bar ? (True or False) Default: True.
592
+ x_test (np.ndarray): Test input data.
593
+
594
+ y_test (np.ndarray): Test labels. one-hot encoded.
595
+
596
+ W (list[np.ndarray]): List of neural network weight matrices.
597
+
598
+ activation_potentiation (list): List of activation functions.
599
+
600
+ loading_bar_status (bool): Option to show a loading bar (optional).
601
+
602
+ show_metrics (bool): Option to show metrics (optional).
571
603
 
572
- show_metrics (bool): (True or None) (optional) Default: None
604
+ 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!]
573
605
 
574
606
  Returns:
575
- tuple: A tuple containing the predicted labels and the accuracy of the model.
607
+ tuple: Predicted labels, model accuracy, and other evaluation metrics.
576
608
  """
577
- predict_probabilitys = []
578
- real_classes = []
579
- predict_classes = []
580
-
581
- try:
609
+ # Pre-checks
582
610
 
583
- Wc = [0] * len(W) # Wc = Weight copy
584
- true_predict = 0
585
- y_preds = []
586
- y_preds_raw = []
587
- acc_list = []
611
+ x_test = x_test.astype(dtype, copy=False)
588
612
 
589
- Wc = np.copy(W)
590
-
591
-
592
- if loading_bar_status == True:
613
+ if len(y_test[0]) < 256:
614
+ if y_test.dtype != np.uint8:
615
+ y_test = np.array(y_test, copy=False).astype(np.uint8, copy=False)
616
+ elif len(y_test[0]) <= 32767:
617
+ if y_test.dtype != np.uint16:
618
+ y_test = np.array(y_test, copy=False).astype(np.uint16, copy=False)
619
+ else:
620
+ if y_test.dtype != np.uint32:
621
+ y_test = np.array(y_test, copy=False).astype(np.uint32, copy=False)
593
622
 
594
- loading_bar = initialize_loading_bar(total=len(x_test), ncols=64, desc='Testing', bar_format=bar_format_normal)
623
+ predict_probabilitys = np.empty((len(x_test), W.shape[0]), dtype=np.float32)
624
+ real_classes = np.empty(len(x_test), dtype=np.int32)
625
+ predict_classes = np.empty(len(x_test), dtype=np.int32)
595
626
 
596
- for inpIndex, Input in enumerate(x_test):
597
- Input = np.array(Input)
598
- Input = Input.ravel()
599
- neural_layer = Input
627
+ true_predict = 0
628
+ acc_list = np.empty(len(x_test), dtype=np.float32)
600
629
 
601
-
602
- neural_layer = feed_forward(neural_layer, W, is_training=False, Class='?', activation_potentiation=activation_potentiation)
630
+ if loading_bar_status:
631
+ loading_bar = initialize_loading_bar(total=len(x_test), ncols=64, desc='Testing', bar_format=bar_format_normal)
603
632
 
633
+ for inpIndex in range(len(x_test)):
634
+ Input = x_test[inpIndex].ravel()
604
635
 
605
- W = np.copy(Wc)
606
-
607
- neural_layer = Softmax(neural_layer)
636
+ neural_layer = Input
608
637
 
609
- max_value = max(neural_layer)
638
+ neural_layer = feed_forward(neural_layer, np.copy(W), is_training=False, Class='?', activation_potentiation=activation_potentiation)
610
639
 
611
- predict_probabilitys.append(max_value)
612
-
613
- RealOutput = np.argmax(y_test[inpIndex])
614
- real_classes.append(RealOutput)
615
- PredictedOutput = np.argmax(neural_layer)
616
- predict_classes.append(PredictedOutput)
617
-
618
- if RealOutput == PredictedOutput:
619
- true_predict += 1
620
- acc = true_predict / len(y_test)
640
+ predict_probabilitys[inpIndex] = Softmax(neural_layer)
621
641
 
642
+ RealOutput = np.argmax(y_test[inpIndex])
643
+ real_classes[inpIndex] = RealOutput
644
+ PredictedOutput = np.argmax(neural_layer)
645
+ predict_classes[inpIndex] = PredictedOutput
622
646
 
623
- acc_list.append(acc)
624
- y_preds.append(PredictedOutput)
625
- y_preds_raw.append(Softmax(neural_layer))
647
+ if RealOutput == PredictedOutput:
648
+ true_predict += 1
626
649
 
627
- if loading_bar_status == True:
628
- loading_bar.update(1)
629
-
630
- if inpIndex > 0 and loading_bar_status == True:
631
- loading_bar.set_postfix({"Test Accuracy": acc})
650
+ acc = true_predict / (inpIndex + 1)
651
+ acc_list[inpIndex] = acc
632
652
 
633
- if show_metrics == True:
634
-
635
- loading_bar.close()
636
- plot_evaluate(x_test, y_test, y_preds, acc_list, W=W, activation_potentiation=activation_potentiation)
637
-
638
- W = np.copy(Wc)
653
+ if loading_bar_status:
654
+ loading_bar.update(1)
655
+ loading_bar.set_postfix({"Test Accuracy": acc})
639
656
 
640
- except Exception as e:
657
+ if loading_bar_status:
658
+ loading_bar.close()
641
659
 
642
- print(Fore.RED + 'ERROR:' + str(e) + Style.RESET_ALL)
643
- sys.exit()
660
+ if show_metrics:
661
+ # Plot the evaluation metrics
662
+ plot_evaluate(x_test, y_test, predict_classes, acc_list, W=np.copy(W), activation_potentiation=activation_potentiation)
644
663
 
645
- return W, y_preds, acc, None, None, y_preds_raw
664
+ return W, predict_classes, acc_list[-1], None, None, predict_probabilitys