Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reorganize concept drift methods #184

Merged
merged 4 commits into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified docs/source/images/detectors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions frouros/detectors/concept_drift/streaming/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
PageHinkley,
PageHinkleyConfig,
)
from .ddm_based import (
from .statistical_process_control import (
DDM,
DDMConfig,
ECDDWT,
Expand All @@ -22,14 +22,14 @@
HDDMWConfig,
RDDM,
RDDMConfig,
STEPD,
STEPDConfig,
)
from .window_based import (
ADWIN,
ADWINConfig,
KSWIN,
KSWINConfig,
STEPD,
STEPDConfig,
)

__all__ = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
"""Concept drift DDM based detection methods' init."""
"""Concept drift SPC (statistical process control) detection methods' init."""

from .ddm import DDM, DDMConfig
from .ecdd import ECDDWT, ECDDWTConfig
from .eddm import EDDM, EDDMConfig
from .hddm import HDDMA, HDDMAConfig, HDDMW, HDDMWConfig
from .rddm import RDDM, RDDMConfig
from .stepd import STEPD, STEPDConfig

__all__ = [
"DDM",
Expand All @@ -18,8 +17,6 @@
"HDDMAConfig",
"HDDMW",
"HDDMWConfig",
"STEPD",
"STEPDConfig",
"RDDM",
"RDDMConfig",
]
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Supervised DDM based base module."""
"""Concept drift SPC (statistical process control) base module."""

import abc
from typing import Dict, List, Optional, Tuple, Union
Expand All @@ -14,8 +14,8 @@
from frouros.utils.stats import Mean


class DDMBaseConfig(ConceptDriftStreamingBaseConfig):
"""Class representing a DDM based configuration class."""
class SPCBaseConfig(ConceptDriftStreamingBaseConfig):
"""Class representing a SPC configuration class."""

def __init__(
self,
Expand Down Expand Up @@ -82,20 +82,20 @@ def warning_level(self, value: float) -> None:
self._warning_level = value


class DDMBased(ConceptDriftStreamingBase):
"""Abstract class representing a DDM based estimator."""
class SPCBase(ConceptDriftStreamingBase):
"""Abstract class representing an SPC estimator."""

config_type = DDMBaseConfig
config_type = SPCBaseConfig

def __init__(
self,
config: Optional[DDMBaseConfig] = None,
config: Optional[SPCBaseConfig] = None,
callbacks: Optional[Union[Callback, List[Callback]]] = None,
) -> None:
"""Init method.

:param config: configuration parameters
:type config: Optional[DDMBaseConfig]
:type config: Optional[SPCBaseConfig]
:param callbacks: callbacks
:type callbacks: Optional[Union[Callback, List[Callback]]]
"""
Expand Down Expand Up @@ -145,20 +145,20 @@ def _update(self, value: Union[int, float], **kwargs) -> None:
pass


class DDMErrorBased(DDMBased):
"""Abstract class representing a DDM error based estimator."""
class SPCErrorBase(SPCBase):
"""Abstract class representing a SPC error estimator."""

config_type = DDMBaseConfig
config_type = SPCBaseConfig

def __init__(
self,
config: Optional[DDMBaseConfig] = None,
config: Optional[SPCBaseConfig] = None,
callbacks: Optional[Union[Callback, List[Callback]]] = None,
) -> None:
"""Init method.

:param config: configuration parameters
:type config: Optional[DDMBaseConfig]
:type config: Optional[SPCBaseConfig]
:param callbacks: callbacks
:type callbacks: Optional[Union[Callback, List[Callback]]]
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
from contextlib import suppress
from typing import Union

from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBaseConfig,
DDMErrorBased,
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBaseConfig,
SPCErrorBase,
)


class DDMConfig(DDMBaseConfig):
class DDMConfig(SPCBaseConfig):
"""DDM (Drift detection method) [gama2004learning]_ configuration.

:References:
Expand All @@ -22,7 +22,7 @@ class DDMConfig(DDMBaseConfig):
"""


class DDM(DDMErrorBased):
class DDM(SPCErrorBase):
"""DDM (Drift detection method) [gama2004learning]_ detector.

:References:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
import numpy as np # type: ignore

from frouros.callbacks import Callback
from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBased,
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBase,
ECDDBaseConfig,
)
from frouros.utils.stats import EWMA, Mean
Expand All @@ -23,7 +23,7 @@ class ECDDWTConfig(ECDDBaseConfig):
"""


class ECDDWT(DDMBased):
class ECDDWT(SPCBase):
"""ECDDWT (EWMA Concept Drift Detection Warning) [ross2012exponentially]_ detector.

:References:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
import numpy as np # type: ignore

from frouros.callbacks import Callback
from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBaseConfig,
DDMBased,
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBaseConfig,
SPCBase,
)


class EDDMConfig(DDMBaseConfig):
class EDDMConfig(SPCBaseConfig):
"""EDDM (Early drift detection method) [baena2006early]_ configuration.

:References:
Expand Down Expand Up @@ -133,7 +133,7 @@ def min_num_misclassified_instances(self, value: int) -> None:
self._min_num_misclassified_instances = value


class EDDM(DDMBased):
class EDDM(SPCBase):
"""EDDM (Early drift detection method) [baena2006early]_ detector.

:References:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import numpy as np # type: ignore

from frouros.callbacks import Callback
from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBaseConfig,
DDMBased,
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBaseConfig,
SPCBase,
)
from frouros.utils.stats import EWMA, Mean


class HDDMBaseConfig(DDMBaseConfig):
class HDDMBaseConfig(SPCBaseConfig):
"""HDDM (Hoeffding's drift detection method) [frias2014online]_ configuration.

:References:
Expand Down Expand Up @@ -318,7 +318,7 @@ def update_cut_point(self, epsilon_z: float) -> None:
self.y = copy.deepcopy(self.z)


class HDDMA(DDMBased):
class HDDMA(SPCBase):
"""HDDM-A (Hoeffding's drift detection method with A-Test) [frias2014online]_ detector.

:References:
Expand Down Expand Up @@ -614,7 +614,7 @@ def update_stats(self, value: float, alpha: float) -> None:
self.sample_decrease_2.update(value=value)


class HDDMW(DDMBased):
class HDDMW(SPCBase):
"""HDDM-W (Hoeffding's drift detection method with W-Test) [frias2014online]_ detector.

:References:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
from typing import List, Optional, Union

from frouros.callbacks import Callback
from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBaseConfig,
DDMErrorBased,
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBaseConfig,
SPCErrorBase,
)
from frouros.utils.data_structures import CircularQueue
from frouros.utils.stats import Mean


class RDDMConfig(DDMBaseConfig):
class RDDMConfig(SPCBaseConfig):
"""RDDM (Reactive Drift detection method) [barros2017rddm]_ configuration.

:References:
Expand Down Expand Up @@ -110,7 +110,7 @@ def max_num_instances_warning(self, value: int) -> None:
self._max_num_instances_warning = value


class RDDM(DDMErrorBased):
class RDDM(SPCErrorBase):
"""RDDM (Reactive Drift detection method) [barros2017rddm]_ detector.

:References:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@

from .adwin import ADWIN, ADWINConfig
from .kswin import KSWIN, KSWINConfig
from .stepd import STEPD, STEPDConfig


__all__ = [
"ADWIN",
"ADWINConfig",
"KSWIN",
"KSWINConfig",
"STEPD",
"STEPDConfig",
]
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
from scipy.stats import norm # type: ignore

from frouros.callbacks import Callback
from frouros.detectors.concept_drift.streaming.ddm_based.base import (
DDMBaseConfig,
DDMBased,
from frouros.detectors.concept_drift.streaming.window_based.base import (
WindowBaseConfig,
WindowBased,
)
from frouros.utils.data_structures import AccuracyQueue


class STEPDConfig(DDMBaseConfig):
class STEPDConfig(WindowBaseConfig):
"""STEPD (Statistical test of equal proportions) [nishida2007detecting]_ configuration.

:References:
Expand Down Expand Up @@ -88,7 +88,7 @@ def alpha_w(self, value: float) -> None:
self._alpha_w = value


class STEPD(DDMBased):
class STEPD(WindowBased):
"""STEPD (Statistical test of equal proportions) [nishida2007detecting]_ detector.

:References:
Expand Down Expand Up @@ -122,10 +122,29 @@ def __init__(
"window_accuracy": AccuracyQueue(max_len=self.config.min_num_instances),
**self.additional_vars, # type: ignore
}
self.warning = False
self._set_additional_vars_callback()
self._min_num_instances = 2 * self.config.min_num_instances
self._distribution = norm()

@property
def warning(self) -> bool:
"""Warning property.

:return: warning
:rtype: bool
"""
return self._warning

@warning.setter
def warning(self, value: bool) -> None:
"""Warning setter.

:param value: value to be set
:type value: bool
"""
self._warning = value

@property
def correct_total(self) -> int:
"""Number of correct labels property.
Expand Down
9 changes: 5 additions & 4 deletions frouros/tests/integration/test_callback.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
STEPD,
)
from frouros.detectors.concept_drift.base import ConceptDriftBase
from frouros.detectors.concept_drift.streaming.ddm_based.base import DDMBased
from frouros.detectors.concept_drift.streaming.statistical_process_control.base import (
SPCBase,
)
from frouros.detectors.data_drift.batch import (
BhattacharyyaDistance,
CVMTest,
Expand Down Expand Up @@ -188,13 +190,12 @@ def _fit_model(model, X, y): # noqa: N803
HDDMA,
HDDMW,
RDDM,
STEPD,
], # pylint: disable=too-many-locals
)
def test_streaming_warning_samples_buffer_on_concept_drift(
dataset_simple: Tuple[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray]],
model: sklearn.pipeline.Pipeline,
detector_class: DDMBased,
detector_class: SPCBase,
):
"""Test streaming warning samples buffer on concept drift callback.

Expand All @@ -203,7 +204,7 @@ def test_streaming_warning_samples_buffer_on_concept_drift(
:param model: trained model
:type model: sklearn.pipeline.Pipeline
:param detector_class: concept drift detector
:type detector_class: DDMBased
:type detector_class: SPCBase
"""
_, test = dataset_simple # noqa: N806

Expand Down
Binary file modified images/detectors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.