Thomas Piacentini
← Workshop

Cheat sheet

Clustering, Dimensionality Reduction and Anomalies

Original text · English

Cluster, reduce and flag outliers without labels. K-Means, DBSCAN, GMM, PCA, Isolation Forest, LOF.

Three jobs without labels

reducedRaw datano labelsPCAkeep 90-95% varianceClusteringK-Means, DBSCAN, GMMDetectorIsolation Forest, LOFReconstruction errorhigh error is an outlierAnomaly scorerank, then thresholdFlagged pointshuman review
Nodes and connections
NodeRoleKind
Raw datano labels
PCAkeep 90-95% variance
ClusteringK-Means, DBSCAN, GMM
DetectorIsolation Forest, LOF
Reconstruction errorhigh error is an outlier
Anomaly scorerank, then threshold
Flagged pointshuman review
FromToConnection
Raw dataPCA
PCAClusteringreduced
PCAReconstruction error
Raw dataDetector
DetectorAnomaly score
Reconstruction errorFlagged points
Anomaly scoreFlagged points
Sources

From-scratch calls

TaskCode
K clusters, hard labelskmeans(data, k=3)
Inertia and silhouette per Kfind_best_k(data, max_k=6)
Dense regions, noise is -1dbscan(data, eps=1.5, min_samples=5)
Soft labels with EMgmm(data, k=3)
Project to 2 axesPCA(n_components=2).fit_transform(X)
Separate ringskernel_pca(X, n_components, kernel="rbf", gamma=1.0)
Flag by standard deviationszscore_detect(X, threshold=3.0)
Flag outside the fencesiqr_detect(X, factor=1.5)
Sources

The same in sklearn

km = KMeans(n_clusters=3, random_state=42).fit(data)
db = DBSCAN(eps=1.5, min_samples=5).fit(data)
gmm_model = GaussianMixture(n_components=3, random_state=42).fit(data)
sklearn_pca = SklearnPCA(n_components=2)explained_variance_ratio_
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
reducer = UMAP(n_components=2, n_neighbors=15, min_dist=0.1, random_state=42)
iso = IsolationForest(n_estimators=100, contamination=0.05, random_state=42)
iso.fit(X_train)fit on normal data
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.05, novelty=True)
oc_svm = OneClassSVM(kernel="rbf", gamma="auto", nu=0.05)
Sources

Formulas

Inertia
sum of squared distances from each point to its centroid. Lower is tighter.
Silhouette
(b - a) / \max(a, b), from -1 (wrong cluster) to +1.
Z-score
(x - \text{mean}) / \text{std}. Flag when the absolute value passes the threshold.
IQR fences
Q1 - \text{factor} \cdot IQR and Q3 + \text{factor} \cdot IQR, with IQR = Q3 - Q1.
Isolation score
2^{-\text{average\_path\_length}(x) / c(n)}. Near 1 is an anomaly, near 0.5 is normal.
c(n)
2 * H(n-1) - 2*(n-1)/n, expected path length of a failed search.
Explained ratio
\text{eigenvalue}_k / \sum \text{all eigenvalues}
PCA fraction lost
dropped eigenvalues over all eigenvalues.
Sources

Clustering: use X when

CommandWhat it does
K-MeansLarge data, spherical clusters, known K. Hurt by outliers
DBSCANUnknown K, any shape, finds noise. Fails on varying density
HierarchicalSmall data, needs a dendrogram. O(n^2) memory
GMMOverlapping, elliptical clusters, soft assignments
Ward linkageMerge with the smallest rise in within-cluster variance
Sources

Reduce and detect: use X when

CommandWhat it does
PCAPreprocessing and compression. Fast, global variance
t-SNE2D plots of local neighborhoods. Below 10k samples
UMAP2D plots at scale. Some global structure
Kernel PCANonlinear manifold. Kernel matrix is n by n
Z-score / IQROne feature at a time. Very fast
Isolation ForestNo assumptions. Works in high dimensions
LOFLocal anomalies, clusters of different density. Slow
One-Class SVMSmall to medium data. Kernel matrix grows quadratically
Sources

Anomaly detection pipeline

  1. Baseline collect a period with no or very few anomalies.
  2. Features add rolling statistics, time features and ratios.
  3. Train fit the detector on the baseline. It learns normal.
  4. Score give each new observation an anomaly score.
  5. Threshold pick the cutoff from the cost of false alarms and misses.
  6. Alert send flagged points to human review.
  7. Feedback record true anomalies and false alarms. Tune the threshold.
Sources

Defaults and numbers

SettingDefaultNote
Z-score threshold3.099.7% of Gaussian data is inside
IQR factor1.53.0 flags fewer points
n_estimators100Isolation trees. Usually enough
max_samples256Rows per tree, from the original paper
predict threshold0.5Score above it is an anomaly
contamination0.05Sets the cutoff only, not the scores
t-SNE perplexity30Typical range 5-50
Variance kept0.95Or 0.90 for the PCA cutoff
Sources

Failures and fixes

SymptomCauseFix
K-Means splits moons badlyClusters are not sphericalUse DBSCAN with eps=0.3
K-Means results change per runLocal minimum of inertiaFix the seed or use K-Means++
Z-score misses pointsMultimodal data or outliers in trainingUse IQR or Isolation Forest
Per-feature methods miss a pointUnusual only in the joint spaceUse Isolation Forest
99.9% accuracy, no catches0.1% anomalies, accuracy is uselessPrecision@k and AUPRC
Operators ignore alertsToo many false alarmsStart with a high threshold
Median score drifts upData changed or model is staleRetrain on recent normal data
t-SNE cluster gaps differDistances between clusters mean nothingRead only the clusters
Sources

Abbreviations

DBSCAN
density-based clustering. Core, border and noise points.
GMM
Gaussian Mixture Model. K Gaussians with soft assignments.
EM
Expectation-Maximization. E-step probabilities, M-step parameters.
PCA
Principal Component Analysis. Axes of maximum variance.
t-SNE
t-Distributed Stochastic Neighbor Embedding. Keeps neighbors.
UMAP
Uniform Manifold Approximation and Projection. Faster, more global.
LOF
Local Outlier Factor. Above 1.0 is lower density than neighbors.
AUPRC
area under the precision-recall curve. Better than AUROC here.
Sources

Questions

How do I pick K?
Find the elbow in inertia. Check the silhouette score.
Why model normal data?
Anomalies are rare and change. Deviations from normal include novel types.
What is the best training setup?
Semi-supervised: fit on a clean set of normal data only.
Few labeled anomalies?
Use them for evaluation, not training.
Why is Isolation Forest fast?
Each tree uses a small subsample.
Why reduce dimensions?
Distances converge in high dimensions. Nearest-neighbor search stops working.
Sources
Original source
---
id: unsupervised-anomaly
title: Clustering, Dimensionality Reduction and Anomalies
code: CD
subtitle: Cluster, reduce and flag outliers without labels. K-Means, DBSCAN, GMM, PCA, Isolation Forest, LOF.
hue: 280
sources: phases/02-ml-fundamentals/07-unsupervised-learning, phases/02-ml-fundamentals/16-anomaly-detection, phases/01-math-foundations/10-dimensionality-reduction
source_hash: 3ccb116dd003a31f
---

## Three jobs without labels
type: architecture
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

```arch
node | raw | 1,2 | Raw data | no labels
node | pca | 2,1 | PCA | keep 90-95% variance
node | clu | 3,1 | Clustering | K-Means, DBSCAN, GMM
node | det | 2,3 | Detector | Isolation Forest, LOF
node | rec | 3,2 | Reconstruction error | high error is an outlier
node | score | 3,3 | Anomaly score | rank, then threshold
node | flag | 4,2 | Flagged points | human review
edge | raw | pca |
edge | pca | clu | reduced
edge | pca | rec |
edge | raw | det |
edge | det | score |
edge | rec | flag |
edge | score | flag |
```

## From-scratch calls
type: task-table
from: phases/02-ml-fundamentals/07-unsupervised-learning/code/clustering.py, phases/01-math-foundations/10-dimensionality-reduction/code/dim_reduction.py, phases/02-ml-fundamentals/16-anomaly-detection/code/anomaly_detection.py

| Task | Code |
|---|---|
| K clusters, hard labels | `kmeans(data, k=3)` |
| Inertia and silhouette per K | `find_best_k(data, max_k=6)` |
| Dense regions, noise is -1 | `dbscan(data, eps=1.5, min_samples=5)` |
| Soft labels with EM | `gmm(data, k=3)` |
| Project to 2 axes | `PCA(n_components=2).fit_transform(X)` |
| Separate rings | `kernel_pca(X, n_components, kernel="rbf", gamma=1.0)` |
| Flag by standard deviations | `zscore_detect(X, threshold=3.0)` |
| Flag outside the fences | `iqr_detect(X, factor=1.5)` |

## The same in sklearn
type: annotated-code
lang: python
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

```python
km = KMeans(n_clusters=3, random_state=42).fit(data)
db = DBSCAN(eps=1.5, min_samples=5).fit(data)
gmm_model = GaussianMixture(n_components=3, random_state=42).fit(data)
sklearn_pca = SklearnPCA(n_components=2)          # explained_variance_ratio_
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
reducer = UMAP(n_components=2, n_neighbors=15, min_dist=0.1, random_state=42)
iso = IsolationForest(n_estimators=100, contamination=0.05, random_state=42)
iso.fit(X_train)                                  # fit on normal data
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.05, novelty=True)
oc_svm = OneClassSVM(kernel="rbf", gamma="auto", nu=0.05)
```

## Formulas
type: concepts
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

- **Inertia**: sum of squared distances from each point to its centroid. Lower is tighter.
- **Silhouette**: $(b - a) / \max(a, b)$, from -1 (wrong cluster) to +1.
- **Z-score**: $(x - \text{mean}) / \text{std}$. Flag when the absolute value passes the threshold.
- **IQR fences**: $Q1 - \text{factor} \cdot IQR$ and $Q3 + \text{factor} \cdot IQR$, with $IQR = Q3 - Q1$.
- **Isolation score**: $2^{-\text{average\_path\_length}(x) / c(n)}$. Near 1 is an anomaly, near 0.5 is normal.
- **c(n)**: `2 * H(n-1) - 2*(n-1)/n`, expected path length of a failed search.
- **Explained ratio**: $\text{eigenvalue}_k / \sum \text{all eigenvalues}$
- **PCA fraction lost**: dropped eigenvalues over all eigenvalues.

## Clustering: use X when
type: command-table
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md

| Command | What it does |
|---|---|
| K-Means | Large data, spherical clusters, known K. Hurt by outliers |
| DBSCAN | Unknown K, any shape, finds noise. Fails on varying density |
| Hierarchical | Small data, needs a dendrogram. $O(n^2)$ memory |
| GMM | Overlapping, elliptical clusters, soft assignments |
| Ward linkage | Merge with the smallest rise in within-cluster variance |

## Reduce and detect: use X when
type: command-table
from: phases/01-math-foundations/10-dimensionality-reduction/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md

| Command | What it does |
|---|---|
| PCA | Preprocessing and compression. Fast, global variance |
| t-SNE | 2D plots of local neighborhoods. Below 10k samples |
| UMAP | 2D plots at scale. Some global structure |
| Kernel PCA | Nonlinear manifold. Kernel matrix is n by n |
| Z-score / IQR | One feature at a time. Very fast |
| Isolation Forest | No assumptions. Works in high dimensions |
| LOF | Local anomalies, clusters of different density. Slow |
| One-Class SVM | Small to medium data. Kernel matrix grows quadratically |

## Anomaly detection pipeline
type: flow
from: phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md

1. **Baseline**: collect a period with no or very few anomalies.
2. **Features**: add rolling statistics, time features and ratios.
3. **Train**: fit the detector on the baseline. It learns normal.
4. **Score**: give each new observation an anomaly score.
5. **Threshold**: pick the cutoff from the cost of false alarms and misses.
6. **Alert**: send flagged points to human review.
7. **Feedback**: record true anomalies and false alarms. Tune the threshold.

## Defaults and numbers
type: defaults
from: phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/code/anomaly_detection.py, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

| Setting | Default | Note |
|---|---|---|
| Z-score `threshold` | 3.0 | 99.7% of Gaussian data is inside |
| IQR `factor` | 1.5 | 3.0 flags fewer points |
| `n_estimators` | 100 | Isolation trees. Usually enough |
| `max_samples` | 256 | Rows per tree, from the original paper |
| `predict` threshold | 0.5 | Score above it is an anomaly |
| `contamination` | 0.05 | Sets the cutoff only, not the scores |
| t-SNE perplexity | 30 | Typical range 5-50 |
| Variance kept | 0.95 | Or 0.90 for the PCA cutoff |

## Failures and fixes
type: troubleshooting
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

| Symptom | Cause | Fix |
|---|---|---|
| K-Means splits moons badly | Clusters are not spherical | Use DBSCAN with eps=0.3 |
| K-Means results change per run | Local minimum of inertia | Fix the seed or use K-Means++ |
| Z-score misses points | Multimodal data or outliers in training | Use IQR or Isolation Forest |
| Per-feature methods miss a point | Unusual only in the joint space | Use Isolation Forest |
| 99.9% accuracy, no catches | 0.1% anomalies, accuracy is useless | Precision@k and AUPRC |
| Operators ignore alerts | Too many false alarms | Start with a high threshold |
| Median score drifts up | Data changed or model is stale | Retrain on recent normal data |
| t-SNE cluster gaps differ | Distances between clusters mean nothing | Read only the clusters |

## Abbreviations
type: glossary
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

- **DBSCAN**: density-based clustering. Core, border and noise points.
- **GMM**: Gaussian Mixture Model. K Gaussians with soft assignments.
- **EM**: Expectation-Maximization. E-step probabilities, M-step parameters.
- **PCA**: Principal Component Analysis. Axes of maximum variance.
- **t-SNE**: t-Distributed Stochastic Neighbor Embedding. Keeps neighbors.
- **UMAP**: Uniform Manifold Approximation and Projection. Faster, more global.
- **LOF**: Local Outlier Factor. Above 1.0 is lower density than neighbors.
- **AUPRC**: area under the precision-recall curve. Better than AUROC here.

## Questions
type: qa
from: phases/02-ml-fundamentals/07-unsupervised-learning/docs/en.md, phases/02-ml-fundamentals/16-anomaly-detection/docs/en.md, phases/01-math-foundations/10-dimensionality-reduction/docs/en.md

- **How do I pick K?** Find the elbow in inertia. Check the silhouette score.
- **Why model normal data?** Anomalies are rare and change. Deviations from normal include novel types.
- **What is the best training setup?** Semi-supervised: fit on a clean set of normal data only.
- **Few labeled anomalies?** Use them for evaluation, not training.
- **Why is Isolation Forest fast?** Each tree uses a small subsample.
- **Why reduce dimensions?** Distances converge in high dimensions. Nearest-neighbor search stops working.
Code and artifacts 1
What you take away

Saved in your notebook on this device.

Sources and limits

Reading checkpoints are self-reported. Test results are recorded separately and apply to the executed cases.

AI Engineering from Scratch · 3f9715c · MIT

Download this file ↓