pyerualjetwork 5.0.3__py3-none-any.whl → 5.2__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/neu_cpu.py CHANGED
@@ -6,10 +6,27 @@ NEU (Neural Networks) on CPU
6
6
  ============================
7
7
  This module hosts functions for training and evaluating artificial neural networks on CPU for labeled classification tasks (for now).
8
8
 
9
- Currently, two types of models can be trained:
9
+ Currently, 3 types of models can be trained:
10
10
 
11
11
  PLAN (Potentiation Learning Artificial Neural Network)
12
+ * Training Time for Small Projects: fast
13
+ * Training Time for Big Projects: fast
14
+ * Explainability: high
15
+ * Learning Capacity: medium (compared to single perceptrons)
16
+
12
17
  MLP (Multi-Layer Perceptron → Deep Learning) -- With non-bias
18
+ * Training Time for Small Projects: fast
19
+ * Training Time for Big Projects: slow
20
+ * Explainability: low
21
+ * Learning Capacity: high
22
+
23
+ PTNN (Potentiation Transfer Neural Network) -- With non-bias
24
+ * Training Time for Small Projects: fast
25
+ * Training Time for Big Projects: fast
26
+ * Explainability: low
27
+ * Learning Capacity: high
28
+
29
+ Read learn function docstring for know how to use of these model architectures.
13
30
 
14
31
  For more information about PLAN: https://github.com/HCB06/PyerualJetwork/blob/main/Welcome_to_PLAN/PLAN.pdf
15
32
 
@@ -32,6 +49,7 @@ PyerualJetwork document: https://github.com/HCB06/PyerualJetwork/blob/main/Welco
32
49
 
33
50
  import numpy as np
34
51
  import copy
52
+ import random
35
53
 
36
54
  ### LIBRARY IMPORTS ###
37
55
  from .ui import loading_bars, initialize_loading_bar
@@ -98,23 +116,26 @@ def plan_fit(
98
116
  return normalization(weight, dtype=dtype)
99
117
 
100
118
 
101
- def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, pop_size=None,
119
+ def learn(x_train, y_train, optimizer, gen, pop_size, fit_start=True, batch_size=1,
102
120
  weight_evolve=True, neural_web_history=False, show_current_activations=False, auto_normalization=False,
103
121
  neurons_history=False, early_stop=False, show_history=False, target_loss=None,
104
122
  interval=33.33, target_acc=None, loss='categorical_crossentropy', acc_impact=0.9, loss_impact=0.1,
105
123
  start_this_act=None, start_this_W=None, neurons=[], activation_functions=[], dtype=np.float32):
106
124
  """
107
125
  Optimizes the activation functions for a neural network by leveraging train data to find
108
- the most accurate combination of activation potentiation(or activation function) & weight values for the given dataset.
126
+ the most accurate combination of activation potentiation(or activation function) & weight values for the labeled classificaiton dataset.
109
127
 
110
128
  Why genetic optimization ENE(Eugenic NeuroEvolution) and not backpropagation?
111
129
  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.
112
130
  Since activation functions are not differentiable, we cannot use gradient descent or backpropagation. However, I developed a more powerful genetic optimization algorithm: ENE.
113
131
 
132
+ * This function also able to train classic MLP model architectures.
133
+ * And my newest innovative architecture: PTNN (Potentiation Transfer Neural Network).
134
+
114
135
  :Args:
115
136
  :param x_train: (array-like): Training input data.
116
137
  :param y_train: (array-like): Labels for training data. one-hot encoded.
117
- :param optimizer: (function): Optimization technique with hyperparameters. (PLAN and MLP (both) using ENE for optimization.) Please use this: from pyerualjetwork.ene import evolver (and) optimizer = lambda *args, **kwargs: evolver(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
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 hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
118
139
  ```python
119
140
  optimizer = lambda *args, **kwargs: ene_cpu.evolver(*args,
120
141
  activation_add_prob=0.05,
@@ -131,11 +152,11 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
131
152
  batch_size=0.05,
132
153
  interval=16.67)
133
154
  ```
134
- :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. Options: True or False. Default: True
135
- :param gen: (int, optional): The generation count for genetic optimization.
155
+ :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
+ :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.
136
157
  :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)
137
- :param pop_size: (int, optional): Population size of each generation. Default: count of activation functions
138
- :param weight_evolve: (bool, optional): Activation combinations already optimizes by PLANEAT genetic search algorithm. Should the weight parameters also evolve or should the weights be determined according to the aggregating learning principle of the PLAN algorithm? Default: True (Evolves Weights)
158
+ :param pop_size: (int): Population size of each generation.
159
+ :param weight_evolve: (bool, optional): Activation combinations already optimizes by ENE genetic search algorithm. Should the weight parameters also evolve or should the weights be determined according to the aggregating learning principle of the PLAN algorithm? Default: True (Evolves Weights)
139
160
  :param neural_web_history: (bool, optional): Draws history of neural web. Default is False. [ONLY FOR PLAN MODELS]
140
161
  :param 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
141
162
  :param auto_normalization: (bool, optional): Normalization may solves overflow problem. Default: False
@@ -150,8 +171,8 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
150
171
  :param loss_impact: (float, optional): Impact of loss for optimization [0-1]. Default: 0.1
151
172
  :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
152
173
  :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
153
- :param neurons: (list[int], optional): If you dont want train PLAN model this parameter represents neuron count of each hidden layer for MLP. Number of elements --> Layer count. Default: [] (No hidden layer) --> architecture setted to PLAN, if not --> architecture setted to MLP.
154
- :param activation_functions: (list[str], optional): If you dont want train PLAN model this parameter represents activation function of each hidden layer for MLP. if neurons is not [] --> uses default: ['linear'] * len(neurons). if neurons is [] --> uses [].
174
+ :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.
175
+ :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 [].
155
176
  :param dtype: (numpy.dtype): Data type for the Weight matrices. np.float32 by default. Example: np.float64 or np.float16.
156
177
 
157
178
  Returns:
@@ -165,28 +186,58 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
165
186
  except_this = ['spiral', 'circular']
166
187
  activations = [item for item in all_activations() if item not in except_this]
167
188
  activations_len = len(activations)
168
-
189
+
169
190
  # Pre-checks
170
191
 
171
- if pop_size is None: pop_size = activations_len
192
+ if pop_size > activations_len and fit_start is True:
193
+ for _ in range(pop_size - len(activations)):
194
+ random_index_all_act = random.randint(0, len(activations)-1)
195
+ activations.append(activations[random_index_all_act])
196
+
172
197
  y_train = optimize_labels(y_train, cuda=False)
173
198
 
174
199
  if pop_size < activations_len: raise ValueError(f"pop_size must be higher or equal to {activations_len}")
175
200
 
176
- if gen is None: gen = activations_len
177
-
178
201
  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')
179
202
  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')
180
203
 
181
204
  if neurons != []:
182
- fit_start = False
183
205
  weight_evolve = True
184
- is_mlp = True
206
+
185
207
  if activation_functions == []: activation_functions = ['linear'] * len(neurons)
186
- activations = activation_functions
208
+
209
+ if fit_start is False:
210
+ # MLP
211
+ activations = activation_functions
212
+ model_type = 'MLP'
213
+ activation_potentiations = [0] * pop_size
214
+ activation_potentiation = None
215
+ is_mlp = True
216
+ transfer_learning = False
217
+ else:
218
+ # PTNN
219
+ model_type = 'PLAN' # First generation index gen[0] is PLAN, other index gen[1] it will change to PTNN (PLAN Connects to MLP and will transfer the learned information).
220
+ transfer_learning = True
221
+
222
+ neurons_copy = neurons.copy()
223
+ neurons = []
224
+ gen_copy = gen.copy()
225
+ gen = gen[0] + gen[1]
226
+ activation_potentiations = [0] * pop_size
227
+ activation_potentiation = None
228
+ is_mlp = False # it will change
229
+
187
230
  else:
231
+ # PLAN
232
+ model_type = 'PLAN'
233
+ transfer_learning = False
234
+
235
+ activation_potentiations = [0] * pop_size # NOTE: For PLAN models, activation_potentiations is needed BUT activations variable already mirros activation_potentiation values.
236
+ # So, we don't need to use activation_potentiations variable. activation_potentiations variable is only for PTNN models.
237
+ activation_potentiation = None
188
238
  is_mlp = False
189
239
 
240
+
190
241
  # Initialize visualization components
191
242
  viz_objects = initialize_visualization_for_learner(show_history, neurons_history, neural_web_history, x_train, y_train)
192
243
 
@@ -201,12 +252,12 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
201
252
 
202
253
  progress = initialize_loading_bar(total=activations_len, desc="", ncols=77, bar_format=bar_format_learner)
203
254
 
204
- if fit_start is False or pop_size > activations_len:
205
- weight_pop, act_pop = define_genomes(input_shape=len(x_train[0]), output_shape=len(y_train[0]), neurons=neurons, activation_functions=activation_functions, population_size=pop_size, dtype=dtype)
255
+ if fit_start is False:
256
+ 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)
206
257
 
207
258
  else:
208
- weight_pop = [0] * pop_size
209
- act_pop = [0] * pop_size
259
+ weight_pop = [0] * len(activations)
260
+ act_pop = [0] * len(activations)
210
261
 
211
262
  if start_this_act is not None and start_this_W is not None:
212
263
  weight_pop[0] = start_this_W
@@ -214,6 +265,41 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
214
265
 
215
266
  # LEARNING STARTED
216
267
  for i in range(gen):
268
+
269
+ # TRANSFORMATION PLAN TO MLP FOR PTNN (in later generations)
270
+ if model_type == 'PLAN' and transfer_learning:
271
+ if i == gen_copy[0]:
272
+
273
+ model_type = 'PTNN'
274
+ neurons = neurons_copy
275
+
276
+ for individual in range(len(weight_pop)):
277
+ weight_pop[individual] = np.copy(best_weight)
278
+ activation_potentiations[individual] = final_activations.copy() if isinstance(final_activations, list) else final_activations
279
+
280
+ activation_potentiation = activation_potentiations[0]
281
+
282
+ neurons_copy = [len(y_train[0])] + neurons_copy
283
+ activation_functions = ['linear'] + activation_functions
284
+
285
+ weight_pop, act_pop = define_genomes(input_shape=len(x_train[0]), output_shape=len(y_train[0]), neurons=neurons_copy, activation_functions=activation_functions, population_size=pop_size, dtype=dtype)
286
+
287
+ # 0 indexed individual will keep PLAN's learned informations and in later generations it will share other individuals.
288
+ for l in range(1, len(weight_pop[0])):
289
+ original_shape = weight_pop[0][l].shape
290
+
291
+ identity_matrix = np.eye(original_shape[0], original_shape[1], dtype=weight_pop[0][l].dtype)
292
+ weight_pop[0][l] = identity_matrix
293
+
294
+ for l in range(len(weight_pop)):
295
+ weight_pop[l][0] = np.copy(best_weight)
296
+
297
+ best_weight = np.array(weight_pop[0], dtype=object)
298
+ final_activations = act_pop[0]
299
+ is_mlp = True
300
+ fit_start = False
301
+
302
+
217
303
  postfix_dict["Gen"] = str(i+1) + '/' + str(gen)
218
304
  progress.set_postfix(postfix_dict)
219
305
 
@@ -225,18 +311,21 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
225
311
 
226
312
  x_train_batch, y_train_batch = batcher(x_train, y_train, batch_size=batch_size)
227
313
 
228
- if fit_start is True and i == 0 and j < activations_len:
314
+ if fit_start is True and i == 0:
229
315
  if start_this_act is not None and j == 0:
230
316
  pass
231
317
  else:
318
+
232
319
  act_pop[j] = activations[j]
233
320
  W = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], auto_normalization=auto_normalization, dtype=dtype)
234
321
  weight_pop[j] = W
235
-
322
+
323
+
236
324
  if weight_evolve is False:
237
325
  weight_pop[j] = plan_fit(x_train_batch, y_train_batch, activations=act_pop[j], auto_normalization=auto_normalization, dtype=dtype)
238
326
 
239
- model = evaluate(x_train_batch, y_train_batch, W=weight_pop[j], activations=act_pop[j], auto_normalization=auto_normalization, is_mlp=is_mlp)
327
+
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)
240
329
  acc = model[get_acc()]
241
330
 
242
331
  if loss == 'categorical_crossentropy':
@@ -246,7 +335,7 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
246
335
  train_loss = binary_crossentropy(y_true_batch=y_train_batch,
247
336
  y_pred_batch=model[get_preds_softmax()])
248
337
 
249
- fitness = wals(acc, train_loss, acc_impact, loss_impact)
338
+ fitness = wals(acc, train_loss, acc_impact, loss_impact)
250
339
  target_pop.append(fitness)
251
340
 
252
341
  if fitness >= best_fitness:
@@ -254,11 +343,11 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
254
343
  best_fitness = fitness
255
344
  best_acc = acc
256
345
  best_loss = train_loss
257
- best_weight = np.copy(weight_pop[j]) if is_mlp is False else copy.deepcopy(weight_pop[j])
346
+ best_weight = np.copy(weight_pop[j]) if model_type == 'PLAN' else copy.deepcopy(weight_pop[j])
258
347
  best_model = model
259
348
 
260
349
  final_activations = act_pop[j].copy() if isinstance(act_pop[j], list) else act_pop[j]
261
- if is_mlp is False: final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
350
+ if model_type == 'PLAN': final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
262
351
 
263
352
  if batch_size == 1:
264
353
  postfix_dict[f"{data} Accuracy"] = np.round(best_acc, 4)
@@ -293,7 +382,7 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
293
382
  if target_acc is not None and best_acc >= target_acc:
294
383
  progress.close()
295
384
  train_model = evaluate(x_train, y_train, W=best_weight,
296
- activations=final_activations, auto_normalization=auto_normalization, is_mlp=is_mlp)
385
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
297
386
  if loss == 'categorical_crossentropy':
298
387
  train_loss = categorical_crossentropy(y_true_batch=y_train,
299
388
  y_pred_batch=train_model[get_preds_softmax()])
@@ -302,18 +391,20 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
302
391
  y_pred_batch=train_model[get_preds_softmax()])
303
392
 
304
393
  print('\nActivations: ', final_activations)
305
- print(f'Train Accuracy:', train_model[get_acc()])
306
- print(f'Train Loss: ', train_loss, '\n')
394
+ print('Activation Potentiation: ', activation_potentiation)
395
+ print('Train Accuracy:', train_model[get_acc()])
396
+ print('Train Loss: ', train_loss, '\n')
397
+ print('Model Type:', model_type)
307
398
 
308
399
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
309
400
  best_loss, y_train, interval)
310
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations
401
+ return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
311
402
 
312
403
  # Check target loss
313
404
  if target_loss is not None and best_loss <= target_loss:
314
405
  progress.close()
315
406
  train_model = evaluate(x_train, y_train, W=best_weight,
316
- activations=final_activations, auto_normalization=auto_normalization, is_mlp=is_mlp)
407
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
317
408
 
318
409
  if loss == 'categorical_crossentropy':
319
410
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -323,19 +414,21 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
323
414
  y_pred_batch=train_model[get_preds_softmax()])
324
415
 
325
416
  print('\nActivations: ', final_activations)
326
- print(f'Train Accuracy :', train_model[get_acc()])
327
- print(f'Train Loss : ', train_loss, '\n')
417
+ print('Activation Potentiation: ', activation_potentiation)
418
+ print('Train Accuracy:', train_model[get_acc()])
419
+ print('Train Loss: ', train_loss, '\n')
420
+ print('Model Type:', model_type)
328
421
 
329
422
  # Display final visualizations
330
423
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
331
424
  train_loss, y_train, interval)
332
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations
425
+ return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
333
426
 
334
427
 
335
428
  progress.update(1)
336
429
 
337
430
  if batch_size != 1:
338
- train_model = evaluate(x_train, y_train, best_weight, final_activations, auto_normalization=auto_normalization, is_mlp=is_mlp)
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)
339
432
 
340
433
  if loss == 'categorical_crossentropy':
341
434
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -355,7 +448,7 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
355
448
  best_acc_per_gen_list.append(best_acc)
356
449
  loss_list.append(best_loss)
357
450
 
358
- if is_mlp is False: weight_pop = np.array(weight_pop, copy=False, dtype=dtype)
451
+ if model_type == 'PLAN': weight_pop = np.array(weight_pop, copy=False, dtype=dtype)
359
452
  else: weight_pop = np.array(weight_pop, copy=False, dtype=object)
360
453
 
361
454
  weight_pop, act_pop = optimizer(weight_pop, act_pop, i, np.array(target_pop, dtype=dtype, copy=False), weight_evolve=weight_evolve, is_mlp=is_mlp, bar_status=False)
@@ -366,7 +459,7 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
366
459
  if best_acc_per_gen_list[i] == best_acc_per_gen_list[i-1]:
367
460
  progress.close()
368
461
  train_model = evaluate(x_train, y_train, W=best_weight,
369
- activations=final_activations, auto_normalization=auto_normalization, is_mlp=is_mlp)
462
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
370
463
 
371
464
  if loss == 'categorical_crossentropy':
372
465
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -376,19 +469,21 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
376
469
  y_pred_batch=train_model[get_preds_softmax()])
377
470
 
378
471
  print('\nActivations: ', final_activations)
379
- print(f'Train Accuracy:', train_model[get_acc()])
380
- print(f'Train Loss: ', train_loss, '\n')
472
+ print('Activation Potentiation: ', activation_potentiation)
473
+ print('Train Accuracy:', train_model[get_acc()])
474
+ print('Train Loss: ', train_loss, '\n')
475
+ print('Model Type:', model_type)
381
476
 
382
477
  # Display final visualizations
383
478
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc,
384
479
  train_loss, y_train, interval)
385
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations
480
+ return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
386
481
 
387
482
  # Final evaluation
388
483
  progress.close()
389
484
 
390
485
  train_model = evaluate(x_train, y_train, W=best_weight,
391
- activations=final_activations, auto_normalization=auto_normalization, is_mlp=is_mlp)
486
+ activations=final_activations, activation_potentiations=activation_potentiation, auto_normalization=auto_normalization, model_type=model_type)
392
487
 
393
488
  if loss == 'categorical_crossentropy':
394
489
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -398,21 +493,24 @@ def learn(x_train, y_train, optimizer, fit_start=True, gen=None, batch_size=1, p
398
493
  y_pred_batch=train_model[get_preds_softmax()])
399
494
 
400
495
  print('\nActivations: ', final_activations)
401
- print(f'Train Accuracy:', train_model[get_acc()])
402
- print(f'Train Loss: ', train_loss, '\n')
496
+ print('Activation Potentiation: ', activation_potentiation)
497
+ print('Train Accuracy:', train_model[get_acc()])
498
+ print('Train Loss: ', train_loss, '\n')
499
+ print('Model Type:', model_type)
403
500
 
404
501
  # Display final visualizations
405
502
  display_visualizations_for_learner(viz_objects, best_weight, data, best_acc, train_loss, y_train, interval)
406
- return best_weight, best_model[get_preds_softmax()], best_acc, final_activations
503
+ return best_weight, best_model[get_preds_softmax()], best_acc, final_activations, None, None, None, None, None, None, None, activation_potentiation
407
504
 
408
505
 
409
506
  def evaluate(
410
507
  x_test,
411
508
  y_test,
509
+ model_type,
412
510
  W,
413
511
  activations=['linear'],
414
- auto_normalization=False,
415
- is_mlp=False
512
+ activation_potentiations=[],
513
+ auto_normalization=False
416
514
  ) -> tuple:
417
515
  """
418
516
  Evaluates the neural network model using the given test data.
@@ -422,13 +520,15 @@ def evaluate(
422
520
 
423
521
  y_test (np.ndarray): Test labels (one-hot encoded).
424
522
 
523
+ model_type: (str): Type of the model. Options: 'PLAN', 'MLP', 'PTNN'.
524
+
425
525
  W (np.ndarray): Neural net weight matrix.
426
526
 
427
- activations (list, optional): Activation list. Default = ['linear'].
527
+ activations (list, optional): Activation list for PLAN or MLP models (MLP layers activations if it PTNN model). Default = ['linear'].
528
+
529
+ activation_potentiations (list, optional): Extra activation potentiation list (PLAN layers activations) for PTNN models. Default = [].
428
530
 
429
531
  auto_normalization (bool, optional): Normalization for x_test ? Default = False.
430
-
431
- is_mlp (bool, optional): Evaluate PLAN model or MLP model ? Default: False (PLAN)
432
532
 
433
533
  Returns:
434
534
  tuple: Model (list).
@@ -441,7 +541,7 @@ def evaluate(
441
541
  elif isinstance(activations, list):
442
542
  activations = [item if isinstance(item, list) or isinstance(item, str) else [item] for item in activations]
443
543
 
444
- if is_mlp:
544
+ if model_type == 'MLP':
445
545
  layer = x_test
446
546
  for i in range(len(W)):
447
547
  if i != len(W) - 1 and i != 0: layer = apply_activation(layer, activations[i])
@@ -450,11 +550,28 @@ def evaluate(
450
550
 
451
551
  result = layer
452
552
 
453
- else:
553
+ if model_type == 'PLAN':
454
554
 
455
555
  x_test = apply_activation(x_test, activations)
456
556
  result = x_test @ W.T
457
557
 
558
+ if model_type == 'PTNN':
559
+
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
567
+
568
+ for i in range(1, len(W)):
569
+ if i != len(W) - 1: layer = apply_activation(layer, activations[i])
570
+
571
+ layer = layer @ W[i].T
572
+
573
+ result = layer
574
+
458
575
  max_vals = np.max(result, axis=1, keepdims=True)
459
576
 
460
577
  softmax_preds = np.exp(result - max_vals) / np.sum(np.exp(result - max_vals), axis=1, keepdims=True)