In [20]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix

from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
import warnings
warnings.filterwarnings ("ignore")
In [2]:
data= pd.read_csv(r"C:\Users\hp\Downloads\Dataset.csv")

Check the dataset¶

In [5]:
print(data.shape)
print(data.columns)
print(data.info())
(25192, 42)
Index(['duration', 'protocol_type', 'service', 'flag', 'src_bytes',
       'dst_bytes', 'land', 'wrong_fragment', 'urgent', 'hot',
       'num_failed_logins', 'logged_in', 'num_compromised', 'root_shell',
       'su_attempted', 'num_root', 'num_file_creations', 'num_shells',
       'num_access_files', 'num_outbound_cmds', 'is_host_login',
       'is_guest_login', 'count', 'srv_count', 'serror_rate',
       'srv_serror_rate', 'rerror_rate', 'srv_rerror_rate', 'same_srv_rate',
       'diff_srv_rate', 'srv_diff_host_rate', 'dst_host_count',
       'dst_host_srv_count', 'dst_host_same_srv_rate',
       'dst_host_diff_srv_rate', 'dst_host_same_src_port_rate',
       'dst_host_srv_diff_host_rate', 'dst_host_serror_rate',
       'dst_host_srv_serror_rate', 'dst_host_rerror_rate',
       'dst_host_srv_rerror_rate', 'class'],
      dtype='str')
<class 'pandas.DataFrame'>
RangeIndex: 25192 entries, 0 to 25191
Data columns (total 42 columns):
 #   Column                       Non-Null Count  Dtype  
---  ------                       --------------  -----  
 0   duration                     25192 non-null  int64  
 1   protocol_type                25192 non-null  str    
 2   service                      25192 non-null  str    
 3   flag                         25192 non-null  str    
 4   src_bytes                    25192 non-null  int64  
 5   dst_bytes                    25192 non-null  int64  
 6   land                         25192 non-null  int64  
 7   wrong_fragment               25192 non-null  int64  
 8   urgent                       25192 non-null  int64  
 9   hot                          25192 non-null  int64  
 10  num_failed_logins            25192 non-null  int64  
 11  logged_in                    25192 non-null  int64  
 12  num_compromised              25192 non-null  int64  
 13  root_shell                   25192 non-null  int64  
 14  su_attempted                 25192 non-null  int64  
 15  num_root                     25192 non-null  int64  
 16  num_file_creations           25192 non-null  int64  
 17  num_shells                   25192 non-null  int64  
 18  num_access_files             25192 non-null  int64  
 19  num_outbound_cmds            25192 non-null  int64  
 20  is_host_login                25192 non-null  int64  
 21  is_guest_login               25192 non-null  int64  
 22  count                        25192 non-null  int64  
 23  srv_count                    25192 non-null  int64  
 24  serror_rate                  25192 non-null  float64
 25  srv_serror_rate              25192 non-null  float64
 26  rerror_rate                  25192 non-null  float64
 27  srv_rerror_rate              25192 non-null  float64
 28  same_srv_rate                25192 non-null  float64
 29  diff_srv_rate                25192 non-null  float64
 30  srv_diff_host_rate           25192 non-null  float64
 31  dst_host_count               25192 non-null  int64  
 32  dst_host_srv_count           25192 non-null  int64  
 33  dst_host_same_srv_rate       25192 non-null  float64
 34  dst_host_diff_srv_rate       25192 non-null  float64
 35  dst_host_same_src_port_rate  25192 non-null  float64
 36  dst_host_srv_diff_host_rate  25192 non-null  float64
 37  dst_host_serror_rate         25192 non-null  float64
 38  dst_host_srv_serror_rate     25192 non-null  float64
 39  dst_host_rerror_rate         25192 non-null  float64
 40  dst_host_srv_rerror_rate     25192 non-null  float64
 41  class                        25192 non-null  str    
dtypes: float64(15), int64(23), str(4)
memory usage: 8.1 MB
None

Check target variables¶

In [6]:
print("Total missing values:", data.isnull().sum().sum())
Total missing values: 0
In [7]:
print(data["class"].value_counts())
class
normal     13449
anomaly    11743
Name: count, dtype: int64
In [8]:
sns.countplot(x="class", data=data)

plt.title("Normal vs Anomaly")
plt.xlabel("Class")
plt.ylabel("Number of Records")

plt.show()
No description has been provided for this image

Convert categorical columns into numbers¶

In [9]:
encoder = LabelEncoder()

data["protocol_type"] = encoder.fit_transform(
    data["protocol_type"]
)

data["service"] = encoder.fit_transform(
    data["service"]
)

data["flag"] = encoder.fit_transform(
    data["flag"]
)

data["class"] = encoder.fit_transform(
    data["class"]
)
In [13]:
data.head()
Out[13]:
duration protocol_type service flag src_bytes dst_bytes land wrong_fragment urgent hot ... dst_host_srv_count dst_host_same_srv_rate dst_host_diff_srv_rate dst_host_same_src_port_rate dst_host_srv_diff_host_rate dst_host_serror_rate dst_host_srv_serror_rate dst_host_rerror_rate dst_host_srv_rerror_rate class
0 0 1 19 9 491 0 0 0 0 0 ... 25 0.17 0.03 0.17 0.00 0.00 0.00 0.05 0.00 1
1 0 2 41 9 146 0 0 0 0 0 ... 1 0.00 0.60 0.88 0.00 0.00 0.00 0.00 0.00 1
2 0 1 46 5 0 0 0 0 0 0 ... 26 0.10 0.05 0.00 0.00 1.00 1.00 0.00 0.00 0
3 0 1 22 9 232 8153 0 0 0 0 ... 255 1.00 0.00 0.03 0.04 0.03 0.01 0.00 0.01 1
4 0 1 22 9 199 420 0 0 0 0 ... 255 1.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 1

5 rows × 42 columns

Separate X and Y¶

In [12]:
X = data.drop("class", axis=1)

y = data["class"]
In [14]:
X = data.drop("class", axis=1)

y = data["class"]

Split the data¶

In [15]:
X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.20,
    random_state=42,
    stratify=y
)
In [16]:
print("Training data:", X_train.shape)
print("Testing data:", X_test.shape)
Training data: (20153, 41)
Testing data: (5039, 41)

Logistic Regression¶

In [21]:
model1 = LogisticRegression(max_iter=1000)

model1.fit(X_train, y_train)

prediction1 = model1.predict(X_test)

accuracy1 = accuracy_score(
    y_test,
    prediction1
)

print("Logistic Regression Accuracy:",
      accuracy1)
Logistic Regression Accuracy: 0.9023615796785076
In [22]:
print(
    classification_report(
        y_test,
        prediction1
    )
)
              precision    recall  f1-score   support

           0       0.96      0.83      0.89      2349
           1       0.87      0.97      0.91      2690

    accuracy                           0.90      5039
   macro avg       0.91      0.90      0.90      5039
weighted avg       0.91      0.90      0.90      5039

Decision Tree¶

In [23]:
model2 = DecisionTreeClassifier(
    random_state=42
)

model2.fit(X_train, y_train)

prediction2 = model2.predict(X_test)

accuracy2 = accuracy_score(
    y_test,
    prediction2
)

print("Decision Tree Accuracy:",
      accuracy2)
Decision Tree Accuracy: 0.9950386981543957
In [24]:
print(
    classification_report(
        y_test,
        prediction2
    )
)
              precision    recall  f1-score   support

           0       0.99      0.99      0.99      2349
           1       1.00      1.00      1.00      2690

    accuracy                           1.00      5039
   macro avg       1.00      1.00      1.00      5039
weighted avg       1.00      1.00      1.00      5039

Random Forest¶

In [25]:
model3 = RandomForestClassifier(
    n_estimators=100,
    random_state=42
)

model3.fit(X_train, y_train)

prediction3 = model3.predict(X_test)

accuracy3 = accuracy_score(
    y_test,
    prediction3
)

print("Random Forest Accuracy:",
      accuracy3)
Random Forest Accuracy: 0.9980154792617583
In [26]:
print(
    classification_report(
        y_test,
        prediction3
    )
)
              precision    recall  f1-score   support

           0       1.00      1.00      1.00      2349
           1       1.00      1.00      1.00      2690

    accuracy                           1.00      5039
   macro avg       1.00      1.00      1.00      5039
weighted avg       1.00      1.00      1.00      5039

Compare the three models¶

In [27]:
print("Logistic Regression:",
      accuracy1)

print("Decision Tree:",
      accuracy2)

print("Random Forest:",
      accuracy3)
Logistic Regression: 0.9023615796785076
Decision Tree: 0.9950386981543957
Random Forest: 0.9980154792617583
In [28]:
results = pd.DataFrame({
    "Model": [
        "Logistic Regression",
        "Decision Tree",
        "Random Forest"
    ],
    
    "Accuracy": [
        accuracy1,
        accuracy2,
        accuracy3
    ]
})

print(results)
                 Model  Accuracy
0  Logistic Regression  0.902362
1        Decision Tree  0.995039
2        Random Forest  0.998015
In [29]:
plt.figure(figsize=(8,5))

sns.barplot(
    x="Model",
    y="Accuracy",
    data=results
)

plt.title("Machine Learning Model Comparison")
plt.ylabel("Accuracy")
plt.xlabel("Model")

plt.xticks(rotation=20)

plt.show()
No description has been provided for this image

Confusion matrix for Random Forest¶

In [30]:
cm = confusion_matrix(
    y_test,
    prediction3
)

print(cm)
[[2341    8]
 [   2 2688]]
In [31]:
plt.figure(figsize=(6,5))

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues"
)

plt.title("Random Forest Confusion Matrix")

plt.xlabel("Predicted")
plt.ylabel("Actual")

plt.show()
No description has been provided for this image

Feature importance¶

In [32]:
importance = model3.feature_importances_

features = X.columns

importance_df = pd.DataFrame({
    "Feature": features,
    "Importance": importance
})
In [33]:
importance_df = importance_df.sort_values(
    "Importance",
    ascending=False
)

print(importance_df)
                        Feature  Importance
4                     src_bytes    0.197405
5                     dst_bytes    0.088876
3                          flag    0.083065
32           dst_host_srv_count    0.072693
33       dst_host_same_srv_rate    0.065365
28                same_srv_rate    0.057827
11                    logged_in    0.044737
22                        count    0.042408
29                diff_srv_rate    0.034526
1                 protocol_type    0.034376
24                  serror_rate    0.033200
34       dst_host_diff_srv_rate    0.030342
35  dst_host_same_src_port_rate    0.025441
25              srv_serror_rate    0.024180
2                       service    0.024117
23                    srv_count    0.019773
36  dst_host_srv_diff_host_rate    0.019657
37         dst_host_serror_rate    0.016962
39         dst_host_rerror_rate    0.014435
31               dst_host_count    0.013248
38     dst_host_srv_serror_rate    0.012314
9                           hot    0.011170
40     dst_host_srv_rerror_rate    0.006958
27              srv_rerror_rate    0.005459
12              num_compromised    0.005346
7                wrong_fragment    0.004427
26                  rerror_rate    0.003774
0                      duration    0.003356
30           srv_diff_host_rate    0.002249
21               is_guest_login    0.001124
15                     num_root    0.000376
16           num_file_creations    0.000204
10            num_failed_logins    0.000202
18             num_access_files    0.000135
13                   root_shell    0.000134
8                        urgent    0.000077
14                 su_attempted    0.000025
17                   num_shells    0.000024
6                          land    0.000010
19            num_outbound_cmds    0.000000
20                is_host_login    0.000000
In [34]:
print(
    importance_df.head(15)
)
                        Feature  Importance
4                     src_bytes    0.197405
5                     dst_bytes    0.088876
3                          flag    0.083065
32           dst_host_srv_count    0.072693
33       dst_host_same_srv_rate    0.065365
28                same_srv_rate    0.057827
11                    logged_in    0.044737
22                        count    0.042408
29                diff_srv_rate    0.034526
1                 protocol_type    0.034376
24                  serror_rate    0.033200
34       dst_host_diff_srv_rate    0.030342
35  dst_host_same_src_port_rate    0.025441
25              srv_serror_rate    0.024180
2                       service    0.024117
In [35]:
top_features = importance_df.head(15)

plt.figure(figsize=(10,6))

sns.barplot(
    x="Importance",
    y="Feature",
    data=top_features
)

plt.title(
    "Top 15 Important Features"
)

plt.show()
No description has been provided for this image

Simple error analysis¶

In [36]:
test_results = X_test.copy()

test_results["Actual"] = y_test.values

test_results["Predicted"] = prediction3
In [38]:
errors = test_results[
    test_results["Actual"]
    != test_results["Predicted"]
]

print(errors.head())
       duration  protocol_type  service  flag  src_bytes  dst_bytes  land  \
10216         0              1       19     9        334          0     0   
9807          0              0       13     9          8          0     0   
5036          0              1       22     1          0          0     0   
18019         0              2       46     9        100          0     0   
13183         0              1       17     5          0          0     0   

       wrong_fragment  urgent  hot  ...  dst_host_same_srv_rate  \
10216               0       0    0  ...                    0.33   
9807                0       0    0  ...                    0.01   
5036                0       0    0  ...                    0.00   
18019               0       0    0  ...                    0.03   
13183               0       0    0  ...                    0.05   

       dst_host_diff_srv_rate  dst_host_same_src_port_rate  \
10216                    0.07                         0.35   
9807                     0.03                         0.01   
5036                     0.00                         0.00   
18019                    0.06                         0.03   
13183                    0.05                         0.02   

       dst_host_srv_diff_host_rate  dst_host_serror_rate  \
10216                         0.00                  0.01   
9807                          0.97                  0.00   
5036                          0.00                  0.00   
18019                         0.00                  0.00   
13183                         0.22                  0.01   

       dst_host_srv_serror_rate  dst_host_rerror_rate  \
10216                      0.04                  0.00   
9807                       0.00                  0.01   
5036                       0.00                  0.00   
18019                      0.00                  0.00   
13183                      0.11                  0.00   

       dst_host_srv_rerror_rate  Actual  Predicted  
10216                       0.0       0          1  
9807                        0.0       0          1  
5036                        0.0       1          0  
18019                       0.0       0          1  
13183                       0.0       1          0  

[5 rows x 43 columns]
In [39]:
print(
    "Number of incorrect predictions:",
    len(errors)
)
Number of incorrect predictions: 10

Simple analysis of protocol types¶

In [40]:
test_results["Protocol"] = data.loc[
    X_test.index,
    "protocol_type"
].values
In [41]:
print(
    test_results.groupby("Protocol")[
        ["Actual", "Predicted"]
    ].mean()
)
            Actual  Predicted
Protocol                     
0         0.139130   0.144928
1         0.520128   0.520869
2         0.831008   0.832558
In [42]:
for protocol in test_results["Protocol"].unique():

    subset = test_results[
        test_results["Protocol"] == protocol
    ]

    acc = accuracy_score(
        subset["Actual"],
        subset["Predicted"]
    )

    print(
        "Protocol:",
        protocol,
        "Accuracy:",
        acc
    )
Protocol: 1 Accuracy: 0.998271178068659
Protocol: 0 Accuracy: 0.9942028985507246
Protocol: 2 Accuracy: 0.9984496124031008
In [ ]: