File size: 31,827 Bytes
0ebd797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "complete-wealth",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Running on local URL:  http://127.0.0.1:7865/\n",
      "\n",
      "To create a public link, set `share=True` in `launch()`.\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "\n",
       "        <iframe\n",
       "            width=\"900\"\n",
       "            height=\"500\"\n",
       "            src=\"http://127.0.0.1:7865/\"\n",
       "            frameborder=\"0\"\n",
       "            allowfullscreen\n",
       "        ></iframe>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.lib.display.IFrame at 0x27733bf76d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(<fastapi.applications.FastAPI at 0x27758f30910>,\n",
       " 'http://127.0.0.1:7865/',\n",
       " None)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "950/950 [==============================] - 1s 1ms/step - loss: 9.2114e-04 - accuracy: 0.9996\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import gradio as gr\n",
    "\n",
    "\n",
    "import pandas as pd\n",
    "from math import sqrt;\n",
    "from sklearn import preprocessing\n",
    "from sklearn.ensemble import RandomForestClassifier\n",
    "from sklearn.linear_model import LogisticRegression;\n",
    "from sklearn.metrics import accuracy_score, r2_score, confusion_matrix, mean_absolute_error, mean_squared_error, f1_score, log_loss\n",
    "from sklearn.model_selection import train_test_split\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns \n",
    "import joblib\n",
    " #load packages for ANN\n",
    "import tensorflow as tf\n",
    "    \n",
    "def malware_detection_DL (results, malicious_traffic, benign_traffic):\n",
    "    malicious_dataset = pd.read_csv(malicious_traffic)  #Importing Datasets \n",
    "    benign_dataset = pd.read_csv(benign_traffic)\n",
    "    # Removing duplicated rows from benign_dataset (5380 rows removed)\n",
    "    benign_dataset = benign_dataset[benign_dataset.duplicated(keep=False) == False]\n",
    "    # Combining both datasets together\n",
    "    all_flows = pd.concat([malicious_dataset, benign_dataset])\n",
    "    # Reducing the size of the dataset to reduce the amount of time taken in training models\n",
    "    reduced_dataset = all_flows.sample(38000)\n",
    "    #dataset with columns with nan values dropped\n",
    "    df = reduced_dataset.drop(reduced_dataset.columns[np.isnan(reduced_dataset).any()], axis=1)\n",
    "    #### Isolating independent and dependent variables for training dataset\n",
    "    reduced_y = df['isMalware']\n",
    "    reduced_x = df.drop(['isMalware'], axis=1);\n",
    "    # Splitting datasets into training and test data\n",
    "    x_train, x_test, y_train, y_test = train_test_split(reduced_x, reduced_y, test_size=0.2, random_state=42)\n",
    "   \n",
    "    #scale data between 0 and 1\n",
    "    min_max_scaler = preprocessing.MinMaxScaler()\n",
    "    x_scale = min_max_scaler.fit_transform(reduced_x)\n",
    "    # Splitting datasets into training and test data\n",
    "    x_train, x_test, y_train, y_test = train_test_split(x_scale, reduced_y, test_size=0.2, random_state=42)\n",
    "    #type of layers in ann model is sequential, dense and uses relu activation \n",
    "    ann = tf.keras.models.Sequential()\n",
    "    model = tf.keras.Sequential([\n",
    "        tf.keras.layers.Dense(32, activation ='relu', input_shape=(373,)),\n",
    "        tf.keras.layers.Dense(32, activation = 'relu'),\n",
    "        tf.keras.layers.Dense(1, activation = 'sigmoid'),\n",
    "    ])\n",
    "    \n",
    "    \n",
    "    model.compile(optimizer ='adam', \n",
    "        loss = 'binary_crossentropy',\n",
    "        metrics = ['accuracy'])\n",
    "        #model.fit(x_train, y_train, batch_size=32, epochs = 150, validation_data=(x_test, y_test))\n",
    "        #does not output epochs and gives evalutaion of validation data and history of losses and accuracy\n",
    "    history = model.fit(x_train, y_train, batch_size=32, epochs = 150,verbose=0, validation_data=(x_test, y_test))\n",
    "    _, accuracy = model.evaluate(x_train, y_train)\n",
    "        #return history.history\n",
    "    if results==\"Accuracy\":\n",
    "        #summarize history for accuracy\n",
    "        plt.plot(history.history['accuracy'])\n",
    "        plt.plot(history.history['val_accuracy'])\n",
    "        plt.title('model accuracy')\n",
    "        plt.ylabel('accuracy')\n",
    "        plt.xlabel('epoch')\n",
    "        plt.legend(['train', 'test'], loc='upper left')\n",
    "        return plt.show()\n",
    "    else:\n",
    "        # summarize history for loss\n",
    "        plt.plot(history.history['loss'])\n",
    "        plt.plot(history.history['val_loss'])\n",
    "        plt.title('model loss')\n",
    "        plt.ylabel('loss')\n",
    "        plt.xlabel('epoch')\n",
    "        plt.legend(['train', 'test'], loc='upper left')\n",
    "        return plt.show()\n",
    "    \n",
    "    \n",
    "    \n",
    "iface = gr.Interface(\n",
    "    malware_detection_DL, [gr.inputs.Dropdown([\"Accuracy\",\"Loss\"], label=\"Result Type\"),\n",
    "                                     gr.inputs.Dropdown([\"malicious_flows.csv\"], label = \"Malicious traffic in .csv\"), gr.inputs.Dropdown([\"sample_benign_flows.csv\"], label=\"Benign Traffic in .csv\")\n",
    "                          ], \"plot\",\n",
    "    \n",
    "    \n",
    ")\n",
    "\n",
    "iface.launch()\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "curious-detector",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}