Skip to content

Commit 7333f53

Browse files
Add integration change detection test
1 parent 25f368b commit 7333f53

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Base concept drift ChangeDetection based module."""
2+
3+
import abc
4+
from typing import Union
5+
6+
from frouros.detectors.concept_drift.streaming.base import (
7+
BaseConceptDriftStreaming,
8+
BaseConceptDriftStreamingConfig,
9+
)
10+
11+
12+
class BaseChangeDetectionConfig(BaseConceptDriftStreamingConfig):
13+
"""Class representing a ChangeDetection based configuration class."""
14+
15+
16+
class BaseChangeDetection(BaseConceptDriftStreaming):
17+
"""ChangeDetection based algorithm class."""
18+
19+
config_type = BaseChangeDetectionConfig
20+
21+
@abc.abstractmethod
22+
def _update(self, value: Union[int, float], **kwargs) -> None:
23+
pass

frouros/tests/conftest.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,34 @@ def sea() -> SEA:
5050
return generator
5151

5252

53+
@pytest.fixture(scope="function")
54+
def stream_drift() -> np.ndarray:
55+
"""Stream with drift.
56+
57+
:return: stream with drift
58+
:rtype: np.ndarray
59+
"""
60+
np.random.seed(seed=31)
61+
62+
dist_normal = np.random.normal(
63+
loc=0.0,
64+
scale=0.5,
65+
size=100,
66+
)
67+
dist_drift_1 = np.random.normal(
68+
loc=4.0,
69+
scale=0.2,
70+
size=100,
71+
)
72+
dist_drift_2 = np.random.normal(
73+
loc=6.0,
74+
scale=0.5,
75+
size=100,
76+
)
77+
78+
return np.concatenate((dist_normal, dist_drift_1, dist_drift_2))
79+
80+
5381
@pytest.fixture(scope="module", name="clf_dataset")
5482
def classification_dataset() -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
5583
"""Classification dataset using SEA generator.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""Test change detection detectors."""
2+
3+
from typing import Tuple, List
4+
5+
import numpy as np # type: ignore
6+
import pytest # type: ignore
7+
8+
from frouros.detectors.concept_drift import (
9+
BOCD,
10+
BOCDConfig,
11+
)
12+
from frouros.detectors.concept_drift.streaming.change_detection.base import (
13+
BaseChangeDetection,
14+
)
15+
from frouros.detectors.concept_drift.streaming.change_detection.bocd import (
16+
GaussianUnknownMean,
17+
)
18+
19+
detectors = [
20+
(
21+
BOCD(
22+
config=BOCDConfig(
23+
min_num_instances=1,
24+
model=GaussianUnknownMean(
25+
prior_mean=0,
26+
prior_var=1,
27+
data_var=0.5,
28+
),
29+
hazard=0.01,
30+
),
31+
),
32+
[100, 203],
33+
),
34+
]
35+
36+
37+
@pytest.mark.parametrize("detector_info", detectors)
38+
def test_change_detection_detector(
39+
stream_drift: np.ndarray,
40+
detector_info: Tuple[BaseChangeDetection, List[int]],
41+
) -> None:
42+
"""Test streaming detector.
43+
44+
:param stream_drift: stream with drift
45+
:type stream_drift: numpy.ndarray
46+
:param detector_info: concept drift detector and value function
47+
:type detector_info: Tuple[BaseConceptDrift, Callable]
48+
"""
49+
detector, idx_drifts = detector_info
50+
idx_detected_drifts = []
51+
for i, val in enumerate(stream_drift):
52+
detector.update(value=val)
53+
if detector.status["drift"]:
54+
detector.reset()
55+
idx_detected_drifts.append(i)
56+
57+
assert idx_detected_drifts == idx_drifts

0 commit comments

Comments
 (0)