├── Decision Tree Classifier (Depth = 3 Nodes) Explainable AI Visualization.png ├── Decision Tree Classifier (Depth = 5 Nodes) Explainable AI Visualization.png ├── Decision Tree Classifier (Depth = 8 Nodes) Explainable AI Visualization.png ├── Decision Tree Classifier XAI Visualization Part 2.png ├── Project Proposal.pdf ├── Project Report.docx ├── Project Report.pdf ├── README.md ├── UNSW-NB 15 Dataset Modified (Explainable AI) ML Methods Comparison - Attack or Normal Response.ipynb ├── UNSW-NB 15 Dataset Modified (Explainable AI) ML Methods Comparison - Attack or Normal Response.py ├── UNSW-NB15_LIST_EVENTS.csv ├── UNSW-NB15_features.csv └── UNSW_NB15_training.csv /Decision Tree Classifier (Depth = 3 Nodes) Explainable AI Visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Decision Tree Classifier (Depth = 3 Nodes) Explainable AI Visualization.png -------------------------------------------------------------------------------- /Decision Tree Classifier (Depth = 5 Nodes) Explainable AI Visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Decision Tree Classifier (Depth = 5 Nodes) Explainable AI Visualization.png -------------------------------------------------------------------------------- /Decision Tree Classifier (Depth = 8 Nodes) Explainable AI Visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Decision Tree Classifier (Depth = 8 Nodes) Explainable AI Visualization.png -------------------------------------------------------------------------------- /Decision Tree Classifier XAI Visualization Part 2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Decision Tree Classifier XAI Visualization Part 2.png -------------------------------------------------------------------------------- /Project Proposal.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Project Proposal.pdf -------------------------------------------------------------------------------- /Project Report.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Project Report.docx -------------------------------------------------------------------------------- /Project Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/Project Report.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning-Algorith 2 | The continuing increase of Internet of Things (IoT) based networks have increased the need for Computer networks intrusion detection systems (IDSs). Over the last few years, IDSs for IoT networks have been increasing reliant on machine learning (ML) techniques, algorithms, and models as traditional cybersecurity approaches become less viable for IoT. IDSs that have developed and implemented using machine learning approaches are effective, and accurate in detecting networks attacks with high-performance capabilities. However, the acceptability and trust of these systems may have been hindered due to many of the ML implementations being ‘black boxes’ where human interpretability, transparency, explainability, and logic in prediction outputs is significantly unavailable. The UNSW-NB15 is an IoT-based network traffic data set with classifying normal activities and malicious attack behaviors. Using this dataset, three ML classifiers: Decision Trees, Multi-Layer Perceptrons, and XGBoost, were trained. The ML classifiers and corresponding algorithm for developing a network forensic system based on network flow identifiers and features that can track suspicious activities of botnets proved to be very high-performing based on model performance accuracies. Thereafter, established Explainable AI (XAI) techniques using Scikit-Learn, LIME, ELI5, and SHAP libraries allowed for visualizations of the decision-making frameworks for the three classifiers to increase explainability in classification prediction. The results determined XAI is both feasible and viable as cybersecurity experts and professionals have much to gain with the implementation of traditional ML systems paired with Explainable AI (XAI) techniques. 3 | 4 | 5 | # The datasets used during the current study are available at . 6 | 7 | This current study builds upon previous work for Dr. Theodore Allen’s course at the Ohio State University, ISE 5194: Introduction to Operations Analytics in Spring 2020. This work was limited to a binary classification project that was conducted utilizing multi-linear regression and logistic regression on the UNSW-NB15 for behavior type prediction and direct classification of attack type. 8 | 9 | -------------------------------------------------------------------------------- /UNSW-NB 15 Dataset Modified (Explainable AI) ML Methods Comparison - Attack or Normal Response.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | 4 | # # UNSW-NB 15 Dataset ML Methods Comparison Notebook - Attack or Normal Response 5 | # 6 | # This notebook would implement several modified (Explainable AI (XAI)) machine learning methods: 7 | # 8 | # - Decision Trees 9 | # - Neural Networks: we will use Multi-layer perceptron. 10 | # - XGBoost 11 | # 12 | # We will illustrate them and compare their performances using the raw network packets of the UNSW-NB 15 dataset was created by the IXIA PerfectStorm tool in the Cyber Range Lab of the Australian Centre for Cyber Security (ACCS) for generating a hybrid of real modern normal activities and synthetic contemporary attack behaviours. Further information found at https://www.kaggle.com/mrwellsdavid/unsw-nb15 13 | # 14 | # 15 | # ![unsw-nb15-testbed.jpg](attachment:unsw-nb15-testbed.jpg) 16 | # 17 | # 18 | # 19 | # 20 | # 21 | # 22 | # 23 | # 24 | # 25 | # Tcpdump tool is utilised to capture 100 GB of the raw traffic (e.g., Pcap files). This dataset has nine types of attacks, namely, Fuzzers, Analysis, Backdoors, DoS, Exploits, Generic, Reconnaissance, Shellcode and Worms. The Argus, Bro-IDS tools are used and twelve algorithms are developed to generate totally 49 features with the class label. 26 | # 27 | # These features are described in UNSW-NB15_features.csv file. 28 | # 29 | # A partition from this dataset is configured as a training set and testing set, namely, UNSW_NB15_training-set.csv and UNSW_NB15_testing-set.csv respectively. 30 | # 31 | # The number of records in the training set is 175,341 records and the testing set is 82,332 records from the different types, attack and normal.Figure 1 and 2 show the testbed configuration dataset and the method of the feature creation of the UNSW-NB15, respectively. 32 | # 33 | # The details of the UNSW-NB15 dataset are published in following the papers: 34 | # 35 | # Moustafa, Nour, and Jill Slay. "UNSW-NB15: a comprehensive data set for network intrusion detection systems (UNSW-NB15 network data set)." Military Communications and Information Systems Conference (MilCIS), 2015. IEEE, 2015. 36 | # Moustafa, Nour, and Jill Slay. "The evaluation of Network Anomaly Detection Systems: Statistical analysis of the UNSW-NB15 dataset and the comparison with the KDD99 dataset." Information Security Journal: A Global Perspective (2016): 1-14. 37 | # Moustafa, Nour, et al. . "Novel geometric area analysis technique for anomaly detection using trapezoidal area estimation on large-scale networks." IEEE Transactions on Big Data (2017). 38 | # Moustafa, Nour, et al. "Big data analytics for intrusion detection system: statistical decision-making using finite dirichlet mixture models." Data Analytics and Decision Support for Cybersecurity. Springer, Cham, 2017. 127-156. 39 | # 40 | # Free use of the UNSW-NB15 dataset for academic research purposes is hereby granted in perpetuity. Use for commercial purposes should be agreed by the authors. Nour Moustafa and Jill Slay have asserted their rights under the Copyright. To whom intend the use of the UNSW-NB15 dataset have to cite the above two papers. 41 | # 42 | # 43 | # For more information, please contact the authors: Harshil Patel & Yuesheng Chen are a students in Industrial Engineering at Ohio State University, and they are interested in new Cyber threat intelligence approaches and the technology of Industry 4.0. 44 | # 45 | # In this notebook, the operations conducted include: 46 | # 47 | # - Preprocessing the data to prepare for training XAI ML models. 48 | # - Training XAI ML models based on cross-validation. 49 | # - Evaluating XAI ML models based on testing data. 50 | 51 | # # Libraries 52 | # 53 | # Import libararies to implement the described machine learning methods using a few different `sklearn` algorithms. 54 | 55 | # In[40]: 56 | 57 | 58 | # data cleaning and plots 59 | import pandas as pd 60 | import numpy as np 61 | import seaborn as sns 62 | import matplotlib.pyplot as plt 63 | plt.style.use('ggplot') 64 | get_ipython().run_line_magic('matplotlib', 'inline') 65 | 66 | # sklearn: data preprocessing 67 | from sklearn.compose import ColumnTransformer 68 | from sklearn.preprocessing import StandardScaler, LabelEncoder, OneHotEncoder 69 | 70 | # sklearn: train model 71 | from sklearn.model_selection import train_test_split 72 | from sklearn.model_selection import cross_val_score, cross_validate, StratifiedKFold 73 | from sklearn.metrics import precision_recall_curve, precision_score, recall_score, f1_score, accuracy_score 74 | from sklearn.metrics import roc_curve, auc, roc_auc_score, confusion_matrix, classification_report 75 | 76 | # sklearn classifiers 77 | 78 | from sklearn import tree 79 | from sklearn.tree import DecisionTreeClassifier 80 | 81 | from sklearn import datasets, ensemble, model_selection 82 | from sklearn.ensemble import RandomForestClassifier 83 | 84 | from sklearn.neural_network import MLPClassifier 85 | 86 | 87 | # # Data Processing 88 | # 89 | # ## Load Data 90 | # 91 | # **UNSW-NB15: a comprehensive data set for network intrusion detection systems** 92 | # 93 | # These features are described in UNSW-NB15_features.csv file. 94 | # 95 | # A partition from this dataset is configured as a training set and testing set, namely, UNSW_NB15_training-set.csv and UNSW_NB15_testing-set.csv respectively. 96 | # 97 | # The number of records in the training set is 175,341 records and the testing set is 82,332 records from the different types, attack and normal.Figure 1 and 2 show the testbed configuration dataset and the method of the feature creation of the UNSW-NB15, respectively. The addtional features are as described in UNSW-NB15_features.csv file. 98 | # 99 | # Response Variable: 100 | # 101 | # attack_cat: This dataset has nine types of attacks, namely, Fuzzers, Analysis, Backdoors, DoS, Exploits, Generic, Reconnaissance, Shellcode and Worms. 102 | # 103 | # Label: 0 for normal and 1 for attack records 104 | # 105 | 106 | # In[8]: 107 | 108 | 109 | # Load data 110 | initial_data = pd.read_csv('UNSW_NB15_training.csv') 111 | 112 | 113 | # In[9]: 114 | 115 | 116 | # Look at the first 5 rows 117 | initial_data.head(n=5) 118 | 119 | 120 | # In[10]: 121 | 122 | 123 | # information of the data: 583 data points, 10 features' columns and 1 target column 124 | initial_data.info() 125 | 126 | 127 | # ## Tidy Data 128 | # 129 | # ### Check missing values 130 | # First, we should check if there are missing values in the dataset. We could see that four patients do not have the value of `Albumin_and_Globulin_Ratio`. 131 | 132 | # In[11]: 133 | 134 | 135 | # check if there are Null values 136 | initial_data.isnull().sum() 137 | 138 | 139 | # A basic strategy to use incomplete datasets is to discard entire rows and/or columns containing missing values. Actually, there exists some strategies to impute missing values (see [here](https://scikit-learn.org/stable/modules/impute.html)). For simplicity, we will discard the four rows with missing values. 140 | 141 | # In[12]: 142 | 143 | 144 | # Discard the rows with missing values 145 | data_to_use = initial_data.dropna() 146 | 147 | # Shape of the data: we could see that the number of rows remains the same as no null values were reported 148 | data_to_use.shape 149 | 150 | 151 | # ### Check imbalanced issue on y 152 | # 153 | # First, we get the `X` and `y1` and `y2` . 154 | 155 | # In[13]: 156 | 157 | 158 | X = data_to_use.drop(axis=1, columns=['attack_cat']) # X is a dataframe 159 | X = X.drop(axis=1, columns=['label']) 160 | 161 | 162 | y1 = data_to_use['attack_cat'].values # y is an array 163 | y2 = data_to_use['label'].values 164 | 165 | 166 | # In[14]: 167 | 168 | 169 | # Calculate Y2 ratio 170 | def data_ratio(y2): 171 | ''' 172 | Calculate Y2's ratio 173 | ''' 174 | unique, count = np.unique(y2, return_counts=True) 175 | ratio = round(count[0]/count[1], 1) 176 | return f'{ratio}:1 ({count[0]}/{count[1]})' 177 | 178 | 179 | # In[15]: 180 | 181 | 182 | print('The class ratio for the original data:', data_ratio(y1)) 183 | plt.figure(figsize=(13,5)) 184 | sns.countplot(y1,label="Sum") 185 | plt.show() 186 | 187 | print('The class ratio for the original data:', data_ratio(y2)) 188 | sns.countplot(y2,label="Sum") 189 | plt.show() 190 | 191 | 192 | # We could see that the dataset is not perfectly balanced. There are some sampling techniques to deal with this issue. Here, we ignore this issue because we are aimed to implement several ML models to compare their performance. 193 | 194 | # ### Split training and testing data 195 | # 196 | # It is important to split `X` and `y` as training set and testing set. Here, we will split the original data as 70% training set and 30% testing set. But the partition action from this dataset was pre configured as a training set and testing set, namely, UNSW_NB15_training-set.csv and UNSW_NB15_testing-set.csv respectively. 197 | # 198 | # The number of records in the TESTING set is 175,341 records and the TRAINING set is 82,332 records from the different types, attack and normal. Figure above shows the testbed configuration dataset and the method of the feature creation of the UNSW-NB15, respectively. 199 | # 200 | # Thus the follwing code will not be utilized 201 | 202 | # In[18]: 203 | 204 | 205 | #X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) 206 | 207 | 208 | # In[19]: 209 | 210 | 211 | #print('The class ratio in training data: ', data_ratio(y_train)) 212 | #print('The class ratio in testing data: ', data_ratio(y_test)) 213 | 214 | 215 | # In[20]: 216 | 217 | 218 | # Load data 219 | test_data = pd.read_csv('UNSW_NB15_testing.csv') 220 | X_test = test_data.drop(axis=1, columns=['attack_cat']) # X_test is a dataframe 221 | X_test = X_test.drop(axis=1, columns=['label']) 222 | 223 | 224 | y1_test = test_data['attack_cat'].values # y is an array 225 | y2_test = test_data['label'].values 226 | 227 | 228 | # We will convert the orginal training data to the datframes called X_train, y1_train, y2_train 229 | 230 | # In[21]: 231 | 232 | 233 | X_train = X 234 | y1_train = y1 235 | y2_train = y2 236 | 237 | 238 | # ### Transform training and testing data 239 | # 240 | # #### Transformation on X_train, X_test 241 | # 242 | # Scikit-learn provides a library of transformers. Like other estimators, these are represented by classes with a `fit` method, which learns model parameters (e.g. mean and standard deviation for normalization) from a training set, and a `transform` method which applies this transformation model to unseen data. 243 | # 244 | # **NOTE: The reason of performing transformation after splitting the original data is that we will `fit` those parameters on training set**. 245 | # 246 | # In addition, it is very common to want to perform different data transformation techniques on different columns in your input data. The `ColumnTransformer` is a class in the scikit-learn library that allows you to selectively apply data preparation transforms. For example, it allows you to apply a specific transform or sequence of transforms to just the numerical columns, and a separate sequence of transforms to just the categorical columns. 247 | # 248 | # In our case, we need to perform `OneHotEncoder` on `Gender` column because it is categorical, and perform `StandardScaler` on other numerical columns. 249 | # 250 | # - `OneHotEncoder`: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.OneHotEncoder.html 251 | # - `StandardScaler`: https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html 252 | # 253 | # First, we find out which columns are categorical and which are numerical. 254 | 255 | # In[22]: 256 | 257 | 258 | # determine categorical and numerical columns 259 | numerical_cols = X_train.select_dtypes(include=['int64', 'float64']).columns 260 | categorical_cols = X_train.select_dtypes(include=['object', 'bool']).columns 261 | 262 | 263 | # In[23]: 264 | 265 | 266 | numerical_cols 267 | 268 | 269 | # In[24]: 270 | 271 | 272 | categorical_cols 273 | 274 | 275 | # Then, we construct the `ColumnTransformer` object, and then fit it on training data. 276 | 277 | # In[25]: 278 | 279 | 280 | # define the transformation methods for the columns 281 | t = [('ohe', OneHotEncoder(drop='first'), categorical_cols), 282 | ('scale', StandardScaler(), numerical_cols)] 283 | 284 | col_trans = ColumnTransformer(transformers=t) 285 | 286 | # fit the transformation on training data 287 | col_trans.fit(X_train) 288 | 289 | 290 | # In[26]: 291 | 292 | 293 | X_train_transform = col_trans.transform(X_train) 294 | 295 | 296 | # In[27]: 297 | 298 | 299 | # apply transformation to both training and testing data 300 | # fit the transformation on training data 301 | 302 | 303 | # In[28]: 304 | 305 | 306 | X_test_transform = col_trans.transform(X_test) 307 | 308 | 309 | # We could look at the transformed training data. It becomes an array-like structure rather than a dataframe structure. 310 | 311 | # In[30]: 312 | 313 | 314 | # look at the transformed training data 315 | X_train_transform.shape 316 | 317 | 318 | # In[31]: 319 | 320 | 321 | X_test_transform.shape 322 | 323 | 324 | # #### Transformation on y_train and y_test 325 | # 326 | # `LabelEncoder` is a utility class to help normalize labels such that they contain only values between 0 and n_classes-1. Note that the distinct values/labels in `y` target are 1 ( no liver disease) and 2 (liver disease). In our case, we will transform the label 1 and 2 as 0 and 1, respectively. New label 0 refers to no disease and 1 refers to liver disease. Although it should be much easier to achieve this by subtracting 1 from the `y` array, we provide the `LabelEncoder` transformation which is a standard way of dealing with targeted values. Again, similar to the transformation on `X`, we will apply `fit` method to `y_train` and then apply `transform` method to both `y_train` and `y_test`. 327 | 328 | # In[32]: 329 | 330 | 331 | # Note that the distinct values/labels in `y2` target are 1 and 2. 332 | pd.unique(y1) 333 | 334 | 335 | # In[33]: 336 | 337 | 338 | pd.unique(y2) 339 | 340 | 341 | # In[34]: 342 | 343 | 344 | # Define a LabelEncoder() transformation method and fit on y1_train 345 | target_trans = LabelEncoder() 346 | target_trans.fit(y1_train) 347 | 348 | 349 | # In[35]: 350 | 351 | 352 | # apply transformation method on y1_train and y1_test 353 | y1_train_transform = target_trans.transform(y1_train) 354 | y1_test_transform = target_trans.transform(y1_test) 355 | 356 | 357 | # In[36]: 358 | 359 | 360 | # view the transformed y1_train 361 | y1_train_transform 362 | 363 | 364 | # In[37]: 365 | 366 | 367 | # Define a LabelEncoder() transformation method and fit on y2_train 368 | target_trans = LabelEncoder() 369 | target_trans.fit(y2_train) 370 | y2_train_transform = target_trans.transform(y2_train) 371 | y2_test_transform = target_trans.transform(y2_test) 372 | 373 | 374 | # In[38]: 375 | 376 | 377 | # view the transformed y2_train 378 | y2_train_transform 379 | 380 | 381 | # # Train Modified (Explainable AI (XAI)) ML Models 382 | # 383 | # We will train several XAI machine learning models for the training set and evaluate their performance on both training and testing set. XAI VISULATION WILL BE CREATED ALSO 384 | # 385 | # ## Steps of Training Model and Testing Model Performance with Testing Data 386 | # 387 | # - Step 1: Train a XAI ML model and validate it via 5-fold cross-validation (CV). The CV results will show how good the model has been trained by using the training data given a set of hyperparameters in the ML model. The metrics of evaluating a model include accuracy, precision, recall, F1 score, AUC value of ROC. 388 | # 389 | # 390 | # - Step 2: Evaluate the model by using the testing data. It will show how good the model could be used to make predictions for unseen data. 391 | # 392 | # **NOTE: For simplicity, we do not tune hyperparameters in the ML model and will use the default settings of hyperparameters in each ML model.** 393 | # 394 | # **Let's firstly train a `Decision Tree Classifier` model with regards to Step 1 and Step 2.** using `y2` as the response feature FOR ALL THE XAI ML MODELS 395 | 396 | # ## Explainable AI (XAI) with a Decision Tree Classifier 397 | 398 | # In[134]: 399 | 400 | 401 | # model and fit 402 | DTclf = tree.DecisionTreeClassifier() 403 | DTclf.fit(X_train_transform, y2_train_transform) 404 | 405 | 406 | # In[135]: 407 | 408 | 409 | feature_names = np.array(numerical_cols) 410 | feature_names 411 | 412 | 413 | # ### Feature importance: 414 | # 415 | # Feature importance is calculated as the decrease in node impurity weighted by the probability of reaching that node. The most important features will be higher in the tree. A single feature can be used in different branches of the tree, feature importance then is its total contribution in reducing the impurity. 416 | 417 | # In[74]: 418 | 419 | 420 | importances = DTclf.feature_importances_ 421 | indices = np.argsort(importances) 422 | features = np.array(numerical_cols) 423 | plt.title('Feature Importances of Decision Tree Classifier') 424 | count = 10 # top # importance 425 | plt.barh(range(count), importances[indices][len(indices)-count:], color='g', align='center') 426 | plt.yticks(range(count), [features[i] for i in indices[len(indices)-count:]]) 427 | plt.xlabel('Relative Importance') 428 | plt.show() 429 | 430 | 431 | # In[99]: 432 | 433 | 434 | DTclf.feature_importances_ 435 | 436 | 437 | # #### In this case only the top 10 features are being used. The other features are not being used. Their importance is zero. 438 | 439 | # In[133]: 440 | 441 | 442 | get_ipython().system('pip install eli5') 443 | 444 | 445 | # In[156]: 446 | 447 | 448 | # Create Decision Tree classifer object 449 | DTclf = DecisionTreeClassifier(criterion="entropy", max_depth=5) 450 | 451 | # Train Decision Tree Classifer 452 | DTclf = DTclf.fit(X_train_transform, y2_train_transform) 453 | 454 | #Predict the response for test dataset 455 | y_pred = DTclf.predict(X_test_transform) 456 | 457 | 458 | # In[157]: 459 | 460 | 461 | from sklearn import metrics #Import scikit-learn metrics module for accuracy calculation 462 | # Model Accuracy, how often is the classifier correct? 463 | print("Accuracy:",metrics.accuracy_score(y2_test_transform, y_pred)) 464 | 465 | report=metrics.classification_report(y2_test_transform,y_pred) 466 | 467 | DTclf_name=['Decision Tree Classifer','RegLog'] 468 | 469 | print('Reporting for %s:'%DTclf_name) 470 | 471 | print(report) 472 | 473 | 474 | # In[163]: 475 | 476 | 477 | fig = plt.figure(figsize=(35, 30)) 478 | DTtree = tree.plot_tree(DTclf, feature_names = np.array(numerical_cols), class_names = ['Normal', 'Attack'], fontsize=14, proportion=True, filled=True, rounded=True) 479 | for o in DTtree: 480 | arrow = o.arrow_patch 481 | if arrow is not None: 482 | arrow.set_edgecolor('red') 483 | arrow.set_linewidth(3) 484 | 485 | fig.savefig('Decision Tree Classifier XAI Visualization Part 2.png') 486 | 487 | 488 | # In[164]: 489 | 490 | 491 | import eli5 #for purmutation importance 492 | from eli5.sklearn import PermutationImportance 493 | perm = PermutationImportance(DTclf, random_state=1).fit(X_test_transform, y2_test_transform) 494 | eli5.show_weights(perm, feature_names = np.array(numerical_cols)) 495 | 496 | 497 | # #### Let us visualize the first three levels of the decision tree, max_depth=3, 5, 8 498 | 499 | # In[117]: 500 | 501 | 502 | # visualization of DT Classfier 503 | fig = plt.figure(figsize=(20, 16)) 504 | DTtree = tree.plot_tree(DTclf, feature_names = features, class_names = ['Normal', 'Attack'], fontsize=12, proportion=True, filled=True, rounded=True, max_depth=3) 505 | for o in DTtree: 506 | arrow = o.arrow_patch 507 | if arrow is not None: 508 | arrow.set_edgecolor('red') 509 | arrow.set_linewidth(3) 510 | 511 | fig.savefig('Decision Tree Classifier (Depth = 3 Nodes) Explainable AI Visualization.png') 512 | 513 | 514 | # In[118]: 515 | 516 | 517 | # visualization of DT Classfier 518 | fig = plt.figure(figsize=(20, 16)) 519 | DTtree = tree.plot_tree(DTclf, feature_names = features, class_names = ['Normal', 'Attack'], fontsize=12, proportion=True, filled=True, rounded=True, max_depth=5) 520 | for o in DTtree: 521 | arrow = o.arrow_patch 522 | if arrow is not None: 523 | arrow.set_edgecolor('red') 524 | arrow.set_linewidth(3) 525 | 526 | fig.savefig('Decision Tree Classifier (Depth = 5 Nodes) Explainable AI Visualization.png') 527 | 528 | 529 | # In[119]: 530 | 531 | 532 | # visualization of DT Classfier 533 | fig = plt.figure(figsize=(20, 16)) 534 | DTtree = tree.plot_tree(DTclf, feature_names = features, class_names = ['Normal', 'Attack'], fontsize=10, proportion=True, filled=True, rounded=True, max_depth=8) 535 | for o in DTtree: 536 | arrow = o.arrow_patch 537 | if arrow is not None: 538 | arrow.set_edgecolor('red') 539 | arrow.set_linewidth(3) 540 | 541 | fig.savefig('Decision Tree Classifier (Depth = 8 Nodes) Explainable AI Visualization.png') 542 | 543 | 544 | # ### Model Performance On Testing Set: 545 | 546 | # In[122]: 547 | 548 | 549 | # ===== Step 1: cross-validation ======== 550 | # define Stratified 5-fold cross-validator, it provides train/validate indices to split data in train/validate sets. 551 | cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=123) 552 | 553 | DTclf = tree.DecisionTreeClassifier() 554 | 555 | # define metrics for evaluating 556 | scoring = ['accuracy', 'precision_micro', 'recall_micro', 'f1_micro', 'roc_auc_ovr'] 557 | 558 | # perform the 5-fold CV and get the metrics results 559 | cv_results = cross_validate(estimator=DTclf, 560 | X=X_train_transform, 561 | y=y2_train_transform, 562 | scoring=scoring, 563 | cv=cv, 564 | return_train_score=False) # prevent to show the train scores on cv splits. 565 | 566 | 567 | # In[123]: 568 | 569 | 570 | cv_results 571 | 572 | 573 | # The CV results include: 574 | # 575 | # - `test_score`: The score array for test scores on each cv split. Suffix `_score` in `test_score` changes to a specific metric like `test_accuracy` or `test_f1` if there are multiple scoring metrics in the scoring parameter. 576 | # 577 | # - `fit_time`: The time for fitting the estimator on the train set for each cv split. 578 | # 579 | # - `score_time`: The time for scoring the estimator on the test set for each cv split. 580 | # 581 | # **Typically, we will use the mean value of each metric to represent the evaluation results of cross-validation.** For example, we could calculate the mean value of the `accuracy` score: 582 | 583 | # In[124]: 584 | 585 | 586 | cv_results['test_accuracy'].mean() 587 | 588 | 589 | # **In addition, the cross-validation step is used to find the best set of hyperparameters which give the "best" scores of metrics.** Since we do not tune hyperparameters in this case, we then directly fit the DT Classifer by using the default values of hyperparameters and evaluate it on testing data. 590 | 591 | # In[125]: 592 | 593 | 594 | # ======== Step 2: Evaluate the model using testing data ======= 595 | 596 | # fit the Logistic Regression model 597 | DTclf.fit(X=X_train_transform, y=y2_train_transform) 598 | 599 | # predition on testing data 600 | y_pred_class = clf.predict(X=X_test_transform) 601 | y_pred_score = clf.predict_proba(X=X_test_transform)[:, 1] 602 | 603 | # AUC of ROC 604 | auc_ontest = roc_auc_score(y_true=y2_test_transform, y_score=y_pred_score) 605 | # confusion matrix 606 | cm_ontest = confusion_matrix(y_true=y2_test_transform, y_pred=y_pred_class) 607 | # precision score 608 | precision_ontest = precision_score(y_true=y2_test_transform, y_pred=y_pred_class) 609 | # recall score 610 | recall_ontest = recall_score(y_true=y2_test_transform, y_pred=y_pred_class) 611 | # classifition report 612 | cls_report_ontest = classification_report(y_true=y2_test_transform, y_pred=y_pred_class) 613 | 614 | # print the above results 615 | print('The model scores {:1.5f} ROC AUC on the test set.'.format(auc_ontest)) 616 | print('The precision score on the test set: {:1.5f}'.format(precision_ontest)) 617 | print('The recall score on the test set: {:1.5f}'.format(recall_ontest)) 618 | print('Confusion Matrix:\n', cm_ontest) 619 | # Print classification report: 620 | print('Classification Report:\n', cls_report_ontest) 621 | 622 | 623 | # Through the above steps, we could assess if the trained model is good for making predictions on unseen data. Recall that we are training a ML model to classify types of attack behavior on network packets. Considering that we prefer to having a model to capture the cases of attack as many as possible. In other words, the favorable model could have relatively high "coverage" ability and high "precision" ability. **Therefore, we could choose `F1 score` as the evaluation metric in this case. `F1 score` can be interpreted as a weighted average of the precision and recall, where an F1 score reaches its best value at 1 and worst score at 0.** 624 | 625 | # ###### Exapand DT Classfier to RT Classfier to show XAI also 626 | 627 | # ## Explainable AI (XAI) with a MLP (Multi-Layer Perceptron) 628 | 629 | # Lime: Explaining the predictions of any machine learning classifier 630 | 631 | # In[256]: 632 | 633 | 634 | import sklearn 635 | import sklearn.datasets 636 | import sklearn.ensemble 637 | import numpy as np 638 | import lime 639 | import lime.lime_tabular 640 | from __future__ import print_function 641 | np.random.seed(1) 642 | 643 | 644 | # In[258]: 645 | 646 | 647 | MLP = MLPClassifier(random_state=123, solver='adam', max_iter=8000) 648 | MLP.fit(X_train_transform, y2_train_transform) 649 | 650 | 651 | # #### Explaining predictions 652 | 653 | # In[259]: 654 | 655 | 656 | metrics.accuracy_score(y2_test_transform, gbtree.predict(X_test_transform)) 657 | 658 | 659 | # In[260]: 660 | 661 | 662 | predict_fn = lambda x: gbtree.predict_proba(x).astype(float) 663 | 664 | 665 | # In[261]: 666 | 667 | 668 | features = np.array(numerical_cols) 669 | explainer = lime.lime_tabular.LimeTabularExplainer(X_train_transform ,feature_names = features, class_names = ['Normal', 'Attack'], kernel_width=3) 670 | 671 | 672 | # In[265]: 673 | 674 | 675 | np.random.seed(1) 676 | i = 1653 677 | exp = explainer.explain_instance(X_test_transform[i], predict_fn, num_features=10) 678 | exp.show_in_notebook(show_all=False) 679 | print('True class: ') 680 | if (y2_test_transform[i] == 0): 681 | print('Normal') 682 | else: 683 | print('Attack') 684 | 685 | 686 | # ## Explainable AI (XAI) with XGBoost 687 | 688 | # ###### XGBoost is an optimized distributed gradient boosting library designed to be highly efficient, flexible and portable. As it uses Gradient Boosting and can be parallelized, this algorithm is very popular in data science and is frequently used for regression and classification tasks. The following example shows a simple regression model and is hopefully a good entry point for anyone wanting to create and use XGBoost based models. 689 | 690 | # ###### In an era of AI and ethics, explainability is one of the important recent topics in machine learning and data science. Let’s say you have built a machine learning model that performs well on your training and test data: how do you find out which samples and features offer the highest impact on your model’s output? This is where a library like SHAP can provide you with very valuable insights. SHAP (SHapley Additive exPlanations) is a game-theoretic approach to explaining the output of any machine learning model. The following example shows how an XGBoost-based classifier model can be analyzed with SHAP to help better understand the impact of features on the model output. The chart on the top-right provides a view on the distribution of feature values and their impact on the model. 691 | 692 | # ###### SHAP summary shows top feature contributions. It also shows data point distribution and provides visual indicators of how feature values affect predictions. Here red indicates higher feature value, blue indicates lower feature value. On the x-axis, higher SHAP value to the right corresponds to higher prediction value (more likely listing gets booked), lower SHAP value to the left corresponds to lower prediction value (less likely listing gets booked). 693 | 694 | # #### Gradient boosting machine methods such as XGBoost are state-of-the-art for these types of prediction problems with tabular style input data of many modalities. Tree SHAP (arXiv paper) allows for the exact computation of SHAP values for tree ensemble methods, and has been integrated directly into the C++ XGBoost code base. This allows fast exact computation of SHAP values without sampling and without providing a background dataset (since the background is inferred from the coverage of the trees). 695 | # 696 | # #### Here we demonstrate how to use SHAP values to understand XGBoost model predictions. 697 | 698 | # In[167]: 699 | 700 | 701 | get_ipython().system('pip install xgboost') 702 | 703 | 704 | # In[168]: 705 | 706 | 707 | get_ipython().system('pip install shap') 708 | 709 | 710 | # In[169]: 711 | 712 | 713 | from sklearn.model_selection import train_test_split 714 | import xgboost 715 | import shap 716 | import numpy as np 717 | import matplotlib.pylab as pl 718 | 719 | 720 | # ##### Load Dataset 721 | 722 | # In[171]: 723 | 724 | 725 | xg_train = xgboost.DMatrix(X_train_transform, label=y2_train_transform) 726 | xg_test = xgboost.DMatrix(X_test_transform, label=y2_test_transform) 727 | 728 | 729 | # ##### Train Model 730 | 731 | # In[173]: 732 | 733 | 734 | params = { 735 | "eta": 0.01, 736 | "objective": "binary:logistic", 737 | "subsample": 0.5, 738 | "base_score": np.mean(y2_train_transform), 739 | "eval_metric": "logloss" 740 | } 741 | model = xgboost.train(params, xg_train, 5000, evals = [(xg_test, "test")], verbose_eval=100, early_stopping_rounds=20) 742 | 743 | 744 | # ###### Explain predictions: Here we use the Tree SHAP implementation integrated into XGBoost to explain the testing dataset 745 | 746 | # In[198]: 747 | 748 | 749 | # this takes a minute or two since we are explaining over 30 thousand samples in a model with over a thousand trees 750 | explainer = shap.TreeExplainer(model) 751 | shap_values_test = explainer.shap_values(X_test) 752 | 753 | 754 | # ##### Visualize a single prediction 755 | 756 | # In[221]: 757 | 758 | 759 | # print the JS visualization code to the notebook 760 | shap.initjs() 761 | shap.force_plot(explainer.expected_value, shap_values_test[5,:], X_test.iloc[5,:]) 762 | 763 | 764 | # In[224]: 765 | 766 | 767 | y2_test[5] 768 | 769 | 770 | # ###### Visualize many predictions 771 | 772 | # In[214]: 773 | 774 | 775 | shap.force_plot(explainer.expected_value, shap_values_test[:1000,:], X_test.iloc[:1000,:]) 776 | 777 | 778 | # ###### Bar chart of mean importance 779 | 780 | # In[212]: 781 | 782 | 783 | shap.summary_plot(shap_values_test, X_test, plot_type="bar") 784 | 785 | 786 | # SHAP Summary Plot: 787 | # Rather than use a typical feature importance bar chart, we use a density scatter plot of SHAP values for each feature to identify how much impact each feature has on the model output for individuals in the validation dataset. Features are sorted by the sum of the SHAP value magnitudes across all samples. It is interesting to note that the relationship feature has more total model impact than the captial gain feature, but for those samples where capital gain matters it has more impact than age. In other words, capital gain effects a few predictions by a large amount, while age effects all predictions by a smaller amount. 788 | # 789 | # Note that when the scatter points don't fit on a line they pile up to show density, and the color of each point represents the feature value of that individual. 790 | 791 | # In[211]: 792 | 793 | 794 | shap.summary_plot(shap_values_test, X_test) 795 | 796 | 797 | # ###### SHAP Dependence Plots 798 | # SHAP dependence plots show the effect of a single feature across the whole dataset. They plot a feature's value vs. the SHAP value of that feature across many samples. SHAP dependence plots are similar to partial dependence plots, but account for the interaction effects present in the features, and are only defined in regions of the input space supported by data. The vertical dispersion of SHAP values at a single feature value is driven by interaction effects, and another feature is chosen for coloring to highlight possible interactions. 799 | 800 | # In[225]: 801 | 802 | 803 | for name in X_test.columns: 804 | shap.dependence_plot(name, shap_values_test, X_test, display_features=X_test) 805 | 806 | 807 | # ###### Compute SHAP Interaction Values 808 | # 809 | # See the Tree SHAP paper for more details, but briefly, SHAP interaction values are a generalization of SHAP values to higher order interactions. Fast exact computation of pairwise interactions are implemented in the latest version of XGBoost with the pred_interactions flag. With this flag XGBoost returns a matrix for every prediction, where the main effects are on the diagonal and the interaction effects are off-diagonal. The main effects are similar to the SHAP values you would get for a linear model, and the interaction effects captures all the higher-order interactions are divide them up among the pairwise interaction terms. Note that the sum of the entire interaction matrix is the difference between the model's current output and expected output, and so the interaction effects on the off-diagonal are split in half (since there are two of each). When plotting interaction effects the SHAP package automatically multiplies the off-diagonal values by two to get the full interaction effect. 810 | 811 | # In[227]: 812 | 813 | 814 | # takes a couple minutes since SHAP interaction values take a factor of 2 * # features 815 | # more time than SHAP values to compute, since this is just an example we only explain 816 | # the first 2,000 people in order to run quicker 817 | shap_interaction_values = shap.TreeExplainer(model).shap_interaction_values(X_test.iloc[:2000,:]) 818 | 819 | 820 | # ###### SHAP Interaction Value Summary Plot 821 | # A summary plot of a SHAP interaction value matrix plots a matrix of summary plots with the main effects on the diagonal and the interaction effects off the diagonal. 822 | 823 | # In[228]: 824 | 825 | 826 | shap.summary_plot(shap_interaction_values, X_test.iloc[:2000,:]) 827 | 828 | 829 | # # USING LIME PACKAGE 830 | 831 | # In[235]: 832 | 833 | 834 | get_ipython().system('pip install lime') 835 | 836 | 837 | # In[236]: 838 | 839 | 840 | import sklearn 841 | import sklearn.datasets 842 | import sklearn.ensemble 843 | import numpy as np 844 | import lime 845 | import lime.lime_tabular 846 | from __future__ import print_function 847 | np.random.seed(1) 848 | 849 | 850 | # In[245]: 851 | 852 | 853 | import xgboost 854 | gbtree = xgboost.XGBClassifier(n_estimators=300, max_depth=5) 855 | gbtree.fit(X_train_transform, y2_train_transform) 856 | 857 | 858 | # In[246]: 859 | 860 | 861 | metrics.accuracy_score(y2_test_transform, gbtree.predict(X_test_transform)) 862 | 863 | 864 | # In[251]: 865 | 866 | 867 | predict_fn = lambda x: gbtree.predict_proba(x).astype(float) 868 | 869 | 870 | # #### Explaining predictions 871 | 872 | # In[249]: 873 | 874 | 875 | features = np.array(numerical_cols) 876 | explainer = lime.lime_tabular.LimeTabularExplainer(X_train_transform ,feature_names = features, class_names = ['Normal', 'Attack'], kernel_width=3) 877 | 878 | 879 | # These are just a mix of the continuous and categorical examples we showed before. For categorical features, the feature contribution is always the same as the linear model weight. 880 | 881 | # In[252]: 882 | 883 | 884 | np.random.seed(1) 885 | i = 1653 886 | exp = explainer.explain_instance(X_test_transform[i], predict_fn, num_features=5) 887 | exp.show_in_notebook(show_all=False) 888 | 889 | 890 | # In[254]: 891 | 892 | 893 | i = 10 894 | exp = explainer.explain_instance(X_test_transform[i], predict_fn, num_features=5) 895 | exp.show_in_notebook(show_all=False) 896 | 897 | 898 | # In[ ]: 899 | 900 | 901 | 902 | 903 | -------------------------------------------------------------------------------- /UNSW-NB15_LIST_EVENTS.csv: -------------------------------------------------------------------------------- 1 | Attack category,Attack subcategory,Number of events 2 | normal,,2218761 3 | Fuzzers ,FTP,558 4 | Fuzzers ,HTTP,1497 5 | Fuzzers ,RIP,3550 6 | Fuzzers ,SMB,5245 7 | Fuzzers ,Syslog,1851 8 | Fuzzers ,PPTP,1583 9 | Fuzzers, FTP,248 10 | Fuzzers,DCERPC,164 11 | Fuzzers,OSPF,993 12 | Fuzzers ,TFTP,193 13 | Fuzzers , DCERPC ,455 14 | Fuzzers , OSPF,1746 15 | Fuzzers ,BGP,6163 16 | Reconnaissance ,Telnet,6 17 | Reconnaissance ,SNMP,69 18 | Reconnaissance , SunRPC Portmapper (TCP) UDP Service,2030 19 | Reconnaissance , SunRPC Portmapper (TCP) TCP Service ,2026 20 | Reconnaissance ,SunRPC Portmapper (UDP) UDP Service,2045 21 | Reconnaissance ,NetBIOS,5 22 | Reconnaissance ,DNS,35 23 | Reconnaissance ,HTTP,1867 24 | Reconnaissance ,SunRPC Portmapper (UDP),2028 25 | Reconnaissance , ICMP,1739 26 | Reconnaissance , SCTP,367 27 | Reconnaissance ,MSSQL,5 28 | Reconnaissance ,SMTP,6 29 | Shellcode ,FreeBSD,45 30 | Shellcode ,HP-UX ,12 31 | Shellcode ,NetBSD ,45 32 | Shellcode ,AIX,11 33 | Shellcode ,SCO Unix,12 34 | Shellcode ,Linux,236 35 | Shellcode ,Decoders,102 36 | Shellcode ,IRIX,12 37 | Shellcode ,OpenBSD,22 38 | Shellcode , Mac OS X,149 39 | Shellcode ,BSD,252 40 | Shellcode ,Windows,173 41 | Shellcode ,BSDi,94 42 | Shellcode ,Multiple OS,56 43 | Shellcode ,Solaris,67 44 | Analysis,HTML,616 45 | Analysis,Port Scanner,2055 46 | Analysis,Spam ,6 47 | Backdoors, ,2329 48 | DoS, Ethernet,860 49 | DoS, Microsoft Office,292 50 | DoS, VNC,11 51 | DoS,IRC,1 52 | DoS,RDP,1319 53 | DoS,TCP,30 54 | DoS,VNC,2 55 | DoS, FTP,69 56 | DoS, LDAP,3 57 | DoS, Oracle ,6 58 | DoS, TCP,1712 59 | DoS, TFTP,18 60 | DoS,DCERPC,6 61 | DoS,XINETD,24 62 | DoS, IRC,6 63 | DoS, SNMP,5 64 | DoS,ISAKMP,14 65 | DoS,NTP,2 66 | DoS,Telnet,13 67 | DoS,CUPS,1 68 | DoS,Hypervisor,6 69 | DoS,ICMP,1478 70 | DoS,SunRPC,3 71 | DoS, IMAP,7 72 | DoS,Asterisk,1210 73 | DoS,Browser,1061 74 | DoS,Cisco Skinny,6 75 | DoS,SIP,60 76 | DoS,SMTP,4 77 | DoS,SNMP,29 78 | DoS,SSL,20 79 | DoS,TFTP,3 80 | DoS, SMTP,21 81 | DoS,DNS,375 82 | DoS,IIS Web Server,23 83 | DoS,Miscellaneous,3528 84 | DoS,RTSP,27 85 | DoS, Common Unix Print System (CUPS),6 86 | DoS, SunRPC,17 87 | DoS,IGMP,1267 88 | DoS,Microsoft Office,49 89 | DoS,HTTP,1357 90 | DoS,LDAP,17 91 | DoS,NetBIOS/SMB,1262 92 | DoS,Oracle,1 93 | DoS,Windows Explorer,122 94 | Exploits, Evasions,212 95 | Exploits, SCCP,16 96 | Exploits, SSL ,33 97 | Exploits, VNC,27 98 | Exploits,Backup Appliance,162 99 | Exploits,Browser ,7925 100 | Exploits,Clientside Microsoft Office,130 101 | Exploits,Interbase,21 102 | Exploits,Miscellaneous Batch,1578 103 | Exploits,SOCKS,6 104 | Exploits,TCP,3 105 | Exploits, Apache,1878 106 | Exploits, IMAP,36 107 | Exploits, Microsoft IIS,296 108 | Exploits, SOCKS,1 109 | Exploits,Clientside,657 110 | Exploits,Clientside Microsoft Paint ,8 111 | Exploits,IDS,81 112 | Exploits,SSH,2 113 | Exploits, ICMP,1226 114 | Exploits, IDS,18 115 | Exploits,DCERPC ,121 116 | Exploits,FTP,244 117 | Exploits,RADIUS,569 118 | Exploits,SSL,6 119 | Exploits,WINS ,3 120 | Exploits, Clientside,4480 121 | Exploits, Clientside Microsoft ,120 122 | Exploits, POP3,35 123 | Exploits, SSH,12 124 | Exploits, TCP,912 125 | Exploits, Unix r Service,38 126 | Exploits, WINS,18 127 | Exploits,Cisco IOS,579 128 | Exploits,Clientside Microsoft Media Player ,18 129 | Exploits,Dameware,6 130 | Exploits,IMAP,6 131 | Exploits,LPD ,6 132 | Exploits,MSSQL ,26 133 | Exploits,Office Document,417 134 | Exploits,RTSP,676 135 | Exploits,SCADA,932 136 | Exploits,VNC,5 137 | Exploits,Webserver,465 138 | Exploits, All,6 139 | Exploits, LDAP,75 140 | Exploits, NNTP,18 141 | Exploits, Office Document,2433 142 | Exploits, RTSP,12 143 | Exploits,IGMP,350 144 | Exploits,Oracle,187 145 | Exploits,RDesktop,14 146 | Exploits,Telnet,122 147 | Exploits,Unix 'r' Service,6 148 | Exploits, LPD,35 149 | Exploits,All ,1 150 | Exploits,Apache,37 151 | Exploits,ICMP ,3 152 | Exploits,Microsoft IIS,51 153 | Exploits,PHP,999 154 | Exploits,SMB,2130 155 | Exploits,SunRPC,74 156 | Exploits,Web Application,4639 157 | Exploits, PHP,17 158 | Exploits,DNS,181 159 | Exploits,Evasions,37 160 | Exploits,NNTP,3 161 | Exploits,SMTP,772 162 | Exploits, RADIUS,8 163 | Exploits,Browser FTP,1981 164 | Exploits,Miscellaneous,5178 165 | Exploits,PPTP,13 166 | Exploits,SCCP,3 167 | Exploits,SIP,1043 168 | Exploits,TFTP,87 169 | Generic,All,7 170 | Generic,SIP,436 171 | Generic, HTTP,1 172 | Generic,SMTP,247 173 | Generic, IXIA,7395 174 | Generic, TFTP,116 175 | Generic,IXIA,207243 176 | Generic,Superflow,10 177 | Generic,HTTP,5 178 | Generic,TFTP,21 179 | Reconnaissance,DNS,6 180 | Reconnaissance,SMTP,1 181 | Reconnaissance,HTTP,314 182 | Reconnaissance,SNMP,12 183 | Reconnaissance,SunRPC Portmapper (UDP) TCP Service,349 184 | Reconnaissance,MSSQL,1 185 | Reconnaissance,NetBIOS ,1 186 | Reconnaissance,SCTP,2 187 | Reconnaissance,SunRPC,2 188 | Reconnaissance,Telnet,1 189 | Reconnaissance,ICMP,26 190 | Reconnaissance,SunRPC Portmapper (TCP) TCP Service,349 191 | Reconnaissance,SunRPC Portmapper (TCP) UDP Service,349 192 | Reconnaissance, SunRPC Portmapper (UDP) UDP Service ,346 193 | Shellcode,FreeBSD,8 194 | Shellcode,Linux,39 195 | Shellcode,OpenBSD,4 196 | Shellcode, SCO Unix ,2 197 | Shellcode,HP-UX,2 198 | Shellcode,Mac OS X,26 199 | Shellcode,NetBSD,8 200 | Shellcode,BSD,44 201 | Shellcode,BSDi,16 202 | Shellcode,IRIX,2 203 | Shellcode,AIX,2 204 | Shellcode,Windows,30 205 | Shellcode,Decoders,18 206 | Shellcode,Multiple OS,10 207 | Shellcode,Solaris,12 208 | Worms, ,174 209 | ,Total ,2540044 210 | -------------------------------------------------------------------------------- /UNSW-NB15_features.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harshilpatel1799/IoT-Network-Intrusion-Detection-and-Classification-using-Explainable-XAI-Machine-Learning/fef317e4a882df5919bbe3409fd6bbce7267b37d/UNSW-NB15_features.csv --------------------------------------------------------------------------------