KDD Cup 1999
Network intrusion detection at competition scale: nearly five million TCP connection records, each labelled normal or with one of dozens of attack names. Historically the most-used intrusion-detection benchmark ever — and, by broad consensus, one that should now be used only with its flaws stated up front.
Provenance
The dataset was built for the Third International Knowledge Discovery and Data Mining Tools Competition (1999) (held with KDD-99, the fifth KDD conference) by processing the tcpdump portions of the 1998 DARPA Intrusion Detection System Evaluation, run by MIT Lincoln Laboratory. Traffic was generated on a closed simulated air-force network with hand-injected attacks over seven weeks (training) plus two weeks (test), then summarised into per-connection feature vectors.
The competition task was to classify each connection as normal or as an attack, with attacks grouped into four categories: DoS (denial of service, e.g. syn flood), probe (surveillance, e.g. port scanning), R2L (unauthorised remote-to-local access, e.g. password guessing) and U2R (local privilege escalation, e.g. buffer overflows). Scoring used an asymmetric misclassification-cost matrix. The winning entries were ensembles of C5 decision trees with bagging and boosting (Bernhard Pfahringer’s entry took first place).
Schema
- instances: 4,898,431 connection records in the full training set; the ubiquitous “10%” file has 494,021; the scored (“corrected”) test file has 311,029.
- features: 41 per connection — basic TCP features (duration, protocol, bytes), content features from the payload (e.g.
num_failed_logins,root_shell), and two-second/host-based traffic statistics. A mix of integers, floats and categoricals. - target: a string,
normal.or an attack name. The task description lists 24 training attack types with an additional 14 appearing only in the test data (to punish memorisation); the 10% training file contains 22 attack types, as the loader output below shows. - sklearn additionally ships resampled variants for anomaly detection:
SA(all normal traffic plus a resampled sliver of attacks — with the defaultpercent10=Trueroughly 100k records at3.4% anomalous; the full-data figure of 976,158 records works out to ~0.35%, whatever sklearn's docstring says) and ~SF(logged-in connections only, 699,691 records, 0.3% attacks), plushttpandsmtpslices of SF.
Known flaws — read before benchmarking
This dataset is famous partly because of its criticisms:
- it is a simulation. McHugh’s 2000 critique of the underlying DARPA evaluation argued the synthetic background traffic was never validated against real networks, and the attack mix reflects what the organisers injected, not any operational reality.
- massive duplication. Tavallaee et al., A detailed analysis of the KDD CUP 99 data set (2009), found roughly 78% of training records and 75% of test records are exact duplicates. Learners are biased toward the frequent records, and reported accuracies are inflated — their deduplicated, difficulty-rebalanced NSL-KDD is the usual replacement.
- extreme skew. Two DoS attacks dominate: in the 10% file below,
smurf.andneptune.alone are 78.5% of all records, and roughly 80% of records are attacks. “Anomalies” that constitute the majority class are not anomalies; naive accuracy numbers here are close to meaningless. - it is from 1998. Feature distributions, protocols and attack tooling bear little resemblance to modern traffic. Fine for teaching and for comparing algorithms on a common artefact; not evidence that a method detects real intrusions.
On this site
- k-means clustering — the tagged model: with labels hidden, the connection records are a classic large-scale clustering exercise (cluster, then inspect cluster/attack alignment). The skew above is exactly why k-means on raw KDD finds two giant DoS blobs first.
Loading
sklearn downloads and caches the data on first call (a ~2 MB gzip that unpacks to ~75 MB for the 10% file):
from collections import Counter
from sklearn.datasets import fetch_kddcup99
# percent10=True (default) pulls the canonical 494,021-row "10%" training file
kdd = fetch_kddcup99(percent10=True)
X, y = kdd.data, kdd.target
print(X.shape)
labels = Counter(lab.decode() for lab in y)
for lab, n in labels.most_common(6):
print(f"{lab:<12} {n:>7} ({100*n/len(y):.1f}%)")
print(f"... {len(labels)} labels total (normal + 22 attack types)")
For anomaly-detection experiments prefer fetch_kddcup99(subset="SA") (or "SF", "http", "smtp"), which resample to a low anomaly rate (a few percent for SA under the default 10% subset, 0.3% for ~SF) — or skip straight to NSL-KDD.
Backlinks (2)
1. Wiki /wiki/
Knowledge is a paradox. The more one understand, the more one realises the vastness of his ignorance.