Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion aisp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
https://ais-package.github.io/docs/intro
"""

from importlib.metadata import version

from . import csa
from . import ina
from . import nsa

__author__ = "AISP Development Team"
__version__ = "0.5.1"
__version__ = version('aisp')
__all__ = ["csa", "nsa", "ina"]
3 changes: 2 additions & 1 deletion aisp/base/core/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from inspect import signature


class Base:
"""
Generic base class for models with a common interface.
Expand Down Expand Up @@ -46,4 +47,4 @@ def get_params(self, deep: bool = True) -> dict: # pylint: disable=W0613
key: getattr(self, key)
for key, _ in signature(self.__init__).parameters.items()
if key != "self" and not key.startswith("_") and hasattr(self, key)
}
}
12 changes: 5 additions & 7 deletions aisp/csa/_ai_recognition_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,10 @@ class AIRS(BaseClassifier):
Distance metric used to compute affinity between cells and samples.
seed : int
Seed for the random generation of detector values. Defaults to None.

**kwargs
p : float
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents normalized Euclidean distance.\
Different values of p lead to different variants of the Minkowski Distance.
p : float
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents normalized Euclidean distance.\
Different values of p lead to different variants of the Minkowski Distance.

Attributes
----------
Expand Down Expand Up @@ -153,7 +151,7 @@ def __init__(

self.metric = sanitize_choice(metric, ["manhattan", "minkowski"], "euclidean")

self.p = p
self.p: float = p

self._cells_memory: Optional[Dict[str | int, list[BCell]]] = None
self._all_class_cell_vectors: Optional[List[Tuple[Any, np.ndarray]]] = None
Expand Down
13 changes: 6 additions & 7 deletions aisp/ina/_ai_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,10 @@ class AiNet(BaseClusterer):
use_mst_clustering : bool, default=True
If ``True``, performs clustering with **Minimum Spanning Tree** (MST). If ``False``,
does not perform clustering and predict returns None.
**kwargs
p : float
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents normalized Euclidean distance.\
Different values of p lead to different variants of the Minkowski Distance.
p : float
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents normalized Euclidean distance.\
Different values of p lead to different variants of the Minkowski Distance.

Attributes
----------
Expand Down Expand Up @@ -139,7 +138,7 @@ def __init__(
metric: MetricType = "euclidean",
seed: Optional[int] = None,
use_mst_clustering: bool = True,
**kwargs,
p: float = 2.0
):
self.N: int = sanitize_param(N, 50, lambda x: x > 0)
self.n_clone: int = sanitize_param(n_clone, 10, lambda x: x > 0)
Expand Down Expand Up @@ -175,7 +174,7 @@ def __init__(
metric, ["euclidean", "manhattan", "minkowski"], "euclidean"
)

self.p: np.float64 = np.float64(kwargs.get("p", 2.0))
self.p: float = p
self._metric_params = {}
if self.metric == "minkowski":
self._metric_params["p"] = self.p
Expand Down
4 changes: 2 additions & 2 deletions aisp/nsa/_binary_negative_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ def __init__(
self.no_label_sample_selection: str = sanitize_param(
no_label_sample_selection,
"max_average_difference",
lambda x: x == "nearest_difference",
lambda x: x == "max_nearest_difference",
)

self.classes: Optional[npt.NDArray] = None
Expand Down Expand Up @@ -308,7 +308,7 @@ def _assign_class_to_non_self_sample(self, line: npt.NDArray, c: list):
distances = np.mean(line != self._detectors[_class_], axis=1)
# Assign the label to the class with the greatest distance from
# the nearest detector.
if self.no_label_sample_selection == "nearest_difference":
if self.no_label_sample_selection == "max_nearest_difference":
class_differences[_class_] = distances.min()
# Or based on the greatest distance from the average distances of the detectors.
else:
Expand Down
37 changes: 18 additions & 19 deletions aisp/nsa/_negative_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from __future__ import annotations

from typing import Any, Dict, Literal, Optional, Union, List
from typing import Dict, Literal, Optional, Union, List

import numpy as np
import numpy.typing as npt
Expand Down Expand Up @@ -57,20 +57,17 @@ class RNSA(BaseClassifier):
* ``'default-NSA'``: Default algorithm with fixed radius.
* ``'V-detector'``: This algorithm is based on the article Ji & Dasgupta (2004) [1]_
and uses a variable radius for anomaly detection in feature spaces.

**kwargs : dict
Additional parameters. The following arguments are recognized:
* non_self_label : str, default='non-self'
This variable stores the label that will be assigned when the data has only one
output class, and the sample is classified as not belonging to that class.
* cell_bounds : bool, default=False
If set to ``True``, this option limits the generation of detectors to the space
within the plane between 0 and 1. This means that any detector whose radius exceeds
this limit is discarded, this variable is only used in the ``V-detector`` algorithm.
* p : float, default=2
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents Euclidean distance. Different values of p lead
to different variants of the Minkowski Distance.
* non_self_label : str, default='non-self'
This variable stores the label that will be assigned when the data has only one
output class, and the sample is classified as not belonging to that class.
* cell_bounds : bool, default=False
If set to ``True``, this option limits the generation of detectors to the space
within the plane between 0 and 1. This means that any detector whose radius exceeds
this limit is discarded, this variable is only used in the ``V-detector`` algorithm.
* p : float, default=2
This parameter stores the value of ``p`` used in the Minkowski distance. The default
is ``2``, which represents Euclidean distance. Different values of p lead
to different variants of the Minkowski Distance.

Attributes
----------
Expand Down Expand Up @@ -142,7 +139,9 @@ def __init__(
max_discards: int = 1000,
seed: Optional[int] = None,
algorithm: Literal["default-NSA", "V-detector"] = "default-NSA",
**kwargs: Any,
p: float = 2.0,
non_self_label: str = 'non-self',
cell_bounds: bool = False
):
self.metric: str = sanitize_choice(
metric, ["manhattan", "minkowski"], "euclidean"
Expand All @@ -160,9 +159,9 @@ def __init__(
)
self.max_discards: int = sanitize_param(max_discards, 1000, lambda x: x > 0)

self.p: np.float64 = np.float64(kwargs.get("p", 2))
self.cell_bounds: bool = bool(kwargs.get("cell_bounds", False))
self.non_self_label: str = str(kwargs.get("non_self_label", "non-self"))
self.p: float = p
self.cell_bounds: bool = cell_bounds
self.non_self_label: str = non_self_label

self._detectors: Optional[Dict[str | int, list[Detector]]] = None
self.classes: Optional[npt.NDArray] = None
Expand Down
2 changes: 1 addition & 1 deletion aisp/nsa/tests/test_negative_selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def test_fit_raises_max_discards_error(self, rnsa_data):
def test_predict_raises_feature_dimension_mismatch(self, rnsa_data):
"""Should raise FeatureDimensionMismatch when prediction input has wrong dimensions."""
X, y, seed = rnsa_data
model = RNSA(N=1000, aff_thresh=0.2, seed=seed)
model = RNSA(N=1000, seed=seed)
model.fit(X, y, verbose=False)
x_invalid = np.random.rand(5, 5)
with pytest.raises(FeatureDimensionMismatch):
Expand Down
2 changes: 0 additions & 2 deletions aisp/utils/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,6 @@ class ProgressTable(TableFormatter):

def __init__(self, headers: Mapping[str, int], verbose: bool = True) -> None:
super().__init__(headers)
if not headers or not isinstance(headers, Mapping):
raise ValueError("'headers' must be a non-empty dictionary.")
self.verbose: bool = verbose
self.headers: Mapping[str, int] = headers
self._ascii_only = not _supports_box_drawing()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"display_name": ".venv (3.12.2)",
"language": "python",
"name": "python3"
},
Expand All @@ -218,7 +218,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.12.2"
},
"orig_nbformat": 4
},
Expand Down
Loading
Loading