Skip to content

Commit 7bcc658

Browse files
Add DDM API example
1 parent 32f9bd0 commit 7bcc658

File tree

2 files changed

+68
-7
lines changed
  • frouros
    • detectors/concept_drift/streaming/statistical_process_control
    • utils

2 files changed

+68
-7
lines changed

frouros/detectors/concept_drift/streaming/statistical_process_control/ddm.py

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""DDM (Drift detection method) module."""
22

33
from contextlib import suppress
4-
from typing import Union
4+
from typing import Union, Optional, List
55

6+
from frouros.callbacks.streaming.base import BaseCallbackStreaming
67
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
78
BaseSPCConfig,
89
BaseSPCError,
@@ -12,30 +13,90 @@
1213
class DDMConfig(BaseSPCConfig):
1314
"""DDM (Drift detection method) [gama2004learning]_ configuration.
1415
16+
:param warning_level: warning level factor, defaults to 2.0
17+
:type warning_level: float
18+
:param drift_level: drift level factor, defaults to 3.0
19+
:type drift_level: float
20+
:param min_num_instances: minimum numbers of instances to start looking for changes, defaults to 30
21+
:type min_num_instances: int
22+
1523
:References:
1624
1725
.. [gama2004learning] Gama, Joao, et al.
1826
"Learning with drift detection."
1927
Advances in Artificial Intelligence–SBIA 2004: 17th Brazilian Symposium on
20-
Artificial Intelligence, Sao Luis, Maranhao, Brazil, September 29-Ocotber 1,
28+
Artificial Intelligence, Sao Luis, Maranhao, Brazil, September 29-October 1,
2129
2004. Proceedings 17. Springer Berlin Heidelberg, 2004.
22-
"""
30+
""" # noqa: E501
31+
32+
def __init__( # noqa: D107
33+
self,
34+
warning_level: float = 2.0,
35+
drift_level: float = 3.0,
36+
min_num_instances: int = 30,
37+
) -> None:
38+
super().__init__(
39+
warning_level=warning_level,
40+
drift_level=drift_level,
41+
min_num_instances=min_num_instances,
42+
)
2343

2444

2545
class DDM(BaseSPCError):
2646
"""DDM (Drift detection method) [gama2004learning]_ detector.
2747
48+
:param config: configuration object of the detector, defaults to None. If None, the default configuration of :class:`DDMConfig` is used.
49+
:type config: Optional[DDMConfig]
50+
:param callbacks: callbacks, defaults to None
51+
:type callbacks: Optional[Union[BaseCallbackStreaming, List[BaseCallbackStreaming]]]
52+
53+
:Note:
54+
:func:`update` method expects to receive a value of 0 if the instance is correctly classified (no error) and 1 otherwise (error).
55+
2856
:References:
2957
3058
.. [gama2004learning] Gama, Joao, et al.
3159
"Learning with drift detection."
3260
Advances in Artificial Intelligence–SBIA 2004: 17th Brazilian Symposium on
33-
Artificial Intelligence, Sao Luis, Maranhao, Brazil, September 29-Ocotber 1,
61+
Artificial Intelligence, Sao Luis, Maranhao, Brazil, September 29-October 1,
3462
2004. Proceedings 17. Springer Berlin Heidelberg, 2004.
35-
"""
63+
64+
:Example:
65+
66+
>>> from frouros.detectors.concept_drift import DDM
67+
>>> import numpy as np
68+
>>> np.random.seed(seed=31)
69+
>>> dist_a = np.random.binomial(n=1, p=0.6, size=1000)
70+
>>> dist_b = np.random.binomial(n=1, p=0.8, size=1000)
71+
>>> stream = np.concatenate((dist_a, dist_b))
72+
>>> detector = DDM()
73+
>>> warning_flag = False
74+
>>> for i, value in enumerate(stream):
75+
... _ = detector.update(value=value)
76+
... if detector.drift:
77+
... print(f"Change detected at index {i}")
78+
... break
79+
... if not warning_flag and detector.warning:
80+
... print(f"Warning detected at index {i}")
81+
... warning_flag = True
82+
Warning detected at index 1049
83+
Change detected at index 1131
84+
""" # noqa: E501
3685

3786
config_type = DDMConfig
3887

88+
def __init__( # noqa: D107
89+
self,
90+
config: Optional[DDMConfig] = None,
91+
callbacks: Optional[
92+
Union[BaseCallbackStreaming, List[BaseCallbackStreaming]]
93+
] = None,
94+
) -> None:
95+
super().__init__(
96+
config=config,
97+
callbacks=callbacks,
98+
)
99+
39100
def _update(self, value: Union[int, float], **kwargs) -> None:
40101
self.num_instances += 1
41102
self.error_rate.update(value=value)

frouros/utils/stats.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ def update(self, value: Union[int, float]) -> None:
8787
:type value: int
8888
:raises TypeError: Type error exception
8989
"""
90-
if not isinstance(value, (int, float)):
91-
raise TypeError("value must be of type int or float.")
90+
if not isinstance(value, (int, float, np.number)):
91+
raise TypeError("value must be of type int, float or numpy number.")
9292
self.num_values += 1
9393
self.mean += self.incremental_op(
9494
value=value,

0 commit comments

Comments
 (0)