An Explainable AI-based Intrusion Detection System that combines machine learning classifiers with SHAP and LIME explainability techniques, evaluated across 3 datasets (CIC-IDS-2017, UNSW-NB15, CSE-CIC-IDS-2018) with a novel XAI Confidence Score (XCS) for measuring explanation reliability.
Abstract: We present XAI-IDS, a multi-dataset intrusion detection framework combining XGBoost, Random Forest, LightGBM, and VotingEnsemble classifiers with SHAP and LIME explainability methods and a proposed XAI Confidence Score (XCS) intended to quantify explanation trustworthiness. Models are trained on capped samples (at most 200k / 145k / 200k flows before deduplication) of CIC-IDS-2017 (14 classes), UNSW-NB15 (10 classes) and CSE-CIC-IDS-2018 (only 2 classes were loaded in the current run). XGBoost reaches weighted F1 = 0.9964 on CIC-IDS-2017 and 0.7982 on UNSW-NB15 (macro F1 0.81 and 0.52). XCS has not yet been validated: in the labelled real-data run two of its three terms were constant, and the 5% UNSW-NB15 flag rate comes from probe inputs of random Gaussian noise with no labels. A corrected re-run that compares XCS against model confidence is pending.
Live Documentation: GitHub Pages | Full Results | Model Card
Revision in progress: the reported results are being re-run with a corrected pipeline. See
revision/RERUN_PLAN.mdfor how to run it, andrevision/CHANGES.mdfor what was fixed.
- Architecture
- Datasets
- Installation
- Quick Start
- Results
- Explainability & XCS
- API & Deployment
- Repository Structure
- Testing
- Limitations
- Citation
- Authors
- License
This project evaluates on 3 benchmark intrusion detection datasets:
| Dataset | Classes | Features | Records | Type |
|---|---|---|---|---|
| CIC-IDS-2017 | 14 (1 benign + 13 attacks) | 20 selected | 2.8M+ | Multi-class |
| UNSW-NB15 | 10 (1 normal + 9 attacks) | 20 selected | 2.5M+ | Multi-class |
| CSE-CIC-IDS-2018 | 2 captured (14+ available) | 20 selected | 10M+ | Multi-class (stratified fix applied) |
| Class | Description |
|---|---|
| BENIGN | Normal network traffic |
| DoS Hulk | HTTP flood denial-of-service |
| PortScan | Network port scanning |
| DDoS | Distributed denial-of-service |
| DoS GoldenEye | HTTP DoS using GoldenEye tool |
| FTP-Patator | FTP brute force |
| SSH-Patator | SSH brute force |
| DoS slowloris | Slowloris DoS attack |
| DoS Slowhttptest | Slow HTTP DoS attack |
| Bot | Botnet traffic |
| Web Attack - Brute Force | Web application brute force |
| Web Attack - XSS | Cross-site scripting |
| Infiltration | Network infiltration |
| Web Attack - Sql Injection | SQL injection |
Sources:
- CIC-IDS-2017: UNB CIC | Zenodo Mirror
- UNSW-NB15: UNSW Canberra
- CSE-CIC-IDS-2018: CSE-CIC
- Python 3.10+
- pip
- (Optional) Docker for containerized execution
# Clone the repository
git clone https://github.com/MohammadThabetHassan/xai-ids.git
cd xai-ids
# Install dependencies
pip install -r requirements.txt# Build the container
docker build -t xai-ids .
# Run the pipeline
docker run -v $(pwd)/outputs:/app/outputs xai-idspython run_pipeline.pypython run_pipeline.py --downloadpython run_pipeline.py --sample-size 5000 --skip-explain| Flag | Description |
|---|---|
--download |
Download real CIC-IDS-2017 data (via Zenodo fallback) |
--sample-size N |
Synthetic dataset size (default: 50000) |
--random-sample |
Use random sampling instead of first N rows |
--skip-explain |
Skip SHAP and LIME analysis |
--skip-shap |
Skip SHAP only |
--skip-lime |
Skip LIME only |
--models lr rf xgb |
Select specific models |
--shap-samples N |
Samples for SHAP (default: 500) |
--cv-folds N |
Run N-fold cross-validation (0 to skip) |
--pr-curves |
Generate precision-recall curves |
--calibration |
Generate calibration curves |
--failure-analysis |
Generate failure analysis report |
make pipeline # Full pipeline
make pipeline-small # Quick test with small data
make pipeline-fast # Skip explainability
make test # Run tests
make clean # Remove outputsResults from the multi-dataset evaluation with XGBoost, Random Forest, LightGBM, and VotingEnsemble.
| Model | Accuracy | Precision | Recall | F1-Score |
|---|---|---|---|---|
| XGBoost | 0.9966 | 0.9964 | 0.9966 | 0.9964 |
| VotingEnsemble | 0.9886 | 0.9945 | 0.9886 | 0.9911 |
| RandomForest | 0.9857 | 0.9940 | 0.9857 | 0.9893 |
| LightGBM | 0.9744 | 0.9930 | 0.9744 | 0.9828 |
| Model | Accuracy | Precision | Recall | F1-Score |
|---|---|---|---|---|
| XGBoost | 0.8004 | 0.8120 | 0.8004 | 0.7982 |
| VotingEnsemble | 0.7867 | 0.8240 | 0.7867 | 0.8002 |
| RandomForest | 0.7635 | 0.8202 | 0.7635 | 0.7848 |
| LightGBM | 0.7630 | 0.8291 | 0.7630 | 0.7863 |
| Model | Accuracy | Precision | Recall | F1-Score |
|---|---|---|---|---|
| RandomForest | 0.9993 | 0.9993 | 0.9993 | 0.9992 |
| VotingEnsemble | 0.9993 | 0.9993 | 0.9993 | 0.9992 |
| XGBoost | 0.9990 | 0.9990 | 0.9990 | 0.9990 |
| LightGBM | 0.9990 | 0.9990 | 0.9990 | 0.9990 |
See RESULTS.md for complete per-class breakdowns, XCS scores, and cross-dataset analysis.
| Model | Accuracy | Precision | Recall | F1 (weighted) | F1 (macro) |
|---|---|---|---|---|---|
| XGBoost | 0.8250 | 0.8158 | 0.8250 | 0.8193 | 0.51 |
| Random Forest | 0.8347 | 0.8096 | 0.8347 | 0.8162 | 0.48 |
| Logistic Regression | 0.7601 | 0.7866 | 0.7601 | 0.7651 | 0.48 |
SHAP (SHapley Additive exPlanations) provides global feature importance by computing the average contribution of each feature to predictions.
LIME (Local Interpretable Model-agnostic Explanations) explains individual predictions by fitting surrogate models around specific data points.
The XCS is a novel metric that measures the reliability of explanations for individual predictions:
XCS = w1 × Confidence + w2 × (1 - SHAP_Instability) + w3 × Jaccard(SHAP, LIME)
Where:
- w1 = 0.4: Weight for model prediction confidence
- w2 = 0.3: Weight for SHAP explanation stability (1 - feature ranking variance)
- w3 = 0.3: Weight for agreement between SHAP and LIME (Jaccard similarity of top-k features)
Interpretation:
- XCS > 0.7: High-confidence, reliable explanation
- XCS 0.3–0.7: Moderate confidence, use with caution
- XCS < 0.3: Low-confidence explanation, do not trust
| Dataset | Mean XCS | Correct XCS | Wrong XCS | Flagged (< 0.3) |
|---|---|---|---|---|
| CIC-IDS-2017 | 0.517 | 0.526 | 0.469 | 0 / 74 (0%) |
| UNSW-NB15 | 0.424 | 0.469 | 0.360 | 14 / 80 (17.5%) |
| CSE-CIC-IDS-2018 | 0.550 | 0.550 | N/A | 0 / 86 (0%) |
Key finding: wrong predictions score lower than correct ones across all
datasets. This separation cannot yet be credited to the explainability terms.
In this run shap_instability is 0.5 and jaccard_sl is 0.0 for every
sample, because of two bugs in the XCS code:
- Jaccard: LIME did run, but its top features are condition strings such as
Fwd IAT Std <= 14.59, and these were compared directly with SHAP feature names, so the two sets never overlapped. - Instability:
np.stdwas taken over the flattened neighbour x feature array, i.e. the spread of SHAP values across features rather than across perturbations, so the ratio exceeded the 0.5 clamp for every sample.
XCS therefore reduces to 0.4 x confidence + 0.15
and correlates with confidence at r = 1.000 on CIC-IDS-2017 and UNSW-NB15
(0.998 on CSE-CIC-IDS-2018). The separation shown here is the well-known
tendency of a classifier to be less confident when wrong; it is
not independent evidence for the three-term metric.
The flag rate in this table (17.5% on UNSW-NB15) and the 5% quoted in earlier
versions of the abstract come from different runs and are not comparable: this
table is the real-data run with the two explainability terms inert, while the 5%
figure comes from scripts/recompute_xcs.py, whose inputs are random Gaussian
noise passed through the scaler (no labels, not network traffic). Establishing
whether XCS improves on confidence alone requires re-running the corrected
formula against a labelled real test split and comparing the two as review
triggers.
Values computed on real data (n=74–86 per dataset, the first n test samples of each class).
See explanations/xcs_*.csv for per-sample data.
The Jaccard similarity between SHAP and LIME top-k features measures how consistently both methods identify important features:
| Dataset | Mean Jaccard (SHAP–LIME top-5) |
|---|---|
| CIC-IDS-2017 | 0.180 |
| UNSW-NB15 | 0.111 |
| CSE-CIC-IDS-2018 | 0.429 |
| Overall | 0.216 |
Cross-dataset Jaccard similarity: 0.216 — indicating dataset-specific feature patterns.
# Start the API server
uvicorn api.app:app --host 0.0.0.0 --port 8000
# Test the API
curl -X POST http://localhost:8000/predict \
-H "Content-Type: application/json" \
-d '{"features": [0.0] * 78}'
# Get explanation with prediction
curl -X POST http://localhost:8000/explain \
-H "Content-Type: application/json" \
-d '{"features": [0.0] * 78}'| Endpoint | Method | Description |
|---|---|---|
/ |
GET | API info and loaded models |
/health |
GET | Health check (models, scaler, encoder status) |
/predict |
POST | Make prediction with confidence and probabilities |
/explain |
POST | Prediction with top-10 feature importances |
/classes |
GET | List available prediction classes |
/xcs-summary |
GET | XCS offline evaluation summary per dataset |
# Build
docker build -t xai-ids .
# Run pipeline
docker run -v $(pwd)/outputs:/app/outputs xai-ids
# Run API server
docker run -p 8000:8000 xai-ids uvicorn api.app:app --host 0.0.0.0 --port 8000xai-ids/
├── .github/
│ ├── workflows/
│ │ ├── ci.yml # CI workflow (tests + imports)
│ │ └── pages.yml # GitHub Pages deployment
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── api/
│ └── app.py # FastAPI inference server
├── data/
│ ├── raw/ # Raw CSV files
│ └── processed/ # Processed data
├── docs/
│ ├── methodology.md # Technical methodology
│ └── site/ # GitHub Pages site
├── explanations/
│ ├── shap_lime_jaccard_all.csv # SHAP-LIME agreement
│ ├── xcs_*.csv # XCS scores per dataset
│ └── *.html # LIME explanation files
├── models/ # Trained models (Kaggle notebook)
├── notebooks/
│ └── exploration.ipynb # Interactive demo notebook
├── outputs/
│ ├── figures/ # Confusion matrices, SHAP, LIME plots
│ ├── models/ # Trained models (.pkl) from pipeline
│ ├── reports/ # Classification reports, failure analysis
│ └── results_metrics.csv # Model comparison metrics
├── plots/ # Multi-dataset visualizations
├── src/
│ ├── data/
│ │ ├── download.py # Dataset download utility
│ │ ├── generate_sample.py # Synthetic data generator
│ │ ├── loader.py # Chunked CSV loader
│ │ └── preprocessing.py # Cleaning, encoding, scaling
│ ├── features/
│ │ └── feature_engineering.py # Feature selection utilities
│ ├── models/
│ │ └── train.py # Model training (LR, RF, XGB)
│ ├── evaluation/
│ │ └── metrics.py # Metrics, confusion matrices, charts
│ ├── explainability/
│ │ └── explain.py # SHAP and LIME implementations
│ └── utils/
│ └── logger.py # Centralized logging
├── tests/
│ ├── test_smoke.py # Smoke tests (13 tests)
│ └── test_evaluation.py # Evaluation tests (11 tests)
├── xai_ids_multidataset.ipynb # Kaggle notebook (multi-dataset)
├── config.yaml # Reference configuration
├── Dockerfile # Container definition
├── Makefile # Build automation
├── MODEL_CARD.md # Model card (HuggingFace-style)
├── README.md # This file
├── RESULTS.md # Full results tables
├── requirements.txt # Python dependencies
└── run_pipeline.py # Main pipeline entry point
See docs/REPRODUCIBILITY.md for the supported synthetic-data quick start, expected artifacts, validation commands, and real-dataset caveats.
# Run all tests
python -m pytest tests/ -v
# Run smoke tests only
python -m pytest tests/test_smoke.py -v -xTests include:
- Module import verification (8 tests)
- Synthetic data generation (2 tests)
- Data preprocessing (2 tests)
- Mini end-to-end pipeline execution (1 test)
- Metrics computation (2 tests)
- Cross-validation (2 tests)
- Calibration curves (1 test)
- Failure analysis (2 tests)
- Confusion matrix (2 tests)
- Edge cases (2 tests)
-
Class Imbalance: Severe imbalance in CIC-IDS-2017 (~600:1 ratio) causes poor detection of minority attack classes. Balanced class weights improve macro F1 from 0.44 to 0.51 but rare classes (SQL Injection, Heartbleed) remain challenging.
-
Feature Selection: The Kaggle notebook uses 20 features per dataset (selected by importance), while the main pipeline uses all 78 CIC-IDS-2017 features. Results are not directly comparable.
-
Synthetic vs Real Data: Default
run_pipeline.pyuses synthetic data. Real data requires download via--downloador running the Kaggle notebook. -
Dataset Generalization: Cross-dataset feature importance shows low Jaccard similarity (0.216), meaning models trained on one dataset may not generalize well to others.
-
Research-Grade: This is a research/educational system, not a production-ready IDS. It should be used as part of a defense-in-depth strategy.
If you use this work in your research, please cite:
@software{xai_ids_2026,
author = {Hassan, Mohammad Thabet and Sadek, Fahad and Sami, Ahmed},
title = {XAI-IDS: Explainable AI Intrusion Detection System},
year = {2026},
url = {https://github.com/MohammadThabetHassan/xai-ids},
license = {MIT}
}| Name | Role | GitHub |
|---|---|---|
| Mohammad Thabet Hassan | Lead Developer & Primary Contributor | @MohammadThabetHassan |
| Fahad Sadek | Contributor | @fahad6789123 |
| Ahmed Sami | Contributor | @AhmedSamiAlameri |
Supervisor: Dr. Mehak Khurana — Mehak.Khurana@cud.ac.ae
- Canadian Institute for Cybersecurity — CIC-IDS-2017 and CSE-CIC-IDS-2018 datasets
- UNSW Canberra Cyber — UNSW-NB15 dataset
- SHAP — Lundberg & Lee, NeurIPS 2017
- LIME — Ribeiro, Singh & Guestrin, KDD 2016
- Sharafaldin, I., Lashkari, A.H. and Ghorbani, A.A., "Toward Generating a New Intrusion Detection Dataset and Intrusion Traffic Characterization," ICISSP 2018.
- Lundberg, S.M. and Lee, S.-I., "A Unified Approach to Interpreting Model Predictions," NeurIPS 2017.
- Ribeiro, M.T., Singh, S. and Guestrin, C., "Why Should I Trust You? Explaining the Predictions of Any Classifier," KDD 2016.
- Moustafa, N. and Slay, J., "UNSW-NB15: a comprehensive data set for network intrusion detection systems," MilCIS 2015.
This project is licensed under the MIT License — see the LICENSE file for details.























