aisp 0.2.1__py3-none-any.whl → 0.3.1__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.
@@ -0,0 +1,239 @@
1
+ """Negative Selection Algorithm."""
2
+
3
+ from __future__ import annotations
4
+ from typing import Dict, Literal, Optional, Union
5
+ from tqdm import tqdm
6
+
7
+ import numpy as np
8
+ import numpy.typing as npt
9
+
10
+ from ._ns_core import (
11
+ check_detector_bnsa_validity,
12
+ bnsa_class_prediction
13
+ )
14
+ from ..exceptions import MaxDiscardsReachedError
15
+ from ..utils.sanitizers import sanitize_seed, sanitize_param
16
+ from ._base import BaseNSA
17
+
18
+
19
+ class BNSA(BaseNSA):
20
+ """BNSA (Binary Negative Selection Algorithm).
21
+
22
+ Class is for classification and identification purposes of anomalies through the self and not
23
+ self method.
24
+
25
+ Parameters
26
+ ----------
27
+ N : int, default=100
28
+ Number of detectors.
29
+ aff_thresh : float, default=0.1
30
+ The variable represents the percentage of similarity between the T cell and the own
31
+ samples. The default value is 10% (0.1), while a value of 1.0 represents 100% similarity.
32
+ max_discards : int, default=1000
33
+ This parameter indicates the maximum number of detector discards in sequence, which aims
34
+ to avoid a possible infinite loop if a radius is defined that it is not possible to
35
+ generate non-self detectors.
36
+ seed : Optional[int], default=None
37
+ Seed for the random generation of values in the detectors.
38
+ no_label_sample_selection : str, default="max_average_difference"
39
+ Method for selecting labels for samples designated as non-self by all detectors.
40
+ Available method types:
41
+
42
+ - max_average_difference - Selects the class with the highest average difference among the
43
+ detectors.
44
+
45
+ - max_nearest_difference - Selects the class with the highest difference between the
46
+ nearest and farthest detector from the sample.
47
+ """
48
+
49
+ def __init__(
50
+ self,
51
+ N: int = 100,
52
+ aff_thresh: float = 0.1,
53
+ max_discards: int = 1000,
54
+ seed: Optional[int] = None,
55
+ no_label_sample_selection: Literal[
56
+ "max_average_difference", "max_nearest_difference"
57
+ ] = "max_average_difference",
58
+ ):
59
+ self.N: int = sanitize_param(N, 100, lambda x: x > 0)
60
+ self.aff_thresh: float = sanitize_param(aff_thresh, 0.1, lambda x: 0 < x < 1)
61
+ self.max_discards: float = sanitize_param(max_discards, 1000, lambda x: x > 0)
62
+
63
+ self.seed: Optional[int] = sanitize_seed(seed)
64
+
65
+ if self.seed is not None:
66
+ np.random.seed(seed)
67
+
68
+ self.no_label_sample_selection: str = sanitize_param(
69
+ no_label_sample_selection,
70
+ "max_average_difference",
71
+ lambda x: x == "nearest_difference",
72
+ )
73
+
74
+ self.classes: Union[npt.NDArray, list] = []
75
+ self._detectors: Optional[dict] = None
76
+ self._detectors_stack: Optional[npt.NDArray] = None
77
+
78
+ @property
79
+ def detectors(self) -> Optional[Dict[str, npt.NDArray[np.bool_]]]:
80
+ """Returns the trained detectors, organized by class."""
81
+ return self._detectors
82
+
83
+ def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True) -> BNSA:
84
+ """Training according to X and y, using the method negative selection method.
85
+
86
+ Parameters
87
+ ----------
88
+ X : npt.NDArray
89
+ Training array, containing the samples and their characteristics, [``N samples`` (
90
+ rows)][``N features`` (columns)].
91
+ y : npt.NDArray
92
+ Array of target classes of ``X`` with [``N samples`` (lines)].
93
+ verbose : bool, default=True
94
+ Feedback from detector generation to the user.
95
+
96
+ Returns
97
+ -------
98
+ self : BNSA
99
+ Returns the instance it self.
100
+ """
101
+ super()._check_and_raise_exceptions_fit(X, y, "BNSA")
102
+ # Converts the entire array X to boolean
103
+ X = X.astype(np.bool_)
104
+
105
+ # Identifying the possible classes within the output array `y`.
106
+ self.classes = np.unique(y)
107
+ # Dictionary that will store detectors with classes as keys.
108
+ list_detectors_by_class = {}
109
+ # Separates the classes for training.
110
+ sample_index: dict = self._slice_index_list_by_class(y)
111
+ # Progress bar for generating all detectors.
112
+
113
+ progress = tqdm(
114
+ total=int(self.N * (len(self.classes))),
115
+ bar_format="{desc} ┇{bar}┇ {n}/{total} detectors",
116
+ postfix="\n",
117
+ disable=not verbose
118
+ )
119
+
120
+ for _class_ in self.classes:
121
+ # Initializes the empty set that will contain the valid detectors.
122
+ valid_detectors_set: list = []
123
+ discard_count: int = 0
124
+ # Updating the progress bar with the current class the algorithm is processing.
125
+ progress.set_description_str(
126
+ f"Generating the detectors for the {_class_} class:"
127
+ )
128
+ x_class = X[sample_index[_class_]]
129
+ while len(valid_detectors_set) < self.N:
130
+ # Generates a candidate detector vector randomly with values 0 and 1.
131
+ vector_x = np.random.randint(0, 2, size=X.shape[1]).astype(np.bool_)
132
+ # If the detector is valid, add it to the list of valid detectors.
133
+ if check_detector_bnsa_validity(x_class, vector_x, self.aff_thresh):
134
+ discard_count = 0
135
+ valid_detectors_set.append(vector_x)
136
+ progress.update(1)
137
+ else:
138
+ discard_count += 1
139
+ if discard_count == self.max_discards:
140
+ raise MaxDiscardsReachedError(_class_)
141
+
142
+ # Add detectors to the dictionary with classes as keys.
143
+ list_detectors_by_class[_class_] = np.array(valid_detectors_set)
144
+
145
+ # Notify the completion of detector generation for the classes.
146
+ progress.set_description(
147
+ f"\033[92m✔ Non-self detectors for classes ({', '.join(map(str, self.classes))}) "
148
+ f"successfully generated\033[0m"
149
+ )
150
+ progress.close()
151
+ # Saves the found detectors in the attribute for the class detectors.
152
+ self._detectors = list_detectors_by_class
153
+ self._detectors_stack = np.array(
154
+ [np.stack(self._detectors[class_name]) for class_name in self.classes]
155
+ )
156
+ return self
157
+
158
+ def predict(self, X: npt.NDArray) -> Optional[npt.NDArray]:
159
+ """Prediction of classes based on detectors created after training.
160
+
161
+ Parameters
162
+ ----------
163
+ X : npt.NDArray
164
+ Array with input samples with [``N_samples`` (Lines)] and [``N_characteristics``(
165
+ Columns)]
166
+
167
+ Returns
168
+ -------
169
+ c : Optional[npt.NDArray]
170
+ an ndarray of the form ``C`` [``N samples``], containing the predicted classes for
171
+ ``X``. Returns``None``: If there are no detectors for the prediction.
172
+ """
173
+ # If there are no detectors, Returns None.
174
+ if self._detectors is None or self._detectors_stack is None:
175
+ return None
176
+
177
+ super()._check_and_raise_exceptions_predict(
178
+ X, len(self._detectors[self.classes[0]][0]), "BNSA"
179
+ )
180
+
181
+ # Converts the entire array X to boolean.
182
+ if X.dtype != bool:
183
+ X = X.astype(bool)
184
+
185
+ # Initializes an empty array that will store the predictions.
186
+ c = []
187
+ # For each sample row in X.
188
+ for line in X:
189
+ class_found: bool = True
190
+ # Class prediction based on detectors
191
+ class_index = bnsa_class_prediction(
192
+ line, self._detectors_stack, self.aff_thresh
193
+ )
194
+ # If belonging to one or more classes, adds the class with the greatest
195
+ # average distance
196
+ if class_index > -1:
197
+ c.append(self.classes[class_index])
198
+ class_found = True
199
+ else:
200
+ class_found = False
201
+
202
+ # If there is only one class and the sample is not classified, sets the
203
+ # output as non-self.
204
+ if not class_found and len(self.classes) == 1:
205
+ c.append("non-self")
206
+ # If the class cannot be identified by the detectors
207
+ elif not class_found:
208
+ self.__assign_class_to_non_self_sample(line, c)
209
+
210
+ return np.array(c)
211
+
212
+ def __assign_class_to_non_self_sample(self, line: npt.NDArray, c: list):
213
+ """Determine the class of a sample when all detectors classify it as "non-self".
214
+
215
+ Classification is performed using the ``max_average_difference`` and
216
+ ``max_nearest_difference`` methods.
217
+
218
+ Parameters
219
+ ----------
220
+ line : npt.NDArray
221
+ Sample to be classified.
222
+ c : list
223
+ List of predictions to be updated with the new classification.
224
+ """
225
+ if self._detectors is None:
226
+ raise ValueError("Detectors is not initialized.")
227
+
228
+ class_differences: dict = {}
229
+ for _class_ in self.classes:
230
+ distances = np.sum(line != self._detectors[_class_]) / self.N
231
+ # Assign the label to the class with the greatest distance from
232
+ # the nearest detector.
233
+ if self.no_label_sample_selection == "nearest_difference":
234
+ class_differences[_class_] = distances.min()
235
+ # Or based on the greatest distance from the average distances of the detectors.
236
+ else:
237
+ class_differences[_class_] = distances.sum() / self.N
238
+
239
+ c.append(max(class_differences, key=class_differences.get))
@@ -1,16 +1,14 @@
1
1
  """Negative Selection Algorithm."""
2
2
 
3
+ from __future__ import annotations
3
4
  from typing import Any, Dict, Literal, Optional, Union
4
5
  from tqdm import tqdm
5
6
 
6
7
  import numpy as np
7
8
  import numpy.typing as npt
8
9
 
9
- from ._ns_core import (
10
- check_detector_bnsa_validity,
11
- bnsa_class_prediction,
12
- check_detector_rnsa_validity,
13
- )
10
+ from ..base import set_seed_numba
11
+ from ._ns_core import check_detector_rnsa_validity
14
12
  from ..exceptions import MaxDiscardsReachedError
15
13
  from ..utils.distance import (
16
14
  min_distance_to_class_vectors,
@@ -98,6 +96,7 @@ class RNSA(BaseNSA):
98
96
  self.seed: Optional[int] = sanitize_seed(seed)
99
97
  if self.seed is not None:
100
98
  np.random.seed(seed)
99
+ set_seed_numba(self.seed)
101
100
  self.k: int = sanitize_param(k, 1, lambda x: x > 1)
102
101
  self.N: int = sanitize_param(N, 100, lambda x: x >= 1)
103
102
  self.r: float = sanitize_param(r, 0.05, lambda x: x > 0)
@@ -121,7 +120,7 @@ class RNSA(BaseNSA):
121
120
  """Returns the trained detectors, organized by class."""
122
121
  return self._detectors
123
122
 
124
- def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True) -> "RNSA":
123
+ def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True) -> RNSA:
125
124
  """
126
125
  Perform training according to X and y, using the negative selection method (NegativeSelect).
127
126
 
@@ -148,7 +147,6 @@ class RNSA(BaseNSA):
148
147
  self : RNSA
149
148
  Returns the instance itself.
150
149
  """
151
- progress = None
152
150
  super()._check_and_raise_exceptions_fit(X, y)
153
151
 
154
152
  # Identifying the possible classes within the output array `y`.
@@ -158,22 +156,21 @@ class RNSA(BaseNSA):
158
156
  # Separates the classes for training.
159
157
  sample_index = self._slice_index_list_by_class(y)
160
158
  # Progress bar for generating all detectors.
161
- if verbose:
162
- progress = tqdm(
163
- total=int(self.N * (len(self.classes))),
164
- bar_format="{desc} ┇{bar}┇ {n}/{total} detectors",
165
- postfix="\n",
166
- )
159
+ progress = tqdm(
160
+ total=int(self.N * (len(self.classes))),
161
+ bar_format="{desc} ┇{bar}┇ {n}/{total} detectors",
162
+ postfix="\n",
163
+ disable=not verbose
164
+ )
167
165
  for _class_ in self.classes:
168
166
  # Initializes the empty set that will contain the valid detectors.
169
167
  valid_detectors_set = []
170
168
  discard_count = 0
171
169
  x_class = X[sample_index[_class_]]
172
170
  # Indicating which class the algorithm is currently processing for the progress bar.
173
- if verbose and progress is not None:
174
- progress.set_description_str(
175
- f"Generating the detectors for the {_class_} class:"
176
- )
171
+ progress.set_description_str(
172
+ f"Generating the detectors for the {_class_} class:"
173
+ )
177
174
  while len(valid_detectors_set) < self.N:
178
175
  # Generates a candidate detector vector randomly with values between 0 and 1.
179
176
  vector_x = np.random.random_sample(size=X.shape[1])
@@ -188,8 +185,7 @@ class RNSA(BaseNSA):
188
185
  else:
189
186
  radius = None
190
187
  valid_detectors_set.append(Detector(vector_x, radius))
191
- if verbose and progress is not None:
192
- progress.update(1)
188
+ progress.update(1)
193
189
  else:
194
190
  discard_count += 1
195
191
  if discard_count == self.max_discards:
@@ -198,11 +194,11 @@ class RNSA(BaseNSA):
198
194
  # Add detectors, with classes as keys in the dictionary.
199
195
  list_detectors_by_class[_class_] = valid_detectors_set
200
196
  # Notify completion of detector generation for the classes.
201
- if verbose and progress is not None:
202
- progress.set_description(
203
- f"\033[92m✔ Non-self detectors for classes ({', '.join(map(str, self.classes))}) "
204
- f"successfully generated\033[0m"
205
- )
197
+ progress.set_description(
198
+ f"\033[92m✔ Non-self detectors for classes ({', '.join(map(str, self.classes))}) "
199
+ f"successfully generated\033[0m"
200
+ )
201
+ progress.close()
206
202
  # Saves the found detectors in the attribute for the non-self detectors of the trained model
207
203
  self._detectors = list_detectors_by_class
208
204
  return self
@@ -340,14 +336,12 @@ class RNSA(BaseNSA):
340
336
  if len(knn) < self.k:
341
337
  knn.append(distance)
342
338
  knn.sort()
343
-
344
339
  # Otherwise, add the distance if the new distance is smaller than the largest
345
340
  # distance in the list.
346
- if knn[self.k - 1] > distance:
341
+ elif knn[self.k - 1] > distance:
347
342
  knn[self.k - 1] = distance
348
343
  knn.sort()
349
344
 
350
-
351
345
  def __compare_sample_to_detectors(self, line: npt.NDArray) -> Optional[str]:
352
346
  """
353
347
  Compare a sample with the detectors, verifying if the sample is proper.
@@ -448,229 +442,4 @@ class RNSA(BaseNSA):
448
442
  if (p - new_detector_r) < 0 or (p + new_detector_r) > 1:
449
443
  return False
450
444
 
451
- return (True, new_detector_r)
452
-
453
-
454
- class BNSA(BaseNSA):
455
- """BNSA (Binary Negative Selection Algorithm).
456
-
457
- Class is for classification and identification purposes of anomalies through the self and not
458
- self method.
459
-
460
- Parameters
461
- ----------
462
- N : int, default=100
463
- Number of detectors.
464
- aff_thresh : float, default=0.1
465
- The variable represents the percentage of similarity between the T cell and the own
466
- samples. The default value is 10% (0.1), while a value of 1.0 represents 100% similarity.
467
- max_discards : int, default=1000
468
- This parameter indicates the maximum number of detector discards in sequence, which aims
469
- to avoid a possible infinite loop if a radius is defined that it is not possible to
470
- generate non-self detectors.
471
- seed : Optional[int], default=None
472
- Seed for the random generation of values in the detectors.
473
- no_label_sample_selection : str, default="max_average_difference"
474
- Method for selecting labels for samples designated as non-self by all detectors.
475
- Available method types:
476
-
477
- - max_average_difference - Selects the class with the highest average difference among the
478
- detectors.
479
-
480
- - max_nearest_difference - Selects the class with the highest difference between the
481
- nearest and farthest detector from the sample.
482
- """
483
-
484
- def __init__(
485
- self,
486
- N: int = 100,
487
- aff_thresh: float = 0.1,
488
- max_discards: int = 1000,
489
- seed: Optional[int] = None,
490
- no_label_sample_selection: Literal[
491
- "max_average_difference", "max_nearest_difference"
492
- ] = "max_average_difference",
493
- ):
494
- self.N: int = sanitize_param(N, 100, lambda x: x > 0)
495
- self.aff_thresh: float = sanitize_param(aff_thresh, 0.1, lambda x: 0 < x < 1)
496
- self.max_discards: float = sanitize_param(max_discards, 1000, lambda x: x > 0)
497
-
498
- self.seed: Optional[int] = sanitize_seed(seed)
499
-
500
- if self.seed is not None:
501
- np.random.seed(seed)
502
-
503
- self.no_label_sample_selection: str = sanitize_param(
504
- no_label_sample_selection,
505
- "max_average_difference",
506
- lambda x: x == "nearest_difference",
507
- )
508
-
509
- self.classes: Union[npt.NDArray, list] = []
510
- self._detectors: Optional[dict] = None
511
- self._detectors_stack: Optional[npt.NDArray] = None
512
-
513
- @property
514
- def detectors(self) -> Optional[Dict[str, npt.NDArray[np.bool_]]]:
515
- """Returns the trained detectors, organized by class."""
516
- return self._detectors
517
-
518
- def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True) -> "BNSA":
519
- """Training according to X and y, using the method negative selection method.
520
-
521
- Parameters
522
- ----------
523
- X : npt.NDArray
524
- Training array, containing the samples and their characteristics, [``N samples`` (
525
- rows)][``N features`` (columns)].
526
- y : npt.NDArray
527
- Array of target classes of ``X`` with [``N samples`` (lines)].
528
- verbose : bool, default=True
529
- Feedback from detector generation to the user.
530
-
531
- Returns
532
- -------
533
- self : BNSA
534
- Returns the instance it self.
535
- """
536
- super()._check_and_raise_exceptions_fit(X, y, "BNSA")
537
- progress = None
538
- # Converts the entire array X to boolean
539
- X = X.astype(np.bool_)
540
-
541
- # Identifying the possible classes within the output array `y`.
542
- self.classes = np.unique(y)
543
- # Dictionary that will store detectors with classes as keys.
544
- list_detectors_by_class = {}
545
- # Separates the classes for training.
546
- sample_index: dict = self._slice_index_list_by_class(y)
547
- # Progress bar for generating all detectors.
548
- if verbose:
549
- progress = tqdm(
550
- total=int(self.N * (len(self.classes))),
551
- bar_format="{desc} ┇{bar}┇ {n}/{total} detectors",
552
- postfix="\n",
553
- )
554
-
555
- for _class_ in self.classes:
556
- # Initializes the empty set that will contain the valid detectors.
557
- valid_detectors_set: list = []
558
- discard_count: int = 0
559
- # Updating the progress bar with the current class the algorithm is processing.
560
- if verbose and progress is not None:
561
- progress.set_description_str(
562
- f"Generating the detectors for the {_class_} class:"
563
- )
564
- x_class = X[sample_index[_class_]]
565
- while len(valid_detectors_set) < self.N:
566
- # Generates a candidate detector vector randomly with values 0 and 1.
567
- vector_x = np.random.randint(0, 2, size=X.shape[1]).astype(np.bool_)
568
- # If the detector is valid, add it to the list of valid detectors.
569
- if check_detector_bnsa_validity(x_class, vector_x, self.aff_thresh):
570
- discard_count = 0
571
- valid_detectors_set.append(vector_x)
572
- if verbose and progress is not None:
573
- progress.update(1)
574
- else:
575
- discard_count += 1
576
- if discard_count == self.max_discards:
577
- raise MaxDiscardsReachedError(_class_)
578
-
579
- # Add detectors to the dictionary with classes as keys.
580
- list_detectors_by_class[_class_] = np.array(valid_detectors_set)
581
-
582
- # Notify the completion of detector generation for the classes.
583
- if verbose and progress is not None:
584
- progress.set_description(
585
- f"\033[92m✔ Non-self detectors for classes ({', '.join(map(str, self.classes))}) "
586
- f"successfully generated\033[0m"
587
- )
588
- # Saves the found detectors in the attribute for the class detectors.
589
- self._detectors = list_detectors_by_class
590
- self._detectors_stack = np.array(
591
- [np.stack(self._detectors[class_name]) for class_name in self.classes]
592
- )
593
- return self
594
-
595
- def predict(self, X: npt.NDArray) -> Optional[npt.NDArray]:
596
- """Prediction of classes based on detectors created after training.
597
-
598
- Parameters
599
- ----------
600
- X : npt.NDArray
601
- Array with input samples with [``N_samples`` (Lines)] and [``N_characteristics``(
602
- Columns)]
603
-
604
- Returns
605
- -------
606
- c : Optional[npt.NDArray]
607
- an ndarray of the form ``C`` [``N samples``], containing the predicted classes for
608
- ``X``. Returns``None``: If there are no detectors for the prediction.
609
- """
610
- # If there are no detectors, Returns None.
611
- if self._detectors is None or self._detectors_stack is None:
612
- return None
613
-
614
- super()._check_and_raise_exceptions_predict(
615
- X, len(self._detectors[self.classes[0]][0]), "BNSA"
616
- )
617
-
618
- # Converts the entire array X to boolean.
619
- if X.dtype != bool:
620
- X = X.astype(bool)
621
-
622
- # Initializes an empty array that will store the predictions.
623
- c = []
624
- # For each sample row in X.
625
- for line in X:
626
- class_found: bool = True
627
- # Class prediction based on detectors
628
- class_index = bnsa_class_prediction(
629
- line, self._detectors_stack, self.aff_thresh
630
- )
631
- # If belonging to one or more classes, adds the class with the greatest
632
- # average distance
633
- if class_index > -1:
634
- c.append(self.classes[class_index])
635
- class_found = True
636
- else:
637
- class_found = False
638
-
639
- # If there is only one class and the sample is not classified, sets the
640
- # output as non-self.
641
- if not class_found and len(self.classes) == 1:
642
- c.append("non-self")
643
- # If the class cannot be identified by the detectors
644
- elif not class_found:
645
- self.__assign_class_to_non_self_sample(line, c)
646
-
647
- return np.array(c)
648
-
649
- def __assign_class_to_non_self_sample(self, line: npt.NDArray, c: list):
650
- """Determine the class of a sample when all detectors classify it as "non-self".
651
-
652
- Classification is performed using the ``max_average_difference`` and
653
- ``max_nearest_difference`` methods.
654
-
655
- Parameters
656
- ----------
657
- line : npt.NDArray
658
- Sample to be classified.
659
- c : list
660
- List of predictions to be updated with the new classification.
661
- """
662
- if self._detectors is None:
663
- raise ValueError("Detectors is not initialized.")
664
-
665
- class_differences: dict = {}
666
- for _class_ in self.classes:
667
- distances = np.sum(line != self._detectors[_class_]) / self.N
668
- # Assign the label to the class with the greatest distance from
669
- # the nearest detector.
670
- if self.no_label_sample_selection == "nearest_difference":
671
- class_differences[_class_] = distances.min()
672
- # Or based on the greatest distance from the average distances of the detectors.
673
- else:
674
- class_differences[_class_] = distances.sum() / self.N
675
-
676
- c.append(max(class_differences, key=class_differences.get))
445
+ return True, new_detector_r
aisp/utils/distance.py CHANGED
@@ -5,10 +5,10 @@ import numpy.typing as npt
5
5
  from numba import njit, types
6
6
  from numpy import float64
7
7
 
8
- EUCLIDEAN = 0
9
- MANHATTAN = 1
10
- MINKOWSKI = 2
11
- HAMMING = 3
8
+ EUCLIDEAN: int = 0
9
+ MANHATTAN: int = 1
10
+ MINKOWSKI: int = 2
11
+ HAMMING: int = 3
12
12
 
13
13
 
14
14
  @njit([(types.boolean[:], types.boolean[:])], cache=True)
aisp/utils/validation.py CHANGED
@@ -14,9 +14,9 @@ def detect_vector_data_type(
14
14
  Detect the type of data in a vector.
15
15
 
16
16
  The function detects if the vector contains data of type:
17
- - "binary": binary data (boolean True/False or integer 0/1)
18
- - "continuous": continuous data between 0.0 and 1.0 (float)
19
- - "ranged": numerical data with values outside the normalized range (float)
17
+ - Binary features: boolean values or integers restricted to 0 and 1.
18
+ - Continuous features: floating-point values in the normalized range [0.0, 1.0].
19
+ - Ranged features: floating-point values outside the normalized range.
20
20
 
21
21
  Parameters
22
22
  ----------
@@ -25,8 +25,8 @@ def detect_vector_data_type(
25
25
 
26
26
  Returns
27
27
  -------
28
- Literal["binary-features", "continuous-features", "ranged-features"]
29
- The classified data type of the vector.
28
+ str
29
+ The data type of the vector: "binary-features", "continuous-features", or "ranged-features".
30
30
 
31
31
  Raises
32
32
  ------
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aisp
3
- Version: 0.2.1
3
+ Version: 0.3.1
4
4
  Summary: Package with techniques of artificial immune systems.
5
5
  Author-email: João Paulo da Silva Barros <jpsilvabarr@gmail.com>
6
6
  Maintainer-email: Alison Zille Lopes <alisonzille@gmail.com>
@@ -84,10 +84,11 @@ Artificial Immune Systems (AIS) are inspired by the vertebrate immune system, cr
84
84
  ##### Algorithms implemented:
85
85
 
86
86
  > - [x] [**Negative Selection.**](https://ais-package.github.io/docs/aisp-techniques/Negative%20Selection/)
87
- > - [x] **Clonal Selection Algorithms.**
88
- > * [AIRS - Artificial Immune Recognition System](https://ais-package.github.io/docs/aisp-techniques/Clonal%20Selection%20Algorithms/)
89
- > - [ ] *Dendritic Cells.*
90
- > - [ ] *Immune Network Theory.*
87
+ > - [x] [**Clonal Selection Algorithms.**](https://ais-package.github.io/docs/aisp-techniques/Clonal%20Selection%20Algorithms/)
88
+ > * [AIRS - Artificial Immune Recognition System](https://ais-package.github.io/docs/aisp-techniques/Clonal%20Selection%20Algorithms/airs/)
89
+ > - [ ] *Danger Theory.*
90
+ > - [x] [*Immune Network Theory.*](https://ais-package.github.io/docs/aisp-techniques/Immune%20Network%20Theory)
91
+ > - [AiNet - Artificial Immune Network para Clustering and Compression](https://ais-package.github.io/docs/aisp-techniques/Immune%20Network%20Theory/ainet)
91
92
 
92
93
  </section>
93
94
 
@@ -0,0 +1,31 @@
1
+ aisp/__init__.py,sha256=Lw5uajT371MeIBBN6FoMYQ5jmznkO0NiM-sZVWDXkCg,708
2
+ aisp/exceptions.py,sha256=I9JaQx6p8Jo7qjwwcrqnuewQgyBdUnOSSZofPoBeDNE,1954
3
+ aisp/base/__init__.py,sha256=cDDN6YcYqSU080AvEankhUtIALkSTVmm6XTa48htHjU,211
4
+ aisp/base/_base.py,sha256=uTVh__hQJGe8RCOzCet4ZV3vQbwgj5fXAt4Jdf0x1r0,1792
5
+ aisp/base/_classifier.py,sha256=kFP58oYJP-Spk-_qI61rg0eS1jPb3Af-xQVwI9TzSnw,3373
6
+ aisp/base/_clusterer.py,sha256=tcaZ9UOuQUHSN0qyj45aiZ1nU3QMVEeZous95JZkqtA,2466
7
+ aisp/base/mutation.py,sha256=A_AlGp8S4ooFEMW3Jgv0n0Y6tbhfusaMMWFsoH4HmD8,4762
8
+ aisp/csa/__init__.py,sha256=708jwpqia10bqmh-4-_srwwNuBh7jf2Zix-u8Hfbzmk,348
9
+ aisp/csa/_ai_recognition_sys.py,sha256=E6i1TsTjpUYnSZUCQbyGjeeaiX6K_ZPR-0HQdWKc0rQ,18871
10
+ aisp/csa/_base.py,sha256=pUObVlUB-ugz2plH29oJJBH_7Ny0611sCI0C5kv4ho4,3593
11
+ aisp/csa/_cell.py,sha256=GUxnzvPyIbBm1YYkMhSx0tcV_oyDhJ7wAo5gtr_1CoY,1845
12
+ aisp/ina/__init__.py,sha256=cOnxGcxrBdg6lLv2w2sdlToMahKMh_Gw57AfUUPQjMo,329
13
+ aisp/ina/_ai_network.py,sha256=-mp6ggEBbb4lHwD3EhHl1giAVbnfNQNARCtr7N_4Nkw,20984
14
+ aisp/ina/_base.py,sha256=x9eFUKiAcXSfwqVyBVmS54FDeIcApEtFPGruZvwQOwQ,4404
15
+ aisp/nsa/__init__.py,sha256=vL_HbASV6aGiiHAMx0UShqkL-ly-OYcqQLasKdu9p-M,425
16
+ aisp/nsa/_base.py,sha256=3YKlZzA3yhP2uQHfhyKswbHUutlxkOR4wn6N10nSO-w,4119
17
+ aisp/nsa/_binary_negative_selection.py,sha256=af5z7jjUhuAdVz4MpNOToaHmtrJQxDgiAciMUZ6dGV4,9750
18
+ aisp/nsa/_negative_selection.py,sha256=5IaXmwUolVR3LaDQuxoBY0D4IMuIx2YrUenPAR02H9s,18792
19
+ aisp/nsa/_ns_core.py,sha256=SXkZL-p2VQygU4Pf6J5AP_yPzU4cR6aU6wx-e_vlm-c,5021
20
+ aisp/utils/__init__.py,sha256=RzpKhkg8nCZi4G0C4il97f3ESYs7Bbxq6EjTeOQQUGk,195
21
+ aisp/utils/_multiclass.py,sha256=nWd58ayVfxgdopBQc9b_xywkolJ2fGW3AN-JoD2A9Fw,1134
22
+ aisp/utils/distance.py,sha256=pY23YGZpu6qVCCkZfhaEpRazUULfVUy2piyzYuAryN0,6576
23
+ aisp/utils/metrics.py,sha256=zDAScDbHRnfu24alRcZ6fEIUaWNoCD-QCtOCFBWPPo8,1277
24
+ aisp/utils/sanitizers.py,sha256=u1GizdJ-RKfPWJLnuFiM09lpItZMhDR_EvK8YdVHwDk,1858
25
+ aisp/utils/types.py,sha256=KELzr1kSBT7hHdsABoIS1xmEBGj6gRSH5A5YNG36I_c,1324
26
+ aisp/utils/validation.py,sha256=RqcS2VdFXkNcOH_7Y3yPi7FBoGWR_ReLBPDBx0UMCqI,1431
27
+ aisp-0.3.1.dist-info/licenses/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
28
+ aisp-0.3.1.dist-info/METADATA,sha256=c4c4Zh31XJxi6SO0OA-4YnmSOTn-MqvZNdyRU4TolKA,5173
29
+ aisp-0.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
30
+ aisp-0.3.1.dist-info/top_level.txt,sha256=Q5aJi_rAVT5UNS1As0ZafoyS5dwNibnoyOYV7RWUB9s,5
31
+ aisp-0.3.1.dist-info/RECORD,,