|
15 | 15 | class ECDDWTConfig(BaseECDDConfig): |
16 | 16 | """ECDDWT (EWMA Concept Drift Detection Warning) [ross2012exponentially]_ configuration. |
17 | 17 |
|
| 18 | + :param lambda_: weight given to recent data compared to older data, defaults to 0.2 |
| 19 | + :type lambda_: float |
| 20 | + :param average_run_length: expected time between false positive detections [100, 400 or 1000], defaults to 400 |
| 21 | + :type average_run_length: int |
| 22 | + :param warning_level: warning level value, defaults to 0.5 |
| 23 | + :type warning_level: float |
| 24 | + :param min_num_instances: minimum numbers of instances to start looking for changes, defaults to 30 |
| 25 | + :type min_num_instances: int |
| 26 | +
|
18 | 27 | :References: |
19 | 28 |
|
20 | 29 | .. [ross2012exponentially] Ross, Gordon J., et al. |
21 | 30 | "Exponentially weighted moving average charts for detecting concept drift." |
22 | 31 | Pattern recognition letters 33.2 (2012): 191-198. |
23 | | - """ |
| 32 | + """ # noqa: E501 |
| 33 | + |
| 34 | + def __init__( # noqa: D107 |
| 35 | + self, |
| 36 | + lambda_: float = 0.2, |
| 37 | + average_run_length: int = 400, |
| 38 | + warning_level: float = 0.5, |
| 39 | + min_num_instances: int = 30, |
| 40 | + ) -> None: |
| 41 | + super().__init__( |
| 42 | + lambda_=lambda_, |
| 43 | + average_run_length=average_run_length, |
| 44 | + warning_level=warning_level, |
| 45 | + min_num_instances=min_num_instances, |
| 46 | + ) |
24 | 47 |
|
25 | 48 |
|
26 | 49 | class ECDDWT(BaseSPC): |
27 | 50 | """ECDDWT (EWMA Concept Drift Detection Warning) [ross2012exponentially]_ detector. |
28 | 51 |
|
| 52 | + :param config: configuration object of the detector, defaults to None. If None, the default configuration of :class:`ECDDWTConfig` is used. |
| 53 | + :type config: Optional[ECDDWTConfig] |
| 54 | + :param callbacks: callbacks, defaults to None |
| 55 | + :type callbacks: Optional[Union[BaseCallbackStreaming, List[BaseCallbackStreaming]]] |
| 56 | +
|
| 57 | + :Note: |
| 58 | + :func:`update` method expects to receive a value of 0 if the instance is correctly classified (no error) and 1 otherwise (error). |
| 59 | +
|
29 | 60 | :References: |
30 | 61 |
|
31 | 62 | .. [ross2012exponentially] Ross, Gordon J., et al. |
32 | 63 | "Exponentially weighted moving average charts for detecting concept drift." |
33 | 64 | Pattern recognition letters 33.2 (2012): 191-198. |
34 | | - """ |
| 65 | +
|
| 66 | + :Example: |
| 67 | +
|
| 68 | + >>> from frouros.detectors.concept_drift import ECDDWT |
| 69 | + >>> import numpy as np |
| 70 | + >>> np.random.seed(seed=31) |
| 71 | + >>> dist_a = np.random.binomial(n=1, p=0.6, size=1000) |
| 72 | + >>> dist_b = np.random.binomial(n=1, p=0.8, size=1000) |
| 73 | + >>> stream = np.concatenate((dist_a, dist_b)) |
| 74 | + >>> detector = ECDDWT() |
| 75 | + >>> warning_flag = False |
| 76 | + >>> for i, value in enumerate(stream): |
| 77 | + ... _ = detector.update(value=value) |
| 78 | + ... if detector.drift: |
| 79 | + ... print(f"Change detected at step {i}") |
| 80 | + ... break |
| 81 | + ... if not warning_flag and detector.warning: |
| 82 | + ... print(f"Warning detected at step {i}") |
| 83 | + ... warning_flag = True |
| 84 | + """ # noqa: E501 |
35 | 85 |
|
36 | 86 | config_type = ECDDWTConfig # type: ignore |
37 | 87 |
|
38 | | - def __init__( |
| 88 | + def __init__( # noqa: D107 |
39 | 89 | self, |
40 | 90 | config: Optional[ECDDWTConfig] = None, |
41 | 91 | callbacks: Optional[ |
42 | 92 | Union[BaseCallbackStreaming, List[BaseCallbackStreaming]] |
43 | 93 | ] = None, |
44 | 94 | ) -> None: |
45 | | - """Init method. |
46 | | -
|
47 | | - :param config: configuration parameters |
48 | | - :type config: Optional[ECDDWTConfig] |
49 | | - :param callbacks: callbacks |
50 | | - :type callbacks: Optional[Union[BaseCallbackStreaming, |
51 | | - List[BaseCallbackStreaming]]] |
52 | | - """ |
53 | 95 | super().__init__( |
54 | 96 | config=config, # type: ignore |
55 | 97 | callbacks=callbacks, |
@@ -131,11 +173,12 @@ def _update(self, value: Union[int, float], **kwargs) -> None: |
131 | 173 | * error_rate_variance |
132 | 174 | ) |
133 | 175 | control_limit = self.config.control_limit_func( # type: ignore |
134 | | - p=self.p.mean |
| 176 | + p=self.p.mean, |
135 | 177 | ) |
136 | 178 |
|
137 | 179 | drift_flag = self._check_threshold( |
138 | | - control_limit=control_limit, z_variance=z_variance |
| 180 | + control_limit=control_limit, |
| 181 | + z_variance=z_variance, |
139 | 182 | ) |
140 | 183 |
|
141 | 184 | if drift_flag: |
|
0 commit comments