aisp 0.1.30__py3-none-any.whl → 0.1.32__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,52 +1,57 @@
1
1
  import numpy as np
2
2
  import numpy.typing as npt
3
3
  from tqdm import tqdm
4
- from typing import Dict, Literal, Union
4
+ from typing import Dict, Literal, Optional, Union
5
5
  from collections import namedtuple
6
- from scipy.spatial.distance import hamming
6
+ from scipy.spatial.distance import cdist
7
7
 
8
- from aisp._base import Base
8
+ from ._base import Base
9
9
 
10
10
 
11
11
  class RNSA(Base):
12
12
  """
13
- The ``RNSA`` (Real-Valued Negative Selection Algorithm) class is for classification and identification purposes.
14
- of anomalies through the self and not self method.
13
+ The ``RNSA`` (Real-Valued Negative Selection Algorithm) class is for classification and \
14
+ identification purposes. of anomalies through the self and not self method.
15
15
 
16
16
  Attributes:
17
17
  ---
18
18
  * N (``int``): Number of detectors.
19
19
  * r (``float``): Radius of the detector.
20
20
  * r_s (``float``): rₛ Radius of the ``X`` own samples.
21
- * k (``int``): K number of near neighbors to calculate the average distance of the detectors.
21
+ * k (``int``): K number of near neighbors to calculate the average
22
+ distance of the detectors.
22
23
  * metric (``str``): Way to calculate the distance: ``'euclidean', 'minkowski', or 'manhattan'``.
23
- * max_discards (``int``): This parameter indicates the maximum number of consecutive detector discards,
24
- aimed at preventing a possible infinite loop in case a radius is defined that cannot generate non-self
25
- detectors.
24
+ * max_discards (``int``): This parameter indicates the maximum number of consecutive \
25
+ detector discards, aimed at preventing a possible infinite loop in case a radius is \
26
+ defined that cannot generate non-self detectors.
26
27
  * seed (``int``): Seed for the random generation of detector values.
27
28
  * algorithm(``str``), Set the algorithm version:
28
29
 
29
30
  * ``'default-NSA'``: Default algorithm with fixed radius.
30
- * ``'V-detector'``: This algorithm uses a variable radius for anomaly detection in feature spaces.
31
+ * ``'V-detector'``: This algorithm uses a variable radius for anomaly detection \
32
+ in feature spaces.
31
33
 
32
34
  Defaults to ``'default-NSA'``.
33
35
 
34
- * non_self_label (``str``): This variable stores the label that will be assigned when the data has only one
35
- output class, and the sample is classified as not belonging to that class. Defaults to ``'non-self'``.
36
- * cell_bounds (``bool``): If set to ``True``, this option limits the generation of detectors to the space within
37
- the plane between 0 and 1. This means that any detector whose radius exceeds this limit is discarded,
38
- this variable is only used in the ``V-detector`` algorithm. Defaults to ``False``.
39
- * p (``float``): This parameter stores the value of ``p`` used in the Minkowski distance. The default is ``2``, which
40
- represents normalized Euclidean distance. Different values of p lead to different variants of the Minkowski
41
- distance [learn more](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
42
-
36
+ * non_self_label (``str``): This variable stores the label that will be when the data has \
37
+ only one output class, and the sample is classified as not belonging to that class. \
38
+ Defaults to ``'non-self'``.
39
+ * cell_bounds (``bool``): If set to ``True``, this option limits the generation of \
40
+ detectors to the space within the plane between 0 and 1. This means that any detector \
41
+ whose radius exceeds this limit is discarded, this variable is only used in the \
42
+ ``V-detector`` algorithm. Defaults to ``False``.
43
+ * p (``float``): This parameter stores the value of ``p`` used in the Minkowski distance. \
44
+ The default is ``2``, which represents normalized Euclidean distance. Different values \
45
+ of p lead to different variants of the Minkowski distance \
46
+ [learn more](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
47
+
43
48
  * detectors (``dict``): This variable stores a list of detectors by class.
44
49
  * classes (``npt.NDArray``): list of output classes.
45
-
50
+
46
51
  ---
47
52
 
48
- A classe ``RNSA`` (Algoritmo de Seleção Negativa de Valor Real) tem a finalidade de classificação e identificação
49
- de anomalias através do método self e not self .
53
+ A classe ``RNSA`` (Algoritmo de Seleção Negativa de Valor Real) tem a finalidade de classificação \
54
+ e identificação de anomalias através do método self e not self .
50
55
 
51
56
  Attributes:
52
57
  ---
@@ -55,134 +60,154 @@ class RNSA(Base):
55
60
  * r_s (``float``): O valor de ``rₛ`` é o raio das amostras próprias da matriz ``X``.
56
61
  * k (``int``): K quantidade de vizinhos próximos para calcular a média da distância dos detectores.
57
62
  * metric (``str``): Forma de calcular a distância: ``'euclidiana', 'minkowski', or 'manhattan'``.
58
- * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores em sequência,
59
- que tem como objetivo evitar um possível loop infinito caso seja definido um raio que não seja possível
60
- gerar detectores do não-próprio.
63
+ * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores \
64
+ em sequência, que tem como objetivo evitar um possível loop infinito caso seja definido \
65
+ um raio que não seja possível gerar detectores do não-próprio.
61
66
  * seed (``int``): Semente para a geração randômica dos valores dos detectores.
62
67
  * algorithm (``str``), Definir a versão do algoritmo:
63
68
 
64
69
  * ``'default-NSA'``: Algoritmo padrão com raio fixo.
65
- * ``'V-detector'``: Este algoritmo utiliza um raio variável para a detecção de anomalias em espaços
66
- de características.
70
+ * ``'V-detector'``: Este algoritmo utiliza um raio variável para a detecção de \
71
+ anomalias em espaços de características.
67
72
 
68
73
  Defaults to ``'default-NSA'``.
69
74
 
70
- * non_self_label (``str``): Esta variável armazena o rótulo que será atribuído quando os dados possuírem
71
- apenas uma classe de saída, e a amostra for classificada como não pertencente a essa classe. Defaults to ``'non-self'``.
72
- * cell_bounds (``bool``): Se definido como ``True``, esta opção limita a geração dos detectores ao espaço do plano
73
- compreendido entre 0 e 1. Isso significa que qualquer detector cujo raio ultrapasse esse limite é descartado,
74
- e esta variável é usada exclusivamente no algoritmo ``V-detector``.
75
- * p (``float``): Este parâmetro armazena o valor de ``p`` utilizada na distância de Minkowski. O padrão é ``2``, o que significa
76
- distância euclidiana normalizada. Diferentes valores de p levam a diferentes variantes da distância de
77
- Minkowski [saiba mais](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
78
-
75
+ * non_self_label (``str``): Esta variável armazena o rótulo que será atribuído quando \
76
+ os dados possuírem apenas uma classe de saída, e a amostra for classificada como não \
77
+ pertencente a essa classe. Defaults to ``'non-self'``.
78
+ * cell_bounds (``bool``): Se definido como ``True``, esta opção limita a geração dos \
79
+ detectores ao espaço do plano compreendido entre 0 e 1. Isso significa que qualquer \
80
+ detector cujo raio ultrapasse esse limite é descartado, e esta variável é usada \
81
+ exclusivamente no algoritmo ``V-detector``.
82
+ * p (``float``): Este parâmetro armazena o valor de ``p`` utilizada na distância de \
83
+ Minkowski. O padrão é ``2``, o que significa distância euclidiana normalizada. \
84
+ Diferentes valores de p levam a diferentes variantes da distância de Minkowski \
85
+ [saiba mais](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
86
+
79
87
  * detectors (``dict``): Essa variável armazena uma lista com detectores por classes.
80
88
  * classes (``npt.NDArray``): lista com as classes de saída.
81
89
  """
82
-
83
- def __init__(
84
- self,
85
- N: int = 100,
86
- r: float = 0.05,
87
- r_s: float = 0.0001,
88
- k: int = 1,
89
- metric: Literal['manhattan', 'minkowski', 'euclidean'] = 'euclidean',
90
- max_discards: int = 1000,
91
- seed: int = None,
92
- algorithm: Literal['default-NSA', 'V-detector'] ='default-NSA',
93
- **kwargs: Dict[str, Union[bool, str, float]]
94
- ):
90
+
91
+ def __init__(self, N: int = 100, r: float = 0.05, r_s: float = 0.0001, k: int = 1,
92
+ metric: Literal["manhattan", "minkowski", "euclidean"] = "euclidean", max_discards: int = 1000,
93
+ seed: int = None, algorithm: Literal["default-NSA", "V-detector"] = "default-NSA",
94
+ **kwargs: Dict[str, Union[bool, str, float]]):
95
95
  """
96
96
  Negative Selection class constructor (``RNSA``).
97
97
 
98
98
  Details:
99
99
  ---
100
- This method initializes the ``detectors``, ``classes``, ``k``, ``metric``, ``N``, ``r``, ``r_S``,
101
- ``max_discards``, ``seed`` and ``algorithm`` attributes.
100
+ This method initializes the ``detectors``, ``classes``, ``k``, ``metric``, ``N``, ``r``, \
101
+ ``r_S``, ``max_discards``, ``seed`` and ``algorithm`` attributes.
102
102
 
103
103
  Parameters:
104
104
  ---
105
105
  * N (``int``): Number of detectors. Defaults to ``100``.
106
106
  * r (``float``): Radius of the detector. Defaults to ``0.05``.
107
107
  * r_s (``float``): rₛ Radius of the ``X`` own samples. Defaults to ``0.0001``.
108
- * k (``int``): Number of neighbors near the randomly generated detectors to perform the
109
- distance average calculation. Defaults to ``1``.
108
+ * k (``int``): Number of neighbors near the randomly generated detectors to perform the \
109
+ distance average calculation. Defaults to ``1``.
110
110
  * metric (``str``): Way to calculate the distance between the detector and the sample:
111
111
 
112
- * ``'Euclidean'`` ➜ The calculation of the distance is given by the expression: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
113
- * ``'minkowski'`` ➜ The calculation of the distance is given by the expression: ( |X₁ – Y₁|p + |X₂Y₂|p + ... + |XnYn|p) ¹/ₚ.
114
- * ``'manhattan'`` ➜ The calculation of the distance is given by the expression: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|) .
112
+ * ``'Euclidean'`` ➜ The calculation of the distance is given by the expression: \
113
+ √( (x₁ – x₂)² + (y₁y₂)² + ... + (ynyn)²).
114
+ * ``'minkowski'`` ➜ The calculation of the distance is given by the expression: \
115
+ ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ.
116
+ * ``'manhattan'`` ➜ The calculation of the distance is given by the expression: \
117
+ ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|) .
115
118
 
116
119
  Defaults to ``'euclidean'``.
117
120
 
118
- * max_discards (``int``): This parameter indicates the maximum number of consecutive detector discards, aimed at preventing a
119
- possible infinite loop in case a radius is defined that cannot generate non-self detectors. Defaults to ``1000``.
120
- * seed (``int``): Seed for the random generation of values in the detectors. Defaults to ``None``.
121
+ * max_discards (``int``): This parameter indicates the maximum number of consecutive \
122
+ detector discards, aimed at preventing a possible infinite loop in case a radius is \
123
+ defined that cannot generate non-self detectors. Defaults to ``1000``.
124
+ * seed (``int``): Seed for the random generation of values in the detectors. Defaults \
125
+ to ``None``.
121
126
 
122
127
  * algorithm(``str``), Set the algorithm version:
123
128
 
124
129
  * ``'default-NSA'``: Default algorithm with fixed radius.
125
- * ``'V-detector'``: This algorithm is based on the article "[Real-Valued Negative Selection Algorithm with Variable-Sized Detectors](https://doi.org/10.1007/978-3-540-24854-5_30)", by Ji, Z., Dasgupta, D. (2004), and uses a variable radius for anomaly detection in feature spaces.
130
+ * ``'V-detector'``: This algorithm is based on the article \
131
+ "[Real-Valued Negative Selection Algorithm with Variable-Sized Detectors](https://doi.org/10.1007/978-3-540-24854-5_30)", \
132
+ by Ji, Z., Dasgupta, D. (2004), and uses a variable radius for anomaly \
133
+ detection in feature spaces.
126
134
 
127
135
  Defaults to ``'default-NSA'``.
128
136
 
129
137
  - ``**kwargs``:
130
- - non_self_label (``str``): This variable stores the label that will be assigned when the data has only one
131
- output class, and the sample is classified as not belonging to that class. Defaults to ``'non-self'``.
132
- - cell_bounds (``bool``): If set to ``True``, this option limits the generation of detectors to the space within
133
- the plane between 0 and 1. This means that any detector whose radius exceeds this limit is discarded,
134
- this variable is only used in the ``V-detector`` algorithm. Defaults to ``False``.
135
- - p (``float``): This parameter stores the value of ``p`` used in the Minkowski distance. The default is ``2``, which
136
- represents normalized Euclidean distance. Different values of p lead to different variants of the Minkowski
137
- distance [learn more](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
138
+ - non_self_label (``str``): This variable stores the label that will be assigned \
139
+ when the data has only one output class, and the sample is classified as not \
140
+ belonging to that class. Defaults to ``'non-self'``.
141
+ - cell_bounds (``bool``): If set to ``True``, this option limits the generation \
142
+ of detectors to the space within the plane between 0 and 1. This means that \
143
+ any detector whose radius exceeds this limit is discarded, this variable is \
144
+ only used in the ``V-detector`` algorithm. Defaults to ``False``.
145
+ - p (``float``): This parameter stores the value of ``p`` used in the Minkowski \
146
+ distance. The default is ``2``, which represents normalized Euclidean distance. \
147
+ Different values of p lead to different variants of the Minkowski distance \
148
+ [learn more](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
138
149
  ---
139
150
 
140
151
  Construtor da classe de Seleção negativa (``RNSA``).
141
152
 
142
153
  Details:
143
154
  ---
144
- Este método inicializa os atributos ``detectors``, ``classes``, ``k``, ``metric``, ``N``, ``r`` e ``seed``.
155
+ Este método inicializa os atributos ``detectors``, ``classes``, ``k``, ``metric``, ``N``, \
156
+ ``r`` e ``seed``.
145
157
 
146
158
  Parameters:
147
159
  ---
148
160
  * N (``int``): Quantidade de detectores. Defaults to ``100``.
149
161
  * r (``float``): Raio do detector. Defaults to ``0.05``.
150
- * r_s (``float``): O valor de ``rₛ`` é o raio das amostras próprias da matriz ``X``. Defaults to ``0.0001``.
151
- * k (``int``): Quantidade de vizinhos próximos dos detectores gerados aleatoriamente para efetuar o
152
- cálculo da média da distância. Defaults to ``1``.
162
+ * r_s (``float``): O valor de ``rₛ`` é o raio das amostras próprias da matriz ``X``. \
163
+ Defaults to ``0.0001``.
164
+ * k (``int``): Quantidade de vizinhos próximos dos detectores gerados aleatoriamente \
165
+ para efetuar o cálculo da média da distância. Defaults to ``1``.
153
166
  * metric (``str``): Forma para se calcular a distância entre o detector e a amostra:
154
167
 
155
- * ``'euclidiana'`` ➜ O cálculo da distância dá-se pela expressão: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
156
- * ``'minkowski'`` ➜ O cálculo da distância dá-se pela expressão: ( |X₁ – Y₁|p + |X₂Y₂|p + ... + |XnYn|p) ¹/ₚ.
157
- * ``'manhattan'`` ➜ O cálculo da distância dá-se pela expressão: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|).
168
+ * ``'euclidiana'`` ➜ O cálculo da distância dá-se pela expressão: \
169
+ √( (x₁ – x₂)² + (y₁y₂)² + ... + (ynyn)²).
170
+ * ``'minkowski'`` ➜ O cálculo da distância dá-se pela expressão: \
171
+ ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ.
172
+ * ``'manhattan'`` ➜ O cálculo da distância dá-se pela expressão: \
173
+ ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|).
158
174
 
159
175
  Defaults to ``'euclidean'``.
160
176
 
161
- * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores em sequência, que tem como objetivo evitar um
162
- possível loop infinito caso seja definido um raio que não seja possível gerar detectores do não-próprio. Defaults to ``1000``.
163
- * seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
177
+ * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores \
178
+ em sequência, que tem como objetivo evitar um possível loop infinito caso seja definido \
179
+ um raio que não seja possível gerar detectores do não-próprio. Defaults to ``1000``.
180
+ * seed (``int``): Semente para a geração randômica dos valores nos detectores. \
181
+ Defaults to ``None``.
164
182
  * algorithm (``str``), Definir a versão do algoritmo:
165
183
 
166
184
  * ``'default-NSA'``: Algoritmo padrão com raio fixo.
167
- * ``'V-detector'``: Este algoritmo é baseado no artigo "[Real-Valued Negative Selection Algorithm with Variable-Sized Detectors](https://doi.org/10.1007/978-3-540-24854-5_30)", de autoria de Ji, Z., Dasgupta, D. (2004), e utiliza um raio variável para a detecção de anomalias em espaços de características.
185
+ * ``'V-detector'``: Este algoritmo é baseado no artigo \
186
+ "[Real-Valued Negative Selection Algorithm with Variable-Sized Detectors](https://doi.org/10.1007/978-3-540-24854-5_30)", \
187
+ de autoria de Ji, Z., Dasgupta, D. (2004), e utiliza um raio variável para a \
188
+ detecção de anomalias em espaços de características.
168
189
 
169
190
  Defaults to ``'default-NSA'``.
170
191
 
171
192
  - ``**kwargs``:
172
- - non_self_label (``str``): Esta variável armazena o rótulo que será atribuído quando os dados possuírem
173
- apenas uma classe de saída, e a amostra for classificada como não pertencente a essa classe. Defaults to ``'non-self'``.
174
- - cell_bounds (``bool``): Se definido como ``True``, esta opção limita a geração dos detectores ao espaço do plano
175
- compreendido entre 0 e 1. Isso significa que qualquer detector cujo raio ultrapasse esse limite é descartado,
176
- e esta variável é usada exclusivamente no algoritmo ``V-detector``.
177
- - p (``float``): Este parâmetro armazena o valor de ``p`` utilizada na distância de Minkowski. O padrão é ``2``, o que significa
178
- distância euclidiana normalizada. Diferentes valores de p levam a diferentes variantes da distância de
179
- Minkowski [saiba mais](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
193
+ - non_self_label (``str``): Esta variável armazena o rótulo que será atribuído \
194
+ quando os dados possuírem apenas uma classe de saída, e a amostra for \
195
+ classificada como não pertencente a essa classe. Defaults to ``'non-self'``.
196
+ - cell_bounds (``bool``): Se definido como ``True``, esta opção limita a \
197
+ geração dos detectores ao espaço do plano compreendido entre 0 e 1. Isso \
198
+ significa que qualquer detector cujo raio ultrapasse esse limite é descartado, \
199
+ e esta variável é usada exclusivamente no algoritmo ``V-detector``.
200
+ - p (``float``): Este parâmetro armazena o valor de ``p`` utilizada na distância \
201
+ de Minkowski. O padrão é ``2``, o que significa distância euclidiana normalizada. \
202
+ Diferentes valores de p levam a diferentes variantes da distância de Minkowski \
203
+ [saiba mais](https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.distance.minkowski.html).
180
204
  """
181
-
182
- if metric == 'manhattan' or metric == 'minkowski' or metric == 'euclidean':
205
+
206
+ super().__init__(metric)
207
+ if metric == "manhattan" or metric == "minkowski":
183
208
  self.metric = metric
184
209
  else:
185
- self.metric = 'euclidean'
210
+ self.metric = "euclidean"
186
211
 
187
212
  if seed is not None and isinstance(seed, int):
188
213
  np.random.seed(seed)
@@ -204,18 +229,18 @@ class RNSA(Base):
204
229
  self.r: float = 0.05
205
230
  else:
206
231
  self.r: float = r
207
-
232
+
208
233
  if r_s > 0:
209
234
  self.r_s: float = r_s
210
235
  else:
211
236
  self.r_s: float = 0
212
237
 
213
- if algorithm == 'V-detector':
238
+ if algorithm == "V-detector":
214
239
  self._Detector = namedtuple("Detector", "position radius")
215
240
  self._algorithm: str = algorithm
216
241
  else:
217
242
  self._Detector = namedtuple("Detector", "position")
218
- self._algorithm: str = 'default-NSA'
243
+ self._algorithm: str = "default-NSA"
219
244
 
220
245
  if max_discards > 0:
221
246
  self.max_discards: int = max_discards
@@ -223,10 +248,10 @@ class RNSA(Base):
223
248
  self.max_discards: int = 1000
224
249
 
225
250
  # Obtém as variáveis do kwargs.
226
- self.p: float = kwargs.get('p', 2)
227
- self._cell_bounds: bool = kwargs.get('cell_bounds', False)
228
- self.non_self_label: str = kwargs.get('non_self_label', 'non-self')
229
-
251
+ self.p: float = kwargs.get("p", 2)
252
+ self._cell_bounds: bool = kwargs.get("cell_bounds", False)
253
+ self.non_self_label: str = kwargs.get("non_self_label", "non-self")
254
+
230
255
  # Inicializa as demais variáveis da classe como None
231
256
  self.detectors: Union[dict, None] = None
232
257
  self.classes: npt.NDArray = None
@@ -238,8 +263,8 @@ class RNSA(Base):
238
263
 
239
264
  Parameters:
240
265
  ---
241
- * X (``npt.NDArray``): Training array, containing the samples and their characteristics,
242
- [``N samples`` (rows)][``N features`` (columns)].
266
+ * X (``npt.NDArray``): Training array, containing the samples and their characteristics, \
267
+ [``N samples`` (rows)][``N features`` (columns)].
243
268
  * y (``npt.NDArray``): Array of target classes of ``X`` with [``N samples`` (lines)].
244
269
  * verbose (``bool``): Feedback from detector generation to the user.
245
270
  returns:
@@ -248,13 +273,13 @@ class RNSA(Base):
248
273
 
249
274
  ----
250
275
 
251
- A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
276
+ A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
252
277
  de seleção negativa(``NegativeSelect``).
253
278
 
254
279
  Parameters:
255
280
  ---
256
- * X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características,
257
- [``N amostras`` (linhas)][``N características`` (colunas)].
281
+ * X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características, \
282
+ [``N amostras`` (linhas)][``N características`` (colunas)].
258
283
  * y (``npt.NDArray``): Array com as classes alvos de ``X`` com [``N amostras`` (linhas)].
259
284
  * verbose (``bool``): Feedback da geração de detectores para o usuário.
260
285
  Returns:
@@ -262,7 +287,7 @@ class RNSA(Base):
262
287
  (``self``): Retorna a própria instância.
263
288
  """
264
289
  super()._check_and_raise_exceptions_fit(X, y)
265
-
290
+
266
291
  # Identificando as classes possíveis, dentro do array de saídas ``y``.
267
292
  self.classes = np.unique(y)
268
293
  # Dict que armazenará os detectores com as classes como key.
@@ -272,7 +297,7 @@ class RNSA(Base):
272
297
  # Barra de progresso para a geração de todos os detectores.
273
298
  if verbose:
274
299
  progress = tqdm(total=int(self.N * (len(self.classes))),
275
- bar_format='{desc} ┇{bar}┇ {n}/{total} detectors', postfix='\n')
300
+ bar_format="{desc} ┇{bar}┇ {n}/{total} detectors", postfix="\n",)
276
301
  for _class_ in self.classes:
277
302
  # Inicia o conjunto vazio que conterá os detectores válidos.
278
303
  valid_detectors_set = []
@@ -280,19 +305,22 @@ class RNSA(Base):
280
305
  # Informando em qual classe o algoritmo está para a barra de progresso.
281
306
  if verbose:
282
307
  progress.set_description_str(
283
- f'Generating the detectors for the {_class_} class:')
308
+ f"Generating the detectors for the {_class_} class:"
309
+ )
284
310
  while len(valid_detectors_set) < self.N:
285
311
  # Gera um vetor candidato a detector aleatoriamente com valores entre 0 e 1.
286
312
  vector_x = np.random.random_sample(size=X.shape[1])
287
313
  # Verifica a validade do detector para o não-próprio com relação às amostras da classe.
288
314
  valid_detector = self.__checks_valid_detector(
289
- X=X, vector_x=vector_x, samples_index_class=sample_index[_class_])
290
-
315
+ X=X, vector_x=vector_x, samples_index_class=sample_index[_class_]
316
+ )
317
+
291
318
  # Se o detector for válido, adicione a lista dos válidos.
292
- if self._algorithm == 'V-detector' and valid_detector != False:
319
+ if self._algorithm == "V-detector" and valid_detector is not False:
293
320
  discard_count = 0
294
321
  valid_detectors_set.append(
295
- self._Detector(vector_x, valid_detector[1]))
322
+ self._Detector(vector_x, valid_detector[1])
323
+ )
296
324
  if verbose:
297
325
  progress.update(1)
298
326
  elif valid_detector:
@@ -303,21 +331,26 @@ class RNSA(Base):
303
331
  else:
304
332
  discard_count += 1
305
333
  if discard_count == self.max_discards:
306
- raise Exception('An error has been identified:\n'+
307
- f'the maximum number of discards of detectors for the {_class_} class has been reached.\n'+
308
- 'It is recommended to check the defined radius and consider reducing its value.')
309
-
334
+ raise Exception(
335
+ "An error has been identified:\n"
336
+ f"the maximum number of discards of detectors for the {_class_} class "
337
+ "has been reached.\nIt is recommended to check the defined radius and "
338
+ "consider reducing its value."
339
+ )
340
+
310
341
  # Adicionar detectores, com as classes como chave na dict.
311
342
  list_detectors_by_class[_class_] = valid_detectors_set
312
343
  # Informar a finalização da geração dos detectores para as classes.
313
344
  if verbose:
314
345
  progress.set_description(
315
- f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) successfully generated\033[0m')
346
+ f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) '
347
+ f'successfully generated\033[0m'
348
+ )
316
349
  # Armazena os detectores encontrados no atributo, para os detectores da classe.
317
350
  self.detectors = list_detectors_by_class
318
351
  return self
319
352
 
320
- def predict(self, X: npt.NDArray) -> npt.NDArray:
353
+ def predict(self, X: npt.NDArray) -> Optional[npt.NDArray]:
321
354
  """
322
355
  Function to perform the prediction of classes based on detectors
323
356
  created after training.
@@ -335,31 +368,34 @@ class RNSA(Base):
335
368
 
336
369
  ---
337
370
 
338
- Função para efetuar a previsão das classes com base nos detectores
371
+ Função para efetuar a previsão das classes com base nos detectores
339
372
  criados após o treinamento.
340
373
 
341
374
  Parameters:
342
375
  ---
343
- * X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
376
+ * X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
344
377
  [``N características``(Colunas)]
345
378
 
346
379
  Returns:
347
380
  ---
348
- * C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
381
+ * C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
349
382
  contendo as classes previstas para ``X``.
350
383
  * ``None``: Se não existir detectores para a previsão.
351
384
  """
352
385
  # se não houver detectores retorna None.
353
386
  if self.detectors is None:
354
387
  return None
355
- elif not isinstance(X, (np.ndarray, list)):
388
+ elif not isinstance(X, (np.ndarray, list)):
356
389
  raise TypeError("X is not an ndarray or list")
357
390
  elif len(self.detectors[self.classes[0]][0].position) != len(X[0]):
358
- raise Exception('X does not have {} features to make the prediction'.format(
359
- len(self.detectors[self.classes[0]][0])))
391
+ raise Exception(
392
+ "X does not have {} features to make the prediction".format(
393
+ len(self.detectors[self.classes[0]][0])
394
+ )
395
+ )
360
396
 
361
397
  # Inicia um array vazio.
362
- C = np.empty(shape=(0))
398
+ C = np.empty(shape=0)
363
399
  # Para cada linha de amostra em X.
364
400
  for line in X:
365
401
  class_found: bool
@@ -373,25 +409,31 @@ class RNSA(Base):
373
409
  # Se possuir apenas uma classe e não classificar a amostra define a saída como não-própria.
374
410
  if not class_found and len(self.classes) == 1:
375
411
  C = np.append(C, [self.non_self_label])
376
- # Se não identificar a classe com os detectores, coloca a classe com a maior distância da média dos seus detectores.
412
+ # Se não identificar a classe com os detectores, coloca a classe com a maior distância
413
+ # da média dos seus detectores.
377
414
  elif not class_found:
378
415
  average_distance: dict = {}
379
416
  for _class_ in self.classes:
380
417
  detectores = list(
381
- map(lambda x: x.position, self.detectors[_class_]))
382
- average_distance[_class_] = np.average([self.__distance(detector, line) for detector in detectores])
383
- C = np.append(
384
- C, [max(average_distance, key=average_distance.get)])
418
+ map(lambda x: x.position, self.detectors[_class_])
419
+ )
420
+ average_distance[_class_] = np.average(
421
+ [self.__distance(detector, line)
422
+ for detector in detectores]
423
+ )
424
+ C = np.append(C, [max(average_distance, key=average_distance.get)])
385
425
  return C
386
426
 
387
- def __checks_valid_detector(self, X: npt.NDArray = None, vector_x: npt.NDArray = None, samples_index_class: npt.NDArray = None):
427
+ def __checks_valid_detector(self, X: npt.NDArray = None, vector_x: npt.NDArray = None,
428
+ samples_index_class: npt.NDArray = None):
388
429
  """
389
430
  Function to check if the detector has a valid non-proper ``r`` radius for the class.
390
431
 
391
432
  Parameters:
392
433
  ---
393
434
  * X (``npt.NDArray``): Array ``X`` with the samples.
394
- * vector_x (``npt.NDArray``): Randomly generated vector x candidate detector with values ​​between [0, 1].
435
+ * vector_x (``npt.NDArray``): Randomly generated vector x candidate detector with values \
436
+ ​​between [0, 1].
395
437
  * samples_index_class (``npt.NDArray``): Sample positions of a class in ``X``.
396
438
 
397
439
  returns:
@@ -405,7 +447,8 @@ class RNSA(Base):
405
447
  Parameters:
406
448
  ---
407
449
  * X (``npt.NDArray``): Array ``X`` com as amostras.
408
- * vector_x (``npt.NDArray``): Vetor x candidato a detector gerado aleatoriamente com valores entre [0, 1].
450
+ * vector_x (``npt.NDArray``): Vetor x candidato a detector gerado aleatoriamente com valores \
451
+ entre [0, 1].
409
452
  * samples_index_class (``npt.NDArray``): Posições das amostras de uma classe em ``X``.
410
453
 
411
454
  Returns:
@@ -414,37 +457,41 @@ class RNSA(Base):
414
457
 
415
458
  """
416
459
  # Se um ou mais array de entrada possuir zero dados, retorna falso.
417
- if np.size(samples_index_class) == 0 or np.size(X) == 0 or np.size(vector_x) == 0:
460
+ if (np.size(samples_index_class) == 0 or np.size(X) == 0 or np.size(vector_x) == 0):
418
461
  return False
419
- # se self.k > 1 utiliza os k vizinhos mais próximos (knn), se não verifica o detector sem considerar os knn,.
462
+ # se self.k > 1 utiliza os k vizinhos mais próximos (knn), se não verifica o detector sem
463
+ # considerar os knn.
420
464
  if self.k > 1:
421
465
  # Iniciar a lista dos knn vazia.
422
- knn_list = np.empty(shape=(0))
466
+ knn_list = np.empty(shape=0)
423
467
  for i in samples_index_class:
424
- # Calcula a distância entre os dois vetores e adiciona a lista dos knn, se a distância for menor que a maior da lista.
468
+ # Calcula a distância entre os dois vetores e adiciona a lista dos knn, se a
469
+ # distância for menor que a maior da lista.
425
470
  knn_list = self.__compare_KnearestNeighbors_List(
426
- knn_list, self.__distance(X[i], vector_x))
471
+ knn_list, self.__distance(X[i], vector_x)
472
+ )
427
473
  # Se a média das distâncias na lista dos knn, for menor que o raio, retorna verdadeiro.
428
474
  distance_mean = np.mean(knn_list)
429
- if self._algorithm == 'V-detector':
475
+ if self._algorithm == "V-detector":
430
476
  return self.__detector_is_valid_to_Vdetector(distance_mean, vector_x)
431
477
  elif distance_mean > (self.r + self.r_s):
432
478
  return True # Detector é valido!
433
479
  else:
434
480
  distance: Union[float, None] = None
435
481
  for i in samples_index_class:
436
- if self._algorithm == 'V-detector':
482
+ if self._algorithm == "V-detector":
437
483
  new_distance = self.__distance(X[i], vector_x)
438
484
  if distance is None:
439
485
  distance = new_distance
440
486
  elif distance > new_distance:
441
487
  distance = new_distance
442
488
  else:
443
- # Calcula a distância entre os vetores, se menor ou igual ao raio + raio da amostra define a validade do detector como falso.
489
+ # Calcula a distância entre os vetores, se menor ou igual ao raio + raio da
490
+ # amostra define a validade do detector como falso.
444
491
  if (self.r + self.r_s) >= self.__distance(X[i], vector_x):
445
492
  return False # Detector não é valido!
446
-
447
- if self._algorithm == 'V-detector':
493
+
494
+ if self._algorithm == "V-detector":
448
495
  return self.__detector_is_valid_to_Vdetector(distance, vector_x)
449
496
  return True # Detector é valido!
450
497
 
@@ -467,26 +514,26 @@ class RNSA(Base):
467
514
 
468
515
  ---
469
516
 
470
- Compara a distância do k-vizinho mais próximo na posição ``k-1``da lista ``knn``,
517
+ Compara a distância do k-vizinho mais próximo na posição ``k-1``da lista ``knn``,
471
518
  se a distância da nova amostra for menor, substitui ela e ordena em ordem crescente.
472
519
 
473
520
 
474
521
  Parameters:
475
522
  ---
476
523
  knn (npt.NDArray): Lista de distâncias dos k-vizinhos mais próximos.
477
- distance (float): Distância a ser verificada.
524
+ distance (float): Distância a ser verificada.
478
525
 
479
526
  Returns:
480
527
  ---
481
528
  npt.NDArray: Lista de vizinhos mais próximos atualizada e ordenada.
482
529
  """
483
530
  # Se a quantidade de distâncias em knn, for menor que k, adiciona a distância.
484
- if (len(knn) < self.k):
531
+ if len(knn) < self.k:
485
532
  knn = np.append(knn, distance)
486
533
  knn.sort()
487
534
  else:
488
535
  # Se não, adicione a distância, se a nova distancia for menor que a maior distância da lista.
489
- if (knn[self.k - 1] > distance):
536
+ if knn[self.k - 1] > distance:
490
537
  knn[self.k - 1] = distance
491
538
  knn.sort()
492
539
 
@@ -498,7 +545,7 @@ class RNSA(Base):
498
545
 
499
546
  Details:
500
547
  ---
501
- In this function, when there is class ambiguity, it returns the class that has the greatest
548
+ In this function, when there is class ambiguity, it returns the class that has the greatest
502
549
  average distance between the detectors.
503
550
 
504
551
  Parameters:
@@ -507,7 +554,8 @@ class RNSA(Base):
507
554
 
508
555
  returns:
509
556
  ---
510
- * Returns the predicted class with the detectors or None if the sample does not qualify for any class.
557
+ * Returns the predicted class with the detectors or None if the sample does not qualify \
558
+ for any class.
511
559
 
512
560
  ---
513
561
 
@@ -515,8 +563,8 @@ class RNSA(Base):
515
563
 
516
564
  Details:
517
565
  ---
518
- Nesta função, quando possui ambiguidade de classes, retorna a classe que possuir a média de distância
519
- maior entre os detectores.
566
+ Nesta função, quando possui ambiguidade de classes, retorna a classe que possuir a média de \
567
+ distância maior entre os detectores.
520
568
 
521
569
  Parameters:
522
570
  ---
@@ -524,7 +572,8 @@ class RNSA(Base):
524
572
 
525
573
  Returns:
526
574
  ---
527
- * Retorna a classe prevista com os detectores ou None se a amostra não se qualificar a nenhuma classe.
575
+ * Retorna a classe prevista com os detectores ou None se a amostra não se qualificar \
576
+ a nenhuma classe.
528
577
  """
529
578
 
530
579
  # Lista para armazenar as classes e a distância média entre os detectores e a amostra.
@@ -538,7 +587,7 @@ class RNSA(Base):
538
587
  distance = self.__distance(detector.position, line)
539
588
  # Soma as distâncias para calcular a média.
540
589
  sum_distance += distance
541
- if self._algorithm == 'V-detector':
590
+ if self._algorithm == "V-detector":
542
591
  if distance <= detector.radius:
543
592
  class_found = False
544
593
  break
@@ -546,9 +595,10 @@ class RNSA(Base):
546
595
  class_found = False
547
596
  break
548
597
 
549
- # Se a amostra passar por todos os detectores de uma classe, adiciona a classe como possivel previsão.
598
+ # Se a amostra passar por todos os detectores de uma classe, adiciona a classe como
599
+ # possível previsão.
550
600
  if class_found:
551
- possible_classes.append([_class_, sum_distance/self.N])
601
+ possible_classes.append([_class_, sum_distance / self.N])
552
602
  # Se classificar como pertencentes a apenas uma classe, retorna a classe.
553
603
  if len(possible_classes) == 1:
554
604
  return possible_classes[0][0]
@@ -588,33 +638,37 @@ class RNSA(Base):
588
638
 
589
639
  def __detector_is_valid_to_Vdetector(self, distance: float, vector_x: npt.NDArray):
590
640
  """
591
- Check if the distance between the detector and the samples, minus the radius of the samples,
641
+ Check if the distance between the detector and the samples, minus the radius of the samples,
592
642
  is greater than the minimum radius.
593
643
 
594
644
  Parameters:
595
645
  ---
596
646
  distance (``float``): minimum distance calculated between all samples.
597
- vector_x (``numpy.ndarray``): randomly generated candidate detector vector x with values between 0 and 1.
647
+ vector_x (``numpy.ndarray``): randomly generated candidate detector vector x with values \
648
+ between 0 and 1.
649
+
598
650
  Returns:
599
651
  ---
600
- * ``False``: if the calculated radius is smaller than the minimum distance or exceeds the edge of the space,
601
- if this option is enabled.
652
+ * ``False``: if the calculated radius is smaller than the minimum distance or exceeds the \
653
+ edge of the space, if this option is enabled.
602
654
  * ``True`` and the distance minus the radius of the samples, if the radius is valid.`
603
655
 
604
656
  ----
605
657
 
606
- Verifique se a distância entre o detector e as amostras, descontando o raio das amostras, é maior do que o raio mínimo.
658
+ Verifique se a distância entre o detector e as amostras, descontando o raio das amostras, \
659
+ é maior do que o raio mínimo.
607
660
 
608
661
  Parameters:
609
662
  ---
610
663
  distance (``float``): distância mínima calculada entre todas as amostras.
611
- vector_x (``numpy.ndarray``): vetor x candidato do detector gerado aleatoriamente, com valores entre 0 e 1.
612
-
664
+ vector_x (``numpy.ndarray``): vetor x candidato do detector gerado aleatoriamente, com \
665
+ valores entre 0 e 1.
666
+
613
667
  Returns:
614
668
  ---
615
669
 
616
- * ``False``: caso o raio calculado seja menor do que a distância mínima ou ultrapasse a borda do espaço,
617
- caso essa opção esteja habilitada.
670
+ * ``False``: caso o raio calculado seja menor do que a distância mínima ou ultrapasse a \
671
+ borda do espaço, caso essa opção esteja habilitada.
618
672
  * ``True`` e a distância menos o raio das amostras, caso o raio seja válido.
619
673
  """
620
674
  new_detector_r = float(distance - self.r_s)
@@ -630,12 +684,14 @@ class RNSA(Base):
630
684
 
631
685
  def __slice_index_list_by_class(self, y: npt.NDArray) -> dict:
632
686
  """
633
- The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according to the output class,
634
- to loop through the sample array, only in positions where the output is the class being trained.
687
+ The function ``__slice_index_list_by_class(...)``, separates the indices of the lines \
688
+ according to the output class, to loop through the sample array, only in positions where \
689
+ the output is the class being trained.
635
690
 
636
691
  Parameters:
637
692
  ---
638
- * y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the ``X`` sample array.
693
+ * y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the \
694
+ ``X`` sample array.
639
695
 
640
696
  returns:
641
697
  ---
@@ -643,35 +699,36 @@ class RNSA(Base):
643
699
 
644
700
  ---
645
701
 
646
- A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe de saída,
647
- para percorrer o array de amostra, apenas nas posições que a saída for a classe que está sendo treinada.
702
+ A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe \
703
+ de saída, para percorrer o array de amostra, apenas nas posições que a saída for a classe que \
704
+ está sendo treinada.
648
705
 
649
706
  Parameters:
650
707
  ---
651
- * y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saida do array de amostra ``X``.
708
+ * y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saída do array \
709
+ de amostra ``X``.
652
710
 
653
711
  Returns:
654
712
  ---
655
713
  * dict: Um dicionário com a lista de posições do array(``y``), com as classes como chave.
656
714
  """
657
715
  return super()._slice_index_list_by_class(y)
658
-
716
+
659
717
  def score(self, X: npt.NDArray, y: list) -> float:
660
718
  """
661
719
  Score function calculates forecast accuracy.
662
720
 
663
721
  Details:
664
722
  ---
665
- This function performs the prediction of X and checks how many elements are equal between vector y and y_predicted.
666
- This function was added for compatibility with some scikit-learn functions.
723
+ This function performs the prediction of X and checks how many elements are equal between \
724
+ vector y and y_predicted. This function was added for compatibility with some scikit-learn \
725
+ functions.
667
726
 
668
727
  Parameters:
669
728
  -----------
670
729
 
671
- X: np.ndarray
672
- Feature set with shape (n_samples, n_features).
673
- y: np.ndarray
674
- True values with shape (n_samples,).
730
+ * X (np.ndarray): Feature set with shape (n_samples, n_features).
731
+ * y (np.ndarray): True values with shape (n_samples,).
675
732
 
676
733
  Returns:
677
734
  -------
@@ -685,84 +742,88 @@ class RNSA(Base):
685
742
 
686
743
  Details:
687
744
  ---
688
- Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y e y_previsto.
689
- Essa função foi adicionada para oferecer compatibilidade com algumas funções do scikit-learn.
745
+ Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor \
746
+ y e y_previsto. Essa função foi adicionada para oferecer compatibilidade com algumas \
747
+ funções do scikit-learn.
690
748
 
691
749
  Parameters:
692
750
  ---
693
751
 
694
- * X : np.ndarray
695
- Conjunto de características com shape (n_samples, n_features).
696
- * y : np.ndarray
697
- Valores verdadeiros com shape (n_samples,).
752
+ * X (np.ndarray): Conjunto de características com shape (n_samples, n_features).
753
+ * y (np.ndarray): Valores verdadeiros com shape (n_samples,).
698
754
 
699
755
  returns:
700
756
  ---
701
757
 
702
- accuracy : float
703
- A acurácia do modelo.
758
+ * accuracy (float): A acurácia do modelo.
759
+
704
760
  """
705
761
  return super()._score(X, y)
706
762
 
707
763
  def get_params(self, deep: bool = True) -> dict:
708
764
  return {
709
- 'N': self.N,
710
- 'r': self.r,
711
- 'k': self.k,
712
- 'metric': self.metric,
713
- 'seed': self.seed,
714
- 'algorithm': self._algorithm,
715
- 'r_s': self.r_s,
716
- 'cell_bounds': self._cell_bounds,
717
- 'p': self.p
765
+ "N": self.N,
766
+ "r": self.r,
767
+ "k": self.k,
768
+ "metric": self.metric,
769
+ "seed": self.seed,
770
+ "algorithm": self._algorithm,
771
+ "r_s": self.r_s,
772
+ "cell_bounds": self._cell_bounds,
773
+ "p": self.p,
718
774
  }
719
775
 
776
+
720
777
  class BNSA(Base):
721
778
  """
722
- The ``BNSA`` (Binary Negative Selection Algorithm) class is for classification and identification purposes.
723
- of anomalies through the self and not self method.
779
+ The ``BNSA`` (Binary Negative Selection Algorithm) class is for classification and identification \
780
+ purposes of anomalies through the self and not self method.
724
781
 
725
782
  Attributes:
726
783
  ---
727
-
784
+
728
785
  * N (``int``): Number of detectors.
729
- * aff_thresh (``float``): The variable represents the percentage of similarity between the T cell and the own samples.
730
- * max_discards (``int``): This parameter indicates the maximum number of detector discards in sequence, which aims to avoid a
731
- possible infinite loop if a radius is defined that it is not possible to generate non-self detectors.
786
+ * aff_thresh (``float``): The variable represents the percentage of similarity between the \
787
+ T cell and the own samples.
788
+ * max_discards (``int``): This parameter indicates the maximum number of detector discards \
789
+ in sequence, which aims to avoid a possible infinite loop if a radius is defined that \
790
+ it is not possible to generate non-self detectors.
732
791
  * seed (``int``): Seed for the random generation of values in the detectors.
733
-
792
+
734
793
  * detectors (``dict``): This variable stores a list of detectors by class.
735
794
  * classes (``npt.NDArray``): list of output classes.
736
-
795
+
737
796
 
738
797
  ---
739
798
 
740
- A classe ``BNSA`` (Algoritmo de Seleção Negativa Binária) tem a finalidade de classificação e identificação
741
- de anomalias através do método self e not self .
799
+ A classe ``BNSA`` (Algoritmo de Seleção Negativa Binária) tem a finalidade de classificação e \
800
+ identificação de anomalias através do método self e not self .
742
801
 
743
802
  Attributes:
744
803
  ---
745
804
  * N (``int``): Quantidade de detectores. Defaults to ``100``.
746
- * aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a célula T e as amostras próprias.
747
- O valor padrão é de 10% (0,1), enquanto que o valor de 1,0 representa 100% de similaridade.
748
- * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores em sequência, que tem como objetivo evitar um
749
- possível loop infinito caso seja definido um raio que não seja possível gerar detectores do não-próprio. Defaults to ``100``.
805
+ * aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a célula \
806
+ T e as amostras próprias. O valor padrão é de 10% (0,1), enquanto que o valor de 1,0 \
807
+ representa 100% de similaridade.
808
+ * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores \
809
+ em sequência, que tem como objetivo evitar um possível loop infinito caso seja definido \
810
+ um raio que não seja possível gerar detectores do não-próprio. Defaults to ``100``.
750
811
  * seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
812
+ * no_label_sample_selection (``str``): Method for selecting labels for samples designated as \
813
+ non-members by all non-member detectors. Defaults to ``max_average_difference``.
814
+
751
815
 
752
816
  * detectors (``dict``): Essa variável armazena uma lista com detectores por classes.
753
817
  * classes (``npt.NDArray``): lista com as classes de saída.
754
818
 
755
819
  """
756
- def __init__(
757
- self,
758
- N: int = 100,
759
- aff_thresh: float = 0.1,
760
- max_discards: int = 1000,
761
- seed: int = None
762
- ):
820
+
821
+ def __init__(self, N: int = 100, aff_thresh: float = 0.1, max_discards: int = 1000, seed: int = None,
822
+ no_label_sample_selection: Literal["max_average_difference", "max_nearest_difference"] =
823
+ "max_average_difference"):
763
824
  """
764
825
  Constructor of the Negative Selection class (``BNSA``).
765
-
826
+
766
827
  Details:
767
828
  ---
768
829
  This method initializes the ``detectors``, ``classes``, ``N``, ``t`` and ``seed`` attributes.
@@ -770,16 +831,23 @@ class BNSA(Base):
770
831
  Parameters:
771
832
  ---
772
833
  * N (``int``): Number of detectors. Defaults to ``100``.
773
- * aff_thresh (``float``): The variable represents the percentage of similarity between the T cell and the own samples.
774
- The default value is 10% (0.1), while a value of 1.0 represents 100% similarity.
775
- * max_discards (``int``): This parameter indicates the maximum number of detector discards in sequence, which aims to avoid a
776
- possible infinite loop if a radius is defined that it is not possible to generate non-self detectors. Defaults to ``1000``.
834
+ * aff_thresh (``float``): The variable represents the percentage of similarity between \
835
+ the T cell and the own samples. The default value is 10% (0.1), while a value of 1.0 \
836
+ represents 100% similarity.
837
+ * max_discards (``int``): This parameter indicates the maximum number of detector \
838
+ discards in sequence, which aims to avoid a possible infinite loop if a radius is \
839
+ defined that it is not possible to generate non-self detectors. Defaults to ``1000``.
777
840
  * seed (``int``): Seed for the random generation of values in the detectors. Defaults to ``None``.
778
-
841
+ * no_label_sample_selection (``str``): Method for selecting labels for samples designated as \
842
+ non-members by all non-member detectors. Available method types:
843
+ - (``max_average_difference``): Selects the class with the highest average difference \
844
+ among the detectors.
845
+ - (``max_nearest_difference``): Selects the class with the highest difference between \
846
+ the nearest and farthest detector from the sample.
779
847
  ---
780
848
 
781
849
  Construtor da classe de Seleção negativa (``BNSA``).
782
-
850
+
783
851
  Details:
784
852
  ---
785
853
  Este método inicializa os atributos ``detectors``, ``classes``, ``N``, ``t`` e ``seed``.
@@ -787,31 +855,47 @@ class BNSA(Base):
787
855
  Parameters:
788
856
  ---
789
857
  * N (``int``): Quantidade de detectores. Defaults to ``100``.
790
- * aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a célula T e as amostras próprias.
791
- O valor padrão é de 10% (0,1), enquanto que o valor de 1,0 representa 100% de similaridade.
792
- * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores em sequência, que tem como objetivo evitar um
793
- possível loop infinito caso seja definido um raio que não seja possível gerar detectores do não-próprio. Defaults to ``1000``.
858
+ * aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a \
859
+ célula T e as amostras próprias. O valor padrão é de 10% (0,1), enquanto que o valor \
860
+ de 1,0 representa 100% de similaridade.
861
+ * max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores \
862
+ em sequência, que tem como objetivo evitar um possível loop infinito caso seja definido \
863
+ um raio que não seja possível gerar detectores do não-próprio. Defaults to ``1000``.
794
864
  * seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
865
+ * no_label_sample_selection (``str``): Método para a seleção de rótulos para amostras designadas \
866
+ como não pertencentes por todos os detectores não pertencentes. Tipos de métodos disponíveis:
867
+ - (``max_average_difference``): Seleciona a classe com a maior diferença média entre os \
868
+ detectores.
869
+ - (``max_nearest_difference``): Seleciona a classe com a maior diferença entre o detector \
870
+ mais próximo e mais distante da amostra.
871
+
795
872
  """
873
+ super().__init__()
796
874
  if N > 0:
797
875
  self.N: int = N
798
876
  else:
799
877
  self.N: int = 100
800
878
 
801
- if aff_thresh > 0 and aff_thresh < 1:
879
+ if 0 < aff_thresh < 1:
802
880
  self.aff_thresh: float = aff_thresh
803
881
  else:
804
882
  self.aff_thresh: float = 0.1
805
883
  if max_discards > 0:
806
884
  self.max_discards: int = max_discards
807
885
  else:
808
- self.max_discards: int = 0
809
-
886
+ self.max_discards: int = 1000
887
+
810
888
  if seed is not None and isinstance(seed, int):
811
889
  np.random.seed(seed)
812
890
  self.seed: int = seed
813
891
  else:
814
892
  self.seed = None
893
+
894
+ if no_label_sample_selection == 'nearest_difference':
895
+ self.no_label_sample_selection = 'nearest_difference'
896
+ else:
897
+ self.no_label_sample_selection = 'max_average_difference'
898
+
815
899
  self.classes: npt.NDArray = None
816
900
  self.detectors: npt.NDArray = None
817
901
 
@@ -832,22 +916,22 @@ class BNSA(Base):
832
916
 
833
917
  ----
834
918
 
835
- A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
919
+ A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
836
920
  de seleção negativa(``NegativeSelect``).
837
921
 
838
922
  Parameters:
839
923
  ---
840
- * X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características,
841
- [``N amostras`` (linhas)][``N características`` (colunas)].
924
+ * X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características, \
925
+ [``N amostras`` (linhas)][``N características`` (colunas)].
842
926
  * y (``npt.NDArray``): Array com as classes alvos de ``X`` com [``N amostras`` (linhas)].
843
927
  * verbose (``bool``): Feedback da geração de detectores para o usuário.
844
928
  Returns:
845
929
  ---
846
930
  (``self``): Retorna a própria instância.
847
931
  """
848
- super()._check_and_raise_exceptions_fit(X, y, 'BNSA')
849
-
850
- # Converte todo o array X para booleano
932
+ super()._check_and_raise_exceptions_fit(X, y, "BNSA")
933
+
934
+ # Converte todo o array X para boolean
851
935
  if X.dtype != bool:
852
936
  X = X.astype(bool)
853
937
 
@@ -861,7 +945,7 @@ class BNSA(Base):
861
945
  if verbose:
862
946
  progress = tqdm(total=int(self.N * (len(self.classes))),
863
947
  bar_format='{desc} ┇{bar}┇ {n}/{total} detectors', postfix='\n')
864
-
948
+
865
949
  for _class_ in self.classes:
866
950
  # Inicia o conjunto vazio que conterá os detectores válidos.
867
951
  valid_detectors_set: list = []
@@ -869,17 +953,18 @@ class BNSA(Base):
869
953
  # Informando em qual classe o algoritmo está para a barra de progresso.
870
954
  if verbose:
871
955
  progress.set_description_str(
872
- f'Generating the detectors for the {_class_} class:')
956
+ f"Generating the detectors for the {_class_} class:")
873
957
  while len(valid_detectors_set) < self.N:
874
-
958
+
875
959
  is_valid_detector: bool = True
876
960
  # Gera um vetor candidato a detector aleatoriamente com valores 0 e 1.
877
961
  vector_x = np.random.choice([False, True], size=X.shape[1])
878
- for i in sample_index[_class_]:
879
- # Verifica a validade do detector para o não-próprio com relação às amostras da classe.
880
- if hamming(X[i], vector_x) <= self.aff_thresh:
881
- is_valid_detector = False
882
- break
962
+ # Calcula a distância entre o candidato e as amostras da classe.
963
+ distances = cdist(np.expand_dims(vector_x, axis=0),
964
+ X[sample_index[_class_]], metric='hamming')
965
+ # Verifica se alguma das distâncias está abaixo ou igual ao limiar
966
+ is_valid_detector = not np.any(distances <= self.aff_thresh)
967
+
883
968
  # Se o detector for válido, adicione a lista dos válidos.
884
969
  if is_valid_detector:
885
970
  discard_count = 0
@@ -889,22 +974,26 @@ class BNSA(Base):
889
974
  else:
890
975
  discard_count += 1
891
976
  if discard_count == self.max_discards:
892
- raise Exception('An error has been identified:\n'+
893
- f'the maximum number of discards of detectors for the {_class_} class has been reached.\n'+
894
- 'It is recommended to check the defined radius and consider reducing its value.')
895
-
977
+ raise Exception(
978
+ "An error has been identified:\n"
979
+ f"the maximum number of discards of detectors for the {_class_} "
980
+ "class has been reached.\nIt is recommended to check the defined "
981
+ "radius and consider reducing its value."
982
+ )
983
+
896
984
  # Adicionar detectores, com as classes como chave na dict.
897
985
  list_detectors_by_class[_class_] = valid_detectors_set
898
986
 
899
987
  # Informar a finalização da geração dos detectores para as classes.
900
988
  if verbose:
901
989
  progress.set_description(
902
- f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) successfully generated\033[0m')
990
+ f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) '
991
+ f'successfully generated\033[0m')
903
992
  # Armazena os detectores encontrados no atributo, para os detectores da classe.
904
993
  self.detectors = list_detectors_by_class
905
994
  return self
906
995
 
907
- def predict(self, X: npt.NDArray) -> npt.NDArray:
996
+ def predict(self, X: npt.NDArray) -> Optional[npt.NDArray]:
908
997
  """
909
998
  Function to perform the prediction of classes based on detectors
910
999
  created after training.
@@ -922,88 +1011,111 @@ class BNSA(Base):
922
1011
 
923
1012
  ---
924
1013
 
925
- Função para efetuar a previsão das classes com base nos detectores
1014
+ Função para efetuar a previsão das classes com base nos detectores
926
1015
  criados após o treinamento.
927
1016
 
928
1017
  Parameters:
929
1018
  ---
930
- * X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
1019
+ * X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
931
1020
  [``N características``(Colunas)]
932
1021
 
933
1022
  Returns:
934
1023
  ---
935
- * C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
1024
+ * C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
936
1025
  contendo as classes previstas para ``X``.
937
1026
  * ``None``: Se não existir detectores para a previsão.
938
1027
  """
939
1028
  # se não houver detectores retorna None.
940
1029
  if self.detectors is None:
941
1030
  return None
942
- elif not isinstance(X, (np.ndarray, list)):
1031
+ elif not isinstance(X, (np.ndarray, list)):
943
1032
  raise TypeError("X is not an ndarray or list")
944
1033
  elif len(self.detectors[self.classes[0]][0]) != len(X[0]):
945
- raise Exception('X does not have {} features to make the prediction'.format(
946
- len(self.detectors[self.classes[0]][0])))
1034
+ raise Exception(
1035
+ "X does not have {} features to make the prediction".format(
1036
+ len(self.detectors[self.classes[0]][0])
1037
+ )
1038
+ )
947
1039
  # Verifica se a matriz X contém apenas amostras binárias. Caso contrário, lança uma exceção.
948
1040
  if not np.isin(X, [0, 1]).all():
949
1041
  raise ValueError(
950
- "The array X contains values that are not composed only of 0 and 1.")
951
-
952
- # Converte todo o array X para booleano
1042
+ "The array X contains values that are not composed only of 0 and 1."
1043
+ )
1044
+
1045
+ # Converte todo o array X para boolean
953
1046
  if X.dtype != bool:
954
1047
  X = X.astype(bool)
955
-
1048
+
956
1049
  # Inicia um array vazio.
957
- C = np.empty(shape=(0))
1050
+ C = np.empty(shape=0)
958
1051
  # Para cada linha de amostra em X.
959
1052
  for line in X:
960
1053
  class_found: bool = True
961
- # Lista para armazenar as possíveis classes às quais a amostra se adequou ao self na comparação com os detectores non-self.
962
- possible_classes: list = []
1054
+ # Lista para armazenar as possíveis classes às quais a amostra se adequou ao self na
1055
+ # comparação com os detectores non-self.
1056
+ possible_classes: list = []
963
1057
  for _class_ in self.classes:
964
- # Lista para armzenar as taxas de similaridade entre a amostra e os detectores.
1058
+ # Lista para armazenar as taxas de similaridade entre a amostra e os detectores.
965
1059
  similarity_sum: float = 0
966
- for detector in self.detectors[_class_]:
967
- similarity = hamming(line, detector)
968
- if similarity <= self.aff_thresh:
969
- class_found = False
970
- break
971
- else:
972
- similarity_sum += similarity
973
- # Se a amostra passar por todos os detectores de uma classe, adiciona a classe como possivel previsão e sua media de similaridade.
1060
+
1061
+ # Calcula a distância de Hamming entre a linha e todos os detectores
1062
+ distances = cdist(np.expand_dims(line, axis=0),
1063
+ self.detectors[_class_], metric='hamming')
1064
+
1065
+ # Verificar se alguma distância está abaixo ou igual ao limiar
1066
+ if np.any(distances <= self.aff_thresh):
1067
+ class_found = False
1068
+ else:
1069
+ # Somar todas as distâncias
1070
+ similarity_sum = np.sum(distances)
1071
+
1072
+ # Se a amostra passar por todos os detectores de uma classe, adiciona a classe como
1073
+ # possível previsão e sua media de similaridade.
974
1074
  if class_found:
975
1075
  possible_classes.append([_class_, similarity_sum / self.N])
976
-
1076
+
977
1077
  # Se, pertencer a uma ou mais classes, adiciona a classe com a distância média mais distante.
978
- if len(possible_classes) > 0 :
979
- C = np.append(C, [max(possible_classes, key=lambda x: x[1])[0]])
1078
+ if len(possible_classes) > 0:
1079
+ C = np.append(
1080
+ C, [max(possible_classes, key=lambda x: x[1])[0]])
980
1081
  class_found = True
981
1082
  else:
982
1083
  class_found = False
983
1084
 
984
1085
  # Se possuir apenas uma classe e não classificar a amostra define a saída como não-própria.
985
1086
  if not class_found and len(self.classes) == 1:
986
- C = np.append(C, ['non-self'])
987
- # Se não identificar a classe com os detectores, coloca a classe com a maior distância da média dos seus detectores.
1087
+ C = np.append(C, ["non-self"])
1088
+ # Se a classe não puder ser identificada pelos detectores
988
1089
  elif not class_found:
989
1090
  class_differences: dict = {}
990
1091
  for _class_ in self.classes:
991
- difference_sum: float = 0
992
- for detector in self.detectors[_class_]:
993
- difference_sum += hamming(line, detector)
994
- class_differences[_class_] = (difference_sum / self.N)
1092
+ # Atribua-a o rotulo a classe com à maior distância em relação ao detector mais próximo.
1093
+ if self.no_label_sample_selection == 'nearest_difference':
1094
+ difference_min: float = cdist( np.expand_dims(line, axis=0),
1095
+ self.detectors[_class_], metric='hamming'
1096
+ ).min()
1097
+ class_differences[_class_] = difference_min
1098
+ # Ou com base na maior distância com relação à média da distancias dos detectores
1099
+ else:
1100
+ difference_sum: float = cdist( np.expand_dims(line, axis=0),
1101
+ self.detectors[_class_], metric='hamming'
1102
+ ).sum()
1103
+ class_differences[_class_] = difference_sum / self.N
1104
+
995
1105
  C = np.append(C, [max(class_differences, key=class_differences.get)])
996
-
1106
+
997
1107
  return C
998
1108
 
999
1109
  def __slice_index_list_by_class(self, y: npt.NDArray) -> dict:
1000
1110
  """
1001
- The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according to the output class,
1002
- to loop through the sample array, only in positions where the output is the class being trained.
1111
+ The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according \
1112
+ to the output class, to loop through the sample array, only in positions where the output is \
1113
+ the class being trained.
1003
1114
 
1004
1115
  Parameters:
1005
1116
  ---
1006
- * y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the ``X`` sample array.
1117
+ * y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the \
1118
+ ``X`` sample array.
1007
1119
 
1008
1120
  returns:
1009
1121
  ---
@@ -1011,12 +1123,14 @@ class BNSA(Base):
1011
1123
 
1012
1124
  ---
1013
1125
 
1014
- A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe de saída,
1015
- para percorrer o array de amostra, apenas nas posições que a saída for a classe que está sendo treinada.
1126
+ A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe \
1127
+ de saída, para percorrer o array de amostra, apenas nas posições que a saída for a classe que \
1128
+ está sendo treinada.
1016
1129
 
1017
1130
  Parameters:
1018
1131
  ---
1019
- * y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saida do array de amostra ``X``.
1132
+ * y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saída do array \
1133
+ de amostra ``X``.
1020
1134
 
1021
1135
  Returns:
1022
1136
  ---
@@ -1030,8 +1144,8 @@ class BNSA(Base):
1030
1144
 
1031
1145
  Details:
1032
1146
  ---
1033
- This function performs the prediction of X and checks how many elements are equal between vector y and y_predicted.
1034
- This function was added for compatibility with some scikit-learn functions.
1147
+ This function performs the prediction of X and checks how many elements are equal between vector \
1148
+ y and y_predicted. This function was added for compatibility with some scikit-learn functions.
1035
1149
 
1036
1150
  Parameters:
1037
1151
  -----------
@@ -1053,7 +1167,8 @@ class BNSA(Base):
1053
1167
 
1054
1168
  Details:
1055
1169
  ---
1056
- Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y e y_previsto.
1170
+ Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y \
1171
+ e y_previsto.
1057
1172
  Essa função foi adicionada para oferecer compatibilidade com algumas funções do scikit-learn.
1058
1173
 
1059
1174
  Parameters:
@@ -1074,8 +1189,8 @@ class BNSA(Base):
1074
1189
 
1075
1190
  def get_params(self, deep: bool = True) -> dict:
1076
1191
  return {
1077
- 'N': self.N,
1078
- 'aff_thresh': self.aff_thresh,
1079
- 'max_discards': self.max_discards,
1080
- 'seed': self.seed,
1081
- }
1192
+ "N": self.N,
1193
+ "aff_thresh": self.aff_thresh,
1194
+ "max_discards": self.max_discards,
1195
+ "seed": self.seed,
1196
+ }