COPOD - Copula-Based Outlier Detection.
Classes
COPOD scores outliers by their empirical copula tail probability.
ECODDetector it is parameter-free and deterministic, and because it works on ranks it is untouched by monotone rescaling of any feature.__init__( self, contamination: float = 0.1, )
Overview
- Replace every training value by its empirical CDF value, giving the
- For a query point, look up its left- and right-tail copula probability
- Take -\log of each and sum across dimensions to get a tail
- Report the largest of the left, right, and skewness-corrected sums.
Theory
Sklar's theorem says any joint distribution factors as
for a copula C carrying all the dependence. COPOD estimates the marginals F_j empirically and reads the resulting tail probability as a measure of outlyingness: a point deep in the joint tail has a very small copula value and therefore a large -\log.
The skewness correction picks, per dimension, the tail the data is actually skewed towards, so a right-skewed feature is not penalised for having a long right tail by construction.
Parameters
contamination
Attributes
X_train_
skewness_
threshold_
n_features_in_
fit.
Notes
Complexity. Training is O(n d \log n), prediction O(m d \log n), memory O(n d). The ranking runs in the shared C++ kernel tuiml._cpp_ext.stats.tail_probabilities.
Relationship to ECOD. These two are close relatives from the same group, and on most data they score almost identically — the difference is framing rather than mechanism, COPOD arriving at the tail sum through the empirical copula and ECOD through per-dimension ECDFs. The practical reason to prefer ECODDetector is its feature_contributions, which names the features responsible for a flag. COPOD is here because it is the more widely cited baseline and reviewers ask for it by name.
When to use. Same territory as ECOD: high-dimensional tabular data, no tuning budget, a need for deterministic and reproducible scores. Both assume outlyingness shows up in the marginals; neither will find a point that is only strange in the joint distribution.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.anomaly import COPODDetector
>>> rng = np.random.default_rng(0)
>>> X = np.vstack([rng.normal(0, 1, (200, 3)), rng.normal(8, 1, (10, 3))])
>>> detector = COPODDetector(contamination=0.05).fit(X)
>>> int((detector.predict(X)[-10:] == -1).sum())
10
Methods
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'COPODDetector'
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'COPODDetector'
Fit the COPOD detector.
Parameters
X
_y
Returns
self