Skip to content

โš™๏ธ 10-06: Building & Training the IDS Model


๐Ÿ“Œ From Theory to Practice

We've now covered every concept needed to build a real classifier:

This lesson walks through the full, generic workflow for building and training an IDS classifier end-to-end, from a raw CSV file to a trained model making predictions.


๐Ÿงฑ Step 1: Import the Necessary Libraries

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import confusion_matrix, classification_report, f1_score, accuracy_score
Library Role
pandas Loading and manipulating the tabular dataset
numpy Numeric array operations under the hood
matplotlib / seaborn Visualizing data and results
sklearn.preprocessing Encoding categorical labels, scaling numeric features
sklearn.model_selection Splitting data into training and test sets
sklearn.svm The SVM classifier itself (SVC = Support Vector Classifier)
sklearn.metrics Evaluating how good the trained model is

๐Ÿ“‚ Step 2: Load the Dataset

dataset = pd.read_csv("network_traffic.csv")
print(dataset.head())

This loads a CSV file (structured the way NSL-KDD is: one row per connection, one column per feature, plus a label column) into a pandas DataFrame โ€” a table-like structure that's easy to filter, transform, and feed into scikit-learn.


๐Ÿงน Step 3: Clean the Data and Separate Features from the Label

# Drop rows with missing values
dataset = dataset.dropna()

# Separate independent variables (features) from the dependent variable (label)
X = dataset.drop("label", axis=1)
y = dataset["label"]

# Drop columns that add no useful signal
X = X.drop(["num_outbound_cmds", "is_host_login"], axis=1)
  • X holds every feature the model will learn from (duration, protocol type, byte counts, etc.)
  • y holds only the answer we want the model to predict: normal or attack
  • Irrelevant or constant-valued columns are dropped so they don't add noise

๐Ÿ”ค Step 4: Encode Categorical Data

# Encode the label into two numeric classes: 0 = normal, 1 = attack
y = LabelEncoder().fit_transform(y)

# One-hot encode categorical feature columns (protocol_type, service, flag, etc.)
X = pd.concat(
    [pd.get_dummies(X.select_dtypes(include="object")),
     X.select_dtypes(exclude="object")],
    axis=1
)

As covered in 10-04: Feature Engineering (NSL-KDD), the SVM can only work with numbers, so every text-based column has to become numeric before training.


โœ‚๏ธ Step 5: Split Into Training and Test Sets

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)
  • test_size=0.3 means 70% of the data trains the model, and 30% is held back purely for testing โ€” a common, standard split for datasets of this size.
  • random_state=42 fixes the random seed used to shuffle and split the data, so that re-running the code produces the exact same split every time โ€” this makes results reproducible and lets you fairly compare different models or settings later.

๐Ÿ’ก Why hold back a test set at all? If you trained and tested on the same data, the model could simply memorize the answers instead of learning generalizable patterns. Testing on unseen data is the only way to know if the model will work on real, future traffic.


๐Ÿ“ Step 6: Scale the Features

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)   # learn scaling from training data
X_test_scaled = scaler.transform(X_test)          # apply the same scaling to test data

As explained in 10-04: Feature Engineering (NSL-KDD), SVMs are sensitive to the scale of input features. StandardScaler transforms every numeric feature so it has mean 0 and standard deviation 1, putting features like duration and src_bytes on comparable footing.

๐Ÿ’ก Notice fit_transform() is used on the training data (learns the mean/std and applies it), while only transform() is used on the test data (applies the already-learned scaling โ€” no peeking at test data statistics).


๐Ÿง  Step 7: Train the SVM Model

svc = SVC(random_state=42)
svc.fit(X_train_scaled, y_train)
  • SVC() creates a Support Vector Classifier using scikit-learn's default settings (an RBF kernel, as discussed in 10-05: SVMs for Classification)
  • .fit(X_train_scaled, y_train) is where the actual learning happens: the model looks at every training example's features and its true label, and works out the maximum-margin hyperplane that best separates normal from attack

๐Ÿ”ฎ Step 8: Predict on the Test Set

y_pred = svc.predict(X_test_scaled)

This runs the trained model on the held-out test features (X_test_scaled), producing a predicted label (0 or 1) for each test connection. Crucially, the model never saw these rows โ€” or their true labels โ€” during training.

y_pred (the model's guesses) can now be compared against y_test (the actual, correct answers) to see how well the model performs โ€” which is exactly the subject of the next lesson, 10-07: Evaluating Detection Models.


๐Ÿงพ Full Workflow at a Glance

import pandas as pd
from sklearn.preprocessing import LabelEncoder, StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC

# 1. Load
dataset = pd.read_csv("network_traffic.csv").dropna()

# 2. Split features/label
X = dataset.drop("label", axis=1)
y = dataset["label"]
X = X.drop(["num_outbound_cmds", "is_host_login"], axis=1)

# 3. Encode
y = LabelEncoder().fit_transform(y)
X = pd.concat([pd.get_dummies(X.select_dtypes(include="object")),
               X.select_dtypes(exclude="object")], axis=1)

# 4. Train/test split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 5. Scale
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 6. Train
svc = SVC(random_state=42)
svc.fit(X_train_scaled, y_train)

# 7. Predict
y_pred = svc.predict(X_test_scaled)

๐Ÿ“Œ Key Takeaways

  • Building an IDS classifier follows a consistent pipeline: load โ†’ clean โ†’ encode โ†’ split โ†’ scale โ†’ train โ†’ predict.
  • A 70/30 train/test split with a fixed random_state is a standard, reproducible way to hold back unseen data for fair evaluation.
  • Always fit_transform() the scaler on training data only, then transform() the test data with those same learned parameters.
  • SVC() from scikit-learn implements the Support Vector Machine classifier discussed conceptually in 10-05: SVMs for Classification.
  • .fit() trains the model on labeled data; .predict() produces guesses on new, unlabeled data.
  • The model's predictions (y_pred) are only useful once compared against the true test labels (y_test) โ€” covered next in 10-07: Evaluating Detection Models.