├── .DS_Store
├── FIGURE
├── BA.png
├── .DS_Store
├── CAM.png
├── COMP.png
├── MLPF.png
├── STCP.png
└── RESULT.png
├── Final_Report.pdf
├── README.md
├── STCP.ipynb
├── BAfiltering.ipynb
└── MLPF.ipynb
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/.DS_Store
--------------------------------------------------------------------------------
/FIGURE/BA.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/BA.png
--------------------------------------------------------------------------------
/FIGURE/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/.DS_Store
--------------------------------------------------------------------------------
/FIGURE/CAM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/CAM.png
--------------------------------------------------------------------------------
/FIGURE/COMP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/COMP.png
--------------------------------------------------------------------------------
/FIGURE/MLPF.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/MLPF.png
--------------------------------------------------------------------------------
/FIGURE/STCP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/STCP.png
--------------------------------------------------------------------------------
/Final_Report.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/Final_Report.pdf
--------------------------------------------------------------------------------
/FIGURE/RESULT.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/winnieay/Background-Activity-Denoising-for-Event-Camera/HEAD/FIGURE/RESULT.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Background Activity Denoising for Event Camera
2 |
3 | ## Abstract
4 | Background activity (BA) noise events from Dynamic Vision Sensor (DVS) event cameras are uninformative and grow substantially in low-light conditions. While there are noises, it possibly results in problems including event overload and system instability, which would affect the efficiency and accuracy. Higher noise rate possibly renders existing denoising techniques ineffective. Moreover, comparing algorithm accuracy quantitatively is challenging.
5 |
6 | This research would measure filtering performance by using known combinations of signal and noise DVS events to better quantify denoising techniques. Three low-cost filtering algorithms are compared using datasets for stationary and moving camera applications of DVS.
7 |
8 | Algorithm 1 eliminates the majority of the BA noises by using a small fixed size window to measure the time difference between current event and previous events.
9 |
10 | For more thorough correlation verification, Algorithm 2 improves correlation checking that is proportional to the quantity of pixels. It preserves more signal while removing more noise in comparison to current approaches.
11 |
12 | To obtain the better accuracy across datasets, Algorithm 3 makes use of a lightweight multilayer perceptron classifier that depends on local event time surfaces and it has overall best performance comparing the previous two algorithms.
13 |
14 |
15 | ## Background
16 |
17 | ### DAVIS 346 Event Camera
18 | The DAVIS 346 event camera is an innovative and proficient event-based vision sensor created by iniLabs, a prominent supplier of event-based sensing systems. The DAVIS (Dynamic and Active-pixel Vision Sensor) series signifies a notable progression within the domain of event cameras.
19 |
20 |
21 | Figure1 DAVIS 346 Event Camera
22 |
23 |
24 |
25 | ### Background Activity Noises in Event Camera
26 | Leak noises and shot noises are two forms of undesired signals that should be filtered out since they might have an impact on the precision and dependability of event-based systems.
27 |
28 | ## The Output of Event Camera
29 | For conventional cameras, it produces sequences of signal frames containing complete pixel information at regular intervals. Unlike conventional cameras, event cameras capture signals by detecting the brightness changes and encode the time. Thus, the output of event cameras is called Events. Event cameras asynchronously output events, which means it generates signal outputs based on local changes in pixel intensity in real time.
30 |
31 |
32 |
33 | Figure2 The Comparison of Signal Outputs between Event Cameras and Conventional Cameras
34 |
35 |
36 |
37 | Data Format of Each Event:
38 | • Event Coordinates: The X and Y coordinates of the pixel to indicate the location that the event occurred.
39 | • Event Polarity: A binary value (0 or 1) indicating whether the event is ON event or OFF event. The pixel experiencing an increase in intensity is an ON event and a decrease in intensity is an OFF event.
40 | • Event Timestamp: The timestamp is the time while the event occurred and the unit of timestamp is usually in microseconds.
41 |
42 | ## Algorithm Explanation
43 |
44 | ### Algorithm 1 - The Background Activity Filter (BAF)
45 | The BAF functions by analysing the behavioural patterns of adjacent events and deciding as to whether the present event may be categorized as a signal or as a component of the background activity. The successful differentiation of significant events from noise is achieved by the BAF via the use of the concepts of time differences and correlation time.
46 |
47 | Upon the occurrence of an event inside the camera's visual range, the Behaviour Analysis Framework commences its analysis by considering the temporal dimensions of the event. The primary emphasis is on the event's nearest neighbours, which refer to the events that are geographically in closest proximity to it. Through the analysis of these adjacent occurrences, the BAF seeks to discern patterns and associations within the temporal realm.
48 |
49 |
50 | Figure2 The Background Activity Filter (BAF)
51 |
52 |
53 |
54 | ### Algorithm 2 - The Spatiotemporal Correlation Filter (STCP)
55 | The STCF and the Background Activity Filter (BAF) have a same operational principle, which involves analysing the temporal intervals between the present event and its closest neighbouring events. In contrast to the BAF, which primarily focuses on the actions of individual neighbours, the STCF takes into account the combined behaviour of several neighbours in order to arrive at its conclusion.
56 |
57 |
58 | Figure3 The Spatiotemporal Correlation Filter (STCP)
59 |
60 |
61 | ### Algorithm 3 - The Multilayer Perceptron Denoising Filter (MLPF)
62 | In order to investigate the potential improvement in denoising accuracy, we have devised a Deep Neural Network (DNN) denoiser using a basic Multilayer Perceptron (MLP) architecture[11]. The objective is to assess the performance of a lightweight classifier trained on annotated data.
63 |
64 |
65 | Figure4 The Multilayer Perceptron Denoising Filter (MLPF)
66 |
67 |
68 |
69 | ## Result
70 |
71 |
72 | Figure5 The Result of BAF, STCP and MLPF for Comparison
73 |
74 |
75 |
76 | The use of three algorithms, namely STCF, BAF, and MLPF, is viable for the purpose of filtering leak sounds. It is evident that all three algorithms exhibit satisfactory performance in this aspect, but with potential variations in their individual performance characteristics. Conducting a more extensive examination and comparison of the algorithms' performance, specifically in relation to metrics such as true positive rate, false positive rate, and other pertinent measurements, would provide a full comprehension of their respective merits and limitations.
77 |
78 | In the context of filtering shot noises, it has been determined that the STCF algorithm exhibits superior performance in comparison to the BAF method. This implies that the STCF algorithm exhibits more efficacy in discriminating shot sounds from signals, hence yielding a reduced incidence of false positives.
79 | According to the result, it can be concluded that the MLPF algorithm exhibits the most superior performance when compared to the other two filtering algorithms in terms of overall effectiveness. The Multi-Layer Perceptron Filter (MLPF) has superior performance in terms of filtering efficacy when compared to both the Short-Time Fourier Transform Filter (STCF) and the Bandpass Adaptive Filter (BAF), taking into account the mitigation of both leak sounds and shot noises.
80 |
81 |
--------------------------------------------------------------------------------
/STCP.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "provenance": []
7 | },
8 | "kernelspec": {
9 | "name": "python3",
10 | "display_name": "Python 3"
11 | },
12 | "language_info": {
13 | "name": "python"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "code",
19 | "source": [
20 | "!pip install dv\n",
21 | "import cv2\n",
22 | "import glob\n",
23 | "import os\n",
24 | "from tqdm import tqdm\n",
25 | "import numpy as np\n",
26 | "import dv\n",
27 | "import copy\n",
28 | "import time"
29 | ],
30 | "metadata": {
31 | "id": "2db3meBFukRu",
32 | "colab": {
33 | "base_uri": "https://localhost:8080/"
34 | },
35 | "outputId": "682771ac-1b91-4126-801c-b439376d063c"
36 | },
37 | "execution_count": null,
38 | "outputs": [
39 | {
40 | "output_type": "stream",
41 | "name": "stdout",
42 | "text": [
43 | "Requirement already satisfied: dv in /usr/local/lib/python3.10/dist-packages (1.0.12)\n",
44 | "Requirement already satisfied: flatbuffers in /usr/local/lib/python3.10/dist-packages (from dv) (23.5.26)\n",
45 | "Requirement already satisfied: numpy in /usr/local/lib/python3.10/dist-packages (from dv) (1.23.5)\n",
46 | "Requirement already satisfied: lz4 in /usr/local/lib/python3.10/dist-packages (from dv) (4.3.2)\n",
47 | "Requirement already satisfied: zstd in /usr/local/lib/python3.10/dist-packages (from dv) (1.5.5.1)\n",
48 | "Requirement already satisfied: deprecated in /usr/local/lib/python3.10/dist-packages (from dv) (1.2.14)\n",
49 | "Requirement already satisfied: wrapt<2,>=1.10 in /usr/local/lib/python3.10/dist-packages (from deprecated->dv) (1.14.1)\n"
50 | ]
51 | }
52 | ]
53 | },
54 | {
55 | "cell_type": "code",
56 | "source": [
57 | "from google.colab import drive\n",
58 | "drive.mount('/content/drive')"
59 | ],
60 | "metadata": {
61 | "colab": {
62 | "base_uri": "https://localhost:8080/"
63 | },
64 | "id": "33wXv7Xysa4J",
65 | "outputId": "82860d25-7414-4eef-99dd-bcde48aca32d"
66 | },
67 | "execution_count": null,
68 | "outputs": [
69 | {
70 | "output_type": "stream",
71 | "name": "stdout",
72 | "text": [
73 | "Mounted at /content/drive\n"
74 | ]
75 | }
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "source": [
81 | "\n",
82 | "EVENT_PATH = \"/content/drive/MyDrive/driving_346x260_noise_shot_dark_5p3Hz.txt\"\n",
83 | "\n",
84 | "OUTPUT = \"/content/\"\n",
85 | "\n",
86 | "# Filtering parameters\n",
87 | "REFRACTORY_PERIOD = 1000 # in us\n",
88 | "NN_WINDOW = 8000 # in us\n",
89 | "\n",
90 | "# DAVIS Camera's Dimension\n",
91 | "HEIGHT = 260\n",
92 | "WIDTH = 346\n",
93 | "\n",
94 | "class Events(object):\n",
95 | " def __init__(self, num_events: int, width: int, height: int) -> np.ndarray:\n",
96 | " # events contains the following index:\n",
97 | " # t: the timestamp of the event.\n",
98 | " # x: the x position of the event.\n",
99 | " # y: the y position of the event.\n",
100 | " # p: the polarity of the event.\n",
101 | " self.events = np.zeros((num_events), dtype=[(\"t\", np.uint64), (\"x\", np.uint16), (\"y\", np.uint16), (\"p\", np.bool_), (\"s\", np.bool_)])\n",
102 | " self.width = width\n",
103 | " self.height = height\n",
104 | " self.num_events = num_events\n",
105 | "\n",
106 | "# Read event data from file\n",
107 | "def process_text_file(filename: str) -> Events:\n",
108 | " with open(filename, 'r',buffering=4000000) as f:\n",
109 | " num_events = 0\n",
110 | " for _ in f:\n",
111 | " num_events += 1\n",
112 | "\n",
113 | "\n",
114 | " print(\"!!!!!\",num_events)\n",
115 | " events = Events(num_events, WIDTH, HEIGHT)\n",
116 | "\n",
117 | " with open(filename, 'r',buffering=4000000) as f:\n",
118 | " for i, line in enumerate(tqdm(f)):\n",
119 | " event = line.split('\\t')\n",
120 | " if len(event) != 5: print(\"!!!!!!!!!\")\n",
121 | " assert len(event) == 5\n",
122 | " events.events[i][\"x\"], events.events[i][\"y\"],events.events[i][\"t\"], = int(event[0])-1, int(event[1])-1,int(event[3]) #*1e6\n",
123 | " events.events[i][\"p\"] = True if int(event[2]) == 1 else False\n",
124 | " events.events[i][\"s\"] = int(event[4])\n",
125 | " #if(i==100): break\n",
126 | "\n",
127 | " return events\n",
128 | "\n",
129 | "\n",
130 | "\n",
131 | "# Spatiotemporal Correlation Filtering (STCF)\n",
132 | "def Spatiotemporal_Correlation_Filter(event_array: Events, time_window: int=200, k: int=1):\n",
133 | " TP,TN,FP,FN=0,0,0,0\n",
134 | " max_x, max_y = event_array.width - 1, event_array.height - 1\n",
135 | " t0 = np.ones((event_array.height, event_array.width)) - time_window - 1\n",
136 | " x_prev, y_prev, p_prev= 0, 0, 0,\n",
137 | " valid_indices = np.ones(event_array.num_events, dtype=np.bool_)\n",
138 | "\n",
139 | " for i, e in tqdm(enumerate(event_array.events)): #tqdm: process bar; // i is the index, e are thhe content(will go through each)\n",
140 | " count=0\n",
141 | " ts, x, y, p = e[\"t\"], e[\"x\"], e[\"y\"], e[\"p\"]\n",
142 | "\n",
143 | " if x_prev != x or y_prev != y or p_prev != p: #if install the first event, then not go into if () condition\n",
144 | " t0[y][x] = -time_window\n",
145 | " min_x_sub = max(0, x-1)\n",
146 | " max_x_sub = min(max_x, x+1)\n",
147 | " min_y_sub = max(0, y-1)\n",
148 | " max_y_sub = min(max_y, y+1)\n",
149 | "\n",
150 | " t0_temp = t0[min_y_sub:(max_y_sub+1), min_x_sub:(max_x_sub + 1)]\n",
151 | " for c in (ts-t0_temp.reshape(-1,1)):\n",
152 | " if c<= time_window: count+=1\n",
153 | "\n",
154 | "\n",
155 | " if count< k:\n",
156 | " valid_indices[i] = 0 #indixcate each event to tell nosie or signal\n",
157 | " if valid_indices[i]==1 and e[\"s\"]==1: TP+=1\n",
158 | " if valid_indices[i]==0 and e[\"s\"]==0: TN+=1\n",
159 | " if valid_indices[i]==1 and e[\"s\"]==0: FP+=1\n",
160 | " if valid_indices[i]==0 and e[\"s\"]==1: FN+=1\n",
161 | "\n",
162 | " t0[y][x], x_prev, y_prev, p_prev = ts, x, y, p #always update the timestamp\n",
163 | " print()\n",
164 | " print(\"TP\",TP)\n",
165 | " print(\"TN\",TN)\n",
166 | " print(\"FP\",FP)\n",
167 | " print(\"FN\",FN)\n",
168 | " with open('/content/drive/MyDrive/myfile.txt', 'a') as f:\n",
169 | " #f.writelines('!!k=0'+str(k)+'\\n')\n",
170 | " s=str(TP)+'\\t'+str(TN)+'\\t'+str(FP)+'\\t'+str(FN)+'\\n'\n",
171 | " f.writelines(s)\n",
172 | "\n",
173 | " return event_array.events[valid_indices], np.count_nonzero(valid_indices == True)\n",
174 | "\n",
175 | "\n",
176 | "\n",
177 | "if __name__ == \"__main__\":\n",
178 | " \"\"\"\n",
179 | " Generate Video from events\n",
180 | " \"\"\"\n",
181 | " current_events = process_text_file(EVENT_PATH)\n",
182 | " deepcopy = copy.deepcopy(current_events)\n",
183 | " for x in range(1):\n",
184 | " k=x+5\n",
185 | " print(\"!!!!! k=\",k)\n",
186 | " with open('/content/drive/MyDrive/myfile.txt', 'a') as f:\n",
187 | " f.writelines('!!k=0'+str(k)+'\\n')\n",
188 | "\n",
189 | " print()\n",
190 | " current_events = copy.deepcopy(deepcopy)\n",
191 | " print(2000)\n",
192 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 2000)\n",
193 | "\n",
194 | " print()\n",
195 | " current_events = copy.deepcopy(deepcopy)\n",
196 | " print(3000)\n",
197 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 3000)\n",
198 | "\n",
199 | " print()\n",
200 | " current_events = copy.deepcopy(deepcopy)\n",
201 | " print(4000)\n",
202 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 4000)\n",
203 | "\n",
204 | " print()\n",
205 | " current_events = copy.deepcopy(deepcopy)\n",
206 | " print(5000)\n",
207 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 5000)\n",
208 | "\n",
209 | " print()\n",
210 | " current_events = copy.deepcopy(deepcopy)\n",
211 | " print(6000)\n",
212 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 6000)\n",
213 | "\n",
214 | " print()\n",
215 | " current_events = copy.deepcopy(deepcopy)\n",
216 | " print(7000)\n",
217 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 7000)\n",
218 | "\n",
219 | " print()\n",
220 | " current_events = copy.deepcopy(deepcopy)\n",
221 | " print(8000)\n",
222 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 8000)\n",
223 | "\n",
224 | " print()\n",
225 | " current_events = copy.deepcopy(deepcopy)\n",
226 | " print(9000)\n",
227 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 9000)\n",
228 | "\n",
229 | " print()\n",
230 | " current_events = copy.deepcopy(deepcopy)\n",
231 | " print(10000)\n",
232 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 10000)\n",
233 | "\n",
234 | "\n",
235 | " print()\n",
236 | " current_events = copy.deepcopy(deepcopy)\n",
237 | " print(12000)\n",
238 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 12000)\n",
239 | "\n",
240 | " print()\n",
241 | " current_events = copy.deepcopy(deepcopy)\n",
242 | " print(13000)\n",
243 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 13000)\n",
244 | "\n",
245 | " print()\n",
246 | " current_events = copy.deepcopy(deepcopy)\n",
247 | " print(14000)\n",
248 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 14000)\n",
249 | "\n",
250 | " print()\n",
251 | " current_events = copy.deepcopy(deepcopy)\n",
252 | " print(15000)\n",
253 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 15000)\n",
254 | "\n",
255 | " print()\n",
256 | " current_events = copy.deepcopy(deepcopy)\n",
257 | " print(16000)\n",
258 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 16000)\n",
259 | "\n",
260 | " print()\n",
261 | " current_events = copy.deepcopy(deepcopy)\n",
262 | " print(17000)\n",
263 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 17000)\n",
264 | "\n",
265 | " print()\n",
266 | " current_events = copy.deepcopy(deepcopy)\n",
267 | " print(18000)\n",
268 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 18000)\n",
269 | "\n",
270 | " print()\n",
271 | " current_events = copy.deepcopy(deepcopy)\n",
272 | " print(19000)\n",
273 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 19000)\n",
274 | "\n",
275 | " print()\n",
276 | " current_events = copy.deepcopy(deepcopy)\n",
277 | " print(20000)\n",
278 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 20000)\n",
279 | "\n",
280 | " print()\n",
281 | " current_events = copy.deepcopy(deepcopy)\n",
282 | " print(22000)\n",
283 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 22000)\n",
284 | "\n",
285 | " print()\n",
286 | " current_events = copy.deepcopy(deepcopy)\n",
287 | " print(23000)\n",
288 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 23000)\n",
289 | "\n",
290 | " print()\n",
291 | " current_events = copy.deepcopy(deepcopy)\n",
292 | " print(24000)\n",
293 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 24000)\n",
294 | "\n",
295 | " print()\n",
296 | " current_events = copy.deepcopy(deepcopy)\n",
297 | " print(25000)\n",
298 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 25000)\n",
299 | "\n",
300 | "\n",
301 | " print()\n",
302 | " current_events = copy.deepcopy(deepcopy)\n",
303 | " print(26000)\n",
304 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 26000)\n",
305 | "\n",
306 | "\n",
307 | " print()\n",
308 | " current_events = copy.deepcopy(deepcopy)\n",
309 | " print(27000)\n",
310 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 27000)\n",
311 | "\n",
312 | "\n",
313 | " print()\n",
314 | " current_events = copy.deepcopy(deepcopy)\n",
315 | " print(28000)\n",
316 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 28000)\n",
317 | "\n",
318 | " print()\n",
319 | " current_events = copy.deepcopy(deepcopy)\n",
320 | " print(29000)\n",
321 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 29000)\n",
322 | "\n",
323 | " print()\n",
324 | " current_events = copy.deepcopy(deepcopy)\n",
325 | " print(30000)\n",
326 | " current_events.events, current_events.num_events =Spatiotemporal_Correlation_Filter(current_events, 30000)\n",
327 | "\n",
328 | " print()\n",
329 | " current_events = copy.deepcopy(deepcopy)\n",
330 | " print(32000)\n",
331 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 32000,k)\n",
332 | "\n",
333 | " print()\n",
334 | " current_events = copy.deepcopy(deepcopy)\n",
335 | " print(33000)\n",
336 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 33000,k)\n",
337 | "\n",
338 | " print()\n",
339 | " current_events = copy.deepcopy(deepcopy)\n",
340 | " print(34000)\n",
341 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 34000,k)\n",
342 | "\n",
343 | " print()\n",
344 | " current_events = copy.deepcopy(deepcopy)\n",
345 | " print(35000)\n",
346 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 35000,k)\n",
347 | "\n",
348 | " print()\n",
349 | " current_events = copy.deepcopy(deepcopy)\n",
350 | " print(36000)\n",
351 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 36000,k)\n",
352 | "\n",
353 | " print()\n",
354 | " current_events = copy.deepcopy(deepcopy)\n",
355 | " print(37000)\n",
356 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 37000,k)\n",
357 | "\n",
358 | " print()\n",
359 | " current_events = copy.deepcopy(deepcopy)\n",
360 | " print(38000)\n",
361 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 38000,k)\n",
362 | "\n",
363 | " print()\n",
364 | " current_events = copy.deepcopy(deepcopy)\n",
365 | " print(39000)\n",
366 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 39000,k)\n",
367 | "\n",
368 | " print()\n",
369 | " current_events = copy.deepcopy(deepcopy)\n",
370 | " print(40000)\n",
371 | " current_events.events, current_events.num_events = Spatiotemporal_Correlation_Filter(current_events, 40000,k)\n",
372 | "\n",
373 | "\n"
374 | ],
375 | "metadata": {
376 | "id": "uE6ffoKKumPJ",
377 | "colab": {
378 | "base_uri": "https://localhost:8080/"
379 | },
380 | "outputId": "1d007080-1930-48c3-fea3-8a3583e65f7b"
381 | },
382 | "execution_count": null,
383 | "outputs": [
384 | {
385 | "metadata": {
386 | "tags": null
387 | },
388 | "name": "stdout",
389 | "output_type": "stream",
390 | "text": [
391 | "!!!!! 6677980\n"
392 | ]
393 | },
394 | {
395 | "metadata": {
396 | "tags": null
397 | },
398 | "name": "stderr",
399 | "output_type": "stream",
400 | "text": [
401 | "6677980it [00:47, 140305.09it/s]\n"
402 | ]
403 | },
404 | {
405 | "metadata": {
406 | "tags": null
407 | },
408 | "name": "stdout",
409 | "output_type": "stream",
410 | "text": [
411 | "!!!!! k= 5\n",
412 | "\n",
413 | "2000\n"
414 | ]
415 | },
416 | {
417 | "metadata": {
418 | "tags": null
419 | },
420 | "name": "stderr",
421 | "output_type": "stream",
422 | "text": [
423 | "6677980it [08:36, 12936.00it/s]\n"
424 | ]
425 | },
426 | {
427 | "metadata": {
428 | "tags": null
429 | },
430 | "name": "stdout",
431 | "output_type": "stream",
432 | "text": [
433 | "\n",
434 | "TP 2259947\n",
435 | "TN 2449721\n",
436 | "FP 472660\n",
437 | "FN 1495634\n",
438 | "\n",
439 | "3000\n"
440 | ]
441 | },
442 | {
443 | "metadata": {
444 | "tags": null
445 | },
446 | "name": "stderr",
447 | "output_type": "stream",
448 | "text": [
449 | "6677980it [08:37, 12894.76it/s]\n"
450 | ]
451 | },
452 | {
453 | "metadata": {
454 | "tags": null
455 | },
456 | "name": "stdout",
457 | "output_type": "stream",
458 | "text": [
459 | "\n",
460 | "TP 2649564\n",
461 | "TN 2273499\n",
462 | "FP 648882\n",
463 | "FN 1106017\n",
464 | "\n",
465 | "4000\n"
466 | ]
467 | },
468 | {
469 | "metadata": {
470 | "tags": null
471 | },
472 | "name": "stderr",
473 | "output_type": "stream",
474 | "text": [
475 | "6677980it [08:42, 12776.87it/s]\n"
476 | ]
477 | },
478 | {
479 | "metadata": {
480 | "tags": null
481 | },
482 | "name": "stdout",
483 | "output_type": "stream",
484 | "text": [
485 | "\n",
486 | "TP 2899986\n",
487 | "TN 2121379\n",
488 | "FP 801002\n",
489 | "FN 855595\n",
490 | "\n",
491 | "5000\n"
492 | ]
493 | },
494 | {
495 | "metadata": {
496 | "tags": null
497 | },
498 | "name": "stderr",
499 | "output_type": "stream",
500 | "text": [
501 | "6677980it [08:15, 13481.40it/s]\n"
502 | ]
503 | },
504 | {
505 | "metadata": {
506 | "tags": null
507 | },
508 | "name": "stdout",
509 | "output_type": "stream",
510 | "text": [
511 | "\n",
512 | "TP 3071911\n",
513 | "TN 1987733\n",
514 | "FP 934648\n",
515 | "FN 683670\n",
516 | "\n",
517 | "6000\n"
518 | ]
519 | },
520 | {
521 | "metadata": {
522 | "tags": null
523 | },
524 | "name": "stderr",
525 | "output_type": "stream",
526 | "text": [
527 | "6677980it [08:12, 13561.44it/s]\n"
528 | ]
529 | },
530 | {
531 | "metadata": {
532 | "tags": null
533 | },
534 | "name": "stdout",
535 | "output_type": "stream",
536 | "text": [
537 | "\n",
538 | "TP 3197019\n",
539 | "TN 1868130\n",
540 | "FP 1054251\n",
541 | "FN 558562\n",
542 | "\n",
543 | "7000\n"
544 | ]
545 | },
546 | {
547 | "metadata": {
548 | "tags": null
549 | },
550 | "name": "stderr",
551 | "output_type": "stream",
552 | "text": [
553 | "6677980it [08:18, 13403.81it/s]\n"
554 | ]
555 | },
556 | {
557 | "metadata": {
558 | "tags": null
559 | },
560 | "name": "stdout",
561 | "output_type": "stream",
562 | "text": [
563 | "\n",
564 | "TP 3290274\n",
565 | "TN 1759928\n",
566 | "FP 1162453\n",
567 | "FN 465307\n",
568 | "\n",
569 | "8000\n"
570 | ]
571 | },
572 | {
573 | "metadata": {
574 | "tags": null
575 | },
576 | "name": "stderr",
577 | "output_type": "stream",
578 | "text": [
579 | "6677980it [08:14, 13512.00it/s]\n"
580 | ]
581 | },
582 | {
583 | "metadata": {
584 | "tags": null
585 | },
586 | "name": "stdout",
587 | "output_type": "stream",
588 | "text": [
589 | "\n",
590 | "TP 3361815\n",
591 | "TN 1661781\n",
592 | "FP 1260600\n",
593 | "FN 393766\n",
594 | "\n",
595 | "9000\n"
596 | ]
597 | },
598 | {
599 | "metadata": {
600 | "tags": null
601 | },
602 | "name": "stderr",
603 | "output_type": "stream",
604 | "text": [
605 | "6677980it [08:16, 13439.62it/s]\n"
606 | ]
607 | },
608 | {
609 | "metadata": {
610 | "tags": null
611 | },
612 | "name": "stdout",
613 | "output_type": "stream",
614 | "text": [
615 | "\n",
616 | "TP 3417816\n",
617 | "TN 1571867\n",
618 | "FP 1350514\n",
619 | "FN 337765\n",
620 | "\n",
621 | "10000\n"
622 | ]
623 | },
624 | {
625 | "metadata": {
626 | "tags": null
627 | },
628 | "name": "stderr",
629 | "output_type": "stream",
630 | "text": [
631 | "6677980it [08:14, 13517.46it/s]\n"
632 | ]
633 | },
634 | {
635 | "metadata": {
636 | "tags": null
637 | },
638 | "name": "stdout",
639 | "output_type": "stream",
640 | "text": [
641 | "\n",
642 | "TP 3462989\n",
643 | "TN 1488690\n",
644 | "FP 1433691\n",
645 | "FN 292592\n",
646 | "\n",
647 | "12000\n"
648 | ]
649 | },
650 | {
651 | "metadata": {
652 | "tags": null
653 | },
654 | "name": "stderr",
655 | "output_type": "stream",
656 | "text": [
657 | "6677980it [08:12, 13569.23it/s]\n"
658 | ]
659 | },
660 | {
661 | "metadata": {
662 | "tags": null
663 | },
664 | "name": "stdout",
665 | "output_type": "stream",
666 | "text": [
667 | "\n",
668 | "TP 3529929\n",
669 | "TN 1339888\n",
670 | "FP 1582493\n",
671 | "FN 225652\n",
672 | "\n",
673 | "13000\n"
674 | ]
675 | },
676 | {
677 | "metadata": {
678 | "tags": null
679 | },
680 | "name": "stderr",
681 | "output_type": "stream",
682 | "text": [
683 | "6677980it [08:11, 13595.35it/s]\n"
684 | ]
685 | },
686 | {
687 | "metadata": {
688 | "tags": null
689 | },
690 | "name": "stdout",
691 | "output_type": "stream",
692 | "text": [
693 | "\n",
694 | "TP 3555485\n",
695 | "TN 1273421\n",
696 | "FP 1648960\n",
697 | "FN 200096\n",
698 | "\n",
699 | "14000\n"
700 | ]
701 | },
702 | {
703 | "metadata": {
704 | "tags": null
705 | },
706 | "name": "stderr",
707 | "output_type": "stream",
708 | "text": [
709 | "6677980it [08:16, 13462.93it/s]\n"
710 | ]
711 | },
712 | {
713 | "metadata": {
714 | "tags": null
715 | },
716 | "name": "stdout",
717 | "output_type": "stream",
718 | "text": [
719 | "\n",
720 | "TP 3576698\n",
721 | "TN 1210932\n",
722 | "FP 1711449\n",
723 | "FN 178883\n",
724 | "\n",
725 | "15000\n"
726 | ]
727 | },
728 | {
729 | "metadata": {
730 | "tags": null
731 | },
732 | "name": "stderr",
733 | "output_type": "stream",
734 | "text": [
735 | "6677980it [08:22, 13287.20it/s]\n"
736 | ]
737 | },
738 | {
739 | "metadata": {
740 | "tags": null
741 | },
742 | "name": "stdout",
743 | "output_type": "stream",
744 | "text": [
745 | "\n",
746 | "TP 3595112\n",
747 | "TN 1152568\n",
748 | "FP 1769813\n",
749 | "FN 160469\n",
750 | "\n",
751 | "16000\n"
752 | ]
753 | },
754 | {
755 | "metadata": {
756 | "tags": null
757 | },
758 | "name": "stderr",
759 | "output_type": "stream",
760 | "text": [
761 | "6677980it [08:17, 13423.36it/s]\n"
762 | ]
763 | },
764 | {
765 | "metadata": {
766 | "tags": null
767 | },
768 | "name": "stdout",
769 | "output_type": "stream",
770 | "text": [
771 | "\n",
772 | "TP 3610926\n",
773 | "TN 1097947\n",
774 | "FP 1824434\n",
775 | "FN 144655\n",
776 | "\n",
777 | "17000\n"
778 | ]
779 | },
780 | {
781 | "metadata": {
782 | "tags": null
783 | },
784 | "name": "stderr",
785 | "output_type": "stream",
786 | "text": [
787 | "6677980it [08:18, 13401.61it/s]\n"
788 | ]
789 | },
790 | {
791 | "metadata": {
792 | "tags": null
793 | },
794 | "name": "stdout",
795 | "output_type": "stream",
796 | "text": [
797 | "\n",
798 | "TP 3624617\n",
799 | "TN 1046306\n",
800 | "FP 1876075\n",
801 | "FN 130964\n",
802 | "\n",
803 | "18000\n"
804 | ]
805 | },
806 | {
807 | "metadata": {
808 | "tags": null
809 | },
810 | "name": "stderr",
811 | "output_type": "stream",
812 | "text": [
813 | "6677980it [08:12, 13559.96it/s]\n"
814 | ]
815 | },
816 | {
817 | "metadata": {
818 | "tags": null
819 | },
820 | "name": "stdout",
821 | "output_type": "stream",
822 | "text": [
823 | "\n",
824 | "TP 3636734\n",
825 | "TN 998027\n",
826 | "FP 1924354\n",
827 | "FN 118847\n",
828 | "\n",
829 | "19000\n"
830 | ]
831 | },
832 | {
833 | "metadata": {
834 | "tags": null
835 | },
836 | "name": "stderr",
837 | "output_type": "stream",
838 | "text": [
839 | "6677980it [08:13, 13527.93it/s]\n"
840 | ]
841 | },
842 | {
843 | "metadata": {
844 | "tags": null
845 | },
846 | "name": "stdout",
847 | "output_type": "stream",
848 | "text": [
849 | "\n",
850 | "TP 3647112\n",
851 | "TN 952067\n",
852 | "FP 1970314\n",
853 | "FN 108469\n",
854 | "\n",
855 | "20000\n"
856 | ]
857 | },
858 | {
859 | "metadata": {
860 | "tags": null
861 | },
862 | "name": "stderr",
863 | "output_type": "stream",
864 | "text": [
865 | "6677980it [08:20, 13339.58it/s]\n"
866 | ]
867 | },
868 | {
869 | "metadata": {
870 | "tags": null
871 | },
872 | "name": "stdout",
873 | "output_type": "stream",
874 | "text": [
875 | "\n",
876 | "TP 3656599\n",
877 | "TN 909122\n",
878 | "FP 2013259\n",
879 | "FN 98982\n",
880 | "\n",
881 | "22000\n"
882 | ]
883 | },
884 | {
885 | "metadata": {
886 | "tags": null
887 | },
888 | "name": "stderr",
889 | "output_type": "stream",
890 | "text": [
891 | "6677980it [08:19, 13382.72it/s]\n"
892 | ]
893 | },
894 | {
895 | "metadata": {
896 | "tags": null
897 | },
898 | "name": "stdout",
899 | "output_type": "stream",
900 | "text": [
901 | "\n",
902 | "TP 3672067\n",
903 | "TN 830193\n",
904 | "FP 2092188\n",
905 | "FN 83514\n",
906 | "\n",
907 | "23000\n"
908 | ]
909 | },
910 | {
911 | "metadata": {
912 | "tags": null
913 | },
914 | "name": "stderr",
915 | "output_type": "stream",
916 | "text": [
917 | "6677980it [08:20, 13341.02it/s]\n"
918 | ]
919 | },
920 | {
921 | "metadata": {
922 | "tags": null
923 | },
924 | "name": "stdout",
925 | "output_type": "stream",
926 | "text": [
927 | "\n",
928 | "TP 3678631\n",
929 | "TN 794172\n",
930 | "FP 2128209\n",
931 | "FN 76950\n",
932 | "\n",
933 | "24000\n"
934 | ]
935 | },
936 | {
937 | "metadata": {
938 | "tags": null
939 | },
940 | "name": "stderr",
941 | "output_type": "stream",
942 | "text": [
943 | "6677980it [08:14, 13499.32it/s]\n"
944 | ]
945 | },
946 | {
947 | "metadata": {
948 | "tags": null
949 | },
950 | "name": "stdout",
951 | "output_type": "stream",
952 | "text": [
953 | "\n",
954 | "TP 3684522\n",
955 | "TN 759636\n",
956 | "FP 2162745\n",
957 | "FN 71059\n",
958 | "\n",
959 | "25000\n"
960 | ]
961 | },
962 | {
963 | "metadata": {
964 | "tags": null
965 | },
966 | "name": "stderr",
967 | "output_type": "stream",
968 | "text": [
969 | "6677980it [08:15, 13485.51it/s]\n"
970 | ]
971 | },
972 | {
973 | "metadata": {
974 | "tags": null
975 | },
976 | "name": "stdout",
977 | "output_type": "stream",
978 | "text": [
979 | "\n",
980 | "TP 3689847\n",
981 | "TN 727442\n",
982 | "FP 2194939\n",
983 | "FN 65734\n",
984 | "\n",
985 | "26000\n"
986 | ]
987 | },
988 | {
989 | "metadata": {
990 | "tags": null
991 | },
992 | "name": "stderr",
993 | "output_type": "stream",
994 | "text": [
995 | "6677980it [08:15, 13464.62it/s]\n"
996 | ]
997 | },
998 | {
999 | "metadata": {
1000 | "tags": null
1001 | },
1002 | "name": "stdout",
1003 | "output_type": "stream",
1004 | "text": [
1005 | "\n",
1006 | "TP 3694627\n",
1007 | "TN 696683\n",
1008 | "FP 2225698\n",
1009 | "FN 60954\n",
1010 | "\n",
1011 | "27000\n"
1012 | ]
1013 | },
1014 | {
1015 | "metadata": {
1016 | "tags": null
1017 | },
1018 | "name": "stderr",
1019 | "output_type": "stream",
1020 | "text": [
1021 | "6677980it [08:20, 13355.30it/s]\n"
1022 | ]
1023 | },
1024 | {
1025 | "metadata": {
1026 | "tags": null
1027 | },
1028 | "name": "stdout",
1029 | "output_type": "stream",
1030 | "text": [
1031 | "\n",
1032 | "TP 3698843\n",
1033 | "TN 667677\n",
1034 | "FP 2254704\n",
1035 | "FN 56738\n",
1036 | "\n",
1037 | "28000\n"
1038 | ]
1039 | },
1040 | {
1041 | "metadata": {
1042 | "tags": null
1043 | },
1044 | "name": "stderr",
1045 | "output_type": "stream",
1046 | "text": [
1047 | "6677980it [08:17, 13416.31it/s]\n"
1048 | ]
1049 | },
1050 | {
1051 | "metadata": {
1052 | "tags": null
1053 | },
1054 | "name": "stdout",
1055 | "output_type": "stream",
1056 | "text": [
1057 | "\n",
1058 | "TP 3702820\n",
1059 | "TN 639967\n",
1060 | "FP 2282414\n",
1061 | "FN 52761\n",
1062 | "\n",
1063 | "29000\n"
1064 | ]
1065 | },
1066 | {
1067 | "metadata": {
1068 | "tags": null
1069 | },
1070 | "name": "stderr",
1071 | "output_type": "stream",
1072 | "text": [
1073 | "6677980it [08:17, 13420.64it/s]\n"
1074 | ]
1075 | },
1076 | {
1077 | "metadata": {
1078 | "tags": null
1079 | },
1080 | "name": "stdout",
1081 | "output_type": "stream",
1082 | "text": [
1083 | "\n",
1084 | "TP 3706412\n",
1085 | "TN 614027\n",
1086 | "FP 2308354\n",
1087 | "FN 49169\n",
1088 | "\n",
1089 | "30000\n"
1090 | ]
1091 | },
1092 | {
1093 | "metadata": {
1094 | "tags": null
1095 | },
1096 | "name": "stderr",
1097 | "output_type": "stream",
1098 | "text": [
1099 | "6677980it [08:19, 13361.18it/s]\n"
1100 | ]
1101 | },
1102 | {
1103 | "metadata": {
1104 | "tags": null
1105 | },
1106 | "name": "stdout",
1107 | "output_type": "stream",
1108 | "text": [
1109 | "\n",
1110 | "TP 3709653\n",
1111 | "TN 589338\n",
1112 | "FP 2333043\n",
1113 | "FN 45928\n",
1114 | "\n",
1115 | "32000\n"
1116 | ]
1117 | },
1118 | {
1119 | "metadata": {
1120 | "tags": null
1121 | },
1122 | "name": "stderr",
1123 | "output_type": "stream",
1124 | "text": [
1125 | "6677980it [08:21, 13315.81it/s]\n"
1126 | ]
1127 | },
1128 | {
1129 | "metadata": {
1130 | "tags": null
1131 | },
1132 | "name": "stdout",
1133 | "output_type": "stream",
1134 | "text": [
1135 | "\n",
1136 | "TP 2527592\n",
1137 | "TN 2518169\n",
1138 | "FP 404212\n",
1139 | "FN 1227989\n",
1140 | "\n",
1141 | "33000\n"
1142 | ]
1143 | },
1144 | {
1145 | "metadata": {
1146 | "tags": null
1147 | },
1148 | "name": "stderr",
1149 | "output_type": "stream",
1150 | "text": [
1151 | "6677980it [08:19, 13369.42it/s]\n"
1152 | ]
1153 | },
1154 | {
1155 | "metadata": {
1156 | "tags": null
1157 | },
1158 | "name": "stdout",
1159 | "output_type": "stream",
1160 | "text": [
1161 | "\n",
1162 | "TP 2557446\n",
1163 | "TN 2503373\n",
1164 | "FP 419008\n",
1165 | "FN 1198135\n",
1166 | "\n",
1167 | "34000\n"
1168 | ]
1169 | },
1170 | {
1171 | "metadata": {
1172 | "tags": null
1173 | },
1174 | "name": "stderr",
1175 | "output_type": "stream",
1176 | "text": [
1177 | "6677980it [08:29, 13113.63it/s]\n"
1178 | ]
1179 | },
1180 | {
1181 | "metadata": {
1182 | "tags": null
1183 | },
1184 | "name": "stdout",
1185 | "output_type": "stream",
1186 | "text": [
1187 | "\n",
1188 | "TP 2586469\n",
1189 | "TN 2488612\n",
1190 | "FP 433769\n",
1191 | "FN 1169112\n",
1192 | "\n",
1193 | "35000\n"
1194 | ]
1195 | },
1196 | {
1197 | "metadata": {
1198 | "tags": null
1199 | },
1200 | "name": "stderr",
1201 | "output_type": "stream",
1202 | "text": [
1203 | "6677980it [08:20, 13338.28it/s]\n"
1204 | ]
1205 | },
1206 | {
1207 | "metadata": {
1208 | "tags": null
1209 | },
1210 | "name": "stdout",
1211 | "output_type": "stream",
1212 | "text": [
1213 | "\n",
1214 | "TP 2614523\n",
1215 | "TN 2474102\n",
1216 | "FP 448279\n",
1217 | "FN 1141058\n",
1218 | "\n",
1219 | "36000\n"
1220 | ]
1221 | },
1222 | {
1223 | "metadata": {
1224 | "tags": null
1225 | },
1226 | "name": "stderr",
1227 | "output_type": "stream",
1228 | "text": [
1229 | "6677980it [08:21, 13326.92it/s]\n"
1230 | ]
1231 | },
1232 | {
1233 | "metadata": {
1234 | "tags": null
1235 | },
1236 | "name": "stdout",
1237 | "output_type": "stream",
1238 | "text": [
1239 | "\n",
1240 | "TP 2641082\n",
1241 | "TN 2459650\n",
1242 | "FP 462731\n",
1243 | "FN 1114499\n",
1244 | "\n",
1245 | "37000\n"
1246 | ]
1247 | },
1248 | {
1249 | "metadata": {
1250 | "tags": null
1251 | },
1252 | "name": "stderr",
1253 | "output_type": "stream",
1254 | "text": [
1255 | "6677980it [08:27, 13159.32it/s]\n"
1256 | ]
1257 | },
1258 | {
1259 | "metadata": {
1260 | "tags": null
1261 | },
1262 | "name": "stdout",
1263 | "output_type": "stream",
1264 | "text": [
1265 | "\n",
1266 | "TP 2666403\n",
1267 | "TN 2445086\n",
1268 | "FP 477295\n",
1269 | "FN 1089178\n",
1270 | "\n",
1271 | "38000\n"
1272 | ]
1273 | },
1274 | {
1275 | "metadata": {
1276 | "tags": null
1277 | },
1278 | "name": "stderr",
1279 | "output_type": "stream",
1280 | "text": [
1281 | "6677980it [08:17, 13411.16it/s]\n"
1282 | ]
1283 | },
1284 | {
1285 | "metadata": {
1286 | "tags": null
1287 | },
1288 | "name": "stdout",
1289 | "output_type": "stream",
1290 | "text": [
1291 | "\n",
1292 | "TP 2690985\n",
1293 | "TN 2430728\n",
1294 | "FP 491653\n",
1295 | "FN 1064596\n",
1296 | "\n",
1297 | "39000\n"
1298 | ]
1299 | },
1300 | {
1301 | "metadata": {
1302 | "tags": null
1303 | },
1304 | "name": "stderr",
1305 | "output_type": "stream",
1306 | "text": [
1307 | "6677980it [08:22, 13293.73it/s]\n"
1308 | ]
1309 | },
1310 | {
1311 | "metadata": {
1312 | "tags": null
1313 | },
1314 | "name": "stdout",
1315 | "output_type": "stream",
1316 | "text": [
1317 | "\n",
1318 | "TP 2714975\n",
1319 | "TN 2416257\n",
1320 | "FP 506124\n",
1321 | "FN 1040606\n",
1322 | "\n",
1323 | "40000\n"
1324 | ]
1325 | },
1326 | {
1327 | "output_type": "stream",
1328 | "name": "stderr",
1329 | "text": [
1330 | "6677980it [08:18, 13383.54it/s]\n"
1331 | ]
1332 | },
1333 | {
1334 | "output_type": "stream",
1335 | "name": "stdout",
1336 | "text": [
1337 | "\n",
1338 | "TP 2737776\n",
1339 | "TN 2401869\n",
1340 | "FP 520512\n",
1341 | "FN 1017805\n"
1342 | ]
1343 | }
1344 | ]
1345 | },
1346 | {
1347 | "cell_type": "code",
1348 | "execution_count": null,
1349 | "metadata": {
1350 | "id": "u8IIqcSQuAf2"
1351 | },
1352 | "outputs": [],
1353 | "source": []
1354 | }
1355 | ]
1356 | }
--------------------------------------------------------------------------------
/BAfiltering.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "provenance": []
7 | },
8 | "kernelspec": {
9 | "name": "python3",
10 | "display_name": "Python 3"
11 | },
12 | "language_info": {
13 | "name": "python"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "source": [
20 | "The program is to capture the specific frame"
21 | ],
22 | "metadata": {
23 | "id": "9sLRPohGnxkb"
24 | }
25 | },
26 | {
27 | "cell_type": "code",
28 | "source": [
29 | "from google.colab import drive\n",
30 | "drive.mount('/content/drive')"
31 | ],
32 | "metadata": {
33 | "id": "EiZ59ajeFHDu",
34 | "colab": {
35 | "base_uri": "https://localhost:8080/"
36 | },
37 | "outputId": "93f9bd77-c4f1-4948-8095-8c4e508f6cd8"
38 | },
39 | "execution_count": null,
40 | "outputs": [
41 | {
42 | "output_type": "stream",
43 | "name": "stdout",
44 | "text": [
45 | "Mounted at /content/drive\n"
46 | ]
47 | }
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": null,
53 | "metadata": {
54 | "id": "roO6Wq5wVdBc"
55 | },
56 | "outputs": [],
57 | "source": [
58 | "from re import X\n",
59 | "import cv2 as cv2\n",
60 | "import math\n",
61 | "import numpy as np\n",
62 | "from google.colab.patches import cv2_imshow\n",
63 | "\n",
64 | "vlist=[\"00\",\"1000\",\"2000\",\"3000\",\"4000\",\"5000\",\"6000\",\"7000\",\"8000\",\"9000\",\"10000\",\"11000\",\"12000\",\"13000\",\"14000\",\"15000\",\"16000\",\"17000\",\"18000\",\"19000\",\"20000\",\"both_none\"]\n",
65 | "image_path=\"/content/drive/MyDrive/FYP/BEFiltering_image/\"\n",
66 | "for x in vlist:\n",
67 | " path=\"/content/drive/MyDrive/FYP/BEFiltering/BEfiltered_\"+x+\".avi\"\n",
68 | " vid= cv2.VideoCapture(path)\n",
69 | " currentframe=0;\n",
70 | " count=0\n",
71 | " while(1):\n",
72 | " success, frame = vid.read()\n",
73 | " #current position of video file in milliseconds\n",
74 | " vid.set(cv2.CAP_PROP_POS_MSEC,(count*1000))\n",
75 | " if(currentframe==5):\n",
76 | " cv2.imwrite(image_path+\"frame\"+x+\"_\"+str(currentframe) + \"sec.jpg\", frame)\n",
77 | " #print(\"captureframe:\")\n",
78 | " #print(frame.size)\n",
79 | " #cv2_imshow(frame)\n",
80 | " #print(\"frame\"+x)\n",
81 | " break;\n",
82 | " currentframe=currentframe+1\n",
83 | " count=count+1\n",
84 | " #print(frame)"
85 | ]
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "source": [],
90 | "metadata": {
91 | "id": "uMS_zdEgn7sx"
92 | }
93 | },
94 | {
95 | "cell_type": "code",
96 | "source": [
97 | "import cv2\n",
98 | "import math\n",
99 | "import numpy as np\n",
100 | "from google.colab.patches import cv2_imshow\n",
101 | "import matplotlib.pyplot as plt\n",
102 | "\n",
103 | "\n",
104 | "imagelist=[\"00\",\"1000\",\"2000\",\"3000\",\"4000\",\"5000\",\"6000\",\"7000\",\"8000\",\"9000\",\"10000\",\"11000\",\"12000\",\"13000\",\"14000\",\"15000\",\"16000\",\"17000\",\"18000\",\"19000\",\"20000\"]\n",
105 | "image_path=\"/content/drive/MyDrive/FYP/BEFiltering_image/\"\n",
106 | "currentframe=0\n",
107 | "PSNR=0\n",
108 | "result_mse=[]\n",
109 | "result_psnr=[]\n",
110 | "# load the input images\n",
111 | "img1 = cv2.imread(image_path+'frameboth_none_5sec.jpg')\n",
112 | "#img1 = cv2.imread(image_path+'frame_5sec.jpg')\n",
113 | "img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)\n",
114 | "\n",
115 | "for x in imagelist:\n",
116 | " if(x==\"0\"):\n",
117 | " continue\n",
118 | " img2 = cv2.imread(image_path+'frame'+x+'_5sec.jpg')\n",
119 | " # convert the images to grayscale\n",
120 | " img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)\n",
121 | "\n",
122 | " # define the function to compute MSE between two images\n",
123 | " def mse(img1, img2):\n",
124 | " h, w = img1.shape\n",
125 | " diff = cv2.subtract(img1, img2)\n",
126 | " err = np.sum(diff**2)\n",
127 | " mse = err/(float(h*w))\n",
128 | " return mse, diff\n",
129 | "\n",
130 | " def psnr(img1,img2,mse):\n",
131 | " Psnr=0\n",
132 | " max_pixel = 255.0\n",
133 | " if(mse==0):\n",
134 | " return Psnr\n",
135 | " Psnr = 20 * math.log10(max_pixel / math.sqrt(mse))\n",
136 | " return Psnr\n",
137 | "\n",
138 | " error, diff = mse(img1, img2)\n",
139 | " PSNR=psnr(img1, img2, error)\n",
140 | " result_mse.append(error)\n",
141 | " result_psnr.append(PSNR)\n",
142 | " #print(\"Image matching Error between the two images (frame)\"+x+\":\",round(error,4))\n",
143 | " #print(\"Peak Signal-to-Noise Ratio between the two images:\",round(PSNR,4),\"db\")\n",
144 | " #cv2_imshow(img1)\n",
145 | " #cv2_imshow(img2)\n",
146 | " #cv2_imshow(diff)\n",
147 | "\n",
148 | "imagelist = [int(i) for i in imagelist]\n",
149 | "x=imagelist\n",
150 | "y=result_psnr\n",
151 | "# plotting points as a scatter plot\n",
152 | "plt.scatter(x, y, label= \"stars\", color= \"red\", marker= \"*\", s=2)\n",
153 | "\n",
154 | "# x-axis label\n",
155 | "plt.xlabel('NN_WINDOW')\n",
156 | "# frequency label\n",
157 | "plt.ylabel('Result_PSNR')\n",
158 | "# plot title\n",
159 | "plt.title('Background Activity Filtering')\n",
160 | "\n",
161 | "plt.legend()\n",
162 | "plt.show()\n",
163 | "\n"
164 | ],
165 | "metadata": {
166 | "id": "-J7O4oaNitoJ",
167 | "colab": {
168 | "base_uri": "https://localhost:8080/",
169 | "height": 472
170 | },
171 | "outputId": "3eb4bdff-49ab-428a-936c-53ecc8afb90c"
172 | },
173 | "execution_count": null,
174 | "outputs": [
175 | {
176 | "output_type": "display_data",
177 | "data": {
178 | "text/plain": [
179 | ""
180 | ],
181 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjMAAAHHCAYAAABKudlQAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAABGwklEQVR4nO3deVwVZf//8fcB4QCyuSGSqLjnkpoWobklhVqWaeZWopndeWtlWqm3lUvlmpZ5l3XbnVhqtrnctruRqWhpkrdZ3kpu5ZoLoCgiXL8//HJ+HlnkIHAYfT0fj/PIM3Odaz5zBph3M9fM2IwxRgAAABbl4e4CAAAArgZhBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBigBNWrU0D333OPuMtzGZrNp3Lhx7i7DIS4uTjabTXv37nX5szVq1FD//v2LvCZX5bYO7dq1U7t27UqshnHjxslms5XY8oC8EGZw3cj+43/pKyQkRO3bt9dXX33l7vJwiV9//VU2m00+Pj46depUofuZOHGili5dWmR15WbHjh0aN25coYJRfvr375/j5zX79fXXXxeoj4MHD2rcuHFKTEws0tqA0qaMuwsAStqECRMUEREhY4yOHDmiuLg4de7cWcuXL7+uj56UJvPnz1doaKhOnjypTz/9VI8++mih+pk4caIeeOABde3a1Wn6ww8/rF69eslut7vc586dO+Xh8f//P3DHjh0aP3682rVrpxo1ahSqzrzY7Xa9++67OaY3adJEd9555xXX4eDBgxo/frxq1Kihpk2bFmltkvT8889r1KhRRd4v4CrCDK47nTp1UosWLRzvBw4cqMqVK+vDDz+0dJg5c+aMypYt6+4yrpoxRgsXLlSfPn20Z88eLViwoNBhJi+enp7y9PQs1GcLE4AKq0yZMnrooYfynF/Ydbha2T9rZcqUUZky7EbgfpxmwnUvODhYvr6+Of4ov/rqq2rZsqUqVKggX19fNW/eXJ9++mmufcyfP1+33nqr/Pz8VK5cObVp00bffvttvsudN2+eypQpo2effdYx7fjx43r44YcVGBio4OBgxcbG6ueff5bNZlNcXJyjXf/+/eXv76+kpCR17txZAQEB6tu3r6SLO5oRI0YoPDxcdrtd9erV06uvvipjjOPze/fuzdFntsvHt2SPi9i9e7f69++v4OBgBQUFacCAAUpLS3P6bHp6up5++mlVqlRJAQEBuvfee/XHH3/k+z1cbv369dq7d6969eqlXr16ae3atbn2kZWVpZkzZ6px48by8fFRpUqV1LFjR23evNmxHmfOnNG8efMcp2eyx7pcPt7knnvuUc2aNXOtJyoqyin8XjpmJi4uTj169JAktW/f3rGc+Ph4xcbGqmLFisrIyMjR51133aV69eq59L1c7krjfuLj43XLLbdIkgYMGOCo7dJtvmnTJnXs2FFBQUHy8/NT27ZttX79eqd+srf/jh071KdPH5UrV063336707xL2Ww2DR06VEuXLlWjRo1kt9vVsGHDXE+NxcfHq0WLFvLx8VGtWrX0zjvvMA4HhUKYwXUnOTlZf/31l44dO6ZffvlFgwcP1unTp3P8H/DMmTPVrFkzTZgwQRMnTlSZMmXUo0cPffHFF07txo8fr4cfflheXl6aMGGCxo8fr/DwcK1evTrPGv71r39pwIABGjVqlKZNmybp4s65S5cu+vDDDxUbG6tXXnlFhw4dUmxsbK59XLhwQTExMQoJCdGrr76q7t27yxije++9V6+99po6duyoGTNmqF69enr22Wc1fPjwq/reHnzwQaWmpmrSpEl68MEHFRcXp/Hjxzu1efTRR/X666/rrrvu0uTJk+Xl5aW7777bpeUsWLBAtWrV0i233KIuXbrIz89PH374YY52AwcO1LBhwxQeHq4pU6Zo1KhR8vHx0caNGyVJH3zwgex2u1q3bq0PPvhAH3zwgf72t7/lusyePXtqz549+vHHH52m79u3Txs3blSvXr1y/VybNm305JNPSpL+8Y9/OJZz44036uGHH9bx48f1zTffOH3m8OHDWr16db5HXC71119/Ob2Sk5ML9Lkbb7xREyZMkCQ99thjjtratGkjSVq9erXatGmjlJQUjR07VhMnTtSpU6d0xx136IcffsjRX48ePZSWlqaJEydq0KBB+S573bp1+vvf/65evXpp6tSpOnfunLp3767jx4872mzdulUdO3bU8ePHNX78eA0cOFATJkwo9jFOuEYZ4Doxd+5cIynHy263m7i4uBzt09LSnN6fP3/eNGrUyNxxxx2Oabt27TIeHh7m/vvvN5mZmU7ts7KyHP+uXr26ufvuu40xxsycOdPYbDbz0ksvObX/7LPPjCTz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hjIAAAAKp8juAHzhwgWdPn26qLoDAAAoEJfDzPLlyxUXF+c07ZVXXpG/v7+Cg4N111136eTJk0VVHwAAQL5cDjMzZszQmTNnHO83bNigF198US+88II+/vhjHThwQC+99FKRFgkAAJAXl8PML7/8opYtWzref/rpp7rzzjs1ZswYdevWTdOnT9fy5cuLtEgAAIC8uBxmUlNTVaFCBcf7devWqUOHDo73DRs21MGDB4umOgAAgCtwOczccMMN+vXXXyVJp0+f1s8//+x0pOb48ePy8/MrugoBAADy4XKY6dGjh4YNG6YPPvhAgwYNUmhoqG677TbH/M2bN6tevXpFWiQAAEBeXL7PzIsvvqg///xTTz75pEJDQzV//nx5eno65n/44Yfq0qVLkRYJAACQF5cfZ2A1PM4AAADrKdbHGUjSxo0btXz5cp0/f14dOnRQx44dC1UoAADA1XI5zHz66afq2bOnfH195eXlpRkzZmjKlCl65plniqM+AACAfLk8AHjSpEkaNGiQkpOTdfLkSb388suaOHFicdQGAABwRS6PmfH391diYqJq164tSTp//rzKli2rP//8UyEhIcVS5NVgzAwAANbjyv7b5SMzaWlpTp16e3vLx8eHh0wCAAC3KNQA4HfffVf+/v6O9xcuXFBcXJwqVqzomPbkk09efXUAAABX4PJppho1ashms+Xfqc2m33///aoKKyqcZgIAwHqK9dLsvXv3FrYuAACAIufymBlXNW7cWAcOHCjuxQAAgOtUsYeZvXv3KiMjo7gXAwAArlPFHmYAAACKE2EGAABYGmEGAABYGmEGAABYGmEGAABYWqHDzPvvv6/09PQc08+fP6/333/f8f6dd95R5cqVC7sYAACAfLl8B+Bsnp6eOnToUI6HSx4/flwhISHKzMwskgKvFncABgDAeor1QZPZjDG5Ptbgjz/+UFBQUGG7BQAAcInLYaZZs2a6+eabZbPZ1KFDB918882OV5MmTdS6dWtFR0cXqK+1a9eqS5cuCgsLk81m09KlS53m9+/fXzabzenVsWNHV0sGAADXMJefzdS1a1dJUmJiomJiYpyenu3t7a0aNWqoe/fuBerrzJkzatKkiR555BF169Yt1zYdO3bU3LlzHe/tdrurJQMAgGuYy2Fm7Nixki4+Pbtnz57y8fEp9MI7deqkTp065dvGbrcr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nJ577jmdOXNGjz32mE6dOqXbb79dX3/9tXx8fNxVMgAAKGVsxhjj7iKKU0pKioKCgpScnMwpJwAALMKV/XepHTMDAABQEIQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaYQZAABgaaU+zIwbN042m83pVb9+fXeXBQAASoky7i6gIBo2bKiVK1c63pcpY4myAQBACbBEKihTpoxCQ0PdXQYAACiFSv1pJknatWuXwsLCVLNmTfXt21f79+93d0kAAKCUKPVHZiIjIxUXF6d69erp0KFDGj9+vFq3bq3t27crICAgR/v09HSlp6c73qekpJRkuQAAoITZjDHG3UW44tSpU6pevbpmzJihgQMH5pg/btw4jR8/Psf05ORkBQYGlkSJAADgKqWkpCgoKKhA+29LnGa6VHBwsOrWravdu3fnOn/06NFKTk52vA4cOFDCFQIAgJJkuTBz+vRpJSUlqUqVKrnOt9vtCgwMdHoBAIBrV6kPM88884y+++477d27Vxs2bND9998vT09P9e7d292lAQCAUqDUDwD+448/1Lt3bx0/flyVKlXS7bffro0bN6pSpUruLg0AAJQCpT7MLFq0yN0lAACAUqzUn2YCAADID2EGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABYGmEGAABY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\n"
182 | },
183 | "metadata": {}
184 | }
185 | ]
186 | },
187 | {
188 | "cell_type": "code",
189 | "source": [
190 | "import cv2\n",
191 | "import math\n",
192 | "import numpy as np\n",
193 | "from google.colab.patches import cv2_imshow\n",
194 | "import matplotlib.pyplot as plt\n",
195 | "\n",
196 | "\n",
197 | "imagelist=[\"30\",\"1000\",\"1800\",\"2000\",\"5000\",\"8000\",\"10000\",\"12000\",\"15000\",\"18000\",\"20000\",\"50000\",\"80000\",\"100000\",\"120000\",\"150000\",\"180000\",\"200000\",\"500000\",\"800000\",\"1000000\",\"1200000\",\"1500000\",\"1800000\",\"2000000\"]\n",
198 | "image_path=\"/content/drive/MyDrive/FYP/RefractoryFiltering_image/\"\n",
199 | "currentframe=0\n",
200 | "PSNR=0\n",
201 | "result_mse=[]\n",
202 | "result_psnr=[]\n",
203 | "# load the input images\n",
204 | "img1 = cv2.imread(image_path+'frame_NONE_3sec.jpg')\n",
205 | "img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)\n",
206 | "\n",
207 | "for x in imagelist:\n",
208 | " if(x==\"0\"):\n",
209 | " continue\n",
210 | " img2 = cv2.imread(image_path+'frame'+x+'_3sec.jpg')\n",
211 | " # convert the images to grayscale\n",
212 | " img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)\n",
213 | "\n",
214 | " # define the function to compute MSE between two images\n",
215 | " def mse(img1, img2):\n",
216 | " h, w = img1.shape\n",
217 | " diff = cv2.subtract(img1, img2)\n",
218 | " err = np.sum(diff**2)\n",
219 | " mse = err/(float(h*w))\n",
220 | " return mse, diff\n",
221 | "\n",
222 | " def psnr(img1,img2,mse):\n",
223 | " Psnr=0\n",
224 | " max_pixel = 255.0\n",
225 | " if(mse==0):\n",
226 | " return Psnr\n",
227 | " Psnr = 20 * math.log10(max_pixel / math.sqrt(mse))\n",
228 | " return Psnr\n",
229 | "\n",
230 | " error, diff = mse(img1, img2)\n",
231 | " PSNR=psnr(img1, img2, error)\n",
232 | " result_mse.append(error)\n",
233 | " result_psnr.append(PSNR)\n",
234 | " #print(\"Image matching Error between the two images (frame)\"+x+\":\",round(error,4))\n",
235 | " #print(\"Peak Signal-to-Noise Ratio between the two images:\",round(PSNR,4),\"db\")\n",
236 | " #cv2_imshow(img1)\n",
237 | " #cv2_imshow(img2)\n",
238 | " #cv2_imshow(diff)\n",
239 | "\n",
240 | "imagelist = [int(i) for i in imagelist]\n",
241 | "x=imagelist\n",
242 | "y=result_psnr\n",
243 | "# plotting points as a scatter plot\n",
244 | "plt.scatter(x, y, label= \"stars\", color= \"red\", marker= \"*\", s=2)\n",
245 | "\n",
246 | "# x-axis label\n",
247 | "plt.xlabel('REFRACTORY_PERIOD')\n",
248 | "# frequency label\n",
249 | "plt.ylabel('Result_PSNR')\n",
250 | "# plot title\n",
251 | "plt.title('Refractory Filtering')\n",
252 | "\n",
253 | "plt.legend()\n",
254 | "plt.show()\n",
255 | "\n",
256 | "\n"
257 | ],
258 | "metadata": {
259 | "colab": {
260 | "base_uri": "https://localhost:8080/",
261 | "height": 472
262 | },
263 | "id": "UKsSyZmCgQrW",
264 | "outputId": "00200430-cf62-4473-ef17-1fbc237f6cd4"
265 | },
266 | "execution_count": null,
267 | "outputs": [
268 | {
269 | "output_type": "display_data",
270 | "data": {
271 | "text/plain": [
272 | ""
273 | ],
274 | "image/png": "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Pn267rjjDjVs2FCDBw9W9erVdfz4cSUlJennn3/W999/X6ztBAcH66677tLLL7+sy5cvq3Llyvriiy+UkpKSr+/EiRP1xRdfqE2bNhoyZIjq1aunY8eOafHixfrmm28UGhqqW2+9VZ6ennrppZeUnp4uX19f3XPPPapYsaJGjx6tCRMmqGPHjrrvvvu0Z88ezZgxQ7fffrtTgSQsLEwdO3bU4sWLFRoa6lQQul41atRQaGioZs2apTJlyigwMFAtWrRQTEyM3nrrLXXq1EkNGjTQwIEDVblyZR05ckRr1qxRcHCwli9fXqq1jR8/Xl988YVat26tRx55RNnZ2XrjjTd0yy23cPsF3HQ4MgNYQLdu3ez/08/Ozlb9+vW1ZcsWde7cWYmJiRo6dKhmzZolDw8Ph9NDxTF//nzFx8dr+vTpGj16tLy9vQv833zlypW1adMm9ejRQ++//74ef/xxzZs3T23btrV/O29ERIRmzZqlEydOaNCgQerTp49++OEHSbkftm+88YZSU1M1YsQILVq0SEOGDNEXX3zh8B0zRdG/f39JufN9rnb7gZLm7e2td955R56ennr44YfVp08frVu3TlLuEbWkpCQ1a9ZMb7zxhh577DElJiYqIiJCI0aMKPXamjZtqs8//1xly5bVmDFjNGfOHD333HNq166d07fFANydzTBjDIDFffzxx+ratavWr19v//I6FKxr167atWtXvnlQgJVxZAaA5c2ePVvVq1e33wYAuS5evOjwfO/evfrss8/Utm1b1xQElBLmzACwrIULF+o///mPPv30U7322mvcc+h3qlevbr/P1qFDhzRz5kz5+Pho1KhRri4NKFGcZgJgWTabTUFBQerdu7dmzZrFHaZ/Z+DAgVqzZo3S0tLk6+ur2NhYTZw4UbfddpurSwNKFGEGAABYGnNmAACApRFmAACApd30J5hzcnJ09OhRlSlThsmBAABYhDFGZ8+eVWRkpDw8rn7s5aYPM0ePHlVUVJSrywAAAMVw+PBhValS5ap9bvowU6ZMGUm5b0ZwcLCLqwEAAEWRkZGhqKgo++f41dz0YSbv1FJwcDBhBgAAiynKFBEmAAMAAEsjzAAAAEsjzAAAAEu76efMAABQGrKzs3X58mVXl2FZ3t7e8vT0LJF1EWYAAHCCMUZpaWk6c+aMq0uxvNDQUEVERFz398AR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EWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAIClEWYAAICluTTMjB8/XjabzeFRt25d+/LMzEwNHTpU5cuXV1BQkLp3767jx4+7sGIAAOBuXH5kpkGDBjp27Jj98c0339iXjRgxQsuXL9fixYu1bt06HT16VN26dXNhtQAAwN14ubwALy9FRETka09PT9ecOXM0f/583XPPPZKkuXPnql69etq4caNatmx5o0sFAABuyOVHZvbu3avIyEhVr15dffv2VWpqqiQpOTlZly9fVlxcnL1v3bp1VbVqVSUlJRW6vqysLGVkZDg8AADAzculYaZFixZKTEzUihUrNHPmTKWkpOjOO+/U2bNnlZaWJh8fH4WGhjq8Jjw8XGlpaYWuc9KkSQoJCbE/oqKiSnkUAADAlVx6mqlTp072vzdq1EgtWrRQdHS0Fi1aJH9//2Ktc/To0Ro5cqT9eUZGBoEGAICbmMtPM/1WaGioateurX379ikiIkKXLl3SmTNnHPocP368wDk2eXx9fRUcHOzwAAAANy+3CjPnzp3T/v37ValSJTVt2lTe3t5avXq1ffmePXuUmpqq2NhYF1YJAADciUtPMz355JPq0qWLoqOjdfToUY0bN06enp7q06ePQkJCNGjQII0cOVLlypVTcHCwHnvsMcXGxnIlEwAAsHNpmPn555/Vp08fnTp1SmFhYbrjjju0ceNGhYWFSZKmTp0qDw8Pde/eXVlZWYqPj9eMGTNcWTIAAHAzNmOMcXURpSkjI0MhISFKT09n/gwAABbhzOe3W82ZAQAAcBZhBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAAWBphBgAA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UpJDf0mKj4+3909JSVFaWppDn5CQELVo0aLQdZam4ozx9y5cuKDLly+rXLlyDu1r165VxYoVVadOHT3yyCM6depUidZeFMUd37lz5xQdHa2oqCjdf//92rVrl32ZO+3Dkth/c+bM0QMPPKDAwECHdnfYf8Vxrd/BknjP3E1OTo7Onj2b73dw7969ioyMVPXq1dW3b1+lpqa6qMLiufXWW1WpUiW1b99e3377rb39ZtuHc+bMUVxcnKKjox3a3XX/paenS1K+n7ffcpfPQsKMpJMnTyo7O1vh4eEO7eHh4fnO3eZJS0u7av+8P51ZZ2kqzhh/729/+5siIyMdfig7duyoefPmafXq1XrppZe0bt06derUSdnZ2SVa/7UUZ3x16tTR22+/rY8//ljvvfeecnJy1KpVK/3888+S3GsfXu/+++6777Rz50499NBDDu3usv+Ko7DfwYyMDF28eLFEfubdzeTJk3Xu3Dn16tXL3taiRQslJiZqxYoVmjlzplJSUnTnnXfq7NmzLqy0aCpVqqRZs2bpo48+0kcffaSoqCi1bdtWW7dulVQy/265i6NHj+rzzz/P9zvorvsvJydHw4cPV+vWrXXLLbcU2s9dPgtv+rtmo2S8+OKLWrhwodauXeswSfaBBx6w/71hw4Zq1KiRatSoobVr16pdu3auKLXIYmNjFRsba3/eqlUr1atXT2+++aaef/55F1ZW8ubMmaOGDRuqefPmDu1W3n9/NPPnz9eECRP08ccfO8wp6dSpk/3vjRo1UosWLRQdHa1FixZp0KBBrii1yOrUqaM6derYn7dq1Ur79+/X1KlT9e6777qwspL3zjvvKDQ0VF27dnVod9f9N3ToUO3cudNl83ecxZEZSRUqVJCnp6eOHz/u0H78+HFFREQU+JqIiIir9s/705l1lqbijDHP5MmT9eKLL+qLL75Qo0aNrtq3evXqqlChgvbt23fdNTvjesaXx9vbW02aNLHX7k778HrGd/78eS1cuLBI/zC6av8VR2G/g8HBwfL39y+Rnwl3sXDhQj300ENatGhRvkP6vxcaGqratWtbYh8WpHnz5vbab5Z9aIzR22+/rT//+c/y8fG5al932H+PPvqo/v3vf2vNmjWqUqXKVfu6y2chYUaSj4+PmjZtqtWrV9vbcnJytHr1aof/uf9WbGysQ39JWrVqlb1/TEyMIiIiHPpkZGRo06ZNha6zNBVnjFLuLPTnn39eK1asULNmza65nZ9//lmnTp1SpUqVSqTuoiru+H4rOztbO3bssNfuTvvwesa3ePFiZWVlqV+/ftfcjqv2X3Fc63ewJH4m3MGCBQs0cOBALViwwOGy+sKcO3dO+/fvt8Q+LMj27dvttd8s+3DdunXat29fkf5D4cr9Z4zRo48+qqVLl+qrr75STEzMNV/jNp+FJTaV2OIWLlxofH19TWJiovnhhx/MkCFDTGhoqElLSzPGGPPnP//ZPP300/b+3377rfHy8jKTJ082u3fvNuPGjTPe3t5mx44d9j4vvviiCQ0NNR9//LH5z3/+Y+6//34TExNjLl68eMPHZ4zzY3zxxReNj4+P+fDDD82xY8fsj7NnzxpjjDl79qx58sknTVJSkklJSTFffvmlue2220ytWrVMZmam249vwoQJZuXKlWb//v0mOTnZPPDAA8bPz8/s2rXL3sed9qGz48tzxx13mN69e+drd7f9d/bsWbNt2zazbds2I8lMmTLFbNu2zRw6dMgYY8zTTz9t/vznP9v7HzhwwAQEBJinnnrK7N6920yfPt14enqaFStW2Ptc6z270Zwd4/vvv2+8vLzM9OnTHX4Hz5w5Y+/zxBNPmLVr15qUlBTz7bffmri4OFOhQgVz4sQJtx/f1KlTzbJly8zevXvNjh07zLBhw4yHh4f58ssv7X3caR86O748/fr1My1atChwne60/x555BETEhJi1q5d6/DzduHCBXsfd/0sJMz8xj//+U9TtWpV4+PjY5o3b242btxoX9amTRuTkJDg0H/RokWmdu3axsfHxzRo0MB8+umnDstzcnLMmDFjTHh4uPH19TXt2rUze/bsuRFDKZQzY4yOjjaS8j3GjRtnjDHmwoULpkOHDiYsLMx4e3ub6OhoM3jwYJd9UBjj3PiGDx9u7xseHm7uvfdes3XrVof1uds+dPZn9McffzSSzBdffJFvXe62//Iu0/39I29MCQkJpk2bNvlec+uttxofHx9TvXp1M3fu3Hzrvdp7dqM5O8Y2bdpctb8xuZejV6pUyfj4+JjKlSub3r17m3379t3Ygf2Xs+N76aWXTI0aNYyfn58pV66cadu2rfnqq6/yrddd9mFxfkbPnDlj/P39zb/+9a8C1+lO+6+gsUly+L1y189C238HAAAAYEnMmQEAAJZGmAEAAJZGmAEAAJZGmAEAAJZGmAEAAJZGmAEAAJZGmAEAAJZGmAEAAE5bv369unTposjISNlsNi1btszpdRhjNHnyZNWuXVu+vr6qXLmyXnjhBafXQ5gB3NSAAQNks9lks9nk7e2tmJgYjRo1SpmZmfY+ect//1i4cKEkae3atQUuf/bZZwtcHhYWpnvvvVc7duwosKb4+Hh5enpq8+bNBS7ftm2bevbsqfDwcPn5+alWrVoaPHiwfvrpJ40fP77QevMeeQ4fPqy//OUvioyMlI+Pj6KjozVs2DCdOnXKYXtt27a1v9bPz0+1a9fWpEmTZIzRTz/9pICAAM2fP9/hNTk5OWrVqpV69Ojh1D7w8fFRzZo19dxzz+nKlStXfX9tNpvS0tIkyWHcnp6eioqK0pAhQ/Trr786bKtatWqaNm2aQ9uGDRt07733qmzZsvLz81PDhg01ZcoUZWdnO/T77XYDAwNVq1YtDRgwQMnJydccI1Bc58+fV+PGjTV9+vRir2PYsGF66623NHnyZP3444/65JNP1Lx5c+dXVKLfJwygxCQkJJiOHTuaY8eOmdTUVLN06VITHBxsRo0aZe+j/37V+G/vo3Ls2DH7PU/yvn59z549Bd5f6/fLk5OTzT333GOioqJMVlaWQz2HDh0yQUFB5vHHHzcPP/xwvnqXL19ufHx8TJcuXcyqVavMgQMHzMaNG80TTzxhevXqZc6ePetQQ5UqVcxzzz3n0GaMMfv37zcVK1Y0d9xxh1m7dq05dOiQ+eyzz0yDBg1MrVq1zKlTp+zbbNOmjRk8eLA5duyYOXjwoHn77beNl5eXmTFjhjHGmNdee82UK1fOHD161P6al19+2YSHh5tffvnFqX1w8OBBM2PGDGOz2czEiROv+v4eO3bMZGdnG2OMGTdunGnQoIE5duyY+fnnn82qVatMVFSU6dWrl8O2oqOjzdSpU+3PlyxZYry8vMzgwYPNtm3bTEpKipk9e7YpW7as6dGjh8nJySnw5yAlJcWsXLnSdO/e3Xh6epp33nnnmuMErpcks3TpUoe2zMxM88QTT5jIyEgTEBBgmjdvbtasWWNf/sMPPxgvLy/z448/Xv/2r3sNAEpFQkKCuf/++x3aunXrZpo0aWJ/XtA/IL+V92F7+vTpIi//5JNPjCTz/fffO/QdP368eeCBB8zu3btNSEiIw83nzp8/bypUqGC6du1a4HYK2v7vP7zzdOzY0VSpUsVh/cYYc+zYMRMQEOAQpNq0aWOGDRvm0O+2224zf/rTn4wxufeEufvuu03nzp2NMcbs3r3b+Pn5mY8//rjAOn+voH3Qvn1707JlS2PMtd9fY3LDTOPGjR3aRo4cacqWLevQ9tv349y5c6Z8+fKmW7du+daXt38WLlxobyvs56B///6mTJky5tdffy18kEAJKOhn8KGHHjKtWrUy69evN/v27TOvvPKK8fX1NT/99JMxJvfeXLVr1zaTJ0821apVM9HR0WbQoEEO/2EpKk4zARaxc+dObdiwQT4+PqW2jfT0dPspqt9uxxijuXPnql+/fqpbt65q1qypDz/80L585cqVOnnypEaNGlXgekNDQ4u0/V9//VUrV67U//3f/8nf399hWUREhPr27asPPvhApoBbyhlj9PXXX+vHH3+0126z2TR37lx9/fXXmj17tgYMGKAHHnhA9913X5HqKYi/v78uXbpU7NcfPHhQK1euvOp+/OKLL3Tq1Ck9+eST+ZZ16dJFtWvX1oIFC665rREjRujs2bNatWpVsesFiiM1NVVz587V4sWLdeedd6pGjRp68skndccdd2ju3LmSpAMHDujQoUNavHix5s2bp8TERCUnJxfpFPDveZX0AACUnH//+98KCgrSlStXlJWVJQ8PD73xxhsOffr06SNPT0+Hth9++EFVq1a1P69SpYrD8kOHDql8+fL5lp8/f16SdN9996lu3br25V9++aUuXLig+Ph4SVK/fv00Z84c/fnPf5Yk7d27V5IcXlMce/fulTFG9erVK3B5vXr1dPr0af3yyy+qWLGiJGnGjBl66623dOnSJV2+fFl+fn56/PHH7a+Jjo7WtGnT9NBDD6lKlSr64osvilWbMUarV6/WypUr9dhjjzks+/37Gx0drV27dtmf79ixQ0FBQcrOzrbPeZoyZUqh2/rpp5/s4y1I3bp17X2uJm9/HDx48Jp9gZK0Y8cOZWdnq3bt2g7tWVlZ9n97cnJylJWVpXnz5tn7zZkzR02bNtWePXtUp06dIm+PMAO4sbvvvlszZ87U+fPnNXXqVHl5eal79+4OfaZOnaq4uDiHtsjISIfnX3/9tcqUKWN/XrZs2XzLAwICtHHjRk2cOFGzZs1yWP7222+rd+/e8vLK/SejT58+euqpp7R//37VqFGjwCMl18OZ9fXt21fPPPOMTp8+rXHjxqlVq1Zq1aqVQ5+BAwdqzJgxeuyxxxQcHOxULXmB8vLly8rJydGDDz6o8ePHO/T5/fvr7e3tsLxOnTr65JNPlJmZqffee0/bt2/PF4gKcr3va97rfzu5GrgRzp07J09PTyUnJ+f7z1ZQUJAkqVKlSvLy8nIIPHkBPjU1lTAD3CwCAwNVs2ZNSbmBonHjxpozZ44GDRpk7xMREWHvU5iYmJirnurJW16nTh2dOHFCvXv31vr16yXlnvpZunSpLl++rJkzZ9pfk52drbffflsvvPCC/R+jH3/8UbGxscUdrmrWrCmbzabdu3frT3/6U77lu3fvVtmyZRUWFmZvCwkJsY9/0aJFqlmzplq2bJkv4Hl5ednDmDPyAqWPj48iIyMLXMe13t+8K6Ek6cUXX1Tnzp01YcIEPf/88wX2z3s/d+/enS+Y5bXXr1//mrXv3r3bXh9wIzVp0kTZ2dk6ceKE7rzzzgL7tG7dWleuXLH/p0j631HJ6Ohop7bHnBnAIjw8PPT3v/9dzz77rC5evFhq2xk6dKh27typpUuXSpLef/99ValSRd9//722b99uf7z66qtKTExUdna2OnTooAoVKujll18ucJ1nzpwp0rbLly+v9u3ba8aMGfnGmJaWpvfff1+9e/cu9EhDUFCQhg0bpieffLLEjhblBcqqVasWKwwV5Nlnn9XkyZN19OjRApd36NBB5cqV06uvvppv2SeffKK9e/eqT58+19zOtGnTFBwcnC/YASXh3Llz9n8PJCklJUXbt29Xamqqateurb59+6p///5asmSJUlJS9N1332nSpEn69NNPJUlxcXG67bbb9Je//EXbtm1TcnKy/vrXv6p9+/b5Tk9dC2EGsJCePXvK09PT4Xsdzpw5o7S0NIdH3tyX4ggICNDgwYM1btw4GWM0Z84c9ejRQ7fccovDY9CgQTp58qRWrFihwMBAvfXWW/r0009133336csvv9TBgwe1ZcsWjRo1Sg8//HCRt//GG28oKytL8fHxWr9+vQ4fPqwVK1aoffv2RfpCrb/+9a/66aef9NFHHxX7PXDWiRMn8u2Dy5cvF9o/NjZWjRo10sSJEwtcHhgYqDfffFMff/yxhgwZov/85z86ePCg5syZowEDBqhHjx7q1auXw2vyfg4OHTqkVatWqUePHpo/f75mzpxZ5AnYgDO2bNmiJk2aqEmTJpKkkSNHqkmTJho7dqwkae7cuerfv7+eeOIJ1alTR127dtXmzZvt8/k8PDy0fPlyVahQQXfddZc6d+6sevXq2S9CcEqxr8MCUKoKuizYGGMmTZpkwsLCzLlz54ykAh+TJk0yxhTv0mxjjElNTTVeXl7mxRdfNJLMd999V+DrO3XqZL8M2hhjNm/ebLp162bCwsKMr6+vqVmzphkyZIjZu3dvvtcWdmm2McYcPHjQJCQkmPDwcOPt7W2ioqLMY489Zk6ePOnQr6BLs40x5q9//atp0KCB/bterrW9whS2D/LkvX8FPZKSkowxBV+abYwxCxYsML6+viY1NbXQ+tavX2/i4+NNcHCw8fHxMQ0aNDCTJ082V65ccej32+36+fmZGjVqmISEBJOcnOzUeAGrshlTwjP3AAAAbiBOMwEAAEsjzAD4Q0pNTVVQUFChj9TUVFeXCKCIOM0E4A/pypUrV/0yuWrVqpXY1UsAShdhBgAAWBqnmQAAgKURZgAAgKURZgAAgKURZgAAgKURZgAAgKURZgAAgKURZgAAgKURZgAAgKX9f0/6NYOVT1fvAAAAAElFTkSuQmCC\n"
275 | },
276 | "metadata": {}
277 | }
278 | ]
279 | }
280 | ]
281 | }
--------------------------------------------------------------------------------
/MLPF.ipynb:
--------------------------------------------------------------------------------
1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"machine_shape":"hm"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"},"accelerator":"TPU"},"cells":[{"cell_type":"code","source":["from google.colab import drive\n","drive.mount('/content/drive')"],"metadata":{"id":"3InpSKIaxshL","executionInfo":{"status":"ok","timestamp":1699322049597,"user_tz":-480,"elapsed":60992,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"outputId":"3bebd754-69c7-4347-9676-b60a3c895b86","colab":{"base_uri":"https://localhost:8080/"}},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Mounted at /content/drive\n"]}]},{"cell_type":"code","execution_count":null,"metadata":{"id":"ikM5kjZxdPsU","executionInfo":{"status":"ok","timestamp":1699322059138,"user_tz":-480,"elapsed":9545,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"colab":{"base_uri":"https://localhost:8080/"},"outputId":"1462468c-e682-475e-a6b8-19754a9843d6"},"outputs":[{"output_type":"stream","name":"stdout","text":["Requirement already satisfied: tensorflow in /usr/local/lib/python3.10/dist-packages (2.12.0)\n","Requirement already satisfied: absl-py>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.4.0)\n","Requirement already satisfied: astunparse>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.6.3)\n","Requirement already satisfied: flatbuffers>=2.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (23.5.26)\n","Requirement already satisfied: gast<=0.4.0,>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (0.4.0)\n","Requirement already satisfied: google-pasta>=0.1.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (0.2.0)\n","Requirement already satisfied: grpcio<2.0,>=1.24.3 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.59.0)\n","Requirement already satisfied: h5py>=2.9.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (3.9.0)\n","Requirement already satisfied: jax>=0.3.15 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (0.3.25)\n","Requirement already satisfied: keras<2.13,>=2.12.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (2.12.0)\n","Requirement already satisfied: libclang>=13.0.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (16.0.6)\n","Requirement already satisfied: numpy<1.24,>=1.22 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.23.5)\n","Requirement already satisfied: opt-einsum>=2.3.2 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (3.3.0)\n","Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from tensorflow) (23.2)\n","Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (3.20.3)\n","Requirement already satisfied: setuptools in /usr/local/lib/python3.10/dist-packages (from tensorflow) (67.7.2)\n","Requirement already satisfied: six>=1.12.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.16.0)\n","Requirement already satisfied: tensorboard<2.13,>=2.12 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (2.12.0)\n","Requirement already satisfied: tensorflow-estimator<2.13,>=2.12.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (2.12.0)\n","Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (2.3.0)\n","Requirement already satisfied: typing-extensions>=3.6.6 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (4.5.0)\n","Requirement already satisfied: wrapt<1.15,>=1.11.0 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (1.14.1)\n","Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /usr/local/lib/python3.10/dist-packages (from tensorflow) (0.34.0)\n","Requirement already satisfied: wheel<1.0,>=0.23.0 in /usr/local/lib/python3.10/dist-packages (from astunparse>=1.6.0->tensorflow) (0.41.2)\n","Requirement already satisfied: scipy>=1.5 in /usr/local/lib/python3.10/dist-packages (from jax>=0.3.15->tensorflow) (1.11.3)\n","Requirement already satisfied: google-auth<3,>=1.6.3 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (2.17.3)\n","Requirement already satisfied: google-auth-oauthlib<0.5,>=0.4.1 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (0.4.6)\n","Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (3.5)\n","Requirement already satisfied: requests<3,>=2.21.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (2.31.0)\n","Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (0.7.2)\n","Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (1.8.1)\n","Requirement already satisfied: werkzeug>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from tensorboard<2.13,>=2.12->tensorflow) (3.0.1)\n","Requirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.13,>=2.12->tensorflow) (5.3.2)\n","Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.13,>=2.12->tensorflow) (0.3.0)\n","Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard<2.13,>=2.12->tensorflow) (4.9)\n","Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.13,>=2.12->tensorflow) (1.3.1)\n","Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0->tensorboard<2.13,>=2.12->tensorflow) (3.3.1)\n","Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0->tensorboard<2.13,>=2.12->tensorflow) (3.4)\n","Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0->tensorboard<2.13,>=2.12->tensorflow) (2.0.7)\n","Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2.21.0->tensorboard<2.13,>=2.12->tensorflow) (2023.7.22)\n","Requirement already satisfied: MarkupSafe>=2.1.1 in /usr/local/lib/python3.10/dist-packages (from werkzeug>=1.0.1->tensorboard<2.13,>=2.12->tensorflow) (2.1.3)\n","Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/lib/python3.10/dist-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard<2.13,>=2.12->tensorflow) (0.5.0)\n","Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/lib/python3.10/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<0.5,>=0.4.1->tensorboard<2.13,>=2.12->tensorflow) (3.2.2)\n"]}],"source":["!pip install tensorflow\n","\n","\n","from __future__ import print_function\n","import os\n","import tensorflow\n","from concurrent.futures import ThreadPoolExecutor\n","from tensorflow import keras\n","\n","import matplotlib.pyplot as plt\n","import numpy as np\n","import os,sys,glob\n","import pandas as pd\n","\n","import matplotlib\n","\n","\n","from tensorflow.keras.utils import to_categorical\n","from sklearn.model_selection import train_test_split\n","from tensorflow.keras.callbacks import TensorBoard\n","\n","\n","from tensorflow.keras.models import Model, Sequential, load_model\n","from tensorflow.keras.layers import Input, Dense,Embedding,Dropout\n","from tensorflow.keras.callbacks import Callback\n","from tensorflow.keras.optimizers import Adam, SGD\n","from sklearn.metrics import confusion_matrix, f1_score, precision_score, recall_score,accuracy_score, confusion_matrix\n","# from custom_dataloader.dataloader import ti_image_generator\n","from tensorflow.keras.callbacks import ModelCheckpoint\n","from tqdm.keras import TqdmCallback\n","import scipy.io as sio\n","\n","from concurrent.futures import ThreadPoolExecutor\n"]},{"cell_type":"code","source":["os.environ[\"CUDA_DEVICE_ORDER\"] = \"PCI_BUS_ID\"\n","os.environ[\"CUDA_VISIBLE_DEVICES\"] = \"\"\n"],"metadata":{"id":"H9Txn1BddZ7T"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# matplotlib global parameters\n","\n","matplotlib.rcParams.update({'font.size': 14})\n","# Say, \"the default sans-serif font is COMIC SANS\"\n","# matplotlib.rcParams['font.sans-serif'] = \"Arial\"\n","# Then, \"ALWAYS use sans-serif fonts\"\n","matplotlib.rcParams['font.family'] = \"sans-serif\"\n","matplotlib.rcParams['pdf.fonttype'] = 42\n","matplotlib.rcParams['ps.fonttype'] = 42"],"metadata":{"id":"crK4QJzpdbj7"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["import bisect\n","import warnings\n","\n","class Dataset(object):\n"," \"\"\"An abstract class representing a Dataset.\n","\n"," All other datasets should subclass it. All subclasses should override\n"," ``__len__``, that provides the size of the dataset, and ``__getitem__``,\n"," supporting integer indexing in range from 0 to len(self) exclusive.\n"," \"\"\"\n","\n"," def __init__(self, dtype='float32'):\n"," self.dtype = dtype\n","\n"," def __getitem__(self, index):\n"," raise NotImplementedError\n","\n"," def __len__(self):\n"," raise NotImplementedError\n","\n"," def __add__(self, other):\n"," return ConcatDataset([self, other])\n","\n","class ConcatDataset(Dataset):\n"," \"\"\"\n"," Dataset to concatenate multiple datasets.\n"," Purpose: useful to assemble different existing datasets, possibly\n"," large-scale datasets as the concatenation operation is done in an\n"," on-the-fly manner.\n","\n"," Arguments:\n"," datasets (sequence): List of datasets to be concatenated\n"," \"\"\"\n","\n"," @staticmethod\n"," def cumsum(sequence):\n"," r, s = [], 0\n"," for e in sequence:\n"," l = len(e)\n"," r.append(l + s)\n"," s += l\n"," return r\n","\n"," def __init__(self, datasets):\n"," super(ConcatDataset, self).__init__()\n"," assert len(datasets) > 0, 'datasets should not be an empty iterable'\n"," self.datasets = list(datasets)\n"," self.cumulative_sizes = self.cumsum(self.datasets)\n","\n"," def __len__(self):\n"," return self.cumulative_sizes[-1]\n","\n"," def __getitem__(self, idx):\n"," dataset_idx = bisect.bisect_right(self.cumulative_sizes, idx)\n"," if dataset_idx == 0:\n"," sample_idx = idx\n"," else:\n"," sample_idx = idx - self.cumulative_sizes[dataset_idx - 1]\n"," return self.datasets[dataset_idx][sample_idx]\n","\n"," @property\n"," def cummulative_sizes(self):\n"," warnings.warn(\"cummulative_sizes attribute is renamed to \"\n"," \"cumulative_sizes\", DeprecationWarning, stacklevel=2)\n"," return self.cumulative_sizes"],"metadata":{"id":"fDhpRyaydsqa"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["def default_collate_fn(samples):\n"," X = np.array([sample['x'] for sample in samples])\n"," Y = np.array([sample['y'] for sample in samples])\n","\n"," return X, Y\n","\n","class ti_image_generator(keras.utils.Sequence):\n"," def __init__(self,\n"," dataset=Dataset,\n"," collate_fn=default_collate_fn,\n"," batch_size=32,\n"," shuffle=True,\n"," num_workers=0,\n"," replacement=False,\n"," ):\n"," \"\"\"\n"," :param dataset (Dataset): Data set to load\n"," :param batch_size (int): how many samples in one batch\n"," :param shuffle (bool, optional): set to ``True`` to have the data reshuffled\n"," at every epoch (default: ``True``).\n"," :param num_workers (int, optional): how many threads to use for data\n"," loading in one batch. 0 means that the data will be loaded in the main process.\n"," (default: ``0``)\n"," :param replacement (bool): samples are drawn with replacement if ``True``, default=False\n"," :param collate_fn (callable, optional):\n"," \"\"\"\n"," self.dataset = dataset\n"," self.shuffle = shuffle\n"," self.batch_size = batch_size\n"," self.num_workers = num_workers\n"," self.replacement = replacement\n"," self.indices = []\n"," self.collate_fn = collate_fn\n"," self.on_epoch_end()\n","\n"," def __getitem__(self, index):\n"," indices = self.indices[index * self.batch_size: (index + 1) * self.batch_size]\n","\n"," samples = []\n"," if self.num_workers == 0:\n"," for i in indices:\n"," data = self.dataset[i]\n"," samples.append(data)\n"," else:\n"," with ThreadPoolExecutor(max_workers=self.num_workers) as executor:\n"," for sample in executor.map(lambda i: self.dataset[i], indices):\n"," samples.append(sample)\n"," X, Y = self.collate_fn(samples)\n"," return X, Y\n","\n"," def on_epoch_end(self):\n"," n = len(self.dataset)\n"," seq = np.arange(0, n)\n"," if self.shuffle:\n"," if self.replacement:\n"," self.indices = np.random.randint(low=0, high=n, size=(n,),\n"," dtype=np.int64).tolist()\n"," else:\n"," np.random.shuffle(seq)\n"," self.indices = seq\n"," else:\n"," self.indices = seq\n","\n"," def __len__(self):\n"," return int(np.floor(len(self.dataset) / self.batch_size))\n","\n"],"metadata":{"id":"pcg11Yygel6T"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# training params\n","learning_rate = 0.001 #0.001\n","batch_size = 25 #128\n","\n","Train = True\n","# Train = False\n","\n","patchsize = 25\n","\n","hidden = 20\n","resize = 7 #11\n","epochs = 3 #5\n","\n","csvfilepath = \"/content/drive/MyDrive/training_data/\"\n","# hidden = 20\n","# resize = 11\n","\n","\n","csvinputlen = patchsize * patchsize\n","networkinputlen = resize * resize\n","middle = int(csvinputlen / 2)\n","\n","tau = 100000 # 300ms if use exp decay for preprocessing\n","\n","prefix = 'aMSEO1H' + str(hidden) + '_linear_' + str(resize)\n","print(\"test\")"],"metadata":{"id":"iiE_SoEXe9Cc","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1699322470025,"user_tz":-480,"elapsed":402,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"outputId":"b84a6878-5141-434f-af98-0cf9c55707a0"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["test\n"]}]},{"cell_type":"code","source":["def plot_confusion_matrix(cm, savename, title='Confusion Matrix'):\n"," plt.figure(figsize=(12, 8), dpi=100)\n"," np.set_printoptions(precision=2)\n","\n"," classes = ['Not Fall', 'Fall']\n"," ind_array = np.arange(len(classes))\n"," x, y = np.meshgrid(ind_array, ind_array)\n"," for x_val, y_val in zip(x.flatten(), y.flatten()):\n"," c = cm[y_val][x_val]\n"," if c > 0.001:\n"," plt.text(x_val, y_val, \"%0.2f\" % (c,), color='red', fontsize=15, va='center', ha='center')\n","\n"," plt.imshow(cm, interpolation='nearest', cmap=plt.cm.binary)\n"," plt.title(title)\n"," plt.colorbar()\n"," xlocations = np.array(range(len(classes)))\n"," plt.xticks(xlocations, classes, rotation=90)\n"," plt.yticks(xlocations, classes)\n"," plt.ylabel('Actual label')\n"," plt.xlabel('Predict label')\n","\n"," # offset the tick\n"," tick_marks = np.array(range(len(classes))) + 0.5\n"," plt.gca().set_xticks(tick_marks, minor=True)\n"," plt.gca().set_yticks(tick_marks, minor=True)\n"," plt.gca().xaxis.set_ticks_position('none')\n"," plt.gca().yaxis.set_ticks_position('none')\n"," plt.grid(True, which='minor', linestyle='-')\n"," plt.gcf().subplots_adjust(bottom=0.15)\n","\n"," # show confusion matrix\n"," plt.savefig(savename, format='png')\n"," plt.show()\n"],"metadata":{"id":"KVVnMxg9fHxy"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# LossHistory, keep loss and acc\n","class LossHistory(Callback):\n"," def on_train_begin(self, logs={}):\n"," self.losses = {'batch':[], 'epoch':[]}\n"," self.accuracy = {'batch':[], 'epoch':[]}\n"," self.val_loss = {'batch':[], 'epoch':[]}\n"," self.val_acc = {'batch':[], 'epoch':[]}\n","\n"," def on_batch_end(self, batch, logs={}):\n"," self.losses['batch'].append(logs.get('loss'))\n"," self.accuracy['batch'].append(logs.get('accuracy'))\n"," self.val_loss['batch'].append(logs.get('val_loss'))\n"," self.val_acc['batch'].append(logs.get('val_accuracy'))\n","\n"," def on_epoch_end(self, batch, logs={}):\n"," self.losses['epoch'].append(logs.get('loss'))\n"," self.accuracy['epoch'].append(logs.get('accuracy'))\n"," self.val_loss['epoch'].append(logs.get('val_loss'))\n"," self.val_acc['epoch'].append(logs.get('val_accuracy'))\n","\n"," def loss_plot(self, loss_type):\n"," global prefix\n"," global tempfilename\n"," iters = range(len(self.losses[loss_type]))\n"," np.save( prefix + 'acc.npy', np.array(self.accuracy[loss_type]))\n"," np.save( prefix + 'loss.npy', np.array(self.losses[loss_type]))\n","\n"," plt.figure()\n"," # acc\n"," plt.plot(iters, self.accuracy[loss_type], 'r', label='train acc')\n"," # loss\n"," plt.plot(iters, self.losses[loss_type], 'g', label='train loss')\n"," if loss_type == 'epoch':\n"," # val_acc\n"," plt.plot(iters, self.val_acc[loss_type], 'b', label='val acc')\n"," # val_loss\n"," plt.plot(iters, self.val_loss[loss_type], 'k', label='val loss')\n"," plt.grid(True)\n"," plt.xlabel(loss_type)\n"," plt.ylabel('acc-loss')\n"," plt.legend(loc=\"upper right\")\n","\n"," plt.savefig(prefix + 'training.pdf')\n","\n"," # plt.savefig(\"imdb_keras.pdf\")\n"," # plt.show()"],"metadata":{"id":"6zQj-8T5fquJ"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["def preprocessingresize(features, resize,targetEventTS):\n"," features = features.transpose()\n"," # normalization\n"," featuresdiff = features - targetEventTS # features[middle]\n"," featuresNormed = (tau - np.abs(featuresdiff)) * 1.0 / tau\n"," featuresNormed = np.clip(featuresNormed, 0, 1)\n"," # featuresNormed = np.exp(-np.abs(featuresdiff)/tau)\n","\n"," featuresNormed = featuresNormed.transpose()\n","\n"," # crop\n"," features = featuresNormed.reshape(patchsize, patchsize)\n"," margin = int((patchsize - resize) / 2)\n"," cropend = patchsize - margin\n"," features = features[margin:cropend, margin:cropend]\n"," features = features.reshape(resize * resize)\n"," # print(featuresNormed.shape)\n"," return features"],"metadata":{"id":"vAo75R-afx86"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["def preprocessing(features, targetEventTS):\n"," middle = int(patchsize * patchsize / 2)\n"," features = features.transpose()\n"," # normalization\n"," featuresdiff = features - targetEventTS\n"," featuresNormed = (tau - np.abs(featuresdiff)) * 1.0 / tau\n"," featuresNormed = np.clip(featuresNormed, 0, 1)\n"," # featuresNormed = np.exp(-np.abs(featuresdiff)/tau)\n","\n"," featuresNormed = featuresNormed.transpose()\n"," return featuresNormed"],"metadata":{"id":"kvFM6blaf1Ly"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["class MyDataset():\n"," def __init__(self, frame, transform=None):\n"," self.data_frame = frame\n"," self.transform = transform\n","\n"," def __len__(self):\n"," return len(self.data_frame)\n","\n"," def __getitem__(self, idx):\n"," m_data = self.data_frame.iloc[idx, :].values\n"," m_data = m_data.astype('float')\n","\n"," if patchsize > resize:\n"," sample = {'y': m_data[1], 'x': preprocessingresize(m_data[2:2+csvinputlen], resize, m_data[0])}\n"," else:\n"," sample = {'y': m_data[1], 'x': preprocessing(m_data[2:2+csvinputlen], m_data[0])}\n","\n"," if self.transform:\n"," sample = self.transform(sample)\n","\n"," return sample"],"metadata":{"id":"q93MAypSgBQy"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["\n","def splittraintest(csvdir, splitratio):\n"," allFiles = glob.glob(os.path.join(csvdir,'*TI25*.csv'))\n"," print(len(allFiles))\n"," if len(allFiles) > 0:\n"," np_array_list = []\n"," for file_ in allFiles:\n"," print(file_)\n"," #df = np.loadtext(file_,usecols=[i for i in range(2,4+csvinputlen)])\n"," df = pd.read_csv(file_,usecols=[i for i in range(2,4+csvinputlen)], header=0)\n"," # if np.any(np.isnan(pd.DataFrame(df))):\n"," # print('!!!!!!!!!!!!!!!!!!!!!!!there is nan')\n"," # exit(0)\n"," # print(df.size)\n"," np_array_list.append(df.values)\n","\n","\n","\n"," # read all csv files in a folder to one pandas frame\n"," comb_np_array = np.vstack(np_array_list)\n"," np.random.shuffle(comb_np_array)\n"," big_frame = pd.DataFrame(comb_np_array)\n"," big_frame = big_frame.fillna(0)\n"," print(big_frame.head(), big_frame.size)\n","\n","\n","\n"," #big_frame = big_frame.sample(frac=1)\n"," #print('shuffle done')\n","\n"," if np.any(np.isnan(big_frame)):\n"," print('!!!!!!!!!!!!!!!!!!!!!!!there is nan')\n"," exit(0)\n","\n"," # msk = np.random.rand(len(big_frame)) > splitratio\n"," # print('mask done')\n"," # trainset = big_frame[msk]\n"," # testset = big_frame[~msk]\n","\n"," # split train and test set\n"," leng = len(big_frame)\n"," trainset = big_frame.iloc[:int(splitratio*leng)]\n"," testset = big_frame.iloc[int(splitratio*leng):]\n"," del big_frame\n"," # del msk\n"," return trainset, testset"],"metadata":{"id":"7bgnm7AOgKp6"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["Train = True"],"metadata":{"id":"HIRzpc4ugUoK"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["train = {}\n","val = {}\n","\n","traindata, testdata = splittraintest(csvdir=csvfilepath, splitratio=0.8)\n","\n","trainset = MyDataset(traindata)\n","testset = MyDataset(testdata)\n","\n","# datagenerator = DataGenerator(dataset, batch_size=batch_size, shuffle=True)\n","traingenerator = ti_image_generator(trainset, batch_size=batch_size, shuffle=True)\n","testgenerator = ti_image_generator(testset, batch_size=batch_size, shuffle=True)\n","\n"],"metadata":{"id":"tXY4Lvs4J-Hx","colab":{"base_uri":"https://localhost:8080/"},"executionInfo":{"status":"ok","timestamp":1699322108534,"user_tz":-480,"elapsed":49405,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"outputId":"7e5d7809-399a-4b6b-ed79-174ad269de2e"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["5\n","/content/drive/MyDrive/training_data/mixedhotellightTI25.csv\n","/content/drive/MyDrive/training_data/mixeddrishot5long3TI25.csv\n","/content/drive/MyDrive/training_data/mixeddrishot5long1TI25.csv\n","/content/drive/MyDrive/training_data/mixeddrishot5long2TI25.csv\n","/content/drive/MyDrive/training_data/mixeddot1lightTI25.csv\n"," 0 1 2 3 4 5 6 \\\n","0 132 722607 0 699661 1611974467 1611962560 1611973685 \n","1 247 699850 0 3319395 178947710 52814832 0 \n","2 99 2127771 1 2052459 0 0 0 \n","3 151 2116976 1 0 0 0 0 \n","4 20 726382 0 53046859 720047 179025535 3324793 \n","\n"," 7 8 9 ... 617 618 619 \\\n","0 1611932463 1611888122 698562 ... 178887182 0 0 \n","1 178880158 53086541 179007714 ... 3303503 699586 52887584 \n","2 0 2048809 2057378 ... 0 0 0 \n","3 2037015 2099485 0 ... 2048709 2103615 2093288 \n","4 3337386 3310000 703834 ... 3283612 3276016 3270919 \n","\n"," 620 621 622 623 624 625 626 \n","0 3335687 52907453 3314797 712958 3286511 0 0 \n","1 179001168 178993463 3301604 3277915 3270019 53206781 0 \n","2 0 0 0 2040014 2086691 0 2082313 \n","3 2102383 0 0 0 0 2056357 2068756 \n","4 3263722 3255426 3252328 3238834 711244 65570586 179001741 \n","\n","[5 rows x 627 columns] 217252992\n"]}]},{"cell_type":"code","source":["if Train:\n"," inputs = Input(shape=(networkinputlen, ), name='input')\n"," x = Dense(hidden, activation='relu', name='fc1')(inputs) #input_shape=(networkinputlen, ),\n"," #x = Dense(hidden, activation='relu', name='fc2')(x)\n"," x = Dropout(0.2)(x)\n"," x = Dense(units=1, activation='sigmoid', name='output')(x)\n"," model = Model(inputs, x)\n","model.summary()"],"metadata":{"id":"LEnuu4F2id4E","executionInfo":{"status":"ok","timestamp":1699322478973,"user_tz":-480,"elapsed":323,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"colab":{"base_uri":"https://localhost:8080/"},"outputId":"6f2e6f59-26d1-4961-fc88-819c23dace72"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["Model: \"model_1\"\n","_________________________________________________________________\n"," Layer (type) Output Shape Param # \n","=================================================================\n"," input (InputLayer) [(None, 49)] 0 \n"," \n"," fc1 (Dense) (None, 20) 1000 \n"," \n"," dropout_1 (Dropout) (None, 20) 0 \n"," \n"," output (Dense) (None, 1) 21 \n"," \n","=================================================================\n","Total params: 1,021\n","Trainable params: 1,021\n","Non-trainable params: 0\n","_________________________________________________________________\n"]}]},{"cell_type":"code","source":["print(len(traingenerator))\n","print(traingenerator[0])\n","print(traingenerator[1])\n","print(traingenerator[1][0])\n","print(traingenerator[1][0][24][24])\n","#list(traingenerator[1][0][i][24] for i in range(len(traingenerator[1][0])))\n","\n","#y_true = np.concatenate([traingenerator[i][0][24][24] for i in range(len(traingenerator))])\n","#print(y_true)\n","#print(len(y_true))\n"],"metadata":{"id":"PDQjEb95M7TS","executionInfo":{"status":"ok","timestamp":1699322108535,"user_tz":-480,"elapsed":18,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"colab":{"base_uri":"https://localhost:8080/"},"outputId":"1cbbc4fa-2c7d-4a51-dfdd-bdb22b5f7aa6"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["5657\n","(array([[0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0.99953, 0.99953, 0.99953, ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0. , ..., 0.9997 , 0.9997 , 0. ],\n"," ...,\n"," [0. , 0. , 0. , ..., 0.99863, 0.99863, 0.99863],\n"," [0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0.9984 , ..., 0.9984 , 0.9984 , 0.9984 ]]), array([7.50137000e+05, 5.30814400e+06, 1.60742798e+09, 5.68618500e+06,\n"," 2.06805400e+06, 2.08902200e+06, 5.79304700e+06, 2.04671000e+06,\n"," 1.60887454e+09, 5.39167200e+06, 2.07567400e+06, 2.12872300e+06,\n"," 2.09441400e+06, 2.07265300e+06, 2.07629600e+06, 5.91102800e+06,\n"," 3.99616800e+06, 7.34122000e+05, 4.97703900e+06, 2.07269800e+06,\n"," 3.91260800e+06, 1.60746130e+09, 2.06360900e+06, 2.08419200e+06,\n"," 7.41983000e+05, 1.60872833e+09, 3.89531900e+06, 7.40941000e+05,\n"," 1.60876208e+09, 2.06330800e+06, 3.93688300e+06, 2.09518700e+06,\n"," 2.10698100e+06, 1.60877408e+09, 7.17553000e+05, 5.57969400e+06,\n"," 3.98977100e+06, 2.09508700e+06, 1.60897449e+09, 2.03651500e+06,\n"," 3.92950000e+06, 3.89813500e+06, 1.61114561e+09, 7.34345000e+05,\n"," 3.96538300e+06, 2.05524300e+06, 1.60740696e+09, 3.93969500e+06,\n"," 2.09870700e+06]))\n","(array([[0.99896, 0.99896, 0.99896, ..., 0.99896, 0.99896, 0.99896],\n"," [0. , 0. , 0. , ..., 0. , 0.99799, 0. ],\n"," [0.9993 , 0. , 0.9993 , ..., 0.9993 , 0.9993 , 0. ],\n"," ...,\n"," [0.99878, 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0. , ..., 0. , 0.99774, 0.99774],\n"," [0. , 0. , 0. , ..., 0. , 0. , 0. ]]), array([2.05525600e+06, 7.55634000e+05, 1.61121035e+09, 2.10063500e+06,\n"," 3.93218300e+06, 1.60747219e+09, 3.93359800e+06, 2.12817100e+06,\n"," 3.97778800e+06, 1.61097126e+09, 5.89298500e+06, 7.45790000e+05,\n"," 2.13835100e+06, 3.92870100e+06, 2.11767600e+06, 7.33134000e+05,\n"," 3.92921300e+06, 3.89861500e+06, 1.60893476e+09, 1.61119926e+09,\n"," 7.04159000e+05, 2.07061100e+06, 1.60889160e+09, 2.07048400e+06,\n"," 3.98092400e+06, 3.96250100e+06, 1.61112222e+09, 5.66664200e+06,\n"," 5.38685700e+06, 2.09398700e+06, 2.04099200e+06, 1.61095711e+09,\n"," 2.12417000e+06, 3.92484500e+06, 1.61116545e+09, 3.92056700e+06,\n"," 7.33345000e+05, 3.92990000e+06, 5.12127700e+06, 1.61108955e+09,\n"," 3.98647300e+06, 5.99137100e+06, 2.03731500e+06, 3.89592500e+06,\n"," 5.42246200e+06, 2.07798200e+06, 7.44137000e+05, 2.08869000e+06,\n"," 1.61099750e+09]))\n","[[0.99896 0.99896 0.99896 ... 0.99896 0.99896 0.99896]\n"," [0. 0. 0. ... 0. 0.99799 0. ]\n"," [0.9993 0. 0.9993 ... 0.9993 0.9993 0. ]\n"," ...\n"," [0.99878 0. 0. ... 0. 0. 0. ]\n"," [0. 0. 0. ... 0. 0.99774 0.99774]\n"," [0. 0. 0. ... 0. 0. 0. ]]\n","0.99779\n"]}]},{"cell_type":"code","source":["# Execute Main Block\n","\n","print(len(traingenerator))\n","print(len(testgenerator))\n","\n","if Train:\n"," print('Build model...')\n","\n"," #inputs = Input(shape=[networkinputlen, ], name='input')\n"," #x = Dense(hidden, input_shape=(networkinputlen, ), activation='relu', name='fc1')(inputs) #\n"," ## x = Dense(hidden, activation='relu', name='fc2')(x)\n"," #x = Dropout(0.2)(x)\n"," #x = Dense(1, activation='sigmoid', name='output')(x)\n"," # # x = Dense(2, activation='softmax', name='output')(x)\n"," #model = Model(inputs, x)\n","\n"," optimizer = Adam(learning_rate=0.001)\n"," #optimizer = SGD(lr=0.00001,decay=1e-6,momentum=0.9,nesterov=True)\n","\n"," #model.compile(optimizer, loss='mse',metrics='accuracy')#metrics=['accuracy'] metrics=[tensorflow.keras.metrics.Accuracy()]\n"," #model.compile(optimizer, loss='mse',metrics=[tensorflow.keras.metrics.MeanSquaredError()])#metrics=['accuracy'] metrics=[tensorflow.keras.metrics.Accuracy()]\n"," model.compile(optimizer, loss='mean_squared_error', metrics=[tensorflow.keras.metrics.Accuracy()])#metrics=['accuracy']\n"," #model.compile(optimizer='rmsprop', loss='binary_crossentropy',metrics=[tensorflow.keras.metrics.BinaryAccuracy()])\n","\n"," #original\n"," #model.compile(optimizer, loss='mean_squared_error',metrics=['accuracy'])\n"," #model.compile(optimizer, loss='loss='binary_crossentropy',metrics=['accuracy'])\n"," #model.compile(optimizer, loss='categorical_crossentropy',metrics=['accuracy']) # for 2 output\n","\n"," history = LossHistory()\n","\n"," filepath=\"aweightsI\"+str(resize) + 'H' + str(hidden) + \"-{epoch:02d}-{val_accuracy:.3f}.h5\"\n"," #checkpoint = ModelCheckpoint(filepath,monitor='val_accuracy',mode='max' ,save_best_only='True',period=10)\n"," #aa = np.concatenate([traingenerator[i][0][24] for i in range(len(traingenerator))])\n"," #print(np.count_nonzero(aa),len(aa))\n"," #bb = [traingenerator[i][0] for i in range(len(traingenerator))]\n"," #bb=[bb[i][0] for i in range(len(traingenerator))]\n"," #bb=[bb[i] for i in range(49)]\n"," #print(len(bb))\n"," model.fit(traingenerator,epochs=3, validation_data=testgenerator, verbose=2, workers=1,use_multiprocessing=False,batch_size=batch_size)#callbacks=[history,checkpoint],\n"," model.summary(show_trainable=True)\n"," #history.loss_plot('epoch')\n","\n"," model.save( prefix + '.h5')\n","else:\n"," model = load_model( prefix + '.h5')\n"," model.summary()\n","\n","#model.save('/content/drive/MyDrive/training data/model')"],"metadata":{"id":"tvo94TBef7Vi","executionInfo":{"status":"ok","timestamp":1699322788791,"user_tz":-480,"elapsed":228812,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"colab":{"base_uri":"https://localhost:8080/"},"outputId":"00abcca7-64f3-49b2-a89c-207b4b41cd6d"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["5657\n","1414\n","Build model...\n","Epoch 1/3\n","5657/5657 - 77s - loss: 594248239100723200.0000 - accuracy: 0.0000e+00 - val_loss: 601152141331005440.0000 - val_accuracy: 0.0000e+00 - 77s/epoch - 14ms/step\n","Epoch 2/3\n","5657/5657 - 76s - loss: 594257791107989504.0000 - accuracy: 0.0000e+00 - val_loss: 601041365534507008.0000 - val_accuracy: 0.0000e+00 - 76s/epoch - 13ms/step\n","Epoch 3/3\n","5657/5657 - 75s - loss: 594257103913222144.0000 - accuracy: 0.0000e+00 - val_loss: 601040747059216384.0000 - val_accuracy: 0.0000e+00 - 75s/epoch - 13ms/step\n","Model: \"model_1\"\n","____________________________________________________________________________\n"," Layer (type) Output Shape Param # Trainable \n","============================================================================\n"," input (InputLayer) [(None, 49)] 0 Y \n"," \n"," fc1 (Dense) (None, 20) 1000 Y \n"," \n"," dropout_1 (Dropout) (None, 20) 0 Y \n"," \n"," output (Dense) (None, 1) 21 Y \n"," \n","============================================================================\n","Total params: 1,021\n","Trainable params: 1,021\n","Non-trainable params: 0\n","____________________________________________________________________________\n"]}]},{"cell_type":"code","source":["n_batches = len(testgenerator)\n","print(n_batches)\n","print(len(testgenerator[0][0]))\n","print(len(testgenerator[0][0][0]))\n","print(len(testgenerator[0][1]))\n","print(testgenerator[0])\n","\n","\n","\n","y_true = np.concatenate([testgenerator[i][0][24] for i in range(n_batches)])\n","#y_true = np.concatenate([testgenerator[i][1] for i in range(n_batches)])\n","\n","\n","\n","initpredictions = model.predict(testgenerator, steps=n_batches)\n","print(initpredictions)\n","\n","y_pred = (initpredictions > 0.5).astype(int)\n","y_true = np.ceil(np.reshape(y_true, [-1]))\n","\n","\n","\n","y_pred = np.reshape(y_pred, [-1])\n","print(y_true.shape, y_pred.shape)\n","print(y_true, y_pred)\n","print(np.count_nonzero(y_true),np.count_nonzero(y_pred))\n","finderrorloc = y_true == y_pred\n","indices = np.where(finderrorloc == False)\n","\n","accuracy = accuracy_score(y_true, y_pred)\n","print(accuracy)\n","#precision = precision_score(y_true, y_pred)\n","TPR = recall_score(y_true, y_pred, average=None)\n","print('TPR:',TPR)\n","f1score = f1_score(y_true, y_pred, average=None)\n","print('f1score:',f1score)\n","tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()\n","print(tn,\" \", fp,\" \", fn,\" \", tp)\n","print(confusion_matrix(y_true, y_pred).ravel())\n","specificity = tn * 1.0 / (tn + fp) # TNR\n","FPR = fp * 1.0 / (tn + fp)\n","print('FPR:',FPR)\n","#print( prefix + '.h5')\n","print('testacc:',accuracy)\n","#print('precision:',precision)\n","\n","\n","\n","cm= confusion_matrix(y_true, y_pred)\n","\n","print(cm)\n","\n","cm_normalized = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n","print(cm_normalized)\n","\n","# plot output distribution\n","initpredictions = np.array(initpredictions)\n","initpredictions = initpredictions.reshape((initpredictions.shape[0] * initpredictions.shape[1]))\n","plt.clf()\n","plt.hist(initpredictions, bins=20, label='network output')\n","plt.legend()\n","plt.savefig(prefix + 'outputhist.pdf')"],"metadata":{"id":"4r3LWJWcgkYr","executionInfo":{"status":"ok","timestamp":1699322320329,"user_tz":-480,"elapsed":30031,"user":{"displayName":"WINNIE AU YEUNG","userId":"11722732131156570153"}},"colab":{"base_uri":"https://localhost:8080/","height":1000},"outputId":"563522ed-7422-410f-a7f9-03d9dcf29f5c"},"execution_count":null,"outputs":[{"output_type":"stream","name":"stdout","text":["1414\n","49\n","49\n","49\n","(array([[0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0.99971, 0.99971, 0.99971, ..., 0. , 0. , 0. ],\n"," ...,\n"," [0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0. , ..., 0. , 0. , 0. ],\n"," [0. , 0. , 0. , ..., 0. , 0. , 0.99846]]), array([3.91680600e+06, 1.61104617e+09, 2.13266900e+06, 5.92910200e+06,\n"," 5.40897100e+06, 2.12666400e+06, 1.61110094e+09, 3.98137100e+06,\n"," 5.37984900e+06, 1.60740123e+09, 1.60894069e+09, 2.04410600e+06,\n"," 2.12726300e+06, 2.05164300e+06, 2.07447700e+06, 7.21251000e+05,\n"," 1.61103083e+09, 2.06260200e+06, 3.98690500e+06, 4.93022100e+06,\n"," 3.98807200e+06, 2.05260800e+06, 1.60871875e+09, 7.28404000e+05,\n"," 7.54235000e+05, 5.99684300e+06, 1.61099260e+09, 3.97747700e+06,\n"," 3.99679500e+06, 2.04137700e+06, 3.99757000e+06, 3.95428800e+06,\n"," 7.09356000e+05, 3.91890500e+06, 2.08959000e+06, 1.60864936e+09,\n"," 3.94131200e+06, 2.09432100e+06, 3.96928100e+06, 1.60875739e+09,\n"," 7.50201000e+05, 1.61100745e+09, 2.05690500e+06, 2.08960200e+06,\n"," 2.10206900e+06, 3.97887600e+06, 1.61112193e+09, 1.61104089e+09,\n"," 1.60894508e+09]))\n","1414/1414 [==============================] - 16s 11ms/step\n","[[1.]\n"," [1.]\n"," [1.]\n"," ...\n"," [1.]\n"," [1.]\n"," [1.]]\n","(69286,) (69286,)\n","[0. 0. 0. ... 1. 1. 1.] [1 1 1 ... 1 1 1]\n","23390 69286\n","0.33758623675778654\n","TPR: [0. 1.]\n","f1score: [0. 0.5047693]\n","0 45896 0 23390\n","[ 0 45896 0 23390]\n","FPR: 1.0\n","testacc: 0.33758623675778654\n","[[ 0 45896]\n"," [ 0 23390]]\n","[[0. 1.]\n"," [0. 1.]]\n"]},{"output_type":"display_data","data":{"text/plain":[""],"image/png":"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\n"},"metadata":{}}]},{"cell_type":"code","source":[],"metadata":{"id":"b1DHW4EohcLC"},"execution_count":null,"outputs":[]}]}
--------------------------------------------------------------------------------