|
1 | 1 | """DDM (Drift detection method) module.""" |
2 | 2 |
|
3 | 3 | from contextlib import suppress |
4 | | -from typing import Union |
| 4 | +from typing import Union, Optional, List |
5 | 5 |
|
| 6 | +from frouros.callbacks.streaming.base import BaseCallbackStreaming |
6 | 7 | from frouros.detectors.concept_drift.streaming.statistical_process_control.base import ( |
7 | 8 | BaseSPCConfig, |
8 | 9 | BaseSPCError, |
|
12 | 13 | class DDMConfig(BaseSPCConfig): |
13 | 14 | """DDM (Drift detection method) [gama2004learning]_ configuration. |
14 | 15 |
|
| 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 | +
|
15 | 23 | :References: |
16 | 24 |
|
17 | 25 | .. [gama2004learning] Gama, Joao, et al. |
18 | 26 | "Learning with drift detection." |
19 | 27 | 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, |
21 | 29 | 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 | + ) |
23 | 43 |
|
24 | 44 |
|
25 | 45 | class DDM(BaseSPCError): |
26 | 46 | """DDM (Drift detection method) [gama2004learning]_ detector. |
27 | 47 |
|
| 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 | +
|
28 | 56 | :References: |
29 | 57 |
|
30 | 58 | .. [gama2004learning] Gama, Joao, et al. |
31 | 59 | "Learning with drift detection." |
32 | 60 | 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, |
34 | 62 | 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 |
36 | 85 |
|
37 | 86 | config_type = DDMConfig |
38 | 87 |
|
| 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 | + |
39 | 100 | def _update(self, value: Union[int, float], **kwargs) -> None: |
40 | 101 | self.num_instances += 1 |
41 | 102 | self.error_rate.update(value=value) |
|
0 commit comments