In our submission for NUS DSA4266, AY2025/26 Sem 2, we train a machine learning model to perform real-time NID (Network Intrusion Detection) tasks, i.e. to predict zero-day anomalous network activity and classify them into one of the known attack types if possible.
- Shane Bharathan
- Tan Shayne
- Yong Kai Xin Dione
- Au Yong Hsien, Ray
- Lam Regan
Supervised by: Prof. Lee Joon Sern
For our project, we use the uv package manager. To get started, please install the correct version for your operating system at this website. Then run the following commands to install the required packages:
uv init
uv sync
You should see the package installations run in your shell.
Important
The project comes with a pyproject.toml file which is necessary for the sync command to work. Please make sure this is included or the command will not work as expected.
The entry point for new users is main.py. In the main block, default code has been provided and need only be replaced to change the run configurations. By default, configurations are taken from those provided in the conf folder. As we are using Hydra configurations, managing configurations across the board is made easy. Users have 2 options to change the configurations:
- Create a new file under
conf/models(if you want to change the model architecture) orconf/training(if you want to change the training loop) and then set these new files as the default inconf/config.yaml. OR - Continue to use the defaults provided and pass all overrides of the configurations you want to add in the
overridesargument. More instructions on how to do this below.
If you want to make major changes to any of the configurations, we recommend option 1. If you wish to keep the defaults and just make minor edits, option 2 is right for you.
Depending on what you wish to change, you should go to the corresponding folders. If you want to change the model configurations, head to conf/model. For training configurations, head to conf/training. For default configurations, change conf/config.yaml. By changing the default configurations, please note that all subsequent use will revert to these defaults, unless explicitly overridden in the overrides argument.
In the example below, we create a new file called cnn_small.yaml and add it to conf/model. The table below shows a side-by-side comparison of how the architectures differ.
| cnn_base.yaml | cnn_small.yaml |
|---|---|
n_features: 64
window_size: 20
n_classes: 2
global_pool: "avg"
conv_blocks:
- out_channels: 128
kernel_size: 5
stride: 1
activation: "relu"
dropout: 0.1
- out_channels: 256
kernel_size: 3
stride: 1
activation: "relu"
dropout: 0.1
- out_channels: 256
kernel_size: 3
stride: 1
activation: "relu"
dropout: 0.2
classifier:
hidden_dims: [256, 128]
dropout: 0.3
|
n_features: 64
window_size: 20
n_classes: 2
global_pool: "avg"
conv_blocks:
- out_channels: 128
kernel_size: 3
stride: 1
activation: "relu"
dropout: 0.1
- out_channels: 256
kernel_size: 3
stride: 1
activation: "relu"
dropout: 0.2
classifier:
hidden_dims: [64]
dropout: 0.3
|
Then, to use cnn_variant as the new default, we change the default model argument in conf/config.yaml:
defaults:
- model: cnn_variant
- training: base
If you only wish to make minor changes over the default configurations, or you want to do a quick switch of configuration files, you can do this using the overrides argument in run. Each override is a string mapping an argument to its new value. In the example below, we change :
if __name__ == "__main__":
run(
model_cls=CNN,
overrides=[
"model=cnn_variant",
"training.experiment_name=cnn_variant_experiment",
"training.epochs=20"
],
debug_mode=False,
)
| Model Type | Configuration | Train Loss | Validation Loss | Test Loss | Accuracy | Recall | Precision | F1 | Parameters | Epochs |
|---|---|---|---|---|---|---|---|---|---|---|
| CNN | Base | 0.0360 | 0.0268 | 0.0251 | 0.9959 | 0.9703 | 0.9957 | 0.9826 | 438,021 | 3 |
| CNN | Small | 0.0088 | 0.5635 | 0.5187 | 0.9454 | 0.5788 | 0.9692 | 0.6219 | 141,380 | 3 |
| Transformer | Base | 0.0174 | 0.0105 | 0.0085 | 0.9972 | 0.9980 | 0.9800 | 0.9888 | 76,674 | 1 |
| GRU | Base | 0.0014 | 0.0010 | 0.0008 | 0.9999 | 0.9999 | 0.9992 | 0.9996 | 50,050 | 2 |
The main entrypoint for this repo is main.py.
.
├── data
│ ├── clean
│ │ ├── test.csv
│ │ ├── train.csv
│ │ └── val.csv
│ ├── clean_n10
│ │ ├── test.csv
│ │ ├── train.csv
│ │ └── val.csv
│ └── raw
│ ├── NetFlow_v3_Features.csv
│ └── NF-UNSW-NB15-v3.csv
├── main.py
├── outputs
├── plots
│ └── correlation_heatmap.png
├── pyproject.toml
├── README.md
├── runs
├── src
│ ├── conf
│ │ ├── config.yaml
│ │ ├── model
│ │ │ ├── cnn_base.yaml
│ │ │ ├── cnn_n10.yaml
│ │ │ ├── cnn_small.yaml
│ │ │ ├── gru_base.yaml
│ │ │ ├── gru_n10.yaml
│ │ │ ├── transformer_base.yaml
│ │ │ └── transformer_n10.yaml
│ │ └── training
│ │ └── base.yaml
│ ├── datasets
│ │ ├── base.py
│ │ ├── modified.py
│ │ ├── prep_n10.py
│ │ └── prep.py
│ ├── eda
│ │ ├── DSA4266 Cleaning.ipynb
│ │ ├── DSA4266_Cleaning_New.ipynb
│ │ └── temporal_analysis.ipynb
│ ├── models
│ │ ├── cnn.py
│ │ ├── evals.py
│ │ ├── gru.py
│ │ ├── schemas.py
│ │ ├── training.py
│ │ └── transformer.py
│ ├── scripts
│ │ ├── liftoff.sh
│ │ ├── setup.sh
│ │ └── tensorboard.sh
│ └── utils
│ ├── helpers.py
│ └── prettier.py
└── uv.lock
@misc{luay2025NetFlowDatasetsV3,
title = {Temporal Analysis of NetFlow Datasets for Network Intrusion Detection Systems},
author = {Majed Luay and Siamak Layeghy and Seyedehfaezeh Hosseininoorbin and Mohanad Sarhan and Nour Moustafa and Marius Portmann},
year = {2025},
eprint = {2503.04404},
archivePrefix= {arXiv},\
primaryClass = {cs.LG},
url = {https://arxiv.org/abs/2503.04404}
}