Anomaly detection is ranking rows by how unusual they are and deciding how many to look at. The hard parts
are not the algorithm: defining unusual relative to what (a feature's normal range, the usual
combination of features, the entity's own history, the time of day), choosing the alert budget, and
evaluating with almost no labels. scripts/anomaly_scores.py scores rows with four complementary
detectors (robust z, Mahalanobis, k-NN distance, Isolation Forest) plus a rank ensemble, and explains each
alert; scripts/anomaly_eval.py measures precision at the alert budget when labels exist and detector
agreement and thresholds when they do not.
Trigger Conditions
Activate this skill when the user:
- Wants to find outliers, unusual transactions, faulty sensors, abnormal user behaviour or data-quality errors
- Has few or no labels for the bad events (fraud before labels, new failure modes)
- Asks Isolation Forest vs LOF vs one-class SVM vs autoencoder, or how to set
contamination - Needs to explain why a row was flagged, or to choose a threshold for an alert queue
- Wants to evaluate an anomaly detector or compare detectors
Supervised fraud models (enough labels): fraud-detection-model-designer; PCA-based process monitoring (T², Q): pca-dimensionality-reducer; rare-positive classification: imbalanced-class-handler; time-series anomalies via forecasts: time-series-forecasting-model-builder.
Workflow
1. DEFINE -> what is anomalous: point / contextual (given time, entity, segment) / collective (a sequence)
2. NORMAL -> a reference period / population that is mostly normal; remove known incidents
3. FEATURES -> deviations from the right context (vs own history, vs peer group, vs time of day)
4. SCORE -> python scripts/anomaly_scores.py --train ref.csv --score new.csv --drop id --out scores.csv
5. BUDGET -> how many alerts per day can be reviewed? threshold = score of the k-th row
6. EVALUATE -> python scripts/anomaly_eval.py scores.csv --scores ... --label known --k 10 20 50
7. EXPLAIN -> deviating features per alert; route to the owner; collect review outcomes as labels
8. ITERATE -> labels accumulate -> semi-supervised -> supervised model (fraud-detection skill)Anomaly Types and Features
| Type | Example | Make it detectable by |
|---|---|---|
| Point | a sensor reading of 999 | per-feature robust z / IQR, Isolation Forest |
| Combination | temperature and pressure each normal, together impossible | Mahalanobis, k-NN, Isolation Forest, PCA Q residual |
| Contextual | 3 a.m. login, high spend on a normally small card | features relative to context: ratio to entity mean, hour-of-day baselines |
| Collective | 50 small transactions in 5 minutes | window aggregates (velocity), sequence models |
| Drift / new regime | gradual sensor drift | residuals vs a forecast, change-point detection |
The best detector cannot see a contextual anomaly if the context is not in the features. Build "relative to normal for this entity / time" features first (time-based-feature-builder).
Detector Guide
| Detector | Finds | Scale | Notes |
|---|---|---|---|
| Robust z (median/MAD), IQR fences | extreme single features | any | transparent; misses combinations |
| Mahalanobis (robust covariance: MinCovDet) | unusual combinations, elliptical normal data | p < ~50 | assumes one Gaussian-ish blob |
| k-NN distance | isolated points | n < ~10^6 with an index | scale features; k 5-20 |
| Local Outlier Factor | points less dense than their neighbours | n < ~10^5 | handles varying density; novelty=True to score new data |
| Isolation Forest | easy-to-isolate points, mixed shapes | large n, many features | robust default; contamination only sets the threshold |
| One-class SVM | boundary of normal data | n < ~10^4 | sensitive to nu, gamma, scaling |
| PCA reconstruction / autoencoder | rows that break correlation structure | high-dimensional | autoencoders need lots of normal data |
| Forecast residuals | time-series spikes and level shifts | per series | seasonality-aware baselines |
On the sensor fixture (6 planted anomalies, one contextual) every detector reaches ROC-AUC >= 0.99; the contextual one (temperature 76 and pressure 26.5, each plausible alone) is ranked high mainly by Mahalanobis. The pure-Python Isolation Forest's PR-AUC (0.976) is in line with scikit-learn's (0.944) on the same data.
Code for each detector in scikit-learn / PyOD: detector-recipes.md.
Thresholds and Alert Budgets
| Method | Use |
|---|---|
| Alert budget (top k per period) | analysts review a fixed number: threshold = score of the k-th row |
| Score percentile (99th, 99.5th) | expected anomaly rate known roughly |
| median + 3 MAD of the score | robust cut on raw (not rank-normalised) scores |
contamination= | scikit-learn's way to place the threshold at a percentile; does not change the scores |
| Cost-based | expected loss per missed anomaly vs review cost, once some labels exist |
anomaly_eval.py prints each of these per score column.
Evaluation With and Without Labels
| Situation | Measure |
|---|---|
| Some labelled incidents | precision@k at the alert budget, recall on known incidents, PR-AUC |
| No labels | detector agreement (Spearman, top-k Jaccard), stability across reference periods, reviewer feedback rate |
| Synthetic checks | inject known anomalies (spikes, swapped columns, combinations) and measure recall |
| Online | share of alerts confirmed by reviewers; time to detect real incidents |
Few labels mean wide intervals: report counts ("caught 5 of 6 known incidents at 10 alerts/day"). Evaluation design and label collection loops: evaluation-and-operations.md.
Explaining Alerts
For each alert show the features that deviate most (robust z per feature), the detector(s) that flagged it,
and the context (entity history, peer group). anomaly_scores.py lists the top three deviating features per
row; for Isolation Forest models in production, SHAP's TreeExplainer also works.
Output Format
When building an anomaly detector, deliver:
- Definition - anomaly type(s), unit (row / entity / window), reference period.
- Features - context-relative features and scaling.
- Detectors - chosen detectors and why; scores from
anomaly_scores.py. - Threshold - alert budget and the matching cut-off.
- Evaluation - precision@k / recall on known incidents (or agreement and synthetic recall).
- Explanations and workflow - per-alert reasons, review queue, how labels feed back.
Scripts
python scripts/anomaly_scores.py --train sensors.csv --drop reading_id is_anomaly --top 10
python scripts/anomaly_scores.py --train reference.csv --score new.csv --drop id --out scores.csv
python scripts/anomaly_scores.py --train data.csv --columns temperature pressure --k 10 --trees 200 --jsonFits on --train (the normal reference) and scores --score (default: the training rows): robust z (max |x −
median| / 1.4826 MAD), Mahalanobis with covariance from the central 90% of rows, distance to the k-th nearest
neighbour on standardised features, Isolation Forest (--trees, subsamples of 256), and the mean of rank-normalised
scores; top rows with their three most deviating features; --out writes every score. Exit codes: 0 scored, 2
usage error.
python scripts/anomaly_eval.py scores.csv --scores score_iforest score_knn score_ensemble --label is_anomaly --k 5 10 20
python scripts/anomaly_eval.py scores.csv --scores score_robust_z score_mahalanobis --k 10With --label: ROC-AUC, PR-AUC, precision@k and recall@k per score and the best detector per budget (ties
listed). Without labels: Spearman agreement and top-k Jaccard between detectors. Always: thresholds at each budget,
99th/99.5th percentiles and median + 3 MAD with the number of rows each flags. Exit codes: 0 evaluated, 2 usage
error.
Additional Resources
| File | Content |
|---|---|
| detector-recipes.md | scikit-learn and PyOD code: robust z, MinCovDet, LOF (novelty), IsolationForest, OneClassSVM, PCA/autoencoder reconstruction, ensembles |
| contextual-and-time-series.md | Context-relative features, peer groups, seasonal baselines, forecast residuals, change points, collective anomalies |
| evaluation-and-operations.md | Precision@k with few labels, synthetic injection, agreement, alert budgets, review loops, drift and retraining |
catboost-model-builder
Build CatBoost models that use its strengths correctly: raw categorical columns as cat_features (ordered target statistics, no manual encoding), text_features, Pool construction with NaN-safe categories, ordered boosting and has_time for temporal data, symmetric (oblivious) trees, overfitting detector with eval_set and use_best_model, losses for classification, regression (Quantile, Poisson, Tweedie) and ranking (YetiRank), class weights, monotone constraints, feature importance (PredictionValuesChange, LossFunctionChange) and SHAP values, GPU training and model export. Plans cat/text/numeric columns from a CSV and generates a runnable training script, and checks parameter sets for the conflicts CatBoost rejects (iterations vs n_estimators, Bayesian bootstrap with subsample, multiple class-weight options, depth > 16, use_best_model without eval_set).
categorical-encoding-selector
Choose and implement the right encoding for every categorical column given the model family and the data: one-hot (with infrequent-level grouping and handle_unknown), ordinal with an explicit order, cross-fitted target encoding (scikit-learn TargetEncoder, CatBoost ordered statistics, category_encoders inside CV), frequency/count encoding, feature hashing, native categorical support in LightGBM, HistGradientBoosting, XGBoost and CatBoost, prefix levels for codes (zip3, NAICS-2), and embeddings. Measures cardinality, rare-level share, unseen-level rate on a time-ordered holdout and target signal per column, emits the ColumnTransformer, and quantifies target-encoding leakage (in-sample vs out-of-fold vs holdout AUC).
classification-model-selector
Choose the right classification algorithm for tabular, text or mixed data and prove the choice with a fair bake-off: logistic regression (L2, L1, elastic net), linear SVM, naive Bayes, k-NN, RBF SVM, decision trees, random forest, extra trees, HistGradientBoosting, LightGBM, XGBoost, CatBoost, explainable boosting machines (EBM/GAM), points scorecards and MLPs, matched to data size, width, categorical and high-cardinality share, missingness, class imbalance, text, and constraints such as interpretability, monotonic constraints, calibrated probabilities, latency budgets and tiny deployable models. Ranks candidates with starting hyperparameters and cautions, then generates a bake-off script running every candidate on identical CV folds with per-fold metrics, fit time and prediction latency.
clustering-algorithm-selector
Choose the right clustering algorithm and check that clustering makes sense at all: cluster tendency (Hopkins statistic with a correlated-features caveat, nearest-neighbour isolation), then k-means / MiniBatchKMeans, Gaussian mixtures with BIC, agglomerative (Ward, average, complete, single) with dendrograms, DBSCAN, HDBSCAN, OPTICS, spectral clustering, BIRCH, mean shift, k-prototypes and k-modes for mixed or categorical data, and Gower distance, matched to data size, expected shapes, noise, varying density, known k, soft memberships, hierarchy and streaming. Covers preprocessing (scaling, encoding, dimensionality, distance metrics), validation (internal indices, bootstrap stability, external labels, business profiling) and assigning new points.
collaborative-filtering-implementer
Implement collaborative filtering recommenders that beat popularity: item-based kNN with cosine, Jaccard or asymmetric similarity, shrinkage, neighbourhood size, positive-only or mean-centred rating signals and 'because you liked X' explanations; implicit ALS with confidence weighting, BPR pairwise ranking and the closed-form EASE model in plain NumPy, tuned on a temporal validation split by recall@k and NDCG@k and refit on all data; plus user-kNN, explicit matrix factorisation, the implicit/LightFM libraries, hyperparameter ranges, cold-start fallbacks, scaling with sparse matrices and approximate nearest neighbours. Produces top-k lists in the format of the recommendation evaluator.
counterfactual-explanation-generator
Generate counterfactual explanations and algorithmic recourse: the smallest realistic change to a row's features that changes the model's decision. Solves exact minimal-cost recourse for linear and logistic models (MAD-scaled L1 cost, immutable features, increase/decrease directions, bounds, integer and binary features, diverse alternatives, features every counterfactual must change, and a no-recourse finding when immutable features decide), generates DiCE counterfactuals for any scikit-learn model with constraints turned into permitted ranges and every result re-predicted, and validates counterfactuals from any method for constraint violations, implausible values, off-manifold rows, broken derived-feature relations and failure to flip the prediction.