Clustering finds structure as a side effect of grouping; three other algorithms are built specifically to answer "how anomalous is this point," and are the ones most often wired directly into an intrusion detection pipeline.
| Method | How it decides a point is anomalous |
|---|---|
| Isolation Forest | Randomly splits features until a point is isolated; anomalies isolate in fewer splits because they sit apart from the crowd |
| One-Class SVM | Learns a boundary around the dense region of normal data; anything outside the boundary is flagged |
| Local Outlier Factor | Compares a point's local density to its neighbours' local density; a point in a sparse neighbourhood scores as anomalous even if the dataset as a whole is dense elsewhere |
isolation_forest.py
from sklearn.ensemble import IsolationForest
iso = IsolationForest(n_estimators=200, contamination=0.02, random_state=3)
iso.fit(scaled)
anomaly_scores = iso.decision_function(scaled) # higher = more normal
is_anomaly = iso.predict(scaled) == -1 # True = flagged
ocsvm_and_lof.py
from sklearn.svm import OneClassSVM
from sklearn.neighbors import LocalOutlierFactor
ocsvm = OneClassSVM(kernel="rbf", nu=0.02, gamma="scale")
ocsvm.fit(scaled)
ocsvm_flagged = ocsvm.predict(scaled) == -1
# LOF has no separate .fit()/.predict(): it scores the training set itself
lof = LocalOutlierFactor(n_neighbors=20, contamination=0.02)
lof_flagged = lof.fit_predict(scaled) == -1
ML concept: novelty versus outlier mode
By default, LocalOutlierFactor and OneClassSVM operate in outlier detection mode: they score the data they were fit on. Set novelty=True on LocalOutlierFactor to instead fit once on known-clean historical data and then call .predict() on new, incoming flows, the mode an actual production IDS needs, since real traffic arrives continuously, not as one fixed batch.

