|
- from typing import Any, Callable, List, Dict, Union, Optional, Sequence, Tuple
- from numpy import ndarray
- from collections import OrderedDict
- from scipy import sparse
- import os
- import sklearn
- import numpy
- import typing
-
- # Custom import commands if any
- import warnings
- import numpy as np
- from sklearn.utils import check_array
- from sklearn.exceptions import NotFittedError
- # from numba import njit
- from pyod.utils.utility import argmaxn
-
- from d3m.container.numpy import ndarray as d3m_ndarray
- from d3m.container import DataFrame as d3m_dataframe
- from d3m.metadata import hyperparams, params, base as metadata_base
- from d3m import utils
- from d3m.base import utils as base_utils
- from d3m.exceptions import PrimitiveNotFittedError
- from d3m.primitive_interfaces.base import CallResult, DockerContainer
-
- # from d3m.primitive_interfaces.supervised_learning import SupervisedLearnerPrimitiveBase
- from d3m.primitive_interfaces.unsupervised_learning import UnsupervisedLearnerPrimitiveBase
- from d3m.primitive_interfaces.transformer import TransformerPrimitiveBase
-
- from d3m.primitive_interfaces.base import ProbabilisticCompositionalityMixin, ContinueFitMixin
- from d3m import exceptions
- import pandas
-
- from d3m import container, utils as d3m_utils
-
- from detection_algorithm.UODBasePrimitive import Params_ODBase, Hyperparams_ODBase, UnsupervisedOutlierDetectorBase
- from pyod.models.lof import LOF
- import uuid
- # from typing import Union
-
- Inputs = d3m_dataframe
- Outputs = d3m_dataframe
-
-
- class Params(Params_ODBase):
- ######## Add more Attributes #######
-
- pass
-
-
- class Hyperparams(Hyperparams_ODBase):
- ######## Add more Hyperparamters #######
-
- n_neighbors = hyperparams.Hyperparameter[int](
- default=20,
- description='Number of neighbors to use by default for `kneighbors` queries. If n_neighbors is larger than the number of samples provided, all samples will be used.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/TuningParameter']
- )
-
- algorithm = hyperparams.Enumeration[str](
- values=['auto', 'ball_tree', 'kd_tree', 'brute'],
- default='auto',
- description='Algorithm used to compute the nearest neighbors.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/TuningParameter']
- )
-
- leaf_size = hyperparams.Hyperparameter[int](
- default=30,
- description='Leaf size passed to `BallTree` or `KDTree`. This can affect the speed of the construction and query, as well as the memory required to store the tree. The optimal value depends on the nature of the problem.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/TuningParameter']
- )
-
-
- metric = hyperparams.Enumeration[str](
- values=['cityblock', 'cosine', 'euclidean', 'l1', 'l2',
- 'manhattan', 'braycurtis', 'canberra', 'chebyshev',
- 'correlation', 'dice', 'hamming', 'jaccard', 'kulsinski',
- 'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto',
- 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath',
- 'sqeuclidean', 'yule'],
- default='minkowski',
- description='metric used for the distance computation. Any metric from scikit-learn or scipy.spatial.distance can be used.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/TuningParameter']
- )
-
-
- p = hyperparams.Hyperparameter[int](
- default=2,
- description='Parameter for the Minkowski metric from.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/TuningParameter']
- )
-
- metric_params = hyperparams.Union[Union[Dict, None]](
- configuration=OrderedDict(
- init=hyperparams.Hyperparameter[Dict](
- default={},
- ),
- ninit=hyperparams.Hyperparameter[None](
- default=None,
- ),
- ),
- default='ninit',
- description='Additional keyword arguments for the metric function.',
- semantic_types=['https://metadata.datadrivendiscovery.org/types/ControlParameter'],
- )
-
- pass
-
-
- class LOFPrimitive(UnsupervisedOutlierDetectorBase[Inputs, Outputs, Params, Hyperparams]):
- """
- Wrapper of Pyod LOF Class with more functionalities.
- Unsupervised Outlier Detection using Local Outlier Factor (LOF).
- The anomaly score of each sample is called Local Outlier Factor.
- It measures the local deviation of density of a given sample with
- respect to its neighbors.
- It is local in that the anomaly score depends on how isolated the object
- is with respect to the surrounding neighborhood.
- More precisely, locality is given by k-nearest neighbors, whose distance
- is used to estimate the local density.
- By comparing the local density of a sample to the local densities of
- its neighbors, one can identify samples that have a substantially lower
- density than their neighbors. These are considered outliers.
- See :cite:`breunig2000lof` for details.
-
- Parameters
- ----------
- n_neighbors : int, optional (default=20)
- Number of neighbors to use by default for `kneighbors` queries.
- If n_neighbors is larger than the number of samples provided,
- all samples will be used.
-
- algorithm : {'auto', 'ball_tree', 'kd_tree', 'brute'}, optional
- Algorithm used to compute the nearest neighbors:
- - 'ball_tree' will use BallTree
- - 'kd_tree' will use KDTree
- - 'brute' will use a brute-force search.
- - 'auto' will attempt to decide the most appropriate algorithm
- based on the values passed to :meth:`fit` method.
- Note: fitting on sparse input will override the setting of
- this parameter, using brute force.
-
- leaf_size : int, optional (default=30)
- Leaf size passed to `BallTree` or `KDTree`. This can
- affect the speed of the construction and query, as well as the memory
- required to store the tree. The optimal value depends on the
- nature of the problem.
-
- metric : string or callable, default 'minkowski'
- metric used for the distance computation. Any metric from scikit-learn
- or scipy.spatial.distance can be used.
- If 'precomputed', the training input X is expected to be a distance
- matrix.
- If metric is a callable function, it is called on each
- pair of instances (rows) and the resulting value recorded. The callable
- should take two arrays as input and return one value indicating the
- distance between them. This works for Scipy's metrics, but is less
- efficient than passing the metric name as a string.
- Valid values for metric are:
- - from scikit-learn: ['cityblock', 'cosine', 'euclidean', 'l1', 'l2',
- 'manhattan']
- - from scipy.spatial.distance: ['braycurtis', 'canberra', 'chebyshev',
- 'correlation', 'dice', 'hamming', 'jaccard', 'kulsinski',
- 'mahalanobis', 'matching', 'minkowski', 'rogerstanimoto',
- 'russellrao', 'seuclidean', 'sokalmichener', 'sokalsneath',
- 'sqeuclidean', 'yule']
- See the documentation for scipy.spatial.distance for details on these
- metrics:
- http://docs.scipy.org/doc/scipy/reference/spatial.distance.html
-
- p : integer, optional (default = 2)
- Parameter for the Minkowski metric from
- sklearn.metrics.pairwise.pairwise_distances. When p = 1, this is
- equivalent to using manhattan_distance (l1), and euclidean_distance
- (l2) for p = 2. For arbitrary p, minkowski_distance (l_p) is used.
- See http://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise.pairwise_distances
-
- metric_params : dict, optional (default = None)
- Additional keyword arguments for the metric function.
-
- contamination : float in (0., 0.5), optional (default=0.1)
- The amount of contamination of the data set, i.e. the proportion
- of outliers in the data set. When fitting this is used to define the
- threshold on the decision function.
-
- n_jobs : int, optional (default = 1)
- The number of parallel jobs to run for neighbors search.
- If ``-1``, then the number of jobs is set to the number of CPU cores.
- Affects only kneighbors and kneighbors_graph methods.
-
- Attributes
- ----------
- decision_scores_ : numpy array of shape (n_samples,)
- The outlier scores of the training data.
- The higher, the more abnormal. Outliers tend to have higher
- scores. This value is available once the detector is
- fitted.
- threshold_ : float
- The threshold is based on ``contamination``. It is the
- ``n_samples * contamination`` most abnormal samples in
- ``decision_scores_``. The threshold is calculated for generating
- binary outlier labels.
- labels_ : int, either 0 or 1
- The binary labels of the training data. 0 stands for inliers
- and 1 for outliers/anomalies. It is generated by applying
- ``threshold_`` on ``decision_scores_``.
- """
-
- metadata = metadata_base.PrimitiveMetadata({
- "name": "TODS.anomaly_detection_primitives.LOFPrimitive",
- "python_path": "d3m.primitives.tods.detection_algorithm.pyod_lof",
- "source": {'name': "DATALAB @Taxes A&M University", 'contact': 'mailto:khlai037@tamu.edu',
- 'uris': ['https://gitlab.com/lhenry15/tods.git']},
- "algorithm_types": [metadata_base.PrimitiveAlgorithmType.LOCAL_OUTLIER_FACTOR, ],
- "primitive_family": metadata_base.PrimitiveFamily.ANOMALY_DETECTION,
- "version": "0.0.1",
- "hyperparams_to_tune": ['n_neighbors', 'algorithm', 'leaf_size', 'p', 'contamination'],
- "id": str(uuid.uuid3(uuid.NAMESPACE_DNS, 'LOFPrimitive')),
- })
-
- def __init__(self, *,
- hyperparams: Hyperparams, #
- random_seed: int = 0,
- docker_containers: Dict[str, DockerContainer] = None) -> None:
- super().__init__(hyperparams=hyperparams, random_seed=random_seed, docker_containers=docker_containers)
-
- self._clf = LOF(contamination=hyperparams['contamination'],
- n_neighbors=hyperparams['n_neighbors'],
- algorithm=hyperparams['algorithm'],
- leaf_size=hyperparams['leaf_size'],
- metric=hyperparams['metric'],
- p=hyperparams['p'],
- metric_params=hyperparams['metric_params'],
- )
-
- return
-
- def set_training_data(self, *, inputs: Inputs) -> None:
- """
- Set training data for outlier detection.
- Args:
- inputs: Container DataFrame
-
- Returns:
- None
- """
- super().set_training_data(inputs=inputs)
-
- def fit(self, *, timeout: float = None, iterations: int = None) -> CallResult[None]:
- """
- Fit model with training data.
- Args:
- *: Container DataFrame. Time series data up to fit.
-
- Returns:
- None
- """
- return super().fit()
-
- def produce(self, *, inputs: Inputs, timeout: float = None, iterations: int = None) -> CallResult[Outputs]:
- """
- Process the testing data.
- Args:
- inputs: Container DataFrame. Time series data up to outlier detection.
-
- Returns:
- Container DataFrame
- 1 marks Outliers, 0 marks normal.
- """
- return super().produce(inputs=inputs, timeout=timeout, iterations=iterations)
-
- def get_params(self) -> Params:
- """
- Return parameters.
- Args:
- None
-
- Returns:
- class Params
- """
- return super().get_params()
-
- def set_params(self, *, params: Params) -> None:
- """
- Set parameters for outlier detection.
- Args:
- params: class Params
-
- Returns:
- None
- """
- super().set_params(params=params)
-
|