aberrant 0.5.0__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.
- aberrant/__init__.py +15 -0
- aberrant/base/__init__.py +46 -0
- aberrant/base/architecture.py +76 -0
- aberrant/base/exceptions.py +51 -0
- aberrant/base/model.py +48 -0
- aberrant/base/pipeline.py +127 -0
- aberrant/base/similarity.py +48 -0
- aberrant/base/transformer.py +56 -0
- aberrant/drift/__init__.py +13 -0
- aberrant/drift/adwin.py +297 -0
- aberrant/drift/base.py +54 -0
- aberrant/drift/kswin.py +151 -0
- aberrant/drift/page_hinkley.py +172 -0
- aberrant/model/__init__.py +40 -0
- aberrant/model/deep/__init__.py +16 -0
- aberrant/model/deep/autoencoder.py +116 -0
- aberrant/model/distance/__init__.py +20 -0
- aberrant/model/distance/knn.py +62 -0
- aberrant/model/distance/lof.py +256 -0
- aberrant/model/iforest/__init__.py +40 -0
- aberrant/model/iforest/asd.py +226 -0
- aberrant/model/iforest/halfspace.py +321 -0
- aberrant/model/iforest/mondrian.py +427 -0
- aberrant/model/iforest/online.py +760 -0
- aberrant/model/iforest/rand_hist.py +114 -0
- aberrant/model/iforest/random_cut.py +461 -0
- aberrant/model/iforest/xstream.py +424 -0
- aberrant/model/null.py +50 -0
- aberrant/model/quantile_threshold.py +149 -0
- aberrant/model/random.py +57 -0
- aberrant/model/stat/__init__.py +35 -0
- aberrant/model/stat/multi.py +317 -0
- aberrant/model/stat/uni.py +780 -0
- aberrant/model/svm/__init__.py +20 -0
- aberrant/model/svm/adaptive.py +293 -0
- aberrant/model/svm/gadget.py +144 -0
- aberrant/model/svm/todo.txt +3 -0
- aberrant/model/threshold.py +99 -0
- aberrant/stream/__init__.py +46 -0
- aberrant/stream/dataset/__init__.py +205 -0
- aberrant/stream/dataset/loader.py +362 -0
- aberrant/stream/dataset/registry.py +402 -0
- aberrant/stream/dataset/streamers.py +260 -0
- aberrant/stream/streamer.py +135 -0
- aberrant/transform/__init__.py +11 -0
- aberrant/transform/preprocessing/__init__.py +8 -0
- aberrant/transform/preprocessing/scaler.py +182 -0
- aberrant/transform/projection/__init__.py +9 -0
- aberrant/transform/projection/incremental_pca.py +269 -0
- aberrant/transform/projection/random_projection.py +110 -0
- aberrant/utils/__init__.py +0 -0
- aberrant/utils/deep/__init__.py +0 -0
- aberrant/utils/deep/architecture.py +91 -0
- aberrant/utils/deep/loss_func.py +28 -0
- aberrant/utils/similar/__init__.py +0 -0
- aberrant/utils/similar/faiss_engine.py +172 -0
- aberrant-0.5.0.dist-info/METADATA +168 -0
- aberrant-0.5.0.dist-info/RECORD +60 -0
- aberrant-0.5.0.dist-info/WHEEL +4 -0
- aberrant-0.5.0.dist-info/licenses/LICENSE +21 -0
aberrant/__init__.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""ABERRANT: Online Anomaly Detection library for streaming data.
|
|
2
|
+
|
|
3
|
+
A Python library implementing the online learning paradigm for anomaly
|
|
4
|
+
detection. All models process data one point at a time, updating their
|
|
5
|
+
state incrementally without storing historical data.
|
|
6
|
+
|
|
7
|
+
Modules:
|
|
8
|
+
base: Core abstract classes (BaseModel, BaseTransformer, Pipeline)
|
|
9
|
+
drift: Concept drift detection algorithms (ADWIN, KSWIN, PageHinkley)
|
|
10
|
+
model: Anomaly detection models
|
|
11
|
+
stream: Streaming data utilities
|
|
12
|
+
transform: Data transformers (scalers, projections)
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
__version__ = "0.5.0"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Base classes for online anomaly detection models and components.
|
|
2
|
+
|
|
3
|
+
This module provides the fundamental abstract base classes that define the
|
|
4
|
+
interfaces for models, transformers, pipelines, and other core components
|
|
5
|
+
in the aberrant library.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import importlib
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from aberrant.base.exceptions import (
|
|
12
|
+
AberrantError,
|
|
13
|
+
IncompatibleComponentError,
|
|
14
|
+
ModelNotFittedError,
|
|
15
|
+
PipelineError,
|
|
16
|
+
TransformationError,
|
|
17
|
+
UnsupportedFeatureError,
|
|
18
|
+
ValidationError,
|
|
19
|
+
)
|
|
20
|
+
from aberrant.base.model import BaseModel
|
|
21
|
+
from aberrant.base.pipeline import Pipeline
|
|
22
|
+
from aberrant.base.similarity import BaseSimilaritySearchEngine
|
|
23
|
+
from aberrant.base.transformer import BaseTransformer
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"Architecture",
|
|
27
|
+
"BaseModel",
|
|
28
|
+
"BaseSimilaritySearchEngine",
|
|
29
|
+
"BaseTransformer",
|
|
30
|
+
"IncompatibleComponentError",
|
|
31
|
+
"ModelNotFittedError",
|
|
32
|
+
"AberrantError",
|
|
33
|
+
"Pipeline",
|
|
34
|
+
"PipelineError",
|
|
35
|
+
"TransformationError",
|
|
36
|
+
"UnsupportedFeatureError",
|
|
37
|
+
"ValidationError",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def __getattr__(name: str) -> Any:
|
|
42
|
+
"""Lazy import of Architecture to avoid torch dependency."""
|
|
43
|
+
if name == "Architecture":
|
|
44
|
+
module = importlib.import_module("aberrant.base.architecture")
|
|
45
|
+
return module.Architecture
|
|
46
|
+
raise AttributeError(f"module 'aberrant.base' has no attribute '{name}'")
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""Neural network architecture base class for deep learning models."""
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import random
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import torch
|
|
8
|
+
from torch import nn
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Architecture(abc.ABC, nn.Module):
|
|
12
|
+
"""
|
|
13
|
+
Abstract base class for defining neural network architectures.
|
|
14
|
+
|
|
15
|
+
This class ensures that any neural network architecture can be plugged into
|
|
16
|
+
online anomaly detection models. It provides a consistent interface and
|
|
17
|
+
device handling capabilities.
|
|
18
|
+
|
|
19
|
+
Subclasses must implement the `forward` and `input_size` methods.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, device: torch.device | None = None) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Initialize the architecture.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
device: The device to run the model on. If None, uses CPU.
|
|
28
|
+
"""
|
|
29
|
+
super().__init__()
|
|
30
|
+
self.device = device or torch.device("cpu")
|
|
31
|
+
self.to(self.device)
|
|
32
|
+
|
|
33
|
+
@abc.abstractmethod
|
|
34
|
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
|
35
|
+
"""
|
|
36
|
+
Forward pass through the network.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
x: Input tensor.
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
Output tensor.
|
|
43
|
+
"""
|
|
44
|
+
raise NotImplementedError
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
@abc.abstractmethod
|
|
48
|
+
def input_size(self) -> int:
|
|
49
|
+
"""
|
|
50
|
+
The expected input size for the network.
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Number of input features.
|
|
54
|
+
"""
|
|
55
|
+
raise NotImplementedError
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def set_seed(seed: int) -> None:
|
|
59
|
+
"""
|
|
60
|
+
Set random seeds for reproducibility.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
seed: Random seed value.
|
|
64
|
+
"""
|
|
65
|
+
random.seed(seed)
|
|
66
|
+
np.random.seed(seed)
|
|
67
|
+
torch.manual_seed(seed)
|
|
68
|
+
if torch.cuda.is_available():
|
|
69
|
+
torch.cuda.manual_seed(seed)
|
|
70
|
+
torch.cuda.manual_seed_all(seed)
|
|
71
|
+
torch.backends.cudnn.deterministic = True
|
|
72
|
+
torch.backends.cudnn.benchmark = False
|
|
73
|
+
|
|
74
|
+
def __repr__(self) -> str:
|
|
75
|
+
"""Return a string representation of the architecture."""
|
|
76
|
+
return f"{self.__class__.__name__}(input_size={self.input_size}, device={self.device})"
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Custom exceptions for the aberrant library."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class AberrantError(Exception):
|
|
5
|
+
"""Base exception class for all aberrant-specific errors."""
|
|
6
|
+
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ModelNotFittedError(AberrantError):
|
|
11
|
+
"""Raised when a model method is called before the model has been fitted."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, message: str = "Model has not been fitted yet.") -> None:
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TransformationError(AberrantError):
|
|
18
|
+
"""Raised when a transformation operation fails."""
|
|
19
|
+
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class PipelineError(AberrantError):
|
|
24
|
+
"""Raised when a pipeline operation fails."""
|
|
25
|
+
|
|
26
|
+
pass
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ValidationError(AberrantError):
|
|
30
|
+
"""Raised when input validation fails."""
|
|
31
|
+
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UnsupportedFeatureError(AberrantError):
|
|
36
|
+
"""Raised when an unsupported feature is encountered."""
|
|
37
|
+
|
|
38
|
+
def __init__(self, feature_name: str) -> None:
|
|
39
|
+
super().__init__(f"Feature '{feature_name}' has not been seen during training.")
|
|
40
|
+
self.feature_name = feature_name
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class IncompatibleComponentError(PipelineError):
|
|
44
|
+
"""Raised when pipeline components are incompatible."""
|
|
45
|
+
|
|
46
|
+
def __init__(self, component_name: str, expected_type: str) -> None:
|
|
47
|
+
super().__init__(
|
|
48
|
+
f"Component '{component_name}' is not compatible. Expected: {expected_type}"
|
|
49
|
+
)
|
|
50
|
+
self.component_name = component_name
|
|
51
|
+
self.expected_type = expected_type
|
aberrant/base/model.py
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Base model interface for online anomaly detection."""
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseModel(abc.ABC):
|
|
7
|
+
"""
|
|
8
|
+
Abstract base class for online anomaly detection models.
|
|
9
|
+
|
|
10
|
+
This class defines the interface that all online anomaly detection models should implement.
|
|
11
|
+
Online models process one data point at a time, updating their internal state and providing
|
|
12
|
+
anomaly scores for each data point.
|
|
13
|
+
|
|
14
|
+
Subclasses must implement the `learn_one` and `score_one` methods.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
@abc.abstractmethod
|
|
18
|
+
def learn_one(self, x: dict[str, float]) -> None:
|
|
19
|
+
"""
|
|
20
|
+
Update the model with a single data point.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
x: A dictionary representing a single data point. The keys are feature names,
|
|
24
|
+
and the values are the corresponding feature values.
|
|
25
|
+
"""
|
|
26
|
+
raise NotImplementedError
|
|
27
|
+
|
|
28
|
+
@abc.abstractmethod
|
|
29
|
+
def score_one(self, x: dict[str, float]) -> float:
|
|
30
|
+
"""
|
|
31
|
+
Compute the anomaly score for a single data point.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
x: A dictionary representing a single data point. The keys are feature names,
|
|
35
|
+
and the values are the corresponding feature values.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
The anomaly score for the data point. Higher scores indicate greater anomaly.
|
|
39
|
+
"""
|
|
40
|
+
raise NotImplementedError
|
|
41
|
+
|
|
42
|
+
def __repr__(self) -> str:
|
|
43
|
+
"""Return a string representation of the model."""
|
|
44
|
+
return f"{self.__class__.__name__}()"
|
|
45
|
+
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
"""Return a human-readable string representation of the model."""
|
|
48
|
+
return self.__repr__()
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"""Pipeline for chaining transformers and models together."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from .exceptions import IncompatibleComponentError, PipelineError
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Pipeline:
|
|
9
|
+
"""
|
|
10
|
+
Pipeline for chaining transformers and models.
|
|
11
|
+
|
|
12
|
+
A pipeline allows you to chain multiple components together, where the output
|
|
13
|
+
of one component becomes the input of the next. The pipeline can contain
|
|
14
|
+
transformers (which modify data) and models (which score data).
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
first: The first component in the pipeline (transformer or model).
|
|
18
|
+
second: The second component in the pipeline (transformer or model).
|
|
19
|
+
|
|
20
|
+
Example:
|
|
21
|
+
>>> scaler = MinMaxScaler()
|
|
22
|
+
>>> model = RandomModel()
|
|
23
|
+
>>> pipeline = Pipeline(scaler, model)
|
|
24
|
+
>>> pipeline.learn_one({"feature": 1.0})
|
|
25
|
+
>>> score = pipeline.score_one({"feature": 2.0})
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, first: Any, second: Any) -> None:
|
|
29
|
+
self._validate_components(first, second)
|
|
30
|
+
self.first = first
|
|
31
|
+
self.second = second
|
|
32
|
+
|
|
33
|
+
def learn_one(self, x: dict[str, float]) -> None:
|
|
34
|
+
"""
|
|
35
|
+
Learn from a single data point through the pipeline.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
x: A dictionary representing a single data point.
|
|
39
|
+
"""
|
|
40
|
+
self.first.learn_one(x)
|
|
41
|
+
transformed_x = self.first.transform_one(x)
|
|
42
|
+
self.second.learn_one(transformed_x)
|
|
43
|
+
|
|
44
|
+
def transform_one(self, x: dict[str, float]) -> dict[str, float]:
|
|
45
|
+
"""
|
|
46
|
+
Transform a single data point through the pipeline.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
x: A dictionary representing a single data point.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The transformed data point.
|
|
53
|
+
"""
|
|
54
|
+
transformed_x = self.first.transform_one(x)
|
|
55
|
+
transformed = self.second.transform_one(transformed_x)
|
|
56
|
+
if not isinstance(transformed, dict):
|
|
57
|
+
raise PipelineError(
|
|
58
|
+
"The final transformer must return a dict[str, float] from transform_one."
|
|
59
|
+
)
|
|
60
|
+
return transformed
|
|
61
|
+
|
|
62
|
+
def score_one(self, x: dict[str, float]) -> float:
|
|
63
|
+
"""
|
|
64
|
+
Score a single data point using the pipeline.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
x: A dictionary representing a single data point.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The anomaly score for the data point.
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
PipelineError: If the final component doesn't support scoring.
|
|
74
|
+
"""
|
|
75
|
+
transformed_x = self.first.transform_one(x)
|
|
76
|
+
|
|
77
|
+
if hasattr(self.second, "score_one"):
|
|
78
|
+
score = self.second.score_one(transformed_x)
|
|
79
|
+
if not isinstance(score, int | float):
|
|
80
|
+
raise PipelineError(
|
|
81
|
+
"The final component must return a numeric score from score_one."
|
|
82
|
+
)
|
|
83
|
+
return float(score)
|
|
84
|
+
else:
|
|
85
|
+
raise PipelineError(
|
|
86
|
+
f"The final component ({self.second.__class__.__name__}) does not have a 'score_one' method."
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
def __or__(self, other: Any) -> "Pipeline":
|
|
90
|
+
"""Overload the | operator to allow further chaining of pipelines."""
|
|
91
|
+
return Pipeline(self, other)
|
|
92
|
+
|
|
93
|
+
def __repr__(self) -> str:
|
|
94
|
+
"""Return a string representation of the pipeline."""
|
|
95
|
+
return f"Pipeline({self.first!r} | {self.second!r})"
|
|
96
|
+
|
|
97
|
+
def __str__(self) -> str:
|
|
98
|
+
"""Return a human-readable string representation of the pipeline."""
|
|
99
|
+
return f"{self.first.__class__.__name__} | {self.second.__class__.__name__}"
|
|
100
|
+
|
|
101
|
+
def _validate_components(self, first: Any, second: Any) -> None:
|
|
102
|
+
"""
|
|
103
|
+
Validate that the pipeline components are compatible.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
first: The first component.
|
|
107
|
+
second: The second component.
|
|
108
|
+
|
|
109
|
+
Raises:
|
|
110
|
+
IncompatibleComponentError: If components are not compatible.
|
|
111
|
+
"""
|
|
112
|
+
# Check first component has required methods
|
|
113
|
+
if not hasattr(first, "learn_one"):
|
|
114
|
+
raise IncompatibleComponentError(
|
|
115
|
+
first.__class__.__name__, "component with 'learn_one' method"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
if not hasattr(first, "transform_one"):
|
|
119
|
+
raise IncompatibleComponentError(
|
|
120
|
+
first.__class__.__name__, "component with 'transform_one' method"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Check second component has required methods
|
|
124
|
+
if not hasattr(second, "learn_one"):
|
|
125
|
+
raise IncompatibleComponentError(
|
|
126
|
+
second.__class__.__name__, "component with 'learn_one' method"
|
|
127
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Base similarity search engine interface."""
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseSimilaritySearchEngine(abc.ABC):
|
|
7
|
+
"""
|
|
8
|
+
Abstract base class for similarity search engines.
|
|
9
|
+
|
|
10
|
+
This class defines the interface for similarity search engines that can store
|
|
11
|
+
data points and find similar neighbors for query points.
|
|
12
|
+
|
|
13
|
+
Subclasses must implement the `append` and `search` methods.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@abc.abstractmethod
|
|
17
|
+
def append(self, x: dict[str, float]) -> None:
|
|
18
|
+
"""
|
|
19
|
+
Add a data point to the search engine.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
x: A dictionary representing a single data point. The keys are feature names,
|
|
23
|
+
and the values are the corresponding feature values.
|
|
24
|
+
"""
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
@abc.abstractmethod
|
|
28
|
+
def search(self, x: dict[str, float], n_neighbors: int) -> float:
|
|
29
|
+
"""
|
|
30
|
+
Search for the n nearest neighbors of a data point.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
x: A dictionary representing the query data point.
|
|
34
|
+
n_neighbors: The number of nearest neighbors to find.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
A similarity or distance score based on the nearest neighbors.
|
|
38
|
+
Should return a consistent numeric value (e.g., 0.0 if insufficient data).
|
|
39
|
+
"""
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
def __repr__(self) -> str:
|
|
43
|
+
"""Return a string representation of the search engine."""
|
|
44
|
+
return f"{self.__class__.__name__}()"
|
|
45
|
+
|
|
46
|
+
def __str__(self) -> str:
|
|
47
|
+
"""Return a human-readable string representation of the search engine."""
|
|
48
|
+
return self.__repr__()
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Base transformer interface for online data transformation."""
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from aberrant.base.pipeline import Pipeline
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from aberrant.base.pipeline import Pipeline
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseTransformer(abc.ABC):
|
|
13
|
+
"""
|
|
14
|
+
Abstract base class for online transformers.
|
|
15
|
+
|
|
16
|
+
This class defines the interface for transformers that can learn from and transform
|
|
17
|
+
data points incrementally. Transformers modify the input data while maintaining
|
|
18
|
+
the streaming nature of the processing.
|
|
19
|
+
|
|
20
|
+
Subclasses must implement the `learn_one` and `transform_one` methods.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
@abc.abstractmethod
|
|
24
|
+
def learn_one(self, x: dict[str, float]) -> None:
|
|
25
|
+
"""
|
|
26
|
+
Update the transformer with a single data point.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
x: A dictionary representing a single data point. The keys are feature names,
|
|
30
|
+
and the values are the corresponding feature values.
|
|
31
|
+
"""
|
|
32
|
+
raise NotImplementedError
|
|
33
|
+
|
|
34
|
+
@abc.abstractmethod
|
|
35
|
+
def transform_one(self, x: dict[str, float]) -> dict[str, float]:
|
|
36
|
+
"""
|
|
37
|
+
Transform a single data point.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
x: A dictionary representing a single data point to transform.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
A dictionary with transformed feature values.
|
|
44
|
+
"""
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
|
|
47
|
+
def __or__(self, other: Any) -> "Pipeline":
|
|
48
|
+
return Pipeline(self, other)
|
|
49
|
+
|
|
50
|
+
def __repr__(self) -> str:
|
|
51
|
+
"""Return a string representation of the transformer."""
|
|
52
|
+
return f"{self.__class__.__name__}()"
|
|
53
|
+
|
|
54
|
+
def __str__(self) -> str:
|
|
55
|
+
"""Return a human-readable string representation of the transformer."""
|
|
56
|
+
return self.__repr__()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Concept drift detection algorithms for streaming data."""
|
|
2
|
+
|
|
3
|
+
from aberrant.drift.adwin import ADWIN
|
|
4
|
+
from aberrant.drift.base import BaseDriftDetector
|
|
5
|
+
from aberrant.drift.kswin import KSWIN
|
|
6
|
+
from aberrant.drift.page_hinkley import PageHinkley
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"ADWIN",
|
|
10
|
+
"BaseDriftDetector",
|
|
11
|
+
"KSWIN",
|
|
12
|
+
"PageHinkley",
|
|
13
|
+
]
|