pyerualjetwork 5.1__py3-none-any.whl → 5.5__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 (29) hide show
  1. pyerualjetwork/__init__.py +15 -14
  2. pyerualjetwork/cpu/__init__.py +24 -0
  3. pyerualjetwork/{activation_functions_cpu.py → cpu/activation_functions.py} +40 -4
  4. pyerualjetwork/{data_operations_cpu.py → cpu/data_ops.py} +17 -19
  5. pyerualjetwork/{metrics_cpu.py → cpu/metrics.py} +3 -1
  6. pyerualjetwork/{visualizations_cpu.py → cpu/visualizations.py} +96 -139
  7. pyerualjetwork/cuda/__init__.py +24 -0
  8. pyerualjetwork/{activation_functions_cuda.py → cuda/activation_functions.py} +54 -5
  9. pyerualjetwork/{data_operations_cuda.py → cuda/data_ops.py} +16 -16
  10. pyerualjetwork/{metrics_cuda.py → cuda/metrics.py} +1 -1
  11. pyerualjetwork/{visualizations_cuda.py → cuda/visualizations.py} +8 -244
  12. pyerualjetwork/{ene_cpu.py → ene.py} +29 -95
  13. pyerualjetwork/fitness_functions.py +0 -1
  14. pyerualjetwork/help.py +5 -5
  15. pyerualjetwork/issue_solver.py +39 -11
  16. pyerualjetwork/{memory_operations.py → memory_ops.py} +1 -1
  17. pyerualjetwork/model_ops.py +734 -0
  18. pyerualjetwork/{neu_cpu.py → nn.py} +199 -91
  19. pyerualjetwork/{model_operations_cpu.py → old_cpu_model_ops.py} +62 -59
  20. pyerualjetwork/{model_operations_cuda.py → old_cuda_model_ops.py} +99 -86
  21. {pyerualjetwork-5.1.dist-info → pyerualjetwork-5.5.dist-info}/METADATA +16 -18
  22. pyerualjetwork-5.5.dist-info/RECORD +27 -0
  23. pyerualjetwork/ene_cuda.py +0 -962
  24. pyerualjetwork/neu_cuda.py +0 -588
  25. pyerualjetwork-5.1.dist-info/RECORD +0 -26
  26. /pyerualjetwork/{loss_functions_cpu.py → cpu/loss_functions.py} +0 -0
  27. /pyerualjetwork/{loss_functions_cuda.py → cuda/loss_functions.py} +0 -0
  28. {pyerualjetwork-5.1.dist-info → pyerualjetwork-5.5.dist-info}/WHEEL +0 -0
  29. {pyerualjetwork-5.1.dist-info → pyerualjetwork-5.5.dist-info}/top_level.txt +0 -0
@@ -2,9 +2,9 @@
2
2
  """
3
3
 
4
4
 
5
- NEU (Neural Networks) on CPU
5
+ NN (Neural Networks)
6
6
  ============================
7
- This module hosts functions for training and evaluating artificial neural networks on CPU for labeled classification tasks (for now).
7
+ This module hosts functions for training and evaluating artificial neural networks for labeled classification tasks.
8
8
 
9
9
  Currently, 3 types of models can be trained:
10
10
 
@@ -40,7 +40,7 @@ Examples: https://github.com/HCB06/PyerualJetwork/tree/main/Welcome_to_PyerualJe
40
40
 
41
41
  PyerualJetwork document: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PyerualJetwork/PYERUALJETWORK_USER_MANUEL_AND_LEGAL_INFORMATION(EN).pdf
42
42
 
43
- - Author: Hasan Can Beydili
43
+ - Creator: Hasan Can Beydili
44
44
  - YouTube: https://www.youtube.com/@HasanCanBeydili
45
45
  - Linkedin: https://www.linkedin.com/in/hasan-can-beydili-77a1b9270/
46
46
  - Instagram: https://www.instagram.com/canbeydilj
@@ -48,24 +48,16 @@ PyerualJetwork document: https://github.com/HCB06/PyerualJetwork/blob/main/Welco
48
48
  """
49
49
 
50
50
  import numpy as np
51
+ import cupy as cp
51
52
  import copy
52
53
  import random
53
54
 
54
55
  ### LIBRARY IMPORTS ###
55
56
  from .ui import loading_bars, initialize_loading_bar
56
- from .data_operations_cpu import normalization, batcher
57
- from .activation_functions_cpu import apply_activation, all_activations
58
- from .model_operations_cpu import get_acc, get_preds_softmax
59
- from .memory_operations import optimize_labels
60
- from .loss_functions_cpu import categorical_crossentropy, binary_crossentropy
57
+ from .cpu.activation_functions import all_activations
58
+ from .model_ops import get_acc, get_preds_softmax, get_preds
59
+ from .memory_ops import optimize_labels, transfer_to_gpu
61
60
  from .fitness_functions import wals
62
- from .visualizations_cpu import (
63
- draw_neural_web,
64
- display_visualizations_for_learner,
65
- update_history_plots_for_learner,
66
- initialize_visualization_for_learner,
67
- update_neuron_history_for_learner
68
- )
69
61
 
70
62
  ### GLOBAL VARIABLES ###
71
63
  bar_format_normal = loading_bars()[0]
@@ -79,48 +71,61 @@ def plan_fit(
79
71
  activations=['linear'],
80
72
  W=None,
81
73
  auto_normalization=False,
74
+ cuda=False,
82
75
  dtype=np.float32
83
76
  ):
84
77
  """
85
78
  Creates a PLAN model to fitting data.
86
79
 
87
80
  Args:
88
- x_train (aray-like[num]): List or numarray of input data.
81
+ x_train (aray-like[num or cup]): List or numarray of input data.
89
82
 
90
- y_train (aray-like[num]): List or numarray of target labels. (one hot encoded)
83
+ y_train (aray-like[num or cup]): List or numarray of target labels. (one hot encoded)
91
84
 
92
85
  activations (list): For deeper PLAN networks, activation function parameters. For more information please run this code: neu.activations_list() default: [None] (optional)
93
86
 
94
- W (numpy.ndarray): If you want to re-continue or update model
87
+ W (numpy.ndarray or cupy.ndarray): If you want to re-continue or update model
95
88
 
96
89
  auto_normalization (bool, optional): Normalization may solves overflow problem. Default: False
97
90
 
91
+ cuda (bool, optional): CUDA GPU acceleration ? Default = False.
92
+
98
93
  dtype (numpy.dtype): Data type for the arrays. np.float32 by default. Example: np.float64 or np.float16.
99
94
 
100
95
  Returns:
101
96
  numpyarray: (Weight matrix).
102
97
  """
98
+
99
+ from .cpu.data_ops import normalization
100
+ if not cuda:
101
+ from cpu.activation_functions import apply_activation
102
+ array_type = np
103
103
 
104
+ else:
105
+ from .cuda.activation_functions import apply_activation
106
+ array_type = cp
107
+
108
+
104
109
  # Pre-check
105
110
 
106
111
  if len(x_train) != len(y_train): raise ValueError("x_train and y_train must have the same length.")
107
112
 
108
- weight = np.zeros((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False) if W is None else W
113
+ weight = array_type.zeros((len(y_train[0]), len(x_train[0].ravel()))).astype(dtype, copy=False) if W is None else W
109
114
 
110
115
  if auto_normalization is True: x_train = normalization(apply_activation(x_train, activations))
111
116
  elif auto_normalization is False: x_train = apply_activation(x_train, activations)
112
117
  else: raise ValueError('normalization parameter only be True or False')
113
-
114
- weight += y_train.T @ x_train
115
118
 
116
- return normalization(weight, dtype=dtype)
119
+ weight += y_train.T @ x_train if not cuda else cp.array(y_train).T @ cp.array(x_train)
117
120
 
121
+ return normalization(weight.get() if cuda else weight,dtype=dtype)
118
122
 
119
- def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size=1,
123
+
124
+ def learn(x_train, y_train, optimizer, template_model, gen, pop_size, fit_start=True, batch_size=1,
120
125
  weight_evolve=True, neural_web_history=False, show_current_activations=False, auto_normalization=False,
121
126
  neurons_history=False, early_stop=False, show_history=False, target_loss=None,
122
127
  interval=33.33, target_acc=None, loss='categorical_crossentropy', acc_impact=0.9, loss_impact=0.1,
123
- start_this_act=None, start_this_W=None, neurons=[], activation_functions=[], dtype=np.float32):
128
+ start_this_act=None, start_this_W=None, neurons=[], activation_functions=[], decision_boundary_history=False, cuda=False, dtype=np.float32):
124
129
  """
125
130
  Optimizes the activation functions for a neural network by leveraging train data to find
126
131
  the most accurate combination of activation potentiation(or activation function) & weight values for the labeled classificaiton dataset.
@@ -132,18 +137,29 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
132
137
  * This function also able to train classic MLP model architectures.
133
138
  * And my newest innovative architecture: PTNN (Potentiation Transfer Neural Network).
134
139
 
140
+ Examples:
141
+
142
+ This creates a PLAN model:
143
+ - ```model = learn(x_train, y_train, optimizer, template_model, pop_size=100, gen=100, fit_start=True) ```
144
+
145
+ This creates a MLP model(with 2 hidden layer):
146
+ - ```model = learn(x_train, y_train, optimizer, template_model, pop_size=100, gen=100, fit_start=False, neurons=[64, 64], activation_functions=['tanh', 'tanh']) ```
147
+
148
+ This creates a PTNN model(with 2 hidden layer & 1 aggregation layer(comes with PLAN)):
149
+ - ```model = learn(x_train, y_train, optimizer, template_model, pop_size=100, gen=[10, 100], fit_start=True, neurons=[64, 64], activation_functions=['tanh', 'tanh']) ```
150
+
135
151
  :Args:
136
152
  :param x_train: (array-like): Training input data.
137
153
  :param y_train: (array-like): Labels for training data. one-hot encoded.
138
- :param optimizer: (function): Optimization technique with hyperparameters. (PLAN, MLP & PTNN (all) using ENE for optimization. Gradient based technique's will added in the future.) Please use this: from pyerualjetwork.ene_cpu import evolver (and) optimizer = lambda *args, **kwargs: evolver(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
154
+ :param optimizer: (function): Optimization technique with hyperparameters. (PLAN, MLP & PTNN (all) using ENE for optimization. Gradient based technique's will added in the future.) Please use this: from pyerualjetwork.ene import evolver (and) optimizer = lambda *args, **kwargs: evolver(*args, 'here give your hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
139
155
  ```python
140
- optimizer = lambda *args, **kwargs: ene_cpu.evolver(*args,
156
+ optimizer = lambda *args, **kwargs: ene.evolver(*args,
141
157
  activation_add_prob=0.05,
142
158
  strategy='aggressive',
143
159
  policy='more_selective',
144
160
  **kwargs)
145
161
 
146
- model = neu_cpu.learn(x_train,
162
+ model = nn.learn(x_train,
147
163
  y_train,
148
164
  optimizer,
149
165
  fit_start=True,
@@ -152,6 +168,7 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
152
168
  batch_size=0.05,
153
169
  interval=16.67)
154
170
  ```
171
+ :param template_model: (tuple): Use --> get_model_template() function in the model_ops module.
155
172
  :param fit_start: (bool, optional): 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. Additonaly if you want to train PTNN model you must be give True. Options: True or False. Default: True
156
173
  :param gen: (int or list): The generation count for genetic optimization. If you want to train PTNN model you must give a list of two number. First number for PLAN model training second number for MLP.
157
174
  :param batch_size: (float, optional): Batch size is used in the prediction process to receive train feedback by dividing the train data into chunks and selecting activations based on randomly chosen partitions. This process reduces computational cost and time while still covering the entire train 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)
@@ -172,29 +189,56 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
172
189
  :param 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
173
190
  :param 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
174
191
  :param neurons: (list[int], optional): If you dont want train PLAN model this parameter represents neuron count of each hidden layer for MLP or PTNN. Number of elements --> Layer count. Default: [] (No hidden layer) --> architecture setted to PLAN, if not --> architecture setted to MLP.
192
+ :param decision_boundary_history: (bool, optional): At the end of the training, the decision boundary history is shown in animation form. Note: If you are sure of your memory, set it to True. Default: False
175
193
  :param activation_functions: (list[str], optional): If you dont want train PLAN model this parameter represents activation function of each hidden layer for MLP or PTNN. if neurons is not [] --> uses default: ['linear'] * len(neurons). if neurons is [] --> uses [].
176
194
  :param dtype: (numpy.dtype): Data type for the Weight matrices. np.float32 by default. Example: np.float64 or np.float16.
195
+ :param cuda: (bool, optional): CUDA GPU acceleration ? Default = False.
177
196
 
178
197
  Returns:
179
198
  tuple: A list for model parameters: [Weight matrix, Train Preds, Train Accuracy, [Activations functions]].
180
199
  """
181
200
 
182
- from .ene_cpu import define_genomes
183
-
201
+ from .ene import define_genomes
202
+ from .cpu.visualizations import display_decision_boundary_history, create_decision_boundary_hist, plot_decision_boundary
203
+
204
+ if cuda is False:
205
+ from .cpu.data_ops import batcher
206
+ from .cpu.loss_functions import categorical_crossentropy, binary_crossentropy
207
+ from .cpu.visualizations import (
208
+ draw_neural_web,
209
+ display_visualizations_for_learner,
210
+ update_history_plots_for_learner,
211
+ initialize_visualization_for_learner,
212
+ update_neuron_history_for_learner)
213
+
214
+ else:
215
+ from .cuda.data_ops import batcher
216
+ from .cuda.loss_functions import categorical_crossentropy, binary_crossentropy
217
+ from .cuda.visualizations import (
218
+ draw_neural_web,
219
+ display_visualizations_for_learner,
220
+ update_history_plots_for_learner,
221
+ initialize_visualization_for_learner,
222
+ update_neuron_history_for_learner)
223
+
184
224
  data = 'Train'
185
225
 
186
226
  except_this = ['spiral', 'circular']
187
227
  activations = [item for item in all_activations() if item not in except_this]
188
228
  activations_len = len(activations)
189
-
229
+
190
230
  # Pre-checks
191
231
 
232
+ if cuda:
233
+ x_train = transfer_to_gpu(x_train, dtype=dtype)
234
+ y_train = transfer_to_gpu(y_train, dtype=dtype)
235
+
192
236
  if pop_size > activations_len and fit_start is True:
193
237
  for _ in range(pop_size - len(activations)):
194
238
  random_index_all_act = random.randint(0, len(activations)-1)
195
239
  activations.append(activations[random_index_all_act])
196
240
 
197
- y_train = optimize_labels(y_train, cuda=False)
241
+ y_train = optimize_labels(y_train, cuda=cuda)
198
242
 
199
243
  if pop_size < activations_len: raise ValueError(f"pop_size must be higher or equal to {activations_len}")
200
244
 
@@ -250,7 +294,7 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
250
294
  loss_list = []
251
295
  target_pop = []
252
296
 
253
- progress = initialize_loading_bar(total=activations_len, desc="", ncols=77, bar_format=bar_format_learner)
297
+ progress = initialize_loading_bar(total=pop_size, desc="", ncols=77, bar_format=bar_format_learner)
254
298
 
255
299
  if fit_start is False:
256
300
  weight_pop, act_pop = define_genomes(input_shape=len(x_train[0]), output_shape=len(y_train[0]), neurons=neurons, activation_functions=activations, population_size=pop_size, dtype=dtype)
@@ -266,10 +310,10 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
266
310
  # LEARNING STARTED
267
311
  for i in range(gen):
268
312
 
269
- # TRANSFORMATION PLAN TO MLP FOR PTNN (in later generations)
313
+ # TRANSFORMATION PLAN TO MLP FOR PTNN (in later generations)
270
314
  if model_type == 'PLAN' and transfer_learning:
271
315
  if i == gen_copy[0]:
272
-
316
+
273
317
  model_type = 'PTNN'
274
318
  neurons = neurons_copy
275
319
 
@@ -308,24 +352,24 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
308
352
  progress.update(0)
309
353
 
310
354
  for j in range(pop_size):
311
-
312
- x_train_batch, y_train_batch = batcher(x_train, y_train, batch_size=batch_size)
313
355
 
356
+ x_train_batch, y_train_batch = batcher(x_train, y_train, batch_size=batch_size)
357
+
314
358
  if fit_start is True and i == 0:
315
359
  if start_this_act is not None and j == 0:
316
360
  pass
317
361
  else:
318
362
 
319
363
  act_pop[j] = activations[j]
320
- W = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], auto_normalization=auto_normalization, dtype=dtype)
364
+ W = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], cuda=cuda, auto_normalization=auto_normalization, dtype=dtype)
321
365
  weight_pop[j] = W
322
366
 
323
367
 
324
368
  if weight_evolve is False:
325
- weight_pop[j] = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], auto_normalization=auto_normalization, dtype=dtype)
369
+ weight_pop[j] = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], cuda=cuda, auto_normalization=auto_normalization, dtype=dtype)
326
370
 
327
371
 
328
- model = evaluate(x_train_batch, y_train_batch, W=weight_pop[j], activations=act_pop[j], activation_potentiations=activation_potentiations[j], auto_normalization=auto_normalization, model_type=model_type)
372
+ model = evaluate(x_train_batch, y_train_batch, W=weight_pop[j], activations=act_pop[j], activation_potentiations=activation_potentiations[j], auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
329
373
  acc = model[get_acc()]
330
374
 
331
375
  if loss == 'categorical_crossentropy':
@@ -336,8 +380,8 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
336
380
  y_pred_batch=model[get_preds_softmax()])
337
381
 
338
382
  fitness = wals(acc, train_loss, acc_impact, loss_impact)
339
- target_pop.append(fitness)
340
-
383
+ target_pop.append(fitness if not cuda else fitness.get())
384
+
341
385
  if fitness >= best_fitness:
342
386
 
343
387
  best_fitness = fitness
@@ -346,7 +390,13 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
346
390
  best_weight = np.copy(weight_pop[j]) if model_type == 'PLAN' else copy.deepcopy(weight_pop[j])
347
391
  best_model = model
348
392
 
349
- final_activations = act_pop[j].copy() if isinstance(act_pop[j], list) else act_pop[j]
393
+ if isinstance(act_pop[j], list) and model_type == 'PLAN':
394
+ final_activations = act_pop[j].copy()
395
+ elif isinstance(act_pop[j], str):
396
+ final_activations = act_pop[j]
397
+ else:
398
+ final_activations = copy.deepcopy(act_pop[j])
399
+
350
400
  if model_type == 'PLAN': final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
351
401
 
352
402
  if batch_size == 1:
@@ -382,7 +432,7 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
382
432
  if target_acc is not None and best_acc >= target_acc:
383
433
  progress.close()
384
434
  train_model = evaluate(x_train, y_train, W=best_weight,
385
- activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
435
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
386
436
  if loss == 'categorical_crossentropy':
387
437
  train_loss = categorical_crossentropy(y_true_batch=y_train,
388
438
  y_pred_batch=train_model[get_preds_softmax()])
@@ -396,15 +446,26 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
396
446
  print('Train Loss: ', train_loss, '\n')
397
447
  print('Model Type:', model_type)
398
448
 
449
+ if decision_boundary_history: display_decision_boundary_history(fig, artist, interval=interval)
450
+
399
451
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
400
452
  best_loss, y_train, interval)
401
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
453
+
454
+ model = template_model._replace(weights=best_weight,
455
+ predictions=best_model[get_preds()],
456
+ accuracy=best_acc,
457
+ activations=final_activations,
458
+ softmax_predictions=best_model[get_preds_softmax()],
459
+ model_type=model_type,
460
+ activation_potentiation=activation_potentiation)
461
+
462
+ return model
402
463
 
403
464
  # Check target loss
404
465
  if target_loss is not None and best_loss <= target_loss:
405
466
  progress.close()
406
467
  train_model = evaluate(x_train, y_train, W=best_weight,
407
- activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
468
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
408
469
 
409
470
  if loss == 'categorical_crossentropy':
410
471
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -419,16 +480,33 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
419
480
  print('Train Loss: ', train_loss, '\n')
420
481
  print('Model Type:', model_type)
421
482
 
483
+ if decision_boundary_history: display_decision_boundary_history(fig, artist, interval=interval)
484
+
422
485
  # Display final visualizations
423
486
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
424
487
  train_loss, y_train, interval)
425
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
488
+
489
+ model = template_model._replace(weights=best_weight,
490
+ predictions=best_model[get_preds()],
491
+ accuracy=best_acc,
492
+ activations=final_activations,
493
+ softmax_predictions=best_model[get_preds_softmax()],
494
+ model_type=model_type,
495
+ activation_potentiation=activation_potentiation)
496
+
497
+ return model
426
498
 
427
499
 
428
500
  progress.update(1)
429
501
 
502
+ if decision_boundary_history:
503
+ if i == 0:
504
+ fig, ax = create_decision_boundary_hist()
505
+ artist = []
506
+ artist = plot_decision_boundary(x_train_batch, y_train_batch, activations=act_pop[np.argmax(target_pop)], W=weight_pop[np.argmax(target_pop)], cuda=cuda, model_type=model_type, ax=ax, artist=artist)
507
+
430
508
  if batch_size != 1:
431
- train_model = evaluate(x_train, y_train, W=best_weight, activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
509
+ train_model = evaluate(x_train, y_train, W=best_weight, activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
432
510
 
433
511
  if loss == 'categorical_crossentropy':
434
512
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -459,7 +537,7 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
459
537
  if best_acc_per_gen_list[i] == best_acc_per_gen_list[i-1]:
460
538
  progress.close()
461
539
  train_model = evaluate(x_train, y_train, W=best_weight,
462
- activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
540
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
463
541
 
464
542
  if loss == 'categorical_crossentropy':
465
543
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -474,16 +552,27 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
474
552
  print('Train Loss: ', train_loss, '\n')
475
553
  print('Model Type:', model_type)
476
554
 
555
+ if decision_boundary_history: display_decision_boundary_history(fig, artist, interval=interval)
556
+
477
557
  # Display final visualizations
478
558
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
479
559
  train_loss, y_train, interval)
480
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
560
+
561
+ model = template_model._replace(weights=best_weight,
562
+ predictions=best_model[get_preds()],
563
+ accuracy=best_acc,
564
+ activations=final_activations,
565
+ softmax_predictions=best_model[get_preds_softmax()],
566
+ model_type=model_type,
567
+ activation_potentiation=activation_potentiation)
568
+
569
+ return model
481
570
 
482
571
  # Final evaluation
483
572
  progress.close()
484
573
 
485
574
  train_model = evaluate(x_train, y_train, W=best_weight,
486
- activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
575
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, cuda=cuda, model_type=model_type)
487
576
 
488
577
  if loss == 'categorical_crossentropy':
489
578
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -492,25 +581,40 @@ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size
492
581
  train_loss = binary_crossentropy(y_true_batch=y_train,
493
582
  y_pred_batch=train_model[get_preds_softmax()])
494
583
 
584
+
495
585
  print('\nActivations: ', final_activations)
496
586
  print('Activation Potentiation: ', activation_potentiation)
497
587
  print('Train Accuracy:', train_model[get_acc()])
498
588
  print('Train Loss: ', train_loss, '\n')
499
589
  print('Model Type:', model_type)
500
590
 
591
+ if decision_boundary_history: display_decision_boundary_history(fig, artist, interval=interval)
592
+
501
593
  # Display final visualizations
502
594
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc, train_loss, y_train, interval)
503
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
595
+
596
+ model = template_model._replace(weights=best_weight,
597
+ predictions=best_model[get_preds()],
598
+ accuracy=best_acc,
599
+ activations=final_activations,
600
+ softmax_predictions=best_model[get_preds_softmax()],
601
+ model_type=model_type,
602
+ activation_potentiation=activation_potentiation)
603
+
604
+ return model
504
605
 
505
606
 
506
607
  def evaluate(
507
608
  x_test,
508
609
  y_test,
509
- model_type,
510
- W,
610
+ model=None,
611
+ model_type=None,
612
+ W=None,
511
613
  activations=['linear'],
512
614
  activation_potentiations=[],
513
- auto_normalization=False
615
+ auto_normalization=False,
616
+ show_report=False,
617
+ cuda=False
514
618
  ) -> tuple:
515
619
  """
516
620
  Evaluates the neural network model using the given test data.
@@ -520,61 +624,65 @@ def evaluate(
520
624
 
521
625
  y_test (np.ndarray): Test labels (one-hot encoded).
522
626
 
523
- model_type: (str): Type of the model. Options: 'PLAN', 'MLP', 'PTNN'.
627
+ model (tuple, optional): Trained model.
628
+
629
+ model_type: (str, optional): Type of the model. Options: 'PLAN', 'MLP', 'PTNN'.
630
+
631
+ W (array-like, optional): Neural net weight matrix.
524
632
 
525
- W (np.ndarray): Neural net weight matrix.
526
-
527
633
  activations (list, optional): Activation list for PLAN or MLP models (MLP layers activations if it PTNN model). Default = ['linear'].
528
634
 
529
635
  activation_potentiations (list, optional): Extra activation potentiation list (PLAN layers activations) for PTNN models. Default = [].
530
636
 
531
637
  auto_normalization (bool, optional): Normalization for x_test ? Default = False.
532
638
 
533
- Returns:
534
- tuple: Model (list).
535
- """
639
+ show_report (bool, optional): show test report. Default = False
536
640
 
537
- if auto_normalization: x_test = normalization(x_test, dtype=x_test.dtype)
641
+ cuda (bool, optional): CUDA GPU acceleration ? Default = False.
538
642
 
539
- if isinstance(activations, str):
540
- activations = [activations]
541
- elif isinstance(activations, list):
542
- activations = [item if isinstance(item, list) or isinstance(item, str) else [item] for item in activations]
643
+ Returns:
644
+ tuple: W, preds, accuracy, None, None, softmax_preds
645
+ """
543
646
 
544
- if model_type == 'MLP':
545
- layer = x_test
546
- for i in range(len(W)):
547
- if i != len(W) - 1 and i != 0: layer = apply_activation(layer, activations[i])
647
+ from .cpu.visualizations import plot_evaluate
648
+ from .model_ops import predict_from_memory
548
649
 
549
- layer = layer @ W[i].T
650
+ if not cuda:
651
+ from .cpu.data_ops import normalization
652
+
653
+ if model:
654
+ sample_acc = model.accuracy
655
+ if hasattr(sample_acc, "get"): model = model._replace(accuracy=sample_acc.get())
550
656
 
551
- result = layer
657
+ else:
658
+ from .cuda.data_ops import normalization
659
+ x_test = cp.array(x_test)
660
+ y_test = cp.array(y_test)
552
661
 
553
- if model_type == 'PLAN':
662
+ if model:
663
+ sample_acc = model.accuracy
664
+ if isinstance(sample_acc, np.number): model = model._replace(accuracy=cp.array(sample_acc))
554
665
 
555
- x_test = apply_activation(x_test, activations)
556
- result = x_test @ W.T
666
+ if model is None:
667
+ from .model_ops import get_model_template
668
+ template_model = get_model_template()
669
+
670
+ model = template_model._replace(weights=W,
671
+ activations=activations,
672
+ model_type=model_type,
673
+ activation_potentiation=activation_potentiations)
557
674
 
558
- if model_type == 'PTNN':
675
+ result = predict_from_memory(x_test, model, cuda=cuda)
559
676
 
560
- if isinstance(activation_potentiations, str):
561
- activation_potentiations = [activation_potentiations]
562
- elif isinstance(activation_potentiations, list):
563
- activation_potentiations = [item if isinstance(item, list) or isinstance(item, str) else [item] for item in activation_potentiations]
564
-
565
- x_test = apply_activation(x_test, activation_potentiations)
566
- layer = x_test @ W[0].T
677
+ if auto_normalization: x_test = normalization(x_test, dtype=x_test.dtype)
567
678
 
568
- for i in range(1, len(W)):
569
- if i != len(W) - 1: layer = apply_activation(layer, activations[i])
679
+ array_type = cp if cuda else np
570
680
 
571
- layer = layer @ W[i].T
681
+ max_vals = array_type.max(result, axis=1, keepdims=True)
682
+
683
+ softmax_preds = array_type.exp(result - max_vals) / array_type.sum(array_type.exp(result - max_vals), axis=1, keepdims=True)
684
+ accuracy = (array_type.argmax(softmax_preds, axis=1) == array_type.argmax(y_test, axis=1)).mean()
572
685
 
573
- result = layer
686
+ if show_report: plot_evaluate(x_test, y_test, result, acc=accuracy, model=model, cuda=cuda)
574
687
 
575
- max_vals = np.max(result, axis=1, keepdims=True)
576
-
577
- softmax_preds = np.exp(result - max_vals) / np.sum(np.exp(result - max_vals), axis=1, keepdims=True)
578
- accuracy = (np.argmax(softmax_preds, axis=1) == np.argmax(y_test, axis=1)).mean()
579
-
580
688
  return W, result, accuracy, None, None, softmax_preds