aisp 0.1.1__py3-none-any.whl → 0.1.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {aisp-0.1.1.dist-info → aisp-0.1.2.dist-info}/METADATA +7 -4
- aisp-0.1.2.dist-info/RECORD +5 -0
- aisp-0.1.2.dist-info/top_level.txt +1 -0
- aisp/NSA/__init__.py +0 -4
- aisp/NSA/_negativeSelection.py +0 -1052
- aisp/_base.py +0 -198
- aisp-0.1.1.dist-info/RECORD +0 -8
- aisp-0.1.1.dist-info/top_level.txt +0 -1
- {aisp-0.1.1.dist-info → aisp-0.1.2.dist-info}/LICENSE +0 -0
- {aisp-0.1.1.dist-info → aisp-0.1.2.dist-info}/WHEEL +0 -0
@@ -1,8 +1,11 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: aisp
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.2
|
4
4
|
Summary: Package with techniques of artificial immune systems.
|
5
|
+
Home-page: https://github.com/AIS-Package/aisp
|
6
|
+
Author: João Paulo da Silva Barros
|
5
7
|
Author-email: João Paulo da Silva Barros <jpsilvabarr@gmail.com>
|
8
|
+
Maintainer: Alison Zille Lopes
|
6
9
|
Maintainer-email: Alison Zille Lopes <alisonzille@gmail.com>
|
7
10
|
License: LGPL-3.0 license
|
8
11
|
Project-URL: Homepage, https://ais-package.github.io/
|
@@ -23,7 +26,7 @@ Description-Content-Type: text/markdown
|
|
23
26
|
License-File: LICENSE
|
24
27
|
Requires-Dist: numpy (>=1.22.4)
|
25
28
|
Requires-Dist: scipy (>=1.8.1)
|
26
|
-
Requires-Dist: tqdm (
|
29
|
+
Requires-Dist: tqdm (>=4.64.1)
|
27
30
|
|
28
31
|
<div align = center>
|
29
32
|
|
@@ -72,7 +75,7 @@ Requires-Dist: tqdm (==4.64.1)
|
|
72
75
|
|
73
76
|
#### Introduction
|
74
77
|
|
75
|
-
The **AISP** is a python package that implements artificial immune systems techniques, distributed under the GNU Lesser General Public License v3.0 (
|
78
|
+
The **AISP** is a python package that implements artificial immune systems techniques, distributed under the GNU Lesser General Public License v3.0 (LGPLv3).
|
76
79
|
|
77
80
|
The package started in **2022** as a research package at the Federal Institute of Northern Minas Gerais - Salinas campus (**IFNMG - Salinas**).
|
78
81
|
|
@@ -182,7 +185,7 @@ Below are some examples that use a database for classification with the [Jupyter
|
|
182
185
|
|
183
186
|
#### Introdução
|
184
187
|
|
185
|
-
O **AISP** é um pacote python que implementa as técnicas dos sistemas imunológicos artificiais, distribuído sob a licença GNU Lesser General Public License v3.0 (
|
188
|
+
O **AISP** é um pacote python que implementa as técnicas dos sistemas imunológicos artificiais, distribuído sob a licença GNU Lesser General Public License v3.0 (LGPLv3).
|
186
189
|
|
187
190
|
O pacote teve início no ano de **2022** como um pacote de pesquisa no instituto federal do norte de minas gerais - campus salinas (**IFNMG - Salinas**).
|
188
191
|
|
@@ -0,0 +1,5 @@
|
|
1
|
+
aisp-0.1.2.dist-info/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
|
2
|
+
aisp-0.1.2.dist-info/METADATA,sha256=xFBao7vEWR_R05xAj8nfa0f3QiuYkzPRRaY5ngIjFW8,8232
|
3
|
+
aisp-0.1.2.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
4
|
+
aisp-0.1.2.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
5
|
+
aisp-0.1.2.dist-info/RECORD,,
|
@@ -0,0 +1 @@
|
|
1
|
+
|
aisp/NSA/__init__.py
DELETED
aisp/NSA/_negativeSelection.py
DELETED
@@ -1,1052 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
from tqdm import tqdm
|
4
|
-
from typing import Dict, Literal, Union
|
5
|
-
from collections import namedtuple
|
6
|
-
from scipy.spatial.distance import hamming
|
7
|
-
|
8
|
-
from aisp._base import Base
|
9
|
-
|
10
|
-
|
11
|
-
class RNSA(Base):
|
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.
|
15
|
-
|
16
|
-
Attributes:
|
17
|
-
---
|
18
|
-
* N (``int``): Number of detectors.
|
19
|
-
* r (``float``): Radius of the detector.
|
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.
|
22
|
-
* 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.
|
26
|
-
* seed (``int``): Seed for the random generation of detector values.
|
27
|
-
* algorithm(``str``), Set the algorithm version:
|
28
|
-
|
29
|
-
* ``'default-NSA'``: Default algorithm with fixed radius.
|
30
|
-
* ``'V-detector'``: This algorithm uses a variable radius for anomaly detection in feature spaces.
|
31
|
-
|
32
|
-
Defaults to ``'default-NSA'``.
|
33
|
-
|
34
|
-
* cell_bounds (``bool``): If set to ``True``, this option limits the generation of detectors to
|
35
|
-
the space within the plane between 0 and 1.
|
36
|
-
* detectors (``dict``): This variable stores a list of detectors by class.
|
37
|
-
* classes (``npt.NDArray``): list of output classes.
|
38
|
-
|
39
|
-
---
|
40
|
-
|
41
|
-
A classe ``RNSA`` (Algoritmo de Seleção Negativa de Valor Real) tem a finalidade de classificação e identificação
|
42
|
-
de anomalias através do método self e not self .
|
43
|
-
|
44
|
-
Attributes:
|
45
|
-
---
|
46
|
-
* N (``int``): Quantidade de detectores.
|
47
|
-
* r (``float``): Raio do detector.
|
48
|
-
* r_s (``float``): O valor de ``rₛ`` é o raio das amostras próprias da matriz ``X``.
|
49
|
-
* k (``int``): K quantidade de vizinhos próximos para calcular a média da distância dos detectores.
|
50
|
-
* metric (``str``): Forma de calcular a distância: ``'euclidiana', 'minkowski', or 'manhattan'``.
|
51
|
-
* max_discards (``int``): Este parâmetro indica o número máximo de descartes de detectores em sequência,
|
52
|
-
que tem como objetivo evitar um possível loop infinito caso seja definido um raio que não seja possível
|
53
|
-
gerar detectores do não-próprio.
|
54
|
-
* seed (``int``): Semente para a geração randômica dos valores dos detectores.
|
55
|
-
* algorithm (``str``), Definir a versão do algoritmo:
|
56
|
-
|
57
|
-
* ``'default-NSA'``: Algoritmo padrão com raio fixo.
|
58
|
-
* ``'V-detector'``: Este algoritmo utiliza um raio variável para a detecção de anomalias em espaços
|
59
|
-
de características.
|
60
|
-
|
61
|
-
Defaults to ``'default-NSA'``.
|
62
|
-
|
63
|
-
* cell_bounds (``bool``): Se definido como ``True``, esta opção limita a geração dos detectores ao espaço
|
64
|
-
do plano compreendido entre 0 e 1.
|
65
|
-
|
66
|
-
|
67
|
-
* detectors (``dict``): Essa variável armazena uma lista com detectores por classes.
|
68
|
-
* classes (``npt.NDArray``): lista com as classes de saída.
|
69
|
-
"""
|
70
|
-
def __init__(
|
71
|
-
self,
|
72
|
-
N: int = 100,
|
73
|
-
r: float = 0.05,
|
74
|
-
r_s: float = 0.0001,
|
75
|
-
k: int = 1,
|
76
|
-
metric: Literal['manhattan', 'minkowski', 'euclidean'] = 'euclidean',
|
77
|
-
max_discards: int = 1000,
|
78
|
-
seed: int = None,
|
79
|
-
algorithm: Literal['default-NSA', 'V-detector'] ='default-NSA',
|
80
|
-
**kwargs: Dict[str, Union[bool, str]]
|
81
|
-
):
|
82
|
-
"""
|
83
|
-
Negative Selection class constructor (``RNSA``).
|
84
|
-
|
85
|
-
Details:
|
86
|
-
---
|
87
|
-
This method initializes the ``detectors``, ``classes``, ``k``, ``metric``, ``N``, ``r``, ``r_S``,
|
88
|
-
``max_discards``, ``seed`` and ``algorithm`` attributes.
|
89
|
-
|
90
|
-
Parameters:
|
91
|
-
---
|
92
|
-
* N (``int``): Number of detectors. Defaults to ``100``.
|
93
|
-
* r (``float``): Radius of the detector. Defaults to ``0.05``.
|
94
|
-
* r_s (``float``): rₛ Radius of the ``X`` own samples. Defaults to ``0.0001``.
|
95
|
-
* k (``int``): Number of neighbors near the randomly generated detectors to perform the
|
96
|
-
distance average calculation. Defaults to ``1``.
|
97
|
-
* metric (``str``): Way to calculate the distance between the detector and the sample:
|
98
|
-
|
99
|
-
* ``'Euclidean'`` ➜ The calculation of the distance is given by the expression: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
|
100
|
-
* ``'minkowski'`` ➜ The calculation of the distance is given by the expression: ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ, In this project ``p == 2``.
|
101
|
-
* ``'manhattan'`` ➜ The calculation of the distance is given by the expression: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|) .
|
102
|
-
|
103
|
-
Defaults to ``'euclidean'``.
|
104
|
-
|
105
|
-
* max_discards (``int``): This parameter indicates the maximum number of consecutive detector discards, aimed at preventing a
|
106
|
-
possible infinite loop in case a radius is defined that cannot generate non-self detectors. Defaults to ``1000``.
|
107
|
-
* seed (``int``): Seed for the random generation of values in the detectors. Defaults to ``None``.
|
108
|
-
|
109
|
-
* algorithm(``str``), Set the algorithm version:
|
110
|
-
|
111
|
-
* ``'default-NSA'``: Default algorithm with fixed radius.
|
112
|
-
* ``'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.
|
113
|
-
|
114
|
-
Defaults to ``'default-NSA'``.
|
115
|
-
|
116
|
-
- ``**kwargs``:
|
117
|
-
- non_self_label (``str``): This variable stores the label that will be assigned when the data has only one
|
118
|
-
output class, and the sample is classified as not belonging to that class. Defaults to ``'non-self'``.
|
119
|
-
- cell_bounds (``bool``): If set to ``True``, this option limits the generation of detectors to the space within
|
120
|
-
the plane between 0 and 1. This means that any detector whose radius exceeds this limit is discarded,
|
121
|
-
this variable is only used in the ``V-detector`` algorithm. Defaults to ``False``.
|
122
|
-
|
123
|
-
---
|
124
|
-
|
125
|
-
Construtor da classe de Seleção negativa (``RNSA``).
|
126
|
-
|
127
|
-
Details:
|
128
|
-
---
|
129
|
-
Este método inicializa os atributos ``detectors``, ``classes``, ``k``, ``metric``, ``N``, ``r`` e ``seed``.
|
130
|
-
|
131
|
-
Parameters:
|
132
|
-
---
|
133
|
-
* N (``int``): Quantidade de detectores. Defaults to ``100``.
|
134
|
-
* r (``float``): Raio do detector. Defaults to ``0.05``.
|
135
|
-
* r_s (``float``): O valor de ``rₛ`` é o raio das amostras próprias da matriz ``X``. Defaults to ``0.0001``.
|
136
|
-
* k (``int``): Quantidade de vizinhos próximos dos detectores gerados aleatoriamente para efetuar o
|
137
|
-
cálculo da média da distância. Defaults to ``1``.
|
138
|
-
* metric (``str``): Forma para se calcular a distância entre o detector e a amostra:
|
139
|
-
|
140
|
-
* ``'euclidiana'`` ➜ O cálculo da distância dá-se pela expressão: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
|
141
|
-
* ``'minkowski'`` ➜ O cálculo da distância dá-se pela expressão: ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ, Neste projeto ``p == 2``.
|
142
|
-
* ``'manhattan'`` ➜ O cálculo da distância dá-se pela expressão: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|).
|
143
|
-
|
144
|
-
Defaults to ``'euclidean'``.
|
145
|
-
|
146
|
-
* 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
|
147
|
-
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``.
|
148
|
-
* seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
|
149
|
-
* algorithm (``str``), Definir a versão do algoritmo:
|
150
|
-
|
151
|
-
* ``'default-NSA'``: Algoritmo padrão com raio fixo.
|
152
|
-
* ``'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.
|
153
|
-
|
154
|
-
Defaults to ``'default-NSA'``.
|
155
|
-
|
156
|
-
- ``**kwargs``:
|
157
|
-
- non_self_label (``str``): Esta variável armazena o rótulo que será atribuído quando os dados possuírem
|
158
|
-
apenas uma classe de saída, e a amostra for classificada como não pertencente a essa classe. Defaults to ``'non-self'``.
|
159
|
-
- cell_bounds (``bool``): Se definido como ``True``, esta opção limita a geração dos detectores ao espaço do plano
|
160
|
-
compreendido entre 0 e 1. Isso significa que qualquer detector cujo raio ultrapasse esse limite é descartado,
|
161
|
-
e esta variável é usada exclusivamente no algoritmo ``V-detector``.
|
162
|
-
"""
|
163
|
-
|
164
|
-
if metric == 'manhattan' or metric == 'minkowski' or metric == 'euclidean':
|
165
|
-
self.metric = metric
|
166
|
-
else:
|
167
|
-
self.metric = 'euclidean'
|
168
|
-
|
169
|
-
if seed is not None and isinstance(seed, int):
|
170
|
-
np.random.seed(seed)
|
171
|
-
self.seed: int = seed
|
172
|
-
else:
|
173
|
-
self.seed = None
|
174
|
-
|
175
|
-
if k < 1:
|
176
|
-
self.k: int = 1
|
177
|
-
else:
|
178
|
-
self.k: int = k
|
179
|
-
|
180
|
-
if N < 1:
|
181
|
-
self.N: int = 100
|
182
|
-
else:
|
183
|
-
self.N: int = N
|
184
|
-
|
185
|
-
if r < 0:
|
186
|
-
self.r: float = 0.05
|
187
|
-
else:
|
188
|
-
self.r: float = r
|
189
|
-
|
190
|
-
if r_s > 0:
|
191
|
-
self.r_s: float = r_s
|
192
|
-
else:
|
193
|
-
self.r_s: float = 0
|
194
|
-
|
195
|
-
if algorithm == 'V-detector':
|
196
|
-
self._Detector = namedtuple("Detector", "position radius")
|
197
|
-
self._algorithm: str = algorithm
|
198
|
-
else:
|
199
|
-
self._Detector = namedtuple("Detector", "position")
|
200
|
-
self._algorithm: str = 'default-NSA'
|
201
|
-
|
202
|
-
self._cell_bounds: bool = kwargs.get('cell_bounds', False)
|
203
|
-
self.non_self_label: str = kwargs.get('non_self_label', 'non-self')
|
204
|
-
self.max_discards: int = max_discards
|
205
|
-
self.detectors: Union[dict, None] = None
|
206
|
-
self.classes: npt.NDArray = None
|
207
|
-
|
208
|
-
def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True):
|
209
|
-
"""
|
210
|
-
The function ``fit(...)``, performs the training according to ``X`` and ``y``, using the method
|
211
|
-
negative selection method(``NegativeSelect``).
|
212
|
-
|
213
|
-
Parameters:
|
214
|
-
---
|
215
|
-
* X (``npt.NDArray``): Training array, containing the samples and their characteristics,
|
216
|
-
[``N samples`` (rows)][``N features`` (columns)].
|
217
|
-
* y (``npt.NDArray``): Array of target classes of ``X`` with [``N samples`` (lines)].
|
218
|
-
* verbose (``bool``): Feedback from detector generation to the user.
|
219
|
-
returns:
|
220
|
-
---
|
221
|
-
(``self``): Returns the instance itself.
|
222
|
-
|
223
|
-
----
|
224
|
-
|
225
|
-
A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
|
226
|
-
de seleção negativa(``NegativeSelect``).
|
227
|
-
|
228
|
-
Parameters:
|
229
|
-
---
|
230
|
-
* X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características,
|
231
|
-
[``N amostras`` (linhas)][``N características`` (colunas)].
|
232
|
-
* y (``npt.NDArray``): Array com as classes alvos de ``X`` com [``N amostras`` (linhas)].
|
233
|
-
* verbose (``bool``): Feedback da geração de detectores para o usuário.
|
234
|
-
Returns:
|
235
|
-
---
|
236
|
-
(``self``): Retorna a própria instância.
|
237
|
-
"""
|
238
|
-
super()._check_and_raise_exceptions_fit(X, y)
|
239
|
-
|
240
|
-
# Identificando as classes possíveis, dentro do array de saídas ``y``.
|
241
|
-
self.classes = np.unique(y)
|
242
|
-
# Dict que armazenará os detectores com as classes como key.
|
243
|
-
list_detectors_by_class = dict()
|
244
|
-
# Separa as classes para o treinamento.
|
245
|
-
sample_index = self.__slice_index_list_by_class(y)
|
246
|
-
# Barra de progresso para a geração de todos os detectores.
|
247
|
-
if verbose:
|
248
|
-
progress = tqdm(total=int(self.N * (len(self.classes))),
|
249
|
-
bar_format='{desc} ┇{bar}┇ {n}/{total} detectors', postfix='\n')
|
250
|
-
for _class_ in self.classes:
|
251
|
-
# Inicia o conjunto vazio que conterá os detectores válidos.
|
252
|
-
valid_detectors_set = []
|
253
|
-
discard_count = 0
|
254
|
-
# Informando em qual classe o algoritmo está para a barra de progresso.
|
255
|
-
if verbose:
|
256
|
-
progress.set_description_str(
|
257
|
-
f'Generating the detectors for the {_class_} class:')
|
258
|
-
while len(valid_detectors_set) < self.N:
|
259
|
-
# Gera um vetor candidato a detector aleatoriamente com valores entre 0 e 1.
|
260
|
-
vector_x = np.random.random_sample(size=X.shape[1])
|
261
|
-
# Verifica a validade do detector para o não-próprio com relação às amostras da classe.
|
262
|
-
valid_detector = self.__checks_valid_detector(
|
263
|
-
X=X, vector_x=vector_x, samples_index_class=sample_index[_class_])
|
264
|
-
|
265
|
-
# Se o detector for válido, adicione a lista dos válidos.
|
266
|
-
if self._algorithm == 'V-detector' and valid_detector != False:
|
267
|
-
discard_count = 0
|
268
|
-
valid_detectors_set.append(
|
269
|
-
self._Detector(vector_x, valid_detector[1]))
|
270
|
-
if verbose:
|
271
|
-
progress.update(1)
|
272
|
-
elif valid_detector:
|
273
|
-
discard_count = 0
|
274
|
-
valid_detectors_set.append(self._Detector(vector_x))
|
275
|
-
if verbose:
|
276
|
-
progress.update(1)
|
277
|
-
else:
|
278
|
-
discard_count += 1
|
279
|
-
if discard_count == self.max_discards:
|
280
|
-
raise Exception('An error has been identified:\n'+
|
281
|
-
f'the maximum number of discards of detectors for the {_class_} class has been reached.\n'+
|
282
|
-
'It is recommended to check the defined radius and consider reducing its value.')
|
283
|
-
|
284
|
-
# Adicionar detectores, com as classes como chave na dict.
|
285
|
-
list_detectors_by_class[_class_] = valid_detectors_set
|
286
|
-
# Informar a finalização da geração dos detectores para as classes.
|
287
|
-
if verbose:
|
288
|
-
progress.set_description(
|
289
|
-
f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) successfully generated\033[0m')
|
290
|
-
# Armazena os detectores encontrados no atributo, para os detectores da classe.
|
291
|
-
self.detectors = list_detectors_by_class
|
292
|
-
return self
|
293
|
-
|
294
|
-
def predict(self, X: npt.NDArray) -> npt.NDArray:
|
295
|
-
"""
|
296
|
-
Function to perform the prediction of classes based on detectors
|
297
|
-
created after training.
|
298
|
-
|
299
|
-
Parameters:
|
300
|
-
---
|
301
|
-
* X (``npt.NDArray``): Array with input samples with [``N samples`` (Lines)] and
|
302
|
-
[``N characteristics``(Columns)]
|
303
|
-
|
304
|
-
returns:
|
305
|
-
---
|
306
|
-
* C – (``npt.NDArray``): an ndarray of the form ``C`` [``N samples``],
|
307
|
-
containing the predicted classes for ``X``.
|
308
|
-
* ``None``: If there are no detectors for the prediction.
|
309
|
-
|
310
|
-
---
|
311
|
-
|
312
|
-
Função para efetuar a previsão das classes com base nos detectores
|
313
|
-
criados após o treinamento.
|
314
|
-
|
315
|
-
Parameters:
|
316
|
-
---
|
317
|
-
* X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
|
318
|
-
[``N características``(Colunas)]
|
319
|
-
|
320
|
-
Returns:
|
321
|
-
---
|
322
|
-
* C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
|
323
|
-
contendo as classes previstas para ``X``.
|
324
|
-
* ``None``: Se não existir detectores para a previsão.
|
325
|
-
"""
|
326
|
-
# se não houver detectores retorna None.
|
327
|
-
if self.detectors is None:
|
328
|
-
return None
|
329
|
-
elif not isinstance(X, (np.ndarray, list)):
|
330
|
-
raise TypeError("X is not an ndarray or list")
|
331
|
-
elif len(self.detectors[self.classes[0]][0].position) != len(X[0]):
|
332
|
-
raise Exception('X does not have {} features to make the prediction'.format(
|
333
|
-
len(self.detectors[self.classes[0]][0])))
|
334
|
-
|
335
|
-
# Inicia um array vazio.
|
336
|
-
C = np.empty(shape=(0))
|
337
|
-
# Para cada linha de amostra em X.
|
338
|
-
for line in X:
|
339
|
-
class_found: bool
|
340
|
-
_class_ = self.__compare_sample_to_detectors(line)
|
341
|
-
if _class_ is None:
|
342
|
-
class_found = False
|
343
|
-
else:
|
344
|
-
C = np.append(C, [_class_])
|
345
|
-
class_found = True
|
346
|
-
|
347
|
-
# Se possuir apenas uma classe e não classificar a amostra define a saída como não-própria.
|
348
|
-
if not class_found and len(self.classes) == 1:
|
349
|
-
C = np.append(C, [self.non_self_label])
|
350
|
-
# Se não identificar a classe com os detectores, coloca a classe com a maior distância da média dos seus detectores.
|
351
|
-
elif not class_found:
|
352
|
-
average_distance = dict()
|
353
|
-
for _class_ in self.classes:
|
354
|
-
detectores = list(
|
355
|
-
map(lambda x: x.position, self.detectors[_class_]))
|
356
|
-
average_distance[_class_] = self.__distance(
|
357
|
-
np.average(detectores, axis=0), line)
|
358
|
-
C = np.append(
|
359
|
-
C, [max(average_distance, key=average_distance.get)])
|
360
|
-
return C
|
361
|
-
|
362
|
-
def __checks_valid_detector(self, X: npt.NDArray = None, vector_x: npt.NDArray = None, samples_index_class: npt.NDArray = None):
|
363
|
-
"""
|
364
|
-
Function to check if the detector has a valid non-proper ``r`` radius for the class.
|
365
|
-
|
366
|
-
Parameters:
|
367
|
-
---
|
368
|
-
* X (``npt.NDArray``): Array ``X`` with the samples.
|
369
|
-
* vector_x (``npt.NDArray``): Randomly generated vector x candidate detector with values between [0, 1].
|
370
|
-
* samples_index_class (``npt.NDArray``): Sample positions of a class in ``X``.
|
371
|
-
|
372
|
-
returns:
|
373
|
-
---
|
374
|
-
* Validity (``bool``): Returns whether the detector is valid or not.
|
375
|
-
|
376
|
-
---
|
377
|
-
|
378
|
-
Função para verificar se o detector possui raio ``r`` válido do não-próprio para a classe.
|
379
|
-
|
380
|
-
Parameters:
|
381
|
-
---
|
382
|
-
* X (``npt.NDArray``): Array ``X`` com as amostras.
|
383
|
-
* vector_x (``npt.NDArray``): Vetor x candidato a detector gerado aleatoriamente com valores entre [0, 1].
|
384
|
-
* samples_index_class (``npt.NDArray``): Posições das amostras de uma classe em ``X``.
|
385
|
-
|
386
|
-
Returns:
|
387
|
-
---
|
388
|
-
* Validade (``bool``): Retorna se o detector é válido ou não.
|
389
|
-
|
390
|
-
"""
|
391
|
-
# Se um ou mais array de entrada possuir zero dados, retorna falso.
|
392
|
-
if np.size(samples_index_class) == 0 or np.size(X) == 0 or np.size(vector_x) == 0:
|
393
|
-
return False
|
394
|
-
# se self.k > 1 utiliza os k vizinhos mais próximos (knn), se não verifica o detector sem considerar os knn,.
|
395
|
-
if self.k > 1:
|
396
|
-
# Iniciar a lista dos knn vazia.
|
397
|
-
knn_list = np.empty(shape=(0))
|
398
|
-
for i in samples_index_class:
|
399
|
-
# 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.
|
400
|
-
knn_list = self.__compare_KnearestNeighbors_List(
|
401
|
-
knn_list, self.__distance(X[i], vector_x))
|
402
|
-
# Se a média das distâncias na lista dos knn, for menor que o raio, retorna verdadeiro.
|
403
|
-
distance_mean = np.mean(knn_list)
|
404
|
-
if self._algorithm == 'V-detector':
|
405
|
-
return self.__detector_is_valid_to_Vdetector(distance_mean, vector_x)
|
406
|
-
elif distance_mean > (self.r + self.r_s):
|
407
|
-
return True # Detector é valido!
|
408
|
-
else:
|
409
|
-
distance: Union[float, None] = None
|
410
|
-
for i in samples_index_class:
|
411
|
-
if self._algorithm == 'V-detector':
|
412
|
-
new_distance = self.__distance(X[i], vector_x)
|
413
|
-
if distance is None:
|
414
|
-
distance = new_distance
|
415
|
-
elif distance > new_distance:
|
416
|
-
distance = new_distance
|
417
|
-
else:
|
418
|
-
# Calcula a distância entre os vetores, se menor ou igual ao raio + raio da amostra define a validade do detector como falso.
|
419
|
-
if (self.r + self.r_s) >= self.__distance(X[i], vector_x):
|
420
|
-
return False # Detector não é valido!
|
421
|
-
|
422
|
-
if self._algorithm == 'V-detector':
|
423
|
-
return self.__detector_is_valid_to_Vdetector(distance, vector_x)
|
424
|
-
return True # Detector é valido!
|
425
|
-
|
426
|
-
return False # Detector não é valido!
|
427
|
-
|
428
|
-
def __compare_KnearestNeighbors_List(self, knn: npt.NDArray, distance: float) -> npt.NDArray:
|
429
|
-
"""
|
430
|
-
Compares the k-nearest neighbor distance at position ``k-1`` in the list ``knn``,
|
431
|
-
if the distance of the new sample is less, replace it and sort in ascending order.
|
432
|
-
|
433
|
-
|
434
|
-
Parameters:
|
435
|
-
---
|
436
|
-
knn (npt.NDArray): List of k-nearest neighbor distances.
|
437
|
-
distance (float): Distance to check.
|
438
|
-
|
439
|
-
returns:
|
440
|
-
---
|
441
|
-
npt.NDArray: Updated and sorted nearest neighbor list.
|
442
|
-
|
443
|
-
---
|
444
|
-
|
445
|
-
Compara a distância do k-vizinho mais próximo na posição ``k-1``da lista ``knn``,
|
446
|
-
se a distância da nova amostra for menor, substitui ela e ordena em ordem crescente.
|
447
|
-
|
448
|
-
|
449
|
-
Parameters:
|
450
|
-
---
|
451
|
-
knn (npt.NDArray): Lista de distâncias dos k-vizinhos mais próximos.
|
452
|
-
distance (float): Distância a ser verificada.
|
453
|
-
|
454
|
-
Returns:
|
455
|
-
---
|
456
|
-
npt.NDArray: Lista de vizinhos mais próximos atualizada e ordenada.
|
457
|
-
"""
|
458
|
-
# Se a quantidade de distâncias em knn, for menor que k, adiciona a distância.
|
459
|
-
if (len(knn) < self.k):
|
460
|
-
knn = np.append(knn, distance)
|
461
|
-
knn.sort()
|
462
|
-
else:
|
463
|
-
# Se não, adicione a distância, se a nova distancia for menor que a maior distância da lista.
|
464
|
-
if (knn[self.k - 1] > distance):
|
465
|
-
knn[self.k - 1] = distance
|
466
|
-
knn.sort()
|
467
|
-
|
468
|
-
return knn
|
469
|
-
|
470
|
-
def __compare_sample_to_detectors(self, line: npt.NDArray):
|
471
|
-
"""
|
472
|
-
Function to compare a sample with the detectors, verifying if the sample is proper.
|
473
|
-
|
474
|
-
Details:
|
475
|
-
---
|
476
|
-
In this function, when there is class ambiguity, it returns the class that has the greatest
|
477
|
-
average distance between the detectors.
|
478
|
-
|
479
|
-
Parameters:
|
480
|
-
---
|
481
|
-
* line: vector with N-features
|
482
|
-
|
483
|
-
returns:
|
484
|
-
---
|
485
|
-
* Returns the predicted class with the detectors or None if the sample does not qualify for any class.
|
486
|
-
|
487
|
-
---
|
488
|
-
|
489
|
-
Função para comparar uma amostra com os detectores, verificando se a amostra é própria.
|
490
|
-
|
491
|
-
Details:
|
492
|
-
---
|
493
|
-
Nesta função, quando possui ambiguidade de classes, retorna a classe que possuir a média de distância
|
494
|
-
maior entre os detectores.
|
495
|
-
|
496
|
-
Parameters:
|
497
|
-
---
|
498
|
-
* line: vetor com N-características
|
499
|
-
|
500
|
-
Returns:
|
501
|
-
---
|
502
|
-
* Retorna a classe prevista com os detectores ou None se a amostra não se qualificar a nenhuma classe.
|
503
|
-
"""
|
504
|
-
|
505
|
-
# Lista para armazenar as classes e a distância média entre os detectores e a amostra.
|
506
|
-
possible_classes = []
|
507
|
-
for _class_ in self.classes:
|
508
|
-
# Variável para identificar, se a classe foi encontrada com os detectores.
|
509
|
-
class_found: bool = True
|
510
|
-
sum_distance = 0 # Variável para fazer o somatório das distâncias.
|
511
|
-
for detector in self.detectors[_class_]:
|
512
|
-
# Calcula a distância entre a amostra e os detectores.
|
513
|
-
distance = self.__distance(detector.position, line)
|
514
|
-
# Soma as distâncias para calcular a média.
|
515
|
-
sum_distance += distance
|
516
|
-
if self._algorithm == 'V-detector':
|
517
|
-
if distance <= detector.radius:
|
518
|
-
class_found = False
|
519
|
-
break
|
520
|
-
elif distance <= self.r:
|
521
|
-
class_found = False
|
522
|
-
break
|
523
|
-
|
524
|
-
# Se a amostra passar por todos os detectores de uma classe, adiciona a classe como possivel previsão.
|
525
|
-
if class_found:
|
526
|
-
possible_classes.append([_class_, sum_distance/self.N])
|
527
|
-
# Se classificar como pertencentes a apenas uma classe, retorna a classe.
|
528
|
-
if len(possible_classes) == 1:
|
529
|
-
return possible_classes[0][0]
|
530
|
-
# Se, pertencer a mais de uma classe, retorna a classe com a distância média mais distante.
|
531
|
-
elif len(possible_classes) > 1:
|
532
|
-
return max(possible_classes, key=lambda x: x[1])[0]
|
533
|
-
else: # Se não, retorna None
|
534
|
-
return None
|
535
|
-
|
536
|
-
def __distance(self, u: npt.NDArray, v: npt.NDArray):
|
537
|
-
"""
|
538
|
-
Function to calculate the distance between two points by the chosen ``metric``.
|
539
|
-
|
540
|
-
Parameters:
|
541
|
-
---
|
542
|
-
* u (``npt.NDArray``): Coordinates of the first point.
|
543
|
-
* v (``npt.NDArray``): Coordinates of the second point.
|
544
|
-
|
545
|
-
returns:
|
546
|
-
---
|
547
|
-
* Distance (``double``) between the two points.
|
548
|
-
|
549
|
-
---
|
550
|
-
|
551
|
-
Função para calcular a distância entre dois pontos pela ``metric`` escolhida.
|
552
|
-
|
553
|
-
Parameters:
|
554
|
-
---
|
555
|
-
* u (``npt.NDArray``): Coordenadas do primeiro ponto.
|
556
|
-
* v (``npt.NDArray``): Coordenadas do segundo ponto.
|
557
|
-
|
558
|
-
Returns:
|
559
|
-
---
|
560
|
-
* Distância (``double``) entre os dois pontos.
|
561
|
-
"""
|
562
|
-
return super()._distance(u, v)
|
563
|
-
|
564
|
-
def __detector_is_valid_to_Vdetector(self, distance: float, vector_x: npt.NDArray):
|
565
|
-
"""
|
566
|
-
Check if the distance between the detector and the samples, minus the radius of the samples,
|
567
|
-
is greater than the minimum radius.
|
568
|
-
|
569
|
-
Parameters:
|
570
|
-
---
|
571
|
-
distance (``float``): minimum distance calculated between all samples.
|
572
|
-
vector_x (``numpy.ndarray``): randomly generated candidate detector vector x with values between 0 and 1.
|
573
|
-
Returns:
|
574
|
-
---
|
575
|
-
* ``False``: if the calculated radius is smaller than the minimum distance or exceeds the edge of the space,
|
576
|
-
if this option is enabled.
|
577
|
-
* ``True`` and the distance minus the radius of the samples, if the radius is valid.`
|
578
|
-
|
579
|
-
----
|
580
|
-
|
581
|
-
Verifique se a distância entre o detector e as amostras, descontando o raio das amostras, é maior do que o raio mínimo.
|
582
|
-
|
583
|
-
Parameters:
|
584
|
-
---
|
585
|
-
distance (``float``): distância mínima calculada entre todas as amostras.
|
586
|
-
vector_x (``numpy.ndarray``): vetor x candidato do detector gerado aleatoriamente, com valores entre 0 e 1.
|
587
|
-
|
588
|
-
Returns:
|
589
|
-
---
|
590
|
-
|
591
|
-
* ``False``: caso o raio calculado seja menor do que a distância mínima ou ultrapasse a borda do espaço,
|
592
|
-
caso essa opção esteja habilitada.
|
593
|
-
* ``True`` e a distância menos o raio das amostras, caso o raio seja válido.
|
594
|
-
"""
|
595
|
-
new_detector_r = float(distance - self.r_s)
|
596
|
-
if self.r >= new_detector_r:
|
597
|
-
return False # Detector não é valido!
|
598
|
-
else:
|
599
|
-
# se _cell_bounds igual a True, considera o detector esta dentro do limite do plano.
|
600
|
-
if self._cell_bounds:
|
601
|
-
for p in vector_x:
|
602
|
-
if (p - new_detector_r) < 0 or (p + new_detector_r) > 1:
|
603
|
-
return False
|
604
|
-
return True, new_detector_r
|
605
|
-
|
606
|
-
def __slice_index_list_by_class(self, y: npt.NDArray) -> dict:
|
607
|
-
"""
|
608
|
-
The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according to the output class,
|
609
|
-
to loop through the sample array, only in positions where the output is the class being trained.
|
610
|
-
|
611
|
-
Parameters:
|
612
|
-
---
|
613
|
-
* y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the ``X`` sample array.
|
614
|
-
|
615
|
-
returns:
|
616
|
-
---
|
617
|
-
* dict: A dictionary with the list of array positions(``y``), with the classes as key.
|
618
|
-
|
619
|
-
---
|
620
|
-
|
621
|
-
A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe de saída,
|
622
|
-
para percorrer o array de amostra, apenas nas posições que a saída for a classe que está sendo treinada.
|
623
|
-
|
624
|
-
Parameters:
|
625
|
-
---
|
626
|
-
* y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saida do array de amostra ``X``.
|
627
|
-
|
628
|
-
Returns:
|
629
|
-
---
|
630
|
-
* dict: Um dicionário com a lista de posições do array(``y``), com as classes como chave.
|
631
|
-
"""
|
632
|
-
return super()._slice_index_list_by_class(y)
|
633
|
-
|
634
|
-
def score(self, X: npt.NDArray, y: list) -> float:
|
635
|
-
"""
|
636
|
-
Score function calculates forecast accuracy.
|
637
|
-
|
638
|
-
Details:
|
639
|
-
---
|
640
|
-
This function performs the prediction of X and checks how many elements are equal between vector y and y_predicted.
|
641
|
-
This function was added for compatibility with some scikit-learn functions.
|
642
|
-
|
643
|
-
Parameters:
|
644
|
-
-----------
|
645
|
-
|
646
|
-
X: np.ndarray
|
647
|
-
Feature set with shape (n_samples, n_features).
|
648
|
-
y: np.ndarray
|
649
|
-
True values with shape (n_samples,).
|
650
|
-
|
651
|
-
Returns:
|
652
|
-
-------
|
653
|
-
|
654
|
-
accuracy: float
|
655
|
-
The accuracy of the model.
|
656
|
-
|
657
|
-
---
|
658
|
-
|
659
|
-
Função score calcular a acurácia da previsão.
|
660
|
-
|
661
|
-
Details:
|
662
|
-
---
|
663
|
-
Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y e y_previsto.
|
664
|
-
Essa função foi adicionada para oferecer compatibilidade com algumas funções do scikit-learn.
|
665
|
-
|
666
|
-
Parameters:
|
667
|
-
---
|
668
|
-
|
669
|
-
* X : np.ndarray
|
670
|
-
Conjunto de características com shape (n_samples, n_features).
|
671
|
-
* y : np.ndarray
|
672
|
-
Valores verdadeiros com shape (n_samples,).
|
673
|
-
|
674
|
-
returns:
|
675
|
-
---
|
676
|
-
|
677
|
-
accuracy : float
|
678
|
-
A acurácia do modelo.
|
679
|
-
"""
|
680
|
-
return super()._score(X, y)
|
681
|
-
|
682
|
-
def get_params(self, deep: bool = True) -> dict:
|
683
|
-
return {
|
684
|
-
'N': self.N,
|
685
|
-
'r': self.r,
|
686
|
-
'k': self.k,
|
687
|
-
'metric': self.metric,
|
688
|
-
'seed': self.seed,
|
689
|
-
'algorithm': self._algorithm,
|
690
|
-
'r_s': self.r_s,
|
691
|
-
'cell_bounds': self._cell_bounds
|
692
|
-
}
|
693
|
-
|
694
|
-
class BNSA(Base):
|
695
|
-
"""
|
696
|
-
The ``BNSA`` (Binary Negative Selection Algorithm) class is for classification and identification purposes.
|
697
|
-
of anomalies through the self and not self method.
|
698
|
-
|
699
|
-
Attributes:
|
700
|
-
---
|
701
|
-
|
702
|
-
* N (``int``): Number of detectors.
|
703
|
-
* aff_thresh (``float``): The variable represents the percentage of similarity between the T cell and the own samples.
|
704
|
-
* max_discards (``int``): This parameter indicates the maximum number of detector discards in sequence, which aims to avoid a
|
705
|
-
possible infinite loop if a radius is defined that it is not possible to generate non-self detectors.
|
706
|
-
* seed (``int``): Seed for the random generation of values in the detectors.
|
707
|
-
|
708
|
-
* detectors (``dict``): This variable stores a list of detectors by class.
|
709
|
-
* classes (``npt.NDArray``): list of output classes.
|
710
|
-
|
711
|
-
|
712
|
-
---
|
713
|
-
|
714
|
-
A classe ``BNSA`` (Algoritmo de Seleção Negativa Binária) tem a finalidade de classificação e identificação
|
715
|
-
de anomalias através do método self e not self .
|
716
|
-
|
717
|
-
Attributes:
|
718
|
-
---
|
719
|
-
* N (``int``): Quantidade de detectores. Defaults to ``100``.
|
720
|
-
* aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a célula T e as amostras próprias.
|
721
|
-
O valor padrão é de 10% (0,1), enquanto que o valor de 1,0 representa 100% de similaridade.
|
722
|
-
* 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
|
723
|
-
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``.
|
724
|
-
* seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
|
725
|
-
|
726
|
-
* detectors (``dict``): Essa variável armazena uma lista com detectores por classes.
|
727
|
-
* classes (``npt.NDArray``): lista com as classes de saída.
|
728
|
-
|
729
|
-
"""
|
730
|
-
def __init__(
|
731
|
-
self,
|
732
|
-
N: int = 100,
|
733
|
-
aff_thresh: float = 0.1,
|
734
|
-
max_discards: int = 1000,
|
735
|
-
seed: int = None
|
736
|
-
):
|
737
|
-
"""
|
738
|
-
Constructor of the Negative Selection class (``BNSA``).
|
739
|
-
|
740
|
-
Details:
|
741
|
-
---
|
742
|
-
This method initializes the ``detectors``, ``classes``, ``N``, ``t`` and ``seed`` attributes.
|
743
|
-
|
744
|
-
Parameters:
|
745
|
-
---
|
746
|
-
* N (``int``): Number of detectors. Defaults to ``100``.
|
747
|
-
* aff_thresh (``float``): The variable represents the percentage of similarity between the T cell and the own samples.
|
748
|
-
The default value is 10% (0.1), while a value of 1.0 represents 100% similarity.
|
749
|
-
* max_discards (``int``): This parameter indicates the maximum number of detector discards in sequence, which aims to avoid a
|
750
|
-
possible infinite loop if a radius is defined that it is not possible to generate non-self detectors. Defaults to ``1000``.
|
751
|
-
* seed (``int``): Seed for the random generation of values in the detectors. Defaults to ``None``.
|
752
|
-
|
753
|
-
---
|
754
|
-
|
755
|
-
Construtor da classe de Seleção negativa (``BNSA``).
|
756
|
-
|
757
|
-
Details:
|
758
|
-
---
|
759
|
-
Este método inicializa os atributos ``detectors``, ``classes``, ``N``, ``t`` e ``seed``.
|
760
|
-
|
761
|
-
Parameters:
|
762
|
-
---
|
763
|
-
* N (``int``): Quantidade de detectores. Defaults to ``100``.
|
764
|
-
* aff_thresh (``float``): A variável representa a porcentagem de similaridade entre a célula T e as amostras próprias.
|
765
|
-
O valor padrão é de 10% (0,1), enquanto que o valor de 1,0 representa 100% de similaridade.
|
766
|
-
* 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
|
767
|
-
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``.
|
768
|
-
* seed (``int``): Semente para a geração randômica dos valores nos detectores. Defaults to ``None``.
|
769
|
-
"""
|
770
|
-
if N > 0:
|
771
|
-
self.N: int = N
|
772
|
-
else:
|
773
|
-
self.N: int = 100
|
774
|
-
|
775
|
-
if aff_thresh > 0 and aff_thresh < 1:
|
776
|
-
self.aff_thresh: float = aff_thresh
|
777
|
-
else:
|
778
|
-
self.aff_thresh: float = 0.1
|
779
|
-
if max_discards > 0:
|
780
|
-
self.max_discards: int = max_discards
|
781
|
-
else:
|
782
|
-
self.max_discards: int = 0
|
783
|
-
|
784
|
-
if seed is not None and isinstance(seed, int):
|
785
|
-
np.random.seed(seed)
|
786
|
-
self.seed: int = seed
|
787
|
-
else:
|
788
|
-
self.seed = None
|
789
|
-
self.classes: npt.NDArray = None
|
790
|
-
self.detectors: npt.NDArray = None
|
791
|
-
|
792
|
-
def fit(self, X: npt.NDArray, y: npt.NDArray, verbose: bool = True):
|
793
|
-
"""
|
794
|
-
The function ``fit(...)``, performs the training according to ``X`` and ``y``, using the method
|
795
|
-
negative selection method(``NegativeSelect``).
|
796
|
-
|
797
|
-
Parameters:
|
798
|
-
---
|
799
|
-
* X (``npt.NDArray``): Training array, containing the samples and their characteristics,
|
800
|
-
[``N samples`` (rows)][``N features`` (columns)].
|
801
|
-
* y (``npt.NDArray``): Array of target classes of ``X`` with [``N samples`` (lines)].
|
802
|
-
* verbose (``bool``): Feedback from detector generation to the user.
|
803
|
-
returns:
|
804
|
-
---
|
805
|
-
(``self``): Returns the instance itself.
|
806
|
-
|
807
|
-
----
|
808
|
-
|
809
|
-
A função ``fit(...)``, realiza o treinamento de acordo com ``X`` e ``y``, usando o método
|
810
|
-
de seleção negativa(``NegativeSelect``).
|
811
|
-
|
812
|
-
Parameters:
|
813
|
-
---
|
814
|
-
* X (``npt.NDArray``): Array de treinamento, contendo as amostras é suas características,
|
815
|
-
[``N amostras`` (linhas)][``N características`` (colunas)].
|
816
|
-
* y (``npt.NDArray``): Array com as classes alvos de ``X`` com [``N amostras`` (linhas)].
|
817
|
-
* verbose (``bool``): Feedback da geração de detectores para o usuário.
|
818
|
-
Returns:
|
819
|
-
---
|
820
|
-
(``self``): Retorna a própria instância.
|
821
|
-
"""
|
822
|
-
super()._check_and_raise_exceptions_fit(X, y, 'BNSA')
|
823
|
-
|
824
|
-
if X.dtype != bool:
|
825
|
-
X = X.astype(bool)
|
826
|
-
|
827
|
-
self.classes = np.unique(y)
|
828
|
-
# Dict que armazenará os detectores com as classes como key.
|
829
|
-
list_detectors_by_class = dict()
|
830
|
-
# Separa as classes para o treinamento.
|
831
|
-
sample_index: dict = self.__slice_index_list_by_class(y)
|
832
|
-
# Barra de progresso para a geração de todos os detectores.
|
833
|
-
if verbose:
|
834
|
-
progress = tqdm(total=int(self.N * (len(self.classes))),
|
835
|
-
bar_format='{desc} ┇{bar}┇ {n}/{total} detectors', postfix='\n')
|
836
|
-
|
837
|
-
for _class_ in self.classes:
|
838
|
-
# Inicia o conjunto vazio que conterá os detectores válidos.
|
839
|
-
valid_detectors_set: list = []
|
840
|
-
discard_count: int = 0
|
841
|
-
# Informando em qual classe o algoritmo está para a barra de progresso.
|
842
|
-
if verbose:
|
843
|
-
progress.set_description_str(
|
844
|
-
f'Generating the detectors for the {_class_} class:')
|
845
|
-
while len(valid_detectors_set) < self.N:
|
846
|
-
|
847
|
-
is_valid_detector: bool = True
|
848
|
-
# Gera um vetor candidato a detector aleatoriamente com valores 0 e 1.
|
849
|
-
vector_x = np.random.randint(0, 2, X.shape[1], dtype=bool)
|
850
|
-
for i in sample_index[_class_]:
|
851
|
-
# Verifica a validade do detector para o não-próprio com relação às amostras da classe.
|
852
|
-
if hamming(X[i], vector_x) <= self.aff_thresh:
|
853
|
-
is_valid_detector = False
|
854
|
-
break
|
855
|
-
# Se o detector for válido, adicione a lista dos válidos.
|
856
|
-
if is_valid_detector:
|
857
|
-
discard_count = 0
|
858
|
-
valid_detectors_set.append(vector_x)
|
859
|
-
if verbose:
|
860
|
-
progress.update(1)
|
861
|
-
else:
|
862
|
-
discard_count += 1
|
863
|
-
if discard_count == self.max_discards:
|
864
|
-
raise Exception('An error has been identified:\n'+
|
865
|
-
f'the maximum number of discards of detectors for the {_class_} class has been reached.\n'+
|
866
|
-
'It is recommended to check the defined radius and consider reducing its value.')
|
867
|
-
|
868
|
-
# Adicionar detectores, com as classes como chave na dict.
|
869
|
-
list_detectors_by_class[_class_] = valid_detectors_set
|
870
|
-
|
871
|
-
# Informar a finalização da geração dos detectores para as classes.
|
872
|
-
if verbose:
|
873
|
-
progress.set_description(
|
874
|
-
f'\033[92m✔ Non-self detectors for classes ({", ".join(map(str, self.classes))}) successfully generated\033[0m')
|
875
|
-
# Armazena os detectores encontrados no atributo, para os detectores da classe.
|
876
|
-
self.detectors = list_detectors_by_class
|
877
|
-
return self
|
878
|
-
|
879
|
-
def predict(self, X: npt.NDArray) -> npt.NDArray:
|
880
|
-
"""
|
881
|
-
Function to perform the prediction of classes based on detectors
|
882
|
-
created after training.
|
883
|
-
|
884
|
-
Parameters:
|
885
|
-
---
|
886
|
-
* X (``npt.NDArray``): Array with input samples with [``N samples`` (Lines)] and
|
887
|
-
[``N characteristics``(Columns)]
|
888
|
-
|
889
|
-
returns:
|
890
|
-
---
|
891
|
-
* C – (``npt.NDArray``): an ndarray of the form ``C`` [``N samples``],
|
892
|
-
containing the predicted classes for ``X``.
|
893
|
-
* ``None``: If there are no detectors for the prediction.
|
894
|
-
|
895
|
-
---
|
896
|
-
|
897
|
-
Função para efetuar a previsão das classes com base nos detectores
|
898
|
-
criados após o treinamento.
|
899
|
-
|
900
|
-
Parameters:
|
901
|
-
---
|
902
|
-
* X (``npt.NDArray``): Array com as amostras de entradas com [``N amostras`` (Linhas)] e
|
903
|
-
[``N características``(Colunas)]
|
904
|
-
|
905
|
-
Returns:
|
906
|
-
---
|
907
|
-
* C – (``npt.NDArray``): um ndarray de forma ``C`` [``N amostras``],
|
908
|
-
contendo as classes previstas para ``X``.
|
909
|
-
* ``None``: Se não existir detectores para a previsão.
|
910
|
-
"""
|
911
|
-
# se não houver detectores retorna None.
|
912
|
-
if self.detectors is None:
|
913
|
-
return None
|
914
|
-
elif not isinstance(X, (np.ndarray, list)):
|
915
|
-
raise TypeError("X is not an ndarray or list")
|
916
|
-
elif len(self.detectors[self.classes[0]][0]) != len(X[0]):
|
917
|
-
raise Exception('X does not have {} features to make the prediction'.format(
|
918
|
-
len(self.detectors[self.classes[0]][0])))
|
919
|
-
# Verifica se a matriz X contém apenas amostras binárias. Caso contrário, lança uma exceção.
|
920
|
-
if not np.isin(X, [0, 1]).all():
|
921
|
-
raise ValueError(
|
922
|
-
"The array X contains values that are not composed only of 0 and 1.")
|
923
|
-
|
924
|
-
if X.dtype != bool:
|
925
|
-
X = X.astype(bool)
|
926
|
-
|
927
|
-
# Inicia um array vazio.
|
928
|
-
C = np.empty(shape=(0))
|
929
|
-
# Para cada linha de amostra em X.
|
930
|
-
for line in X:
|
931
|
-
class_found: bool = True
|
932
|
-
# Lista para armazenar as possíveis classes às quais a amostra se adequou ao self na comparação com os detectores non-self.
|
933
|
-
possible_classes: list = []
|
934
|
-
for _class_ in self.classes:
|
935
|
-
# Lista para armzenar as taxas de similaridade entre a amostra e os detectores.
|
936
|
-
similarity_list: list = []
|
937
|
-
for detector in self.detectors[_class_]:
|
938
|
-
similarity = hamming(line, detector)
|
939
|
-
if similarity <= self.aff_thresh:
|
940
|
-
class_found = False
|
941
|
-
break
|
942
|
-
else:
|
943
|
-
similarity_list.append(similarity)
|
944
|
-
# Se a amostra passar por todos os detectores de uma classe, adiciona a classe como possivel previsão e sua media de similaridade.
|
945
|
-
if class_found:
|
946
|
-
possible_classes.append([_class_, min(similarity_list)])
|
947
|
-
|
948
|
-
# Se, pertencer a uma ou mais classes, adiciona a classe com a distância média mais distante.
|
949
|
-
if len(possible_classes) > 0 :
|
950
|
-
C = np.append(C, [max(possible_classes, key=lambda x: x[1])[0]])
|
951
|
-
class_found = True
|
952
|
-
else:
|
953
|
-
class_found = False
|
954
|
-
|
955
|
-
# Se possuir apenas uma classe e não classificar a amostra define a saída como não-própria.
|
956
|
-
if not class_found and len(self.classes) == 1:
|
957
|
-
C = np.append(C, ['non-self'])
|
958
|
-
# Se não identificar a classe com os detectores, coloca a classe com a maior distância da média dos seus detectores.
|
959
|
-
elif not class_found:
|
960
|
-
class_differences = []
|
961
|
-
for _class_ in self.classes:
|
962
|
-
differences = []
|
963
|
-
for detector in self.detectors[_class_]:
|
964
|
-
differences.append(hamming(line, detector))
|
965
|
-
class_differences.append(min(differences))
|
966
|
-
C = np.append(C, [self.classes[class_differences.index(max(class_differences))]])
|
967
|
-
|
968
|
-
return C
|
969
|
-
|
970
|
-
def __slice_index_list_by_class(self, y: npt.NDArray) -> dict:
|
971
|
-
"""
|
972
|
-
The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according to the output class,
|
973
|
-
to loop through the sample array, only in positions where the output is the class being trained.
|
974
|
-
|
975
|
-
Parameters:
|
976
|
-
---
|
977
|
-
* y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the ``X`` sample array.
|
978
|
-
|
979
|
-
returns:
|
980
|
-
---
|
981
|
-
* dict: A dictionary with the list of array positions(``y``), with the classes as key.
|
982
|
-
|
983
|
-
---
|
984
|
-
|
985
|
-
A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe de saída,
|
986
|
-
para percorrer o array de amostra, apenas nas posições que a saída for a classe que está sendo treinada.
|
987
|
-
|
988
|
-
Parameters:
|
989
|
-
---
|
990
|
-
* y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saida do array de amostra ``X``.
|
991
|
-
|
992
|
-
Returns:
|
993
|
-
---
|
994
|
-
* dict: Um dicionário com a lista de posições do array(``y``), com as classes como chave.
|
995
|
-
"""
|
996
|
-
return super()._slice_index_list_by_class(y)
|
997
|
-
|
998
|
-
def score(self, X: npt.NDArray, y: list) -> float:
|
999
|
-
"""
|
1000
|
-
Score function calculates forecast accuracy.
|
1001
|
-
|
1002
|
-
Details:
|
1003
|
-
---
|
1004
|
-
This function performs the prediction of X and checks how many elements are equal between vector y and y_predicted.
|
1005
|
-
This function was added for compatibility with some scikit-learn functions.
|
1006
|
-
|
1007
|
-
Parameters:
|
1008
|
-
-----------
|
1009
|
-
|
1010
|
-
X: np.ndarray
|
1011
|
-
Feature set with shape (n_samples, n_features).
|
1012
|
-
y: np.ndarray
|
1013
|
-
True values with shape (n_samples,).
|
1014
|
-
|
1015
|
-
Returns:
|
1016
|
-
-------
|
1017
|
-
|
1018
|
-
accuracy: float
|
1019
|
-
The accuracy of the model.
|
1020
|
-
|
1021
|
-
---
|
1022
|
-
|
1023
|
-
Função score calcular a acurácia da previsão.
|
1024
|
-
|
1025
|
-
Details:
|
1026
|
-
---
|
1027
|
-
Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y e y_previsto.
|
1028
|
-
Essa função foi adicionada para oferecer compatibilidade com algumas funções do scikit-learn.
|
1029
|
-
|
1030
|
-
Parameters:
|
1031
|
-
---
|
1032
|
-
|
1033
|
-
* X : np.ndarray
|
1034
|
-
Conjunto de características com shape (n_samples, n_features).
|
1035
|
-
* y : np.ndarray
|
1036
|
-
Valores verdadeiros com shape (n_samples,).
|
1037
|
-
|
1038
|
-
returns:
|
1039
|
-
---
|
1040
|
-
|
1041
|
-
accuracy : float
|
1042
|
-
A acurácia do modelo.
|
1043
|
-
"""
|
1044
|
-
return super()._score(X, y)
|
1045
|
-
|
1046
|
-
def get_params(self, deep: bool = True) -> dict:
|
1047
|
-
return {
|
1048
|
-
'N': self.N,
|
1049
|
-
'aff_thresh': self.aff_thresh,
|
1050
|
-
'max_discards': self.max_discards,
|
1051
|
-
'seed': self.seed,
|
1052
|
-
}
|
aisp/_base.py
DELETED
@@ -1,198 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import numpy.typing as npt
|
3
|
-
from typing import Literal
|
4
|
-
from scipy.spatial.distance import euclidean, cityblock, minkowski
|
5
|
-
|
6
|
-
class Base:
|
7
|
-
"""
|
8
|
-
The base class contains functions that are used by more than one class in the package,
|
9
|
-
and therefore are considered essential for the overall functioning of the system.
|
10
|
-
|
11
|
-
---
|
12
|
-
|
13
|
-
A classe base contém funções que são utilizadas por mais de uma classe do pacote,
|
14
|
-
e por isso são consideradas essenciais para o funcionamento geral do sistema.
|
15
|
-
"""
|
16
|
-
def __init__(self, metric: str = 'euclidean'):
|
17
|
-
"""
|
18
|
-
Parameters:
|
19
|
-
---
|
20
|
-
* metric (``str``): Way to calculate the distance between the detector and the sample:
|
21
|
-
|
22
|
-
* ``'Euclidean'`` ➜ The calculation of the distance is given by the expression: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
|
23
|
-
* ``'minkowski'`` ➜ The calculation of the distance is given by the expression: ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ , In this project ``p == 2``.
|
24
|
-
* ``'manhattan'`` ➜ The calculation of the distance is given by the expression: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|) .
|
25
|
-
|
26
|
-
---
|
27
|
-
|
28
|
-
Parameters:
|
29
|
-
---
|
30
|
-
* metric (``str``): Forma para se calcular a distância entre o detector e a amostra:
|
31
|
-
|
32
|
-
* ``'euclidiana'`` ➜ O cálculo da distância dá-se pela expressão: √( (x₁ – x₂)² + (y₁ – y₂)² + ... + (yn – yn)²).
|
33
|
-
* ``'minkowski'`` ➜ O cálculo da distância dá-se pela expressão: ( |X₁ – Y₁|p + |X₂ – Y₂|p + ... + |Xn – Yn|p) ¹/ₚ , Neste projeto ``p == 2``.
|
34
|
-
* ``'manhattan'`` ➜ O cálculo da distância dá-se pela expressão: ( |x₁ – x₂| + |y₁ – y₂| + ... + |yn – yn|).
|
35
|
-
|
36
|
-
Defaults to ``'euclidean'``.
|
37
|
-
"""
|
38
|
-
if metric == 'manhattan' or metric == 'minkowski' or metric == 'euclidean':
|
39
|
-
self.metric = metric
|
40
|
-
else:
|
41
|
-
self.metric = 'euclidean'
|
42
|
-
|
43
|
-
def _distance(self, u: npt.NDArray, v: npt.NDArray):
|
44
|
-
"""
|
45
|
-
Function to calculate the distance between two points by the chosen ``metric``.
|
46
|
-
|
47
|
-
Parameters:
|
48
|
-
---
|
49
|
-
* u (``npt.NDArray``): Coordinates of the first point.
|
50
|
-
* v (``npt.NDArray``): Coordinates of the second point.
|
51
|
-
|
52
|
-
returns:
|
53
|
-
---
|
54
|
-
* Distance (``double``) between the two points.
|
55
|
-
|
56
|
-
---
|
57
|
-
|
58
|
-
Função para calcular a distância entre dois pontos pela ``metric`` escolhida.
|
59
|
-
|
60
|
-
Parameters:
|
61
|
-
---
|
62
|
-
* u (``npt.NDArray``): Coordenadas do primeiro ponto.
|
63
|
-
* v (``npt.NDArray``): Coordenadas do segundo ponto.
|
64
|
-
|
65
|
-
Returns:
|
66
|
-
---
|
67
|
-
* Distância (``double``) entre os dois pontos.
|
68
|
-
"""
|
69
|
-
if self.metric == 'manhattan':
|
70
|
-
return cityblock(u, v)
|
71
|
-
elif self.metric == 'minkowski':
|
72
|
-
return minkowski(u, v, 2)
|
73
|
-
else:
|
74
|
-
return euclidean(u, v)
|
75
|
-
|
76
|
-
def _check_and_raise_exceptions_fit(self, X: npt.NDArray = None, y: npt.NDArray = None, _class_: Literal['RNSA', 'BNSA'] = 'RNSA'):
|
77
|
-
"""
|
78
|
-
Function responsible for verifying fit function parameters and throwing exceptions if the verification is not successful.
|
79
|
-
|
80
|
-
Parameters:
|
81
|
-
---
|
82
|
-
* X (``npt.NDArray``): Training array, containing the samples and their characteristics,
|
83
|
-
[``N samples`` (rows)][``N features`` (columns)].
|
84
|
-
* y (``npt.NDArray``): Array of target classes of ``X`` with [``N samples`` (lines)].
|
85
|
-
* _class_ (Literal[RNSA, BNSA], optional): Current class. Defaults to 'RNSA'.
|
86
|
-
|
87
|
-
---
|
88
|
-
|
89
|
-
Função responsável por verificar os parâmetros da função fit e lançar exceções se a verificação não for bem-sucedida.
|
90
|
-
|
91
|
-
Parâmetros:
|
92
|
-
---
|
93
|
-
* X (``npt.NDArray``): Array de treinamento, contendo as amostras e suas características,
|
94
|
-
[``N samples`` (linhas)][``N features`` (colunas)].
|
95
|
-
* y (``npt.NDArray``): Array de classes alvo de ``X`` com [``N samples`` (linhas)].
|
96
|
-
* _class_ (Literal[RNSA, BNSA], opcional): Classe atual. O padrão é 'RNSA'.
|
97
|
-
"""
|
98
|
-
if not isinstance(X, (np.ndarray)):
|
99
|
-
if isinstance(X, (list)):
|
100
|
-
X = np.array(X)
|
101
|
-
else:
|
102
|
-
raise TypeError("X is not an ndarray.")
|
103
|
-
elif not isinstance(y, (np.ndarray)):
|
104
|
-
if isinstance(y, (list)):
|
105
|
-
y = np.array(y)
|
106
|
-
else:
|
107
|
-
raise TypeError("y is not an ndarray.")
|
108
|
-
if X.shape[0] != y.shape[0]:
|
109
|
-
raise TypeError(
|
110
|
-
"X does not have the same amount of sample for the output classes in y.")
|
111
|
-
|
112
|
-
if _class_ == 'BNSA' and not np.isin(X, [0, 1]).all():
|
113
|
-
raise ValueError(
|
114
|
-
"The array X contains values that are not composed only of 0 and 1.")
|
115
|
-
|
116
|
-
def _slice_index_list_by_class(self, y: npt.NDArray) -> dict:
|
117
|
-
"""
|
118
|
-
The function ``__slice_index_list_by_class(...)``, separates the indices of the lines according to the output class,
|
119
|
-
to loop through the sample array, only in positions where the output is the class being trained.
|
120
|
-
|
121
|
-
Parameters:
|
122
|
-
---
|
123
|
-
* y (npt.NDArray): Receives a ``y``[``N sample``] array with the output classes of the ``X`` sample array.
|
124
|
-
|
125
|
-
returns:
|
126
|
-
---
|
127
|
-
* dict: A dictionary with the list of array positions(``y``), with the classes as key.
|
128
|
-
|
129
|
-
---
|
130
|
-
|
131
|
-
A função ``__slice_index_list_by_class(...)``, separa os índices das linhas conforme a classe de saída,
|
132
|
-
para percorrer o array de amostra, apenas nas posições que a saída for a classe que está sendo treinada.
|
133
|
-
|
134
|
-
Parameters:
|
135
|
-
---
|
136
|
-
* y (npt.NDArray): Recebe um array ``y``[``N amostra``] com as classes de saida do array de amostra ``X``.
|
137
|
-
|
138
|
-
Returns:
|
139
|
-
---
|
140
|
-
* dict: Um dicionário com a lista de posições do array(``y``), com as classes como chave.
|
141
|
-
"""
|
142
|
-
positionSamples = dict()
|
143
|
-
for _class_ in self.classes:
|
144
|
-
# Pega as posições das amostras por classes a partir do y.
|
145
|
-
positionSamples[_class_] = list(np.where(y == _class_)[0])
|
146
|
-
|
147
|
-
return positionSamples
|
148
|
-
|
149
|
-
def _score(self, X: npt.NDArray, y: list) -> float:
|
150
|
-
"""
|
151
|
-
Score function calculates forecast accuracy.
|
152
|
-
|
153
|
-
Details:
|
154
|
-
---
|
155
|
-
This function performs the prediction of X and checks how many elements are equal between vector y and y_predicted.
|
156
|
-
This function was added for compatibility with some scikit-learn functions.
|
157
|
-
|
158
|
-
Parameters:
|
159
|
-
-----------
|
160
|
-
|
161
|
-
X: np.ndarray
|
162
|
-
Feature set with shape (n_samples, n_features).
|
163
|
-
y: np.ndarray
|
164
|
-
True values with shape (n_samples,).
|
165
|
-
|
166
|
-
Returns:
|
167
|
-
-------
|
168
|
-
|
169
|
-
accuracy: float
|
170
|
-
The accuracy of the model.
|
171
|
-
|
172
|
-
---
|
173
|
-
|
174
|
-
Função score calcular a acurácia da previsão.
|
175
|
-
|
176
|
-
Details:
|
177
|
-
---
|
178
|
-
Esta função realiza a previsão de X e verifica quantos elementos são iguais entre o vetor y e y_previsto.
|
179
|
-
Essa função foi adicionada para oferecer compatibilidade com algumas funções do scikit-learn.
|
180
|
-
|
181
|
-
Parameters:
|
182
|
-
---
|
183
|
-
|
184
|
-
* X : np.ndarray
|
185
|
-
Conjunto de características com shape (n_samples, n_features).
|
186
|
-
* y : np.ndarray
|
187
|
-
Valores verdadeiros com shape (n_samples,).
|
188
|
-
|
189
|
-
returns:
|
190
|
-
---
|
191
|
-
|
192
|
-
accuracy : float
|
193
|
-
A acurácia do modelo.
|
194
|
-
"""
|
195
|
-
if len(y) == 0:
|
196
|
-
return 0
|
197
|
-
y_pred = self.predict(X)
|
198
|
-
return np.sum(y == y_pred)/len(y)
|
aisp-0.1.1.dist-info/RECORD
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
aisp/_base.py,sha256=K01pDVHXWRkx_6z9ftJIbhAdKbvKc97SoXUk32jBvC8,8040
|
2
|
-
aisp/NSA/__init__.py,sha256=difX4pOYWybVO9K-Nwrfn122cJYBlftKWad2w0WK2BE,116
|
3
|
-
aisp/NSA/_negativeSelection.py,sha256=SVkDdTNOnuRMG1IJjX7TakAn0uLswPi65JAL2KmMSP0,48346
|
4
|
-
aisp-0.1.1.dist-info/LICENSE,sha256=fTqV5eBpeAZO0_jit8j4Ref9ikBSlHJ8xwj5TLg7gFk,7817
|
5
|
-
aisp-0.1.1.dist-info/METADATA,sha256=CTcHD9-bNxoI-zwgY99xoyHmcoKMcrluxwJMDILbAUI,8113
|
6
|
-
aisp-0.1.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
7
|
-
aisp-0.1.1.dist-info/top_level.txt,sha256=Q5aJi_rAVT5UNS1As0ZafoyS5dwNibnoyOYV7RWUB9s,5
|
8
|
-
aisp-0.1.1.dist-info/RECORD,,
|
@@ -1 +0,0 @@
|
|
1
|
-
aisp
|
File without changes
|
File without changes
|