pyerualjetwork 4.1.6__py3-none-any.whl → 4.1.8__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.
@@ -1,10 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """
3
3
 
4
- MAIN MODULE FOR PLAN
4
+ MAIN MODULE FOR PLAN_CUDA
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,6 +14,7 @@ ANAPLAN document: https://github.com/HCB06/Anaplan/blob/main/Welcome_to_Anaplan/
14
14
  """
15
15
 
16
16
  import cupy as cp
17
+ import numpy as np
17
18
  from colorama import Fore
18
19
  import math
19
20
 
@@ -24,6 +25,7 @@ from .loss_functions_cuda import binary_crossentropy, categorical_crossentropy
24
25
  from .activation_functions_cuda import apply_activation, Softmax, all_activations
25
26
  from .metrics_cuda import metrics
26
27
  from .model_operations_cuda import get_acc, get_preds, get_preds_softmax
28
+ from .memory_operations import transfer_to_gpu, transfer_to_cpu, optimize_labels
27
29
  from .visualizations_cuda import (
28
30
  draw_neural_web,
29
31
  update_neural_web_for_fit,
@@ -106,8 +108,6 @@ def fit(
106
108
  numpyarray([num]): (Weight matrix).
107
109
  """
108
110
  # Pre-checks
109
-
110
- from memory_operations import transfer_to_gpu, transfer_to_cpu
111
111
 
112
112
  if train_bar and val:
113
113
  train_progress = initialize_loading_bar(total=len(x_train), ncols=71, desc='Fitting', bar_format=bar_format_normal)
@@ -188,45 +188,63 @@ def fit(
188
188
  return normalization(LTPW, dtype=dtype)
189
189
 
190
190
 
191
- def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', batch_size=1,
191
+ def learner(x_train, y_train, optimizer, x_test=None, y_test=None, strategy='accuracy', gen=None, batch_size=1,
192
192
  neural_web_history=False, show_current_activations=False, auto_normalization=True,
193
- neurons_history=False, patience=None, depth=None, early_shifting=False,
194
- early_stop=False, loss='categorical_crossentropy', show_history=False,
193
+ neurons_history=False, early_stop=False, loss='categorical_crossentropy', show_history=False,
195
194
  interval=33.33, target_acc=None, target_loss=None, except_this=None,
196
- only_this=None, start_this=None, dtype=cp.float32, memory='gpu'):
195
+ only_this=None, start_this_act=None, start_this_W=None, target_fitness='max', dtype=cp.float32, memory='gpu'):
197
196
  """
198
197
  Optimizes the activation functions for a neural network by leveraging train data to find
199
198
  the most accurate combination of activation potentiation for the given dataset.
200
199
 
200
+ Why genetic optimization and not backpropagation?
201
+ 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.
202
+ Since activation functions are not differentiable, we cannot use gradient descent or backpropagation. However, I developed a more powerful genetic optimization algorithm: PLANEAT.
203
+
201
204
  Args:
202
205
 
203
206
  x_train (array-like): Training input data.
204
207
 
205
208
  y_train (array-like): Labels for training data.
206
209
 
210
+ optimizer (function): PLAN optimization technique with hyperparameters. (PLAN using NEAT(PLANEAT) for optimization.) Please use this: from pyerualjetwork import planeat_cuda (and) optimizer = lambda *args, **kwargs: planeat_cuda.evolve(*args, 'here give your neat hyperparameters for example: activation_add_prob=0.85', **kwargs) Example:
211
+ ```python
212
+ genetic_optimizer = lambda *args, **kwargs: planeat_cuda.evolve(*args,
213
+ activation_add_prob=0.85,
214
+ mutations=False,
215
+ strategy='cross_over',
216
+ **kwargs)
217
+
218
+ model = plan_cuda.learner(x_train,
219
+ y_train,
220
+ optimizer=genetic_optimizer,
221
+ strategy='accuracy',
222
+ show_history=True,
223
+ target_acc=0.94,
224
+ interval=16.67)
225
+ ```
226
+
207
227
  x_test (array-like, optional): Test input data (for improve next gen generilization). If test data is not given then train feedback learning active
208
228
 
209
229
  y_test (array-like, optional): Test Labels (for improve next gen generilization). If test data is not given then train feedback learning active
210
230
 
211
- 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'.
231
+ 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'.
212
232
 
213
233
  patience ((int, float), optional): patience value for adaptive strategies. For 'adaptive_accuracy' Default value: 5. For 'adaptive_loss' Default value: 0.150.
214
234
 
215
- depth (int, optional): The depth of the PLAN neural networks Aggreagation layers.
235
+ gen (int, optional): The generation count for genetic optimization.
216
236
 
217
237
  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)
218
238
 
219
239
  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.
220
240
 
221
- 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
222
-
223
- early_stop (bool, optional): If True, implements early stopping during training.(If test accuracy not improves in two depth stops learning.) Default is False.
241
+ early_stop (bool, optional): If True, implements early stopping during training.(If test accuracy not improves in two gen stops learning.) Default is False.
224
242
 
225
243
  show_current_activations (bool, optional): Should it display the activations selected according to the current strategies during learning, or not? (True or False) This can be very useful if you want to cancel the learning process and resume from where you left off later. After canceling, you will need to view the live training activations in order to choose the activations to be given to the 'start_this' parameter. Default is False
226
244
 
227
245
  show_history (bool, optional): If True, displays the training history after optimization. Default is False.
228
246
 
229
- 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'.
247
+ loss (str, optional): For visualizing and monitoring. PLAN neural networks doesn't need any loss function in training. options: ('categorical_crossentropy' or 'binary_crossentropy') Default is 'categorical_crossentropy'.
230
248
 
231
249
  interval (int, optional): The interval at which evaluations are conducted during training. (33.33 = 30 FPS, 16.67 = 60 FPS) Default is 100.
232
250
 
@@ -238,8 +256,10 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
238
256
 
239
257
  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())
240
258
 
241
- 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
259
+ 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
242
260
 
261
+ start_this_W (cupy.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
262
+
243
263
  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.
244
264
 
245
265
  neural_web_history (bool, optional): Draws history of neural web. Default is False.
@@ -252,18 +272,20 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
252
272
  tuple: A list for model parameters: [Weight matrix, Preds, Accuracy, [Activations functions]]. You can acces this parameters in model_operations module. For example: model_operations.get_weights() for Weight matrix.
253
273
 
254
274
  """
255
- from memory_operations import transfer_to_gpu, transfer_to_cpu
256
275
 
257
- 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)
276
+ 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)
258
277
 
259
278
  activation_potentiation = all_activations()
260
279
 
280
+ y_train = optimize_labels(y_train, cuda=True)
281
+
261
282
  if x_test is None and y_test is None:
262
283
  x_test = x_train
263
284
  y_test = y_train
264
285
  data = 'Train'
265
286
  else:
266
287
  data = 'Test'
288
+ y_test = optimize_labels(y_test, cuda=True)
267
289
 
268
290
  if memory == 'gpu':
269
291
  x_train = transfer_to_gpu(x_train, dtype=dtype)
@@ -272,7 +294,7 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
272
294
  x_test = transfer_to_gpu(x_test, dtype=dtype)
273
295
  y_test = transfer_to_gpu(y_test, dtype=y_train.dtype)
274
296
 
275
- from data_operations_cuda import batcher
297
+ from .data_operations_cuda import batcher
276
298
 
277
299
  elif memory == 'cpu':
278
300
  x_train = transfer_to_cpu(x_train, dtype=dtype)
@@ -281,57 +303,45 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
281
303
  x_test = transfer_to_cpu(x_test, dtype=dtype)
282
304
  y_test = transfer_to_cpu(y_test, dtype=y_train.dtype)
283
305
 
284
- from data_operations import batcher
306
+ from .data_operations import batcher
285
307
 
286
308
  else:
287
309
  raise ValueError("memory parameter must be 'cpu' or 'gpu'.")
288
310
 
289
-
290
- if early_shifting != False:
291
- shift_patience = early_shifting
292
-
293
- # Strategy initialization
294
- if strategy == 'adaptive_accuracy':
295
- strategy = 'accuracy'
296
- adaptive = True
297
- if patience == None:
298
- patience = 5
299
- elif strategy == 'adaptive_loss':
300
- strategy = 'loss'
301
- adaptive = True
302
- if patience == None:
303
- patience = 0.150
304
- else:
305
- adaptive = False
311
+ 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'.")
306
312
 
307
313
  # Filter activation functions
308
- if only_this != None:
314
+ if only_this is not None:
309
315
  activation_potentiation = only_this
310
- if except_this != None:
316
+ if except_this is not None:
311
317
  activation_potentiation = [item for item in activation_potentiation if item not in except_this]
312
- if depth is None:
313
- depth = len(activation_potentiation)
318
+ if gen is None:
319
+ gen = len(activation_potentiation)
314
320
 
321
+ 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']")
322
+ 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']")
323
+
315
324
  # Initialize visualization components
316
325
  viz_objects = initialize_visualization_for_learner(show_history, neurons_history, neural_web_history, x_train, y_train)
317
326
 
318
327
  # Initialize progress bar
319
328
  if batch_size == 1:
320
- ncols = 100
329
+ ncols = 86
321
330
  else:
322
- ncols = 140
323
- progress = initialize_loading_bar(total=len(activation_potentiation), desc="", ncols=ncols, bar_format=bar_format_learner)
331
+ ncols = 99
324
332
 
325
333
  # Initialize variables
326
- activations = []
327
- if start_this is None:
328
- best_activations = []
334
+ act_pop = []
335
+ weight_pop = []
336
+
337
+ if start_this_act is None and start_this_W is None:
329
338
  best_acc = 0
330
339
  else:
331
- best_activations = start_this
340
+ act_pop.append(start_this_act)
341
+ weight_pop.append(start_this_W)
342
+
332
343
  x_test_batch, y_test_batch = batcher(x_test, y_test, batch_size=batch_size)
333
- W = fit(x_train, y_train, activation_potentiation=best_activations, train_bar=False, auto_normalization=auto_normalization, dtype=dtype, memory=memory)
334
- model = evaluate(x_test_batch, y_test_batch, W=W, loading_bar_status=False, activation_potentiation=activations, dtype=dtype, memory=memory)
344
+ model = evaluate(x_test_batch, y_test_batch, W=start_this_W, loading_bar_status=False, activation_potentiation=act_pop, dtype=dtype, memory=memory)
335
345
 
336
346
  if loss == 'categorical_crossentropy':
337
347
  test_loss = categorical_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
@@ -341,12 +351,15 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
341
351
  best_acc = model[get_acc()]
342
352
  best_loss = test_loss
343
353
 
344
- best_acc_per_depth_list = []
354
+ best_acc_per_gen_list = []
345
355
  postfix_dict = {}
346
356
  loss_list = []
347
-
348
- for i in range(depth):
349
- postfix_dict["Depth"] = str(i+1) + '/' + str(depth)
357
+ target_pop = []
358
+
359
+ progress = initialize_loading_bar(total=len(activation_potentiation), desc="", ncols=ncols, bar_format=bar_format_learner)
360
+
361
+ for i in range(gen):
362
+ postfix_dict["Gen"] = str(i+1) + '/' + str(gen)
350
363
  progress.set_postfix(postfix_dict)
351
364
 
352
365
  progress.n = 0
@@ -354,79 +367,65 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
354
367
  progress.update(0)
355
368
 
356
369
  for j in range(len(activation_potentiation)):
357
- for k in range(len(best_activations)):
358
- activations.append(best_activations[k])
359
-
360
- activations.append(activation_potentiation[j])
361
370
 
362
371
  x_test_batch, y_test_batch = batcher(x_test, y_test, batch_size=batch_size)
363
- W = fit(x_train, y_train, activation_potentiation=activations, train_bar=False, auto_normalization=auto_normalization, dtype=dtype, memory=memory)
364
- model = evaluate(x_test_batch, y_test_batch, W=W, loading_bar_status=False, activation_potentiation=activations, dtype=dtype, memory=memory)
372
+
373
+ if i == 0:
374
+ act_pop.append(activation_potentiation[j])
375
+ W = fit(x_train, y_train, activation_potentiation=act_pop[-1], train_bar=False, auto_normalization=auto_normalization, dtype=dtype)
376
+ weight_pop.append(W)
365
377
 
366
- acc = model[get_acc()]
378
+ model = evaluate(x_test_batch, y_test_batch, W=weight_pop[j], loading_bar_status=False, activation_potentiation=act_pop[j], dtype=dtype, memory=memory)
367
379
 
368
- if strategy == 'loss' or strategy == 'all':
369
- if loss == 'categorical_crossentropy':
370
- test_loss = categorical_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
371
- else:
372
- test_loss = binary_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
380
+ acc = model[get_acc()]
381
+ if strategy == 'accuracy': target_pop.append(acc)
373
382
 
374
- if i == 0 and j == 0 and start_this is None:
375
- best_loss = test_loss
383
+ elif strategy == 'f1' or strategy == 'precision' or strategy == 'recall':
384
+ precision_score, recall_score, f1_score = metrics(y_test_batch, model[get_preds()])
376
385
 
377
- if strategy == 'f1' or strategy == 'precision' or strategy == 'recall' or strategy == 'all':
378
- precision_score, recall_score, f1_score = metrics(transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), model[get_preds()])
386
+ if strategy == 'precision':
387
+ target_pop.append(precision_score)
379
388
 
380
- if strategy == 'precision' or strategy == 'all':
381
389
  if i == 0 and j == 0:
382
390
  best_precision = precision_score
383
391
 
384
- if strategy == 'recall' or strategy == 'all':
392
+ if strategy == 'recall':
393
+ target_pop.append(recall_score)
394
+
385
395
  if i == 0 and j == 0:
386
396
  best_recall = recall_score
387
397
 
388
- if strategy == 'f1' or strategy == 'all':
398
+ if strategy == 'f1':
399
+ target_pop.append(f1_score)
400
+
389
401
  if i == 0 and j == 0:
390
402
  best_f1 = f1_score
391
403
 
392
- if early_shifting != False:
393
- if acc <= best_acc:
394
- early_shifting -= 1
395
- if early_shifting == 0:
396
- early_shifting = shift_patience
397
- break
398
-
399
404
  if ((strategy == 'accuracy' and acc >= best_acc) or
400
- (strategy == 'loss' and test_loss <= best_loss) or
401
405
  (strategy == 'f1' and f1_score >= best_f1) or
402
406
  (strategy == 'precision' and precision_score >= best_precision) or
403
- (strategy == 'recall' and recall_score >= best_recall) or
404
- (strategy == 'all' and f1_score >= best_f1 and acc >= best_acc and
405
- test_loss <= best_loss and precision_score >= best_precision and
406
- recall_score >= best_recall)):
407
+ (strategy == 'recall' and recall_score >= best_recall)):
407
408
 
408
- current_best_activation = activation_potentiation[j]
409
409
  best_acc = acc
410
-
410
+ best_weights = weight_pop[j]
411
+ final_activations = act_pop[j]
412
+ best_model = model
413
+
414
+ final_activations = [final_activations[0]] if len(set(final_activations)) == 1 else final_activations # removing if all same
415
+
411
416
  if batch_size == 1:
412
417
  postfix_dict[f"{data} Accuracy"] = best_acc
413
418
  else:
414
419
  postfix_dict[f"{data} Batch Accuracy"] = acc
415
420
  progress.set_postfix(postfix_dict)
416
-
417
- final_activations = activations
418
421
 
419
422
  if show_current_activations:
420
423
  print(f", Current Activations={final_activations}", end='')
421
-
422
- best_weights = W
423
- best_model = model
424
-
425
- if strategy != 'loss':
426
- if loss == 'categorical_crossentropy':
427
- test_loss = categorical_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
428
- else:
429
- test_loss = binary_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
424
+
425
+ if loss == 'categorical_crossentropy':
426
+ test_loss = categorical_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
427
+ else:
428
+ test_loss = binary_crossentropy(y_true_batch=transfer_to_gpu(y_test_batch, dtype=y_test_batch.dtype), y_pred_batch=model[get_preds_softmax()])
430
429
 
431
430
  if batch_size == 1:
432
431
  postfix_dict[f"{data} Loss"] = test_loss
@@ -438,9 +437,9 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
438
437
 
439
438
  # Update visualizations during training
440
439
  if show_history:
441
- depth_list = range(1, len(best_acc_per_depth_list) + 2)
442
- update_history_plots_for_learner(viz_objects, depth_list, loss_list + [test_loss],
443
- best_acc_per_depth_list + [best_acc], x_train, final_activations)
440
+ gen_list = range(1, len(best_acc_per_gen_list) + 2)
441
+ update_history_plots_for_learner(viz_objects, gen_list, loss_list + [test_loss],
442
+ best_acc_per_gen_list + [best_acc], x_train, final_activations)
444
443
 
445
444
  if neurons_history:
446
445
  viz_objects['neurons']['artists'] = (
@@ -508,28 +507,19 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
508
507
  return best_weights, best_model[get_preds()], best_acc, final_activations
509
508
 
510
509
  progress.update(1)
511
- activations = []
512
510
 
513
- best_activations.append(current_best_activation)
514
- best_acc_per_depth_list.append(best_acc)
511
+ best_acc_per_gen_list.append(best_acc)
515
512
  loss_list.append(best_loss)
516
-
517
- # Check adaptive strategy conditions
518
- if adaptive == True and strategy == 'accuracy' and i + 1 >= patience:
519
- check = best_acc_per_depth_list[-patience:]
520
- if all(x == check[0] for x in check):
521
- strategy = 'loss'
522
- adaptive = False
523
- elif adaptive == True and strategy == 'loss' and best_loss <= patience:
524
- strategy = 'accuracy'
525
- adaptive = False
513
+
514
+ weight_pop, act_pop = optimizer(cp.array(weight_pop, dtype=dtype), act_pop, i, cp.array(target_pop, dtype=dtype, copy=False), target_fitness=target_fitness, bar_status=False)
515
+ target_pop = []
526
516
 
527
517
  # Early stopping check
528
518
  if early_stop == True and i > 0:
529
- if best_acc_per_depth_list[i] == best_acc_per_depth_list[i-1]:
519
+ if best_acc_per_gen_list[i] == best_acc_per_gen_list[i-1]:
530
520
  progress.close()
531
521
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
532
- activation_potentiation=final_activations, dtype=dtype)
522
+ activation_potentiation=final_activations, dtype=dtype, memory=memory)
533
523
 
534
524
  if loss == 'categorical_crossentropy':
535
525
  train_loss = categorical_crossentropy(y_true_batch=y_train,
@@ -553,7 +543,7 @@ def learner(x_train, y_train, x_test=None, y_test=None, strategy='accuracy', bat
553
543
  # Final evaluation
554
544
  progress.close()
555
545
  train_model = evaluate(x_train, y_train, W=best_weights, loading_bar_status=False,
556
- activation_potentiation=final_activations, dtype=dtype)
546
+ activation_potentiation=final_activations, dtype=dtype, memory=memory)
557
547
 
558
548
  if loss == 'categorical_crossentropy':
559
549
  train_loss = categorical_crossentropy(y_true_batch=y_train, y_pred_batch=train_model[get_preds_softmax()])
@@ -652,7 +642,6 @@ def evaluate(
652
642
  Returns:
653
643
  tuple: Model (list).
654
644
  """
655
- from memory_operations import transfer_to_cpu, transfer_to_gpu
656
645
 
657
646
  if memory == 'gpu':
658
647
  x_test = transfer_to_gpu(x_test, dtype=dtype)
pyerualjetwork/planeat.py CHANGED
@@ -17,7 +17,7 @@ from tqdm import tqdm
17
17
  ### LIBRARY IMPORTS ###
18
18
  from .plan import feed_forward
19
19
  from .data_operations import normalization
20
- from .ui import loading_bars
20
+ from .ui import loading_bars, initialize_loading_bar
21
21
  from .activation_functions import apply_activation, all_activations
22
22
 
23
23
  def define_genomes(input_shape, output_shape, population_size, dtype=np.float32):
@@ -66,10 +66,10 @@ def define_genomes(input_shape, output_shape, population_size, dtype=np.float32)
66
66
  population_weights[i][j,:] = apply_activation(population_weights[i][j,:], population_activations[i])
67
67
  population_weights[i][j,:] = normalization(population_weights[i][j,:], dtype=dtype)
68
68
 
69
- return np.array(population_weights), population_activations
69
+ return np.array(population_weights, dtype=dtype), population_activations
70
70
 
71
71
 
72
- def evolve(weights, activation_potentiations, what_gen, y_reward, show_info=False, strategy='cross_over', policy='normal_selective', mutations=True, bad_genoms_mutation_prob=None, activation_mutate_prob=0.5, save_best_genom=True, cross_over_mode='tpm', activation_add_prob=0.5, activation_delete_prob=0.5, activation_change_prob=0.5, weight_mutate_prob=1, weight_mutate_rate=32, activation_selection_add_prob=0.5, activation_selection_change_prob=0.5, activation_selection_rate=2, dtype=np.float32):
72
+ def evolve(weights, activation_potentiations, what_gen, fitness, show_info=False, strategy='cross_over', bar_status=True, policy='normal_selective', target_fitness='max', mutations=True, bad_genoms_mutation_prob=None, activation_mutate_prob=0.5, save_best_genom=True, cross_over_mode='tpm', activation_add_prob=0.5, activation_delete_prob=0.5, activation_change_prob=0.5, weight_mutate_prob=1, weight_mutate_rate=32, activation_selection_add_prob=0.7, activation_selection_change_prob=0.5, activation_selection_rate=2, dtype=np.float32):
73
73
  """
74
74
  Applies the evolving process of a population of genomes using selection, crossover, mutation, and activation function potentiation.
75
75
  The function modifies the population's weights and activation functions based on a specified policy, mutation probabilities, and strategy.
@@ -83,8 +83,8 @@ Args:
83
83
 
84
84
  what_gen (int): The current generation number, used for informational purposes or logging.
85
85
 
86
- y_reward (numpy.ndarray): A 1D array containing the fitness or reward values of each genome.
87
- The array is used to rank the genomes based on their performance. PLANEAT maximizes the reward.
86
+ fitness (numpy.ndarray): A 1D array containing the fitness values of each genome.
87
+ The array is used to rank the genomes based on their performance. PLANEAT maximizes or minimizes this fitness for looking 'target' hyperparameter.
88
88
 
89
89
  show_info (bool, optional): If True, prints information about the current generation and the
90
90
  maximum reward obtained. Also shows the current configuration. Default is False.
@@ -96,12 +96,16 @@ Args:
96
96
  (PLAN feature, similar to arithmetic crossover but different.)
97
97
  Default is 'cross_over'.
98
98
 
99
+ bar_status (bool, optional): Loading bar status during evolving process of genomes. True or False. Default: True
100
+
99
101
  policy (str, optional): The selection policy that governs how genomes are selected for reproduction. Options:
100
102
  - 'normal_selective': Normal selection based on reward, where a portion of the bad genes are discarded.
101
103
  - 'more_selective': A more selective policy, where fewer bad genes survive.
102
104
  - 'less_selective': A less selective policy, where more bad genes survive.
103
105
  Default is 'normal_selective'.
104
106
 
107
+ target_fitness (str, optional): Target fitness strategy for PLANEAT optimization. ('max' for machine learning, 'min' for machine unlearning.) Default: 'max'
108
+
105
109
  mutations (bool, optional): If True, mutations are applied to the bad genomes and potentially
106
110
  to the best genomes as well. Default is True.
107
111
 
@@ -139,7 +143,7 @@ Args:
139
143
  WARNING: if you don't understand do NOT change this value. Default is 32.
140
144
 
141
145
  activation_selection_add_prob (float, optional): The probability of adding an existing activation function for cross over.
142
- from the genome. Must be in the range [0, 1]. Default is 0.5.
146
+ from the genome. Must be in the range [0, 1]. Default is 0.7. (WARNING! More higher values make models more complex. For fast training rise this value.)
143
147
 
144
148
  activation_selection_change_prob (float, optional): The probability of changing an activation function in the genome for cross over.
145
149
  Must be in the range [0, 1]. Default is 0.5.
@@ -163,7 +167,7 @@ Returns:
163
167
 
164
168
  Notes:
165
169
  - **Selection Process**:
166
- - The genomes are sorted by their fitness (based on `y_reward`), and then split into "best" and "bad" halves.
170
+ - The genomes are sorted by their fitness (based on `fitness`), and then split into "best" and "bad" halves.
167
171
  - The best genomes are retained, and the bad genomes are modified based on the selected strategy.
168
172
 
169
173
  - **Crossover and Potentiation Strategies**:
@@ -175,13 +179,13 @@ Notes:
175
179
  - `bad_genoms_mutation_prob` determines the probability of applying mutations to the bad genomes.
176
180
  - If `activation_mutate_prob` is provided, activation function mutations are applied to the genomes based on this probability.
177
181
 
178
- - **Population Size**: The population size must be an even number to properly split the best and bad genomes. If `y_reward` has an odd length, an error is raised.
182
+ - **Population Size**: The population size must be an even number to properly split the best and bad genomes. If `fitness` has an odd length, an error is raised.
179
183
 
180
184
  - **Logging**: If `show_info=True`, the current generation and the maximum reward from the population are printed for tracking the learning progress.
181
185
 
182
186
  Example:
183
187
  ```python
184
- weights, activation_potentiations = learner(weights, activation_potentiations, 1, y_reward, info=True, strategy='cross_over', policy='normal_selective')
188
+ weights, activation_potentiations = planeat.evolve(weights, activation_potentiations, 1, fitness, show_info=True, strategy='cross_over', policy='normal_selective')
185
189
  ```
186
190
 
187
191
  - The function returns the updated weights and activations after processing based on the chosen strategy, policy, and mutation parameters.
@@ -219,17 +223,19 @@ Example:
219
223
  if not isinstance(activation_mutate_prob, float) or activation_mutate_prob < 0 or activation_mutate_prob > 1:
220
224
  raise ValueError("activation_mutate_prob parameter must be float and 0-1 range")
221
225
 
222
- if len(y_reward) % 2 == 0:
223
- slice_center = int(len(y_reward) / 2)
226
+ if len(fitness) % 2 == 0:
227
+ slice_center = int(len(fitness) / 2)
224
228
 
225
229
  else:
226
230
  raise ValueError("genome population size must be even number. for example: not 99, make 100 or 98.")
227
231
 
228
- sort_indices = np.argsort(y_reward)
232
+
233
+ ### FITNESS IS SORTED IN ASCENDING (OR DESCENDING) ORDER, AND THE WEIGHT AND ACTIVATIONS OF EACH GENOME ARE SORTED ACCORDING TO THIS ORDER:
229
234
 
230
- ### REWARD LIST IS SORTED IN ASCENDING ORDER, AND THE WEIGHT AND ACTIVATIONS OF EACH GENOME ARE SORTED ACCORDING TO THIS ORDER:
235
+ if target_fitness == 'max': sort_indices = np.argsort(fitness)
236
+ elif target_fitness == 'min': sort_indices = np.argsort(-fitness)
231
237
 
232
- y_reward = y_reward[sort_indices]
238
+ fitness = fitness[sort_indices]
233
239
  weights = weights[sort_indices]
234
240
 
235
241
  activation_potentiations = [activation_potentiations[i] for i in sort_indices]
@@ -249,7 +255,9 @@ Example:
249
255
 
250
256
  bar_format = loading_bars()[0]
251
257
 
252
- for i in tqdm(range(len(bad_weights)), desc="GENERATION: " + str(what_gen), bar_format=bar_format, ncols=50, ascii="▱▰"):
258
+ if bar_status: progress = initialize_loading_bar(len(bad_weights), desc="GENERATION: " + str(what_gen), bar_format=bar_format, ncols=50, ascii="▱▰")
259
+
260
+ for i in range(len(bad_weights)):
253
261
 
254
262
  if policy == 'normal_selective':
255
263
 
@@ -313,7 +321,8 @@ Example:
313
321
 
314
322
  elif mutation_prob < bad_genoms_mutation_prob:
315
323
  bad_weights[i], bad_activations[i] = mutation(bad_weights[i], bad_activations[i], activation_mutate_prob=activation_mutate_prob, activation_add_prob=activation_add_prob, activation_delete_prob=activation_delete_prob, activation_change_prob=activation_change_prob, weight_mutate_prob=weight_mutate_prob, threshold=weight_mutate_rate, dtype=dtype)
316
-
324
+
325
+ if bar_status: progress.update(1)
317
326
 
318
327
  weights = np.vstack((bad_weights, best_weights))
319
328
  activation_potentiations = bad_activations + best_activations
@@ -344,9 +353,9 @@ Example:
344
353
  print(" ACTIVATION SELECTION RATE (THRESHOLD VALUE FOR SINGLE CROSS OVER):", str(activation_selection_rate) + '\n')
345
354
 
346
355
  print("*** Performance ***")
347
- print(" MAX REWARD: ", str(round(max(y_reward), 2)))
348
- print(" MEAN REWARD: ", str(round(np.mean(y_reward), 2)))
349
- print(" MIN REWARD: ", str(round(min(y_reward), 2)) + '\n')
356
+ print(" MAX FITNESS: ", str(round(max(fitness), 2)))
357
+ print(" MEAN FITNESS: ", str(round(np.mean(fitness), 2)))
358
+ print(" MIN FITNESS: ", str(round(min(fitness), 2)) + '\n')
350
359
 
351
360
  print(" BEST GENOME INDEX: ", str(len(weights)-1))
352
361
  print(" NOTE: Genomes are always sorted from the least successful to the most successful according to their performance ranking. Therefore, the genome at the last index is the king of the previous generation. " + '\n')