├── Figures
├── readme
├── Fig1.vsd
├── Fig3.jpg
├── Fig4.jpg
├── Fig5.png
├── Fig7.png
├── Fig8.jpg
├── LSTM.jpg
├── Fig 6.png
├── Fig 9.png
├── Fig 3-4.docx
├── Figure 1.vsdx
└── Picture 1.jpg
├── Statistical result
├── Readme
├── Graphs.spv
├── Output01.spv
├── Results.docx
└── Correlation and Regression.spv
├── Implementation
├── Dataset
│ ├── readme
│ └── data_cases1.csv
├── readme
├── 4_29_2020Cov_ID_Dashboard_.ipynb
├── 5_3_2020_Covid_Prophet_Final.ipynb
└── 5_13_2020_Covid_LSTM.ipynb
└── README.md
/Figures/readme:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Statistical result/Readme:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/Implementation/Dataset/readme:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System
--------------------------------------------------------------------------------
/Figures/Fig1.vsd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig1.vsd
--------------------------------------------------------------------------------
/Figures/Fig3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig3.jpg
--------------------------------------------------------------------------------
/Figures/Fig4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig4.jpg
--------------------------------------------------------------------------------
/Figures/Fig5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig5.png
--------------------------------------------------------------------------------
/Figures/Fig7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig7.png
--------------------------------------------------------------------------------
/Figures/Fig8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig8.jpg
--------------------------------------------------------------------------------
/Figures/LSTM.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/LSTM.jpg
--------------------------------------------------------------------------------
/Figures/Fig 6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig 6.png
--------------------------------------------------------------------------------
/Figures/Fig 9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig 9.png
--------------------------------------------------------------------------------
/Figures/Fig 3-4.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Fig 3-4.docx
--------------------------------------------------------------------------------
/Figures/Figure 1.vsdx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Figure 1.vsdx
--------------------------------------------------------------------------------
/Figures/Picture 1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Figures/Picture 1.jpg
--------------------------------------------------------------------------------
/Statistical result/Graphs.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Statistical result/Graphs.spv
--------------------------------------------------------------------------------
/Statistical result/Output01.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Statistical result/Output01.spv
--------------------------------------------------------------------------------
/Statistical result/Results.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Statistical result/Results.docx
--------------------------------------------------------------------------------
/Implementation/Dataset/data_cases1.csv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Implementation/Dataset/data_cases1.csv
--------------------------------------------------------------------------------
/Statistical result/Correlation and Regression.spv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dr-mushtaq/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System/master/Statistical result/Correlation and Regression.spv
--------------------------------------------------------------------------------
/Implementation/readme:
--------------------------------------------------------------------------------
1 | https://www.youtube.com/watch?v=zlFKgMnaDXk&feature=youtu.be&fbclid=IwAR3vSH3rUeeQRvhxSzADMlqK4CY06GaSbJSaeq-mAYfHXZb9E0M8Dlor4wU
2 | https://www.youtube.com/watch?v=BKceuStrbPo
3 | Python Project – COVID-19 Spread Analysis with Flask
4 | https://data-flair.training/blogs/covid-19-spread-analysis-python/
5 | VISUALIZING & PREDICTING CORONA CASES – LATEST AI PROJECT
6 | https://aihubprojects.com/visualizing-predicting-corona-cases/?fbclid=IwAR2Nhi1mhrTQHuUNQIfDgruUD8I2Dar55HvBpf1bSCI5BQ0G3fICotI28WE
7 | https://aihubprojects.com/visualizing-predicting-corona-cases/
8 | Dect Covid-19 with phone record
9 | https://www.youtube.com/watch?v=J_OmBva8_RA&feature=youtu.be
10 | 5 Covid-19 Projects with Python and Machine Learning
11 | https://thecleverprogrammer.com/2020/11/21/covid-19-projects-with-python-and-machine-learning/?fbclid=IwAR1OQsn_T10YloV0fMcQDBJCa4gauxmKGwq19w4-KRhDgFhexhNUSP97MKM
12 | Attempting to model COVID-related deaths
13 | https://towardsdatascience.com/attempting-to-model-covid-related-deaths-3333045feffa
14 | Machine Learning Project on Covid-19 Cases Prediction with Python
15 | https://thecleverprogrammer.com/2020/11/29/covid-19-cases-prediction-with-python/
16 | https://github.com/SeanPLeary/time-series-h2o-automl-example?fbclid=IwAR2pfRMurZRp_x4Y7ULt1xyQ8Y9wo6YngtAtKQQylhPIleta8Jj-JaOA0lg
17 | 10 Machine Learning Projects on Time Series Forecasting
18 | https://amankharwal.medium.com/10-machine-learning-projects-on-time-series-forecasting-ee0368420ccd
19 | Covid or just a Cough? AI for detecting COVID-19 from Cough Sounds
20 | https://www.kdnuggets.com/2020/12/covid-cough-ai-detecting-sounds.html?fbclid=IwAR3rvlRVAver2FwqyNRO2P6RKQXpl3TfKN5hyLhBCfqsVfVUIsuFDl_Phc8
21 | Develop A Covid-19 Live Web App With Python Django
22 | https://www.udemy.com/course/develop-a-covid-19-live-web-app-with-python-django/learn/lecture/21573382#overview
23 | AI, Machine Learning Tools Help Predict COVID-19 Outcomes
24 | https://healthitanalytics.com/news/ai-machine-learning-tools-help-predict-covid-19-outcomes?fbclid=IwAR1agRS3KCjp67LQkT_Xf6Yo7QB2OInHMmKWBzGznHhKINFeAQSylgStXVs
25 | Time Series Analysis Real World Projects in Python
26 | https://www.udemy.com/course/time-series-analysis-real-world-projects-in-python/learn/lecture/24586578#overview
27 |
28 |
--------------------------------------------------------------------------------
/Implementation/4_29_2020Cov_ID_Dashboard_.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "4-29-2020Cov-ID Dashboard .ipynb",
7 | "provenance": [],
8 | "collapsed_sections": []
9 | },
10 | "kernelspec": {
11 | "name": "python3",
12 | "display_name": "Python 3"
13 | }
14 | },
15 | "cells": [
16 | {
17 | "cell_type": "markdown",
18 | "metadata": {
19 | "id": "view-in-github",
20 | "colab_type": "text"
21 | },
22 | "source": [
23 | "
"
24 | ]
25 | },
26 | {
27 | "cell_type": "markdown",
28 | "metadata": {
29 | "id": "TMaTt-5yvUDc",
30 | "colab_type": "text"
31 | },
32 | "source": [
33 | "## Table of Contents\n",
34 | "\n",
35 | "
\n",
36 | "\n",
37 | "
\n",
38 | "1. Importing Needed Libary \n",
39 | "2. Colab Upgradation \n",
40 | "3. Upload the Dataset \n",
41 | "4. Read Dataset \n",
42 | "5. Data preprocessing \n",
43 | "4.1 Dataset Editing \n",
44 | "4.2 Data Description and analysis \n",
45 | "4.3 Missing values \n",
46 | "4.4 Data Sorting \n",
47 | "4.5 Data Encoding into Categorical \n",
48 | "4.4 Data Sorting \n",
49 | "4.4 Data Sorting \n",
50 | " \n",
51 | "\n",
52 | "
# New Section"
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {
58 | "id": "xbTL0mLS5XLo",
59 | "colab_type": "text"
60 | },
61 | "source": [
62 | "\n",
63 | "1. **Importing Needed Libary** \n",
64 | "\n",
65 | "This program are used to used artifical recourrent neural network called short long term memory (LSTM)\n",
66 | " predicting next week death cases of different state\n",
67 | " \n",
68 | "\n",
69 | "\n",
70 | "\n",
71 | "\n",
72 | "\n"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "metadata": {
78 | "id": "YSX92Kj0G665",
79 | "colab_type": "code",
80 | "colab": {}
81 | },
82 | "source": [
83 | "import matplotlib.pyplot as plt #6\n",
84 | "plt.style.use('fivethirtyeight') #7\n",
85 | "import math #1\n",
86 | "import pandas\n",
87 | "import pandas_datareader as web #2\n",
88 | "from sklearn.preprocessing import MinMaxScaler #3\n",
89 | "from keras.models import Sequential #4 \n",
90 | "from keras.layers import Dense, LSTM #5\n",
91 | "import pandas as pd # selected\n",
92 | "import pylab as pl\n",
93 | "import numpy as np\n",
94 | "import pandas as pd\n",
95 | "import os\n",
96 | "import numpy\n",
97 | "import scipy\n",
98 | "from sklearn.preprocessing import MinMaxScaler\n",
99 | "from sklearn.preprocessing import LabelEncoder\n",
100 | "from sklearn.tree import DecisionTreeClassifier # Import Decision Tree Classifier\n",
101 | "from sklearn.model_selection import train_test_split # Import train_test_split function\n",
102 | "from sklearn import metrics #Import scikit-learn metrics module for accuracy calculation\n",
103 | "from sklearn import preprocessing\n",
104 | "from sklearn.tree import export_graphviz\n",
105 | "from sklearn.externals.six import StringIO \n",
106 | "from IPython.display import Image \n",
107 | "import pydotplus\n",
108 | "from sklearn.ensemble import RandomForestClassifier\n",
109 | "from sklearn.metrics import confusion_matrix \n",
110 | "from sklearn.metrics import accuracy_score \n",
111 | "from sklearn.metrics import classification_report\n",
112 | "from sklearn.linear_model import LogisticRegression\n",
113 | "from sklearn.preprocessing import StandardScaler\n",
114 | "from pandas.plotting import scatter_matrix\n",
115 | "import seaborn as sns"
116 | ],
117 | "execution_count": 0,
118 | "outputs": []
119 | },
120 | {
121 | "cell_type": "code",
122 | "metadata": {
123 | "id": "HRdnMRskS8N1",
124 | "colab_type": "code",
125 | "colab": {}
126 | },
127 | "source": [
128 | "#[3]\n",
129 | "Enrol_window = 100"
130 | ],
131 | "execution_count": 0,
132 | "outputs": []
133 | },
134 | {
135 | "cell_type": "markdown",
136 | "metadata": {
137 | "id": "Rzl0FkXmK1AY",
138 | "colab_type": "text"
139 | },
140 | "source": [
141 | " 2.**Colab Upgradation** "
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "metadata": {
147 | "id": "JGsk7x5Tna9a",
148 | "colab_type": "code",
149 | "colab": {}
150 | },
151 | "source": [
152 | "# This command is used to update the latest version of tensorflow inside colab\n",
153 | "!pip install tensorflow==1.14.0"
154 | ],
155 | "execution_count": 0,
156 | "outputs": []
157 | },
158 | {
159 | "cell_type": "code",
160 | "metadata": {
161 | "id": "_Z53WTKdAj4t",
162 | "colab_type": "code",
163 | "colab": {}
164 | },
165 | "source": [
166 | "# fix random seed for reproducibility\n",
167 | "numpy.random.seed(7)"
168 | ],
169 | "execution_count": 0,
170 | "outputs": []
171 | },
172 | {
173 | "cell_type": "markdown",
174 | "metadata": {
175 | "id": "mSo57tJe6AaC",
176 | "colab_type": "text"
177 | },
178 | "source": [
179 | "3.**Upload the Dataset**\n",
180 | "\n",
181 | " This module is used to upload dataset from Hardisk "
182 | ]
183 | },
184 | {
185 | "cell_type": "code",
186 | "metadata": {
187 | "id": "8o3x_F3IWbht",
188 | "colab_type": "code",
189 | "colab": {}
190 | },
191 | "source": [
192 | "# this code is used to upload dataset from Pc to colab\n",
193 | "from google.colab import files # Please First run this cod in chrom \n",
194 | "def getLocalFiles():\n",
195 | " _files = files.upload() # upload StudentNextSessionf.csv datase\n",
196 | " if len(_files) >0: # Then run above libray \n",
197 | " for k,v in _files.items():\n",
198 | " open(k,'wb').write(v)\n",
199 | "getLocalFiles()"
200 | ],
201 | "execution_count": 0,
202 | "outputs": []
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "metadata": {
207 | "id": "MP2UU-zE62DM",
208 | "colab_type": "text"
209 | },
210 | "source": [
211 | "\n",
212 | "4. **Read Dataset**\n"
213 | ]
214 | },
215 | {
216 | "cell_type": "code",
217 | "metadata": {
218 | "id": "zoh_zm51WnO1",
219 | "colab_type": "code",
220 | "colab": {}
221 | },
222 | "source": [
223 | "##https://www.pluralsight.com/guides/handling-categorical-data-in-machine-learning-models\n",
224 | "#https://machinelearningmastery.com/power-transform-time-series-forecast-data-python/\n",
225 | "#df = pd.read_excel (r'Path where the Excel file is stored\\File name.xlsx')\n",
226 | "#https://www.shanelynn.ie/select-pandas-dataframe-rows-and-columns-using-iloc-loc-and-ix/\n",
227 | "df = pd.read_csv(r\"data_cases.csv\", header=0,index_col=0) # [1]\n",
228 | "X = df.iloc[:,0:3]\n",
229 | "y = df.iloc[:,3]\n",
230 | "#df= web.DataReader('AAPL', data_source='yahoo', start='2012', end='2019-12-17') [1]"
231 | ],
232 | "execution_count": 0,
233 | "outputs": []
234 | },
235 | {
236 | "cell_type": "code",
237 | "metadata": {
238 | "id": "vJRX-_KKmAgY",
239 | "colab_type": "code",
240 | "colab": {}
241 | },
242 | "source": [
243 | "# [2]\n",
244 | "df = pandas.read_csv('Xdata.csv',usecols=['Date','State','Recovered','Deaths'])\n",
245 | "#dataframe.drop(dataframe.index[[16452,16453]])\n",
246 | "X= df.values\n",
247 | "len(X)"
248 | ],
249 | "execution_count": 0,
250 | "outputs": []
251 | },
252 | {
253 | "cell_type": "code",
254 | "metadata": {
255 | "id": "xRz5xQGHRWrB",
256 | "colab_type": "code",
257 | "colab": {}
258 | },
259 | "source": [
260 | "df = pd.read_csv('Xdata.csv', index_col='Date', parse_dates=['Date'])\n",
261 | "df.head() # [3]"
262 | ],
263 | "execution_count": 0,
264 | "outputs": []
265 | },
266 | {
267 | "cell_type": "code",
268 | "metadata": {
269 | "id": "B8QEfc2Evza1",
270 | "colab_type": "code",
271 | "colab": {}
272 | },
273 | "source": [
274 | "# !wget https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv\n",
275 | "!gdown --id 1AsfdLrGESCQnRW5rbMz56A1KBc3Fe5aV # [10] read dataset from google drive\n"
276 | ],
277 | "execution_count": 0,
278 | "outputs": []
279 | },
280 | {
281 | "cell_type": "code",
282 | "metadata": {
283 | "id": "t6rDOZpClbZB",
284 | "colab_type": "code",
285 | "colab": {}
286 | },
287 | "source": [
288 | "#Removing unwanted Columns from the Data Frame [16]\n",
289 | "data = data.drop('Date',axis=1) \n",
290 | "data = data.drop('Adj Close',axis = 1)\n",
291 | "print('\\n\\nData after removing Date and Adj Close : ')\n",
292 | "print(data.head())"
293 | ],
294 | "execution_count": 0,
295 | "outputs": []
296 | },
297 | {
298 | "cell_type": "markdown",
299 | "metadata": {
300 | "id": "Pl4_Vcie85p5",
301 | "colab_type": "text"
302 | },
303 | "source": [
304 | "\n",
305 | "\n",
306 | "5.**Data preprocessing**\n",
307 | "\n",
308 | "\n"
309 | ]
310 | },
311 | {
312 | "cell_type": "markdown",
313 | "metadata": {
314 | "id": "pT3ekeKYCYfr",
315 | "colab_type": "text"
316 | },
317 | "source": [
318 | " **5.1 Dataset Editing**"
319 | ]
320 | },
321 | {
322 | "cell_type": "code",
323 | "metadata": {
324 | "id": "swOcYkYrCRSj",
325 | "colab_type": "code",
326 | "colab": {}
327 | },
328 | "source": [
329 | " d3=dataframe2.iloc[:-1] # [4]"
330 | ],
331 | "execution_count": 0,
332 | "outputs": []
333 | },
334 | {
335 | "cell_type": "code",
336 | "metadata": {
337 | "id": "cj3AyzLZF3R2",
338 | "colab_type": "code",
339 | "colab": {}
340 | },
341 | "source": [
342 | "# Convert the datafram to a numpy array\n",
343 | "dataset=data.values"
344 | ],
345 | "execution_count": 0,
346 | "outputs": []
347 | },
348 | {
349 | "cell_type": "code",
350 | "metadata": {
351 | "id": "KB9b4xdOrH59",
352 | "colab_type": "code",
353 | "colab": {}
354 | },
355 | "source": [
356 | "df = df.iloc[:, 4:] # taking first foure colum [10]"
357 | ],
358 | "execution_count": 0,
359 | "outputs": []
360 | },
361 | {
362 | "cell_type": "code",
363 | "metadata": {
364 | "id": "9FnbVCtWRTzP",
365 | "colab_type": "code",
366 | "colab": {}
367 | },
368 | "source": [
369 | "#removing all rows with zero values on their confirmed field[13]\n",
370 | "df = df[df[\"Confirmed\"] > 0]\n",
371 | "df.describe()"
372 | ],
373 | "execution_count": 0,
374 | "outputs": []
375 | },
376 | {
377 | "cell_type": "code",
378 | "metadata": {
379 | "id": "CB-4-4CHxa_o",
380 | "colab_type": "code",
381 | "colab": {}
382 | },
383 | "source": [
384 | "#Split data into predictors and target [14]\n",
385 | "concrete_data_columns = concrete_data.columns\n",
386 | "predictors = concrete_data[concrete_data_columns[concrete_data_columns != 'Strength']] # all columns except Strength\n",
387 | "target = concrete_data['Strength'] # Strength column"
388 | ],
389 | "execution_count": 0,
390 | "outputs": []
391 | },
392 | {
393 | "cell_type": "markdown",
394 | "metadata": {
395 | "id": "SaGc_loUBjRH",
396 | "colab_type": "text"
397 | },
398 | "source": [
399 | "5.2 **Data Description and analysis**"
400 | ]
401 | },
402 | {
403 | "cell_type": "code",
404 | "metadata": {
405 | "id": "YjBH1EXroPmh",
406 | "colab_type": "code",
407 | "colab": {}
408 | },
409 | "source": [
410 | "df.describe() #[2]"
411 | ],
412 | "execution_count": 0,
413 | "outputs": []
414 | },
415 | {
416 | "cell_type": "code",
417 | "metadata": {
418 | "id": "WBEKOpF-pjQ3",
419 | "colab_type": "code",
420 | "colab": {}
421 | },
422 | "source": [
423 | "df.columns #[2] show colums in dataset "
424 | ],
425 | "execution_count": 0,
426 | "outputs": []
427 | },
428 | {
429 | "cell_type": "code",
430 | "metadata": {
431 | "id": "Gqyio6sxpx2C",
432 | "colab_type": "code",
433 | "colab": {}
434 | },
435 | "source": [
436 | "df.astype(str)# [2] Convert dataset into string "
437 | ],
438 | "execution_count": 0,
439 | "outputs": []
440 | },
441 | {
442 | "cell_type": "code",
443 | "metadata": {
444 | "id": "zF6e2mtMErz5",
445 | "colab_type": "code",
446 | "colab": {}
447 | },
448 | "source": [
449 | "df.shape # Dimension of datasets"
450 | ],
451 | "execution_count": 0,
452 | "outputs": []
453 | },
454 | {
455 | "cell_type": "code",
456 | "metadata": {
457 | "id": "dpko9Z7cE31t",
458 | "colab_type": "code",
459 | "colab": {}
460 | },
461 | "source": [
462 | "df.head(10) # we will see first 10 row of the dataset"
463 | ],
464 | "execution_count": 0,
465 | "outputs": []
466 | },
467 | {
468 | "cell_type": "code",
469 | "metadata": {
470 | "id": "OuRp5yD64AGa",
471 | "colab_type": "code",
472 | "colab": {}
473 | },
474 | "source": [
475 | "daily_cases.shape # Test [10]"
476 | ],
477 | "execution_count": 0,
478 | "outputs": []
479 | },
480 | {
481 | "cell_type": "code",
482 | "metadata": {
483 | "id": "EixOwc_oQVnk",
484 | "colab_type": "code",
485 | "colab": {}
486 | },
487 | "source": [
488 | "#Top 10 Countries by Confirmed Cases, Deaths & Recoveries [13]\n",
489 | "grouped_df = df.groupby(\"County\").max()"
490 | ],
491 | "execution_count": 0,
492 | "outputs": []
493 | },
494 | {
495 | "cell_type": "code",
496 | "metadata": {
497 | "id": "oxpg7mg9X-OR",
498 | "colab_type": "code",
499 | "colab": {}
500 | },
501 | "source": [
502 | "# Confirmed cases[13]\n",
503 | "print(grouped_df.sort_values(\"Confirmed\", ascending=False)[\"Confirmed\"][:10])"
504 | ],
505 | "execution_count": 0,
506 | "outputs": []
507 | },
508 | {
509 | "cell_type": "code",
510 | "metadata": {
511 | "id": "nLT33ParYdAV",
512 | "colab_type": "code",
513 | "colab": {}
514 | },
515 | "source": [
516 | "# Deaths [13]\n",
517 | "print(grouped_df.sort_values(\"Deaths\", ascending=False)[\"Deaths\"][:10])"
518 | ],
519 | "execution_count": 0,
520 | "outputs": []
521 | },
522 | {
523 | "cell_type": "code",
524 | "metadata": {
525 | "id": "L7-2_F6qYvZO",
526 | "colab_type": "code",
527 | "colab": {}
528 | },
529 | "source": [
530 | "# Recoveries\n",
531 | "print(grouped_df.sort_values(\"Recovered\", ascending=False)[\"Recovered\"][:10])"
532 | ],
533 | "execution_count": 0,
534 | "outputs": []
535 | },
536 | {
537 | "cell_type": "markdown",
538 | "metadata": {
539 | "colab_type": "text",
540 | "id": "udLxKyKMuWc6"
541 | },
542 | "source": [
543 | "**5.3 Missing Values**"
544 | ]
545 | },
546 | {
547 | "cell_type": "code",
548 | "metadata": {
549 | "id": "uDAulKRvqsCv",
550 | "colab_type": "code",
551 | "colab": {}
552 | },
553 | "source": [
554 | "### finding all columns that have nan:[2]\n",
555 | "droping_list_all=[]\n",
556 | "for j in range(1,4):\n",
557 | " if not df.iloc[:, j].notnull().all():\n",
558 | " droping_list_all.append(j) \n",
559 | " #print(df.iloc[:,j].unique())\n",
560 | "droping_list_all"
561 | ],
562 | "execution_count": 0,
563 | "outputs": []
564 | },
565 | {
566 | "cell_type": "code",
567 | "metadata": {
568 | "id": "wX6WfCfZq-wy",
569 | "colab_type": "code",
570 | "colab": {}
571 | },
572 | "source": [
573 | "# filling nan with mean in any columns [2]\n",
574 | "for j in range(2,4): \n",
575 | " df.iloc[:,j]=df.iloc[:,j].fillna(df.iloc[:,j].mean()) "
576 | ],
577 | "execution_count": 0,
578 | "outputs": []
579 | },
580 | {
581 | "cell_type": "code",
582 | "metadata": {
583 | "id": "8OxXAMDvrPZV",
584 | "colab_type": "code",
585 | "colab": {}
586 | },
587 | "source": [
588 | "# another sanity check to make sure that there are not more any nan\n",
589 | "df.isnull().sum()\n"
590 | ],
591 | "execution_count": 0,
592 | "outputs": []
593 | },
594 | {
595 | "cell_type": "code",
596 | "metadata": {
597 | "id": "wGPHMsWg8yU-",
598 | "colab_type": "code",
599 | "colab": {}
600 | },
601 | "source": [
602 | "#Count the Null Columns [14]\n",
603 | "train = pd.read_csv(\"train.csv\")\n",
604 | "null_columns=train.columns[train.isnull().any()]\n",
605 | "train[null_columns].isnull().sum()"
606 | ],
607 | "execution_count": 0,
608 | "outputs": []
609 | },
610 | {
611 | "cell_type": "code",
612 | "metadata": {
613 | "id": "PDELWczZ9CvV",
614 | "colab_type": "code",
615 | "colab": {}
616 | },
617 | "source": [
618 | "#Single Column Is Null [14]\n",
619 | "print(train[train[\"Electrical\"].isnull()][null_columns])"
620 | ],
621 | "execution_count": 0,
622 | "outputs": []
623 | },
624 | {
625 | "cell_type": "code",
626 | "metadata": {
627 | "id": "r25aSrQ_9Lyd",
628 | "colab_type": "code",
629 | "colab": {}
630 | },
631 | "source": [
632 | "#All Null Columns[14]\n",
633 | "print(train[train.isnull().any(axis=1)][null_columns].head())"
634 | ],
635 | "execution_count": 0,
636 | "outputs": []
637 | },
638 | {
639 | "cell_type": "markdown",
640 | "metadata": {
641 | "id": "PyPgneFu_v7J",
642 | "colab_type": "text"
643 | },
644 | "source": [
645 | "**5.4 Data Sorting**"
646 | ]
647 | },
648 | {
649 | "cell_type": "code",
650 | "metadata": {
651 | "id": "2EYw6AtRAXPt",
652 | "colab_type": "code",
653 | "colab": {}
654 | },
655 | "source": [
656 | "df=df.sort_values('Date') #[4]"
657 | ],
658 | "execution_count": 0,
659 | "outputs": []
660 | },
661 | {
662 | "cell_type": "code",
663 | "metadata": {
664 | "id": "fONM5PbRxJPP",
665 | "colab_type": "code",
666 | "colab": {}
667 | },
668 | "source": [
669 | "# testing [10]\n",
670 | "daily_cases = df.sum(axis=0)\n",
671 | "daily_cases.index = pd.to_datetime(daily_cases.index)\n",
672 | "daily_cases.head()"
673 | ],
674 | "execution_count": 0,
675 | "outputs": []
676 | },
677 | {
678 | "cell_type": "markdown",
679 | "metadata": {
680 | "id": "bTghoeL4C_Cn",
681 | "colab_type": "text"
682 | },
683 | "source": [
684 | " *5.5* **Data Encoding into Categorical**"
685 | ]
686 | },
687 | {
688 | "cell_type": "code",
689 | "metadata": {
690 | "id": "2OWLnFO3fgoE",
691 | "colab_type": "code",
692 | "colab": {}
693 | },
694 | "source": [
695 | "#=============================================================>Encoding categorical data\n",
696 | "#https://discuss.analyticsvidhya.com/t/error-could-not-convert-string-to-float-while-running-randomforest-model-in-python/4855/2\n",
697 | "#https://medium.com/@contactsunny/label-encoder-vs-one-hot-encoder-in-machine-learning-3fc273365621\n",
698 | "##https://www.pluralsight.com/guides/handling-categorical-data-in-machine-learning-models\n",
699 | "feature_cols = ['Student ID', 'final_result','num_of_prev_attempts','Age','highest_education','Region','Gender','disability','date_submitted','studied_credits','score','sum_click']\n",
700 | "from sklearn.preprocessing import LabelEncoder\n",
701 | "labelencoder_X = LabelEncoder()\n",
702 | "X[:,0] = labelencoder_X.fit_transform(X[:,0])\n",
703 | "X[:,1] = labelencoder_X.fit_transform(X[:,1])\n",
704 | "X[:,2] = labelencoder_X.fit_transform(X[:,2])\n",
705 | "X[:,3] = labelencoder_X.fit_transform(X[:,3])\n",
706 | "X[:,4] = labelencoder_X.fit_transform(X[:,4])\n",
707 | "X[:,5] = labelencoder_X.fit_transform(X[:,5])\n",
708 | "X[:,6] = labelencoder_X.fit_transform(X[:,6])\n",
709 | "X[:,7] = labelencoder_X.fit_transform(X[:,7])\n",
710 | "X[:,8] = labelencoder_X.fit_transform(X[:,8])\n",
711 | "X[:,9] = labelencoder_X.fit_transform(X[:,9])\n",
712 | "X[:,10] = labelencoder_X.fit_transform(X[:,10])\n",
713 | "X[:,11] = labelencoder_X.fit_transform(X[:,11])"
714 | ],
715 | "execution_count": 0,
716 | "outputs": []
717 | },
718 | {
719 | "cell_type": "code",
720 | "metadata": {
721 | "id": "GUWjXWnMEQK7",
722 | "colab_type": "code",
723 | "colab": {}
724 | },
725 | "source": [
726 | "# for classification we need to divide our target variable into categories\n",
727 | "from keras.utils import to_categorical\n",
728 | "y_train = to_categorical(y_train)"
729 | ],
730 | "execution_count": 0,
731 | "outputs": []
732 | },
733 | {
734 | "cell_type": "code",
735 | "metadata": {
736 | "id": "cmR5mrIhEQIH",
737 | "colab_type": "code",
738 | "colab": {}
739 | },
740 | "source": [
741 | ""
742 | ],
743 | "execution_count": 0,
744 | "outputs": []
745 | },
746 | {
747 | "cell_type": "markdown",
748 | "metadata": {
749 | "id": "5F8biWQz4mq5",
750 | "colab_type": "text"
751 | },
752 | "source": [
753 | "*4.6* **Data Normalizaton**"
754 | ]
755 | },
756 | {
757 | "cell_type": "code",
758 | "metadata": {
759 | "id": "a-k0DTjiz2Qq",
760 | "colab_type": "code",
761 | "colab": {}
762 | },
763 | "source": [
764 | "# Normalize the data by substracting the mean and dividing by the standard deviation [14]\n",
765 | "# Data normaliz for regression model\n",
766 | "concrete_data_columns = concrete_data.columns\n",
767 | "predictors = concrete_data[concrete_data_columns[concrete_data_columns != 'Strength']] # all columns except Strength\n",
768 | "target = concrete_data['Strength'] # Strength column"
769 | ],
770 | "execution_count": 0,
771 | "outputs": []
772 | },
773 | {
774 | "cell_type": "markdown",
775 | "metadata": {
776 | "id": "ooJN9wu2tYa4",
777 | "colab_type": "text"
778 | },
779 | "source": [
780 | "**5.0 Statiscial Analysis**"
781 | ]
782 | },
783 | {
784 | "cell_type": "code",
785 | "metadata": {
786 | "id": "X2eXsqXYpm8b",
787 | "colab_type": "code",
788 | "colab": {}
789 | },
790 | "source": [
791 | "# Correlations among columns [2]\n",
792 | "plt.matshow(df.corr(method='spearman'),vmax=1,vmin=-1,cmap='PRGn')\n",
793 | "plt.title('without resampling', size=15)\n",
794 | "plt.colorbar()\n",
795 | "plt.show()"
796 | ],
797 | "execution_count": 0,
798 | "outputs": []
799 | },
800 | {
801 | "cell_type": "code",
802 | "metadata": {
803 | "id": "oZwUcDjSEIih",
804 | "colab_type": "code",
805 | "colab": {}
806 | },
807 | "source": [
808 | "# normalize the dataset\n",
809 | "scaler = MinMaxScaler(feature_range=(0, 1))\n",
810 | "dataset = scaler.fit_transform(dataset)"
811 | ],
812 | "execution_count": 0,
813 | "outputs": []
814 | },
815 | {
816 | "cell_type": "markdown",
817 | "metadata": {
818 | "id": "3dmLdRYDB84U",
819 | "colab_type": "text"
820 | },
821 | "source": [
822 | "6. **Data Ploting**\n"
823 | ]
824 | },
825 | {
826 | "cell_type": "code",
827 | "metadata": {
828 | "id": "eFzAWsNfBWKD",
829 | "colab_type": "code",
830 | "colab": {}
831 | },
832 | "source": [
833 | "# ploting [4]\n",
834 | "plt.figure(figsize = (18,9))\n",
835 | "plt.plot(range(df.shape[0]),(df['Recovered']+df['Deaths'])/2.0)\n",
836 | "plt.xticks(range(0,df.shape[0],500),df['Date'].loc[::500],rotation=45)\n",
837 | "plt.xlabel('Date',fontsize=18)\n",
838 | "plt.ylabel('Death and Recoverd',fontsize=18)\n",
839 | "plt.show()\n"
840 | ],
841 | "execution_count": 0,
842 | "outputs": []
843 | },
844 | {
845 | "cell_type": "code",
846 | "metadata": {
847 | "id": "0MOK018gFf-Y",
848 | "colab_type": "code",
849 | "colab": {}
850 | },
851 | "source": [
852 | "df.hist(column='Deaths', bins=50) # PLOT histogram from dataset \n",
853 | "plt.show ()"
854 | ],
855 | "execution_count": 0,
856 | "outputs": []
857 | },
858 | {
859 | "cell_type": "markdown",
860 | "metadata": {
861 | "id": "KFu9c2SfLDRN",
862 | "colab_type": "text"
863 | },
864 | "source": [
865 | ""
866 | ]
867 | },
868 | {
869 | "cell_type": "code",
870 | "metadata": {
871 | "colab_type": "code",
872 | "id": "NWno337-z89f",
873 | "colab": {}
874 | },
875 | "source": [
876 | "# plot diagram (1)\n",
877 | "def plot_features_distribution(features, title,isLog=False): \n",
878 | " plt.figure(figsize=(12,6))\n",
879 | " plt.title(title)\n",
880 | " for feature in features:\n",
881 | " if(isLog):\n",
882 | " sns.distplot(np.log1p(df[feature]),kde=True,hist=False, bins=120, label=feature)\n",
883 | " else:\n",
884 | " sns.distplot(df[feature],kde=True,hist=False, bins=120, label=feature)\n",
885 | " plt.xlabel('')\n",
886 | " plt.legend()\n",
887 | " plt.show()"
888 | ],
889 | "execution_count": 0,
890 | "outputs": []
891 | },
892 | {
893 | "cell_type": "code",
894 | "metadata": {
895 | "colab_type": "code",
896 | "id": "67xm9epV0JJC",
897 | "colab": {}
898 | },
899 | "source": [
900 | "# plot diagram (2)\n",
901 | "def plot_count(feature, title,size=1,df=df):\n",
902 | " f, ax = plt.subplots(1,1, figsize=(4*size,4))\n",
903 | " total = float(len(df))\n",
904 | " g = sns.countplot(df[feature], order = df[feature].value_counts().index[:30], palette='Set3')\n",
905 | " g.set_title(\"Number and percentage of {}\".format(title))\n",
906 | " if(size > 2):\n",
907 | " plt.xticks(rotation=90, size=8)\n",
908 | " for p in ax.patches:\n",
909 | " height = p.get_height()\n",
910 | " ax.text(p.get_x()+p.get_width()/2.,\n",
911 | " height + 3,\n",
912 | " '{:1.2f}%'.format(100*height/total),\n",
913 | " ha=\"center\") \n",
914 | " plt.show() "
915 | ],
916 | "execution_count": 0,
917 | "outputs": []
918 | },
919 | {
920 | "cell_type": "code",
921 | "metadata": {
922 | "colab_type": "code",
923 | "id": "WtUMzmIl0YXh",
924 | "colab": {}
925 | },
926 | "source": [
927 | "# plot diagram (3)\n",
928 | "plot_count('State','Confirmed')"
929 | ],
930 | "execution_count": 0,
931 | "outputs": []
932 | },
933 | {
934 | "cell_type": "code",
935 | "metadata": {
936 | "id": "PvIrPaXRUi2i",
937 | "colab_type": "code",
938 | "colab": {}
939 | },
940 | "source": [
941 | "# Bar Chart [7,8]\n",
942 | "df=df[:57]\n",
943 | "df.plot('State',['Recovered','Deaths'],kind = 'bar') # Kind=Bar, line, box\n"
944 | ],
945 | "execution_count": 0,
946 | "outputs": []
947 | },
948 | {
949 | "cell_type": "code",
950 | "metadata": {
951 | "id": "7QSi_2eVjC_I",
952 | "colab_type": "code",
953 | "colab": {}
954 | },
955 | "source": [
956 | "# [9]\n",
957 | "from matplotlib import pyplot\n",
958 | "pyplot.figure(1)\n",
959 | "# line plot\n",
960 | "pyplot.subplot(211)\n",
961 | "pyplot.plot(Date)\n",
962 | "# histogram\n",
963 | "pyplot.subplot(212)\n",
964 | "pyplot.hist(Deate)\n",
965 | "pyplot.show()"
966 | ],
967 | "execution_count": 0,
968 | "outputs": []
969 | },
970 | {
971 | "cell_type": "code",
972 | "metadata": {
973 | "id": "EhqXHGV0Lgcq",
974 | "colab_type": "code",
975 | "colab": {}
976 | },
977 | "source": [
978 | "#https://www.datacamp.com/courses/preprocessing-for-machine-learning-in-python\n",
979 | "#https://www.geeksforgeeks.org/data-preprocessing-machine-learning-python/\n",
980 | "#https://towardsdatascience.com/introduction-to-data-preprocessing-in-machine-learning-a9fa83a5dc9d\n",
981 | "#https://machinelearningmastery.com/prepare-data-machine-learning-python-scikit-learn/\n",
982 | "#https://medium.com/data-py-blog/data-preprocessing-for-python-2ab52cbc0edd\n",
983 | "#https://medium.com/datadriveninvestor/data-preprocessing-for-machine-learning-188e9eef1d2c"
984 | ],
985 | "execution_count": 0,
986 | "outputs": []
987 | },
988 | {
989 | "cell_type": "markdown",
990 | "metadata": {
991 | "id": "H7r5nhwzKdFT",
992 | "colab_type": "text"
993 | },
994 | "source": [
995 | " 7.**Feature Importance**\n",
996 | " "
997 | ]
998 | },
999 | {
1000 | "cell_type": "code",
1001 | "metadata": {
1002 | "id": "ngVFSyIiKz8u",
1003 | "colab_type": "code",
1004 | "colab": {}
1005 | },
1006 | "source": [
1007 | "#How to Calculate Feature Importance With Python\n",
1008 | "#https://machinelearningmastery.com/calculate-feature-importance-with-python/?fbclid=IwAR0uvlTGLX2qDJ8bu78fo8HQxq2msGX6mbu9QIQzw9YdUPKeZrOB8Mf4_44\n",
1009 | "#https://machinelearningmastery.com/calculate-feature-importance-with-python/\n",
1010 | " from sklearn.datasets import make_regression\n",
1011 | "from sklearn.ensemble import RandomForestRegressor\n",
1012 | "from matplotlib import pyplot\n",
1013 | "x1=atop(X);\n",
1014 | "model = RandomForestRegressor()\n",
1015 | "# fit the model\n",
1016 | "model.fit(X, y)"
1017 | ],
1018 | "execution_count": 0,
1019 | "outputs": []
1020 | },
1021 | {
1022 | "cell_type": "markdown",
1023 | "metadata": {
1024 | "id": "YQDUyjWsDbZo",
1025 | "colab_type": "text"
1026 | },
1027 | "source": [
1028 | "8.**Data Spliting**"
1029 | ]
1030 | },
1031 | {
1032 | "cell_type": "code",
1033 | "metadata": {
1034 | "id": "prGtyX2iaBLU",
1035 | "colab_type": "code",
1036 | "colab": {}
1037 | },
1038 | "source": [
1039 | "X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) # 70% training and 30% test\n"
1040 | ],
1041 | "execution_count": 0,
1042 | "outputs": []
1043 | },
1044 | {
1045 | "cell_type": "code",
1046 | "metadata": {
1047 | "id": "wdHiejJ2R5b7",
1048 | "colab_type": "code",
1049 | "colab": {}
1050 | },
1051 | "source": [
1052 | "# [3]\n",
1053 | "feature_train, label_train, feature_test, label_test = load_data(df, 'Deaths', Enrol_window, True)\n"
1054 | ],
1055 | "execution_count": 0,
1056 | "outputs": []
1057 | },
1058 | {
1059 | "cell_type": "code",
1060 | "metadata": {
1061 | "id": "_L_zdec1SPoH",
1062 | "colab_type": "code",
1063 | "colab": {}
1064 | },
1065 | "source": [
1066 | "def load_data(datasetname, column, seq_len, normalise_window):\n",
1067 | " # A support function to help prepare datasets for an RNN/LSTM/GRU\n",
1068 | " data = datasetname.loc[:,column]\n",
1069 | "\n",
1070 | " sequence_length = seq_len + 1\n",
1071 | " result = []\n",
1072 | " for index in range(len(data) - sequence_length):\n",
1073 | " result.append(data[index: index + sequence_length])\n",
1074 | " \n",
1075 | " if normalise_window:\n",
1076 | " #result = sc.fit_transform(result)\n",
1077 | " result = normalise_windows(result)\n",
1078 | "\n",
1079 | " result = np.array(result)\n",
1080 | " #Last 10% is used for validation test, first 90% for training\n",
1081 | " row = round(0.9 * result.shape[0])\n",
1082 | " train = result[:int(row), :]\n",
1083 | " np.random.shuffle(train)\n",
1084 | " x_train = train[:, :-1]\n",
1085 | " y_train = train[:, -1]\n",
1086 | " x_test = result[int(row):, :-1]\n",
1087 | " y_test = result[int(row):, -1]\n",
1088 | "\n",
1089 | " x_train = np.reshape(x_train, (x_train.shape[0], x_train.shape[1], 1))\n",
1090 | " x_test = np.reshape(x_test, (x_test.shape[0], x_test.shape[1], 1)) \n",
1091 | "\n",
1092 | " return [x_train, y_train, x_test, y_test]\n"
1093 | ],
1094 | "execution_count": 0,
1095 | "outputs": []
1096 | },
1097 | {
1098 | "cell_type": "code",
1099 | "metadata": {
1100 | "id": "5kJQYO1ZSYuG",
1101 | "colab_type": "code",
1102 | "colab": {}
1103 | },
1104 | "source": [
1105 | "# [3]\n",
1106 | "def normalise_windows(window_data):\n",
1107 | " # A support function to normalize a dataset\n",
1108 | " normalised_data = []\n",
1109 | " for window in window_data:\n",
1110 | " normalised_window = [((float(p) / float(window[0])) - 1) for p in window]\n",
1111 | " normalised_data.append(normalised_window)\n",
1112 | " return normalised_data"
1113 | ],
1114 | "execution_count": 0,
1115 | "outputs": []
1116 | },
1117 | {
1118 | "cell_type": "code",
1119 | "metadata": {
1120 | "id": "U_tdcIaGq32o",
1121 | "colab_type": "code",
1122 | "colab": {}
1123 | },
1124 | "source": [
1125 | "# create the training dataset\n",
1126 | "# create the scaled training dataset\n",
1127 | "train_data=scaled_data[0:training_data_len,:]\n",
1128 | "# split the data into x_train and y_train dataset\n",
1129 | "x_train = []\n",
1130 | "y_train = []\n",
1131 | "\n",
1132 | "for i in range (50, len(train_data)):\n",
1133 | " x_train.append(train_data[i-50:i,0])\n",
1134 | " y_train.append(train_data[i,0])\n",
1135 | " if i<= 51:\n",
1136 | " print(x_train)\n",
1137 | " print(y_train)\n",
1138 | " print()"
1139 | ],
1140 | "execution_count": 0,
1141 | "outputs": []
1142 | },
1143 | {
1144 | "cell_type": "code",
1145 | "metadata": {
1146 | "id": "v7l1O6TJaxr3",
1147 | "colab_type": "code",
1148 | "colab": {}
1149 | },
1150 | "source": [
1151 | "# Convert the x_train and y_train to numpy arrays\n",
1152 | "x_train, y_train = np.array(x_train), np.array(y_train)\n",
1153 | "x_train"
1154 | ],
1155 | "execution_count": 0,
1156 | "outputs": []
1157 | },
1158 | {
1159 | "cell_type": "code",
1160 | "metadata": {
1161 | "id": "On-pcXAqcJGG",
1162 | "colab_type": "code",
1163 | "colab": {}
1164 | },
1165 | "source": [
1166 | "# Reshap the data\n",
1167 | "x_train=np.reshape(x_train, (x_train.shape[0], x_train.shape[1],1))\n",
1168 | "x_train.shape"
1169 | ],
1170 | "execution_count": 0,
1171 | "outputs": []
1172 | },
1173 | {
1174 | "cell_type": "code",
1175 | "metadata": {
1176 | "id": "G2WbDQA3maFZ",
1177 | "colab_type": "code",
1178 | "colab": {}
1179 | },
1180 | "source": [
1181 | "#Split into train and test data [16]\n",
1182 | "data_X = data.loc[:,data.columns != 'Close' ]\n",
1183 | "data_Y = data['Close']\n",
1184 | "train_X, test_X, train_y,test_y = train_test_split(data_X,data_Y,test_size=0.25)\n",
1185 | "print('\\n\\nTraining Set')\n",
1186 | "print(train_X.head())\n",
1187 | "print(train_y.head())"
1188 | ],
1189 | "execution_count": 0,
1190 | "outputs": []
1191 | },
1192 | {
1193 | "cell_type": "markdown",
1194 | "metadata": {
1195 | "id": "SN9GM4UrD_W3",
1196 | "colab_type": "text"
1197 | },
1198 | "source": [
1199 | "9.**Building Models**"
1200 | ]
1201 | },
1202 | {
1203 | "cell_type": "markdown",
1204 | "metadata": {
1205 | "id": "MhZR8yOwETba",
1206 | "colab_type": "text"
1207 | },
1208 | "source": [
1209 | "9.1 **Decision Tree Models**"
1210 | ]
1211 | },
1212 | {
1213 | "cell_type": "code",
1214 | "metadata": {
1215 | "id": "tzSi_BST2TJh",
1216 | "colab_type": "code",
1217 | "colab": {}
1218 | },
1219 | "source": [
1220 | "#https://www.datacamp.com/community/tutorials/decision-tree-classification-python\n",
1221 | "# Create Decision Tree classifer object\n",
1222 | "clf = DecisionTreeClassifier(criterion=\"entropy\", max_depth = 4)\n",
1223 | "# Train Decision Tree Classifer\n",
1224 | "clf = clf.fit(X_train,y_train)\n",
1225 | "#Predict the response for test dataset\n",
1226 | "y_pred = clf.predict(X_test)\n",
1227 | "print(y_pred)\n"
1228 | ],
1229 | "execution_count": 0,
1230 | "outputs": []
1231 | },
1232 | {
1233 | "cell_type": "code",
1234 | "metadata": {
1235 | "id": "6T6ktFVYdd_A",
1236 | "colab_type": "code",
1237 | "colab": {}
1238 | },
1239 | "source": [
1240 | "# build the LSTM model\n",
1241 | "model=Sequential()\n",
1242 | "model.add(LSTM(40, return_sequences=True,input_shape=(x_train.shape[1],1)))\n",
1243 | "model.add(LSTM(40, return_sequences=False))\n",
1244 | "model.add(Dense(25))\n",
1245 | "model.add(Dense(1))"
1246 | ],
1247 | "execution_count": 0,
1248 | "outputs": []
1249 | },
1250 | {
1251 | "cell_type": "code",
1252 | "metadata": {
1253 | "id": "V8B53I7gnv3F",
1254 | "colab_type": "code",
1255 | "colab": {}
1256 | },
1257 | "source": [
1258 | "# compile the model\n",
1259 | "model.compile(optimizer='adam',loss='mean_squared_error')"
1260 | ],
1261 | "execution_count": 0,
1262 | "outputs": []
1263 | },
1264 | {
1265 | "cell_type": "code",
1266 | "metadata": {
1267 | "id": "asZwD5jhoXk9",
1268 | "colab_type": "code",
1269 | "colab": {}
1270 | },
1271 | "source": [
1272 | "# train the model\n",
1273 | "model.fit(x_train,y_train,batch_size=1,epochs=1)"
1274 | ],
1275 | "execution_count": 0,
1276 | "outputs": []
1277 | },
1278 | {
1279 | "cell_type": "code",
1280 | "metadata": {
1281 | "id": "qECXeVx1vy9h",
1282 | "colab_type": "code",
1283 | "colab": {}
1284 | },
1285 | "source": [
1286 | "test_data=scaled_data[training_data_len -40:,:]\n",
1287 | "x_test= []\n",
1288 | "y_test = dataset[training_data_len:,:]\n",
1289 | "for i in range(50, len(test_data)):\n",
1290 | " x_test.append(test_data[i -50:i,0])\n"
1291 | ],
1292 | "execution_count": 0,
1293 | "outputs": []
1294 | },
1295 | {
1296 | "cell_type": "code",
1297 | "metadata": {
1298 | "id": "jfuKDYyExdz5",
1299 | "colab_type": "code",
1300 | "colab": {}
1301 | },
1302 | "source": [
1303 | "x_test=np.array(x_test)"
1304 | ],
1305 | "execution_count": 0,
1306 | "outputs": []
1307 | },
1308 | {
1309 | "cell_type": "code",
1310 | "metadata": {
1311 | "id": "SM_5z8cExsSB",
1312 | "colab_type": "code",
1313 | "colab": {}
1314 | },
1315 | "source": [
1316 | "x_test=np.reshape(x_test,(x_test.shape[0], x_test.shape[1],1))"
1317 | ],
1318 | "execution_count": 0,
1319 | "outputs": []
1320 | },
1321 | {
1322 | "cell_type": "code",
1323 | "metadata": {
1324 | "id": "jk7qbLkYyjhq",
1325 | "colab_type": "code",
1326 | "colab": {}
1327 | },
1328 | "source": [
1329 | "predictions=model.predict(x_test)\n",
1330 | "predictions=scaler.inverse_transform(predictions)"
1331 | ],
1332 | "execution_count": 0,
1333 | "outputs": []
1334 | },
1335 | {
1336 | "cell_type": "code",
1337 | "metadata": {
1338 | "id": "VgZ1BGWyzVaj",
1339 | "colab_type": "code",
1340 | "colab": {}
1341 | },
1342 | "source": [
1343 | "rmse=np.sqrt(np.mean(predictions - y_test)**2)"
1344 | ],
1345 | "execution_count": 0,
1346 | "outputs": []
1347 | },
1348 | {
1349 | "cell_type": "code",
1350 | "metadata": {
1351 | "id": "28nSDcQAaPsr",
1352 | "colab_type": "code",
1353 | "colab": {}
1354 | },
1355 | "source": [
1356 | "predictions"
1357 | ],
1358 | "execution_count": 0,
1359 | "outputs": []
1360 | },
1361 | {
1362 | "cell_type": "markdown",
1363 | "metadata": {
1364 | "id": "DaIXIV8vPPzg",
1365 | "colab_type": "text"
1366 | },
1367 | "source": [
1368 | "6.2 **KNN Classifier** "
1369 | ]
1370 | },
1371 | {
1372 | "cell_type": "code",
1373 | "metadata": {
1374 | "id": "DQlL-JQYWe3e",
1375 | "colab_type": "code",
1376 | "colab": {}
1377 | },
1378 | "source": [
1379 | "from sklearn.neighbors import KNeighborsClassifier\n",
1380 | "k = 1\n",
1381 | "#Train Model and Predict \n",
1382 | "neigh = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train)\n",
1383 | "y_pred = neigh.predict(X_test)"
1384 | ],
1385 | "execution_count": 0,
1386 | "outputs": []
1387 | },
1388 | {
1389 | "cell_type": "code",
1390 | "metadata": {
1391 | "id": "sv3ZMg7qXBJ3",
1392 | "colab_type": "code",
1393 | "colab": {}
1394 | },
1395 | "source": [
1396 | "from sklearn import metrics\n",
1397 | "print(\"Train set Accuracy: \", metrics.accuracy_score(y_train, neigh.predict(X_train)))\n",
1398 | "print(\"Test set Accuracy: \", metrics.accuracy_score(y_test, yhat))\n"
1399 | ],
1400 | "execution_count": 0,
1401 | "outputs": []
1402 | },
1403 | {
1404 | "cell_type": "code",
1405 | "metadata": {
1406 | "id": "P14FdEkQXF1g",
1407 | "colab_type": "code",
1408 | "colab": {}
1409 | },
1410 | "source": [
1411 | "# We can calculate the accuracy of KNN for different Ks.\n",
1412 | "Ks = 10\n",
1413 | "mean_acc = np.zeros((Ks-1))\n",
1414 | "std_acc = np.zeros((Ks-1))\n",
1415 | "ConfustionMx = [];\n",
1416 | "for n in range(1,Ks):\n",
1417 | " \n",
1418 | " #Train Model and Predict \n",
1419 | " neigh = KNeighborsClassifier(n_neighbors = n).fit(X_train,y_train)\n",
1420 | " yhat=neigh.predict(X_test)\n",
1421 | " mean_acc[n-1] = metrics.accuracy_score(y_test, yhat)\n",
1422 | "\n",
1423 | " \n",
1424 | " std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0])\n",
1425 | "\n",
1426 | "mean_acc\n"
1427 | ],
1428 | "execution_count": 0,
1429 | "outputs": []
1430 | },
1431 | {
1432 | "cell_type": "code",
1433 | "metadata": {
1434 | "id": "HGZJSorVXRzp",
1435 | "colab_type": "code",
1436 | "colab": {}
1437 | },
1438 | "source": [
1439 | "# Plot model accuracy for Different number of Neighbors \n",
1440 | "plt.plot(range(1,Ks),mean_acc,'g')\n",
1441 | "plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10)\n",
1442 | "plt.legend(('Accuracy ', '+/- 3xstd'))\n",
1443 | "plt.ylabel('Accuracy ')\n",
1444 | "plt.xlabel('Number of Nabors (K)')\n",
1445 | "plt.tight_layout()\n",
1446 | "plt.show()"
1447 | ],
1448 | "execution_count": 0,
1449 | "outputs": []
1450 | },
1451 | {
1452 | "cell_type": "code",
1453 | "metadata": {
1454 | "id": "7qY94l-DXBIN",
1455 | "colab_type": "code",
1456 | "colab": {}
1457 | },
1458 | "source": [
1459 | "print( \"The best accuracy was with\", mean_acc.max(), \"with k=\", mean_acc.argmax()+1) "
1460 | ],
1461 | "execution_count": 0,
1462 | "outputs": []
1463 | },
1464 | {
1465 | "cell_type": "markdown",
1466 | "metadata": {
1467 | "id": "PMnJfVQOQTob",
1468 | "colab_type": "text"
1469 | },
1470 | "source": [
1471 | "6.3 **Logistic Rregression**"
1472 | ]
1473 | },
1474 | {
1475 | "cell_type": "code",
1476 | "metadata": {
1477 | "id": "E3qQWXzV4H2m",
1478 | "colab_type": "code",
1479 | "colab": {}
1480 | },
1481 | "source": [
1482 | "#https://www.marktechpost.com/2019/06/12/logistic-regression-with-a-real-world-example-in-python/?fbclid=IwAR31FyvXdFxxWam-n6lCKmsBxA7m_MIHdrhwerqpqow1-V9dx2ZeQ_gq-s0\n",
1483 | "classifier = LogisticRegression(random_state=0)\n",
1484 | "classifier.fit(X_train, y_train)\n",
1485 | "y_pred = classifier.predict(X_test)\n",
1486 | "print(y_pred)\n"
1487 | ],
1488 | "execution_count": 0,
1489 | "outputs": []
1490 | },
1491 | {
1492 | "cell_type": "markdown",
1493 | "metadata": {
1494 | "id": "CJHwOa0KRB4X",
1495 | "colab_type": "text"
1496 | },
1497 | "source": [
1498 | "6.4 **Random Forest Classifier**"
1499 | ]
1500 | },
1501 | {
1502 | "cell_type": "code",
1503 | "metadata": {
1504 | "id": "gTZGi49RT3la",
1505 | "colab_type": "code",
1506 | "colab": {}
1507 | },
1508 | "source": [
1509 | "# =========================================================================> RandomForestClassifier================\n",
1510 | "#https://www.kaggle.com/willkoehrsen/visualize-a-decision-tree-w-python-scikit-learn\n",
1511 | "#https://www.kaggle.com/willkoehrsen/visualize-a-decision-tree-w-python-scikit-learn\n",
1512 | "# Limit max depth\n",
1513 | "model = RandomForestClassifier(max_depth = 3, n_estimators=12)\n",
1514 | "# Train\n",
1515 | "model.fit(X_train, y_train)\n",
1516 | "#Predict the response for test dataset\n",
1517 | "y_pred = model.predict(X_test)"
1518 | ],
1519 | "execution_count": 0,
1520 | "outputs": []
1521 | },
1522 | {
1523 | "cell_type": "code",
1524 | "metadata": {
1525 | "id": "BVb6yvuLLdVn",
1526 | "colab_type": "code",
1527 | "colab": {}
1528 | },
1529 | "source": [
1530 | "# Extract single tree\n",
1531 | "estimator_limited = model.estimators_[5]\n",
1532 | "estimator_limited\n",
1533 | "# No max depth\n",
1534 | "model = RandomForestClassifier(max_depth = 3, n_estimators=10)\n",
1535 | "model.fit(X_train, y_train)\n",
1536 | "estimator_nonlimited = model.estimators_[5]\n",
1537 | "\n",
1538 | "from sklearn.tree import export_graphviz\n",
1539 | "export_graphviz(estimator_limited, out_file='tree_limited.dot', feature_names =feature_cols,\n",
1540 | " class_names = y,\n",
1541 | " rounded = True, proportion = False, precision = 2, filled = True)"
1542 | ],
1543 | "execution_count": 0,
1544 | "outputs": []
1545 | },
1546 | {
1547 | "cell_type": "code",
1548 | "metadata": {
1549 | "id": "m5b3WT4hViYx",
1550 | "colab_type": "code",
1551 | "colab": {}
1552 | },
1553 | "source": [
1554 | "export_graphviz(estimator_nonlimited, out_file='tree_nonlimited.dot', feature_names = feature_cols,\n",
1555 | " class_names =y,\n",
1556 | " rounded = True, proportion = False, precision = 2, filled = True)"
1557 | ],
1558 | "execution_count": 0,
1559 | "outputs": []
1560 | },
1561 | {
1562 | "cell_type": "code",
1563 | "metadata": {
1564 | "id": "aXMsWMjgWnsm",
1565 | "colab_type": "code",
1566 | "colab": {}
1567 | },
1568 | "source": [
1569 | "#Convert to png from the command line\n",
1570 | "!dot -Tpng tree_limited.dot -o tree_limited.png -Gdpi=600"
1571 | ],
1572 | "execution_count": 0,
1573 | "outputs": []
1574 | },
1575 | {
1576 | "cell_type": "markdown",
1577 | "metadata": {
1578 | "id": "n284gqLAQzSb",
1579 | "colab_type": "text"
1580 | },
1581 | "source": [
1582 | "6.4 **ANN** "
1583 | ]
1584 | },
1585 | {
1586 | "cell_type": "code",
1587 | "metadata": {
1588 | "id": "ZaPXtuXvRbt9",
1589 | "colab_type": "code",
1590 | "colab": {}
1591 | },
1592 | "source": [
1593 | "#==============================================================================================================================================================\n",
1594 | "# Evaluating Model\n",
1595 | "#===============================================================================================================================================================\n",
1596 | "\n",
1597 | "#=============================================================> accuracy \n",
1598 | "print(\"Accuracy:\",metrics.accuracy_score(y_test, y_pred))"
1599 | ],
1600 | "execution_count": 0,
1601 | "outputs": []
1602 | },
1603 | {
1604 | "cell_type": "code",
1605 | "metadata": {
1606 | "id": "Sdd3fQaQWrNO",
1607 | "colab_type": "code",
1608 | "colab": {}
1609 | },
1610 | "source": [
1611 | "from IPython.display import Image\n",
1612 | "Image(filename = 'tree_limited.png')\n",
1613 | "\n",
1614 | "#======================================================== build CNN\n",
1615 | "#https://www.tensorflow.org/tutorials/estimators/cnn\n",
1616 | "import tensorflow as tf\n",
1617 | "def cnn_model_f(features,labels, mod):\n",
1618 | " # input layer\n",
1619 | " input_layer = tf.reshape(features[\"x\"], [-1, 28, 28, 1])\n",
1620 | " # Convolutional Layer #1\n",
1621 | " conv1 = tf.layers.conv2d(\n",
1622 | " inputs=input_layer,\n",
1623 | " filters=32,\n",
1624 | " kernel_size=[5, 5],\n",
1625 | " padding=\"same\",\n",
1626 | " activation=tf.nn.relu)\n",
1627 | "# Pooling Layer #1\n",
1628 | " pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)\n",
1629 | " # Convolutional Layer #2 and Pooling Layer #2\n",
1630 | " conv2 = tf.layers.conv2d(\n",
1631 | " inputs=pool1,\n",
1632 | " filters=64,\n",
1633 | " kernel_size=[5, 5],\n",
1634 | " padding=\"same\",\n",
1635 | " activation=tf.nn.relu)\n",
1636 | " pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)\n",
1637 | " # Dense Layer\n",
1638 | " pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])\n",
1639 | " dense = tf.layers.dense(inputs=pool2_flat, units=1024, activation=tf.nn.relu)\n",
1640 | " dropout = tf.layers.dropout(\n",
1641 | " inputs=dense, rate=0.4, training=mode == tf.estimator.ModeKeys.TRAIN)\n",
1642 | " # Logits Layer\n",
1643 | " logits = tf.layers.dense(inputs=dropout, units=10)\n",
1644 | " predictions = {\n",
1645 | " # Generate predictions (for PREDICT and EVAL mode)\n",
1646 | " \"classes\": tf.argmax(input=logits, axis=1),\n",
1647 | " # Add `softmax_tensor` to the graph. It is used for PREDICT and by the\n",
1648 | " # `logging_hook`.\n",
1649 | " \"probabilities\": tf.nn.softmax(logits, name=\"softmax_tensor\")\n",
1650 | " }\n",
1651 | " if mode == tf.estimator.ModeKeys.PREDICT:\n",
1652 | " return tf.estimator.EstimatorSpec(mode=mode, predictions=predictions)\n",
1653 | "\n",
1654 | " # Calculate Loss (for both TRAIN and EVAL modes)\n",
1655 | " loss = tf.losses.sparse_softmax_cross_entropy(labels=labels, logits=logits)\n",
1656 | "\n",
1657 | " # Configure the Training Op (for TRAIN mode)\n",
1658 | " if mode == tf.estimator.ModeKeys.TRAIN:\n",
1659 | " optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.001)\n",
1660 | " train_op = optimizer.minimize(\n",
1661 | " loss=loss,\n",
1662 | " global_step=tf.train.get_global_step())\n",
1663 | " return tf.estimator.EstimatorSpec(mode=mode, loss=loss, train_op=train_op)\n",
1664 | "\n",
1665 | " # Add evaluation metrics (for EVAL mode)\n",
1666 | " eval_metric_ops = {\n",
1667 | " \"accuracy\": tf.metrics.accuracy(\n",
1668 | " labels=labels, predictions=predictions[\"classes\"])\n",
1669 | " }\n",
1670 | " return tf.estimator.EstimatorSpec(\n",
1671 | " mode=mode, loss=loss, eval_metric_ops=eval_metric_ops)"
1672 | ],
1673 | "execution_count": 0,
1674 | "outputs": []
1675 | },
1676 | {
1677 | "cell_type": "code",
1678 | "metadata": {
1679 | "id": "JdWT57wSmxP4",
1680 | "colab_type": "code",
1681 | "colab": {}
1682 | },
1683 | "source": [
1684 | "#==============================================================> Making the Confusion Matrix\n",
1685 | "# https://www.marktechpost.com/2019/06/12/logistic-regression-with-a-real-world-example-in-python/?fbclid=IwAR31FyvXdFxxWam-n6lCKmsBxA7m_MIHdrhwerqpqow1-V9dx2ZeQ_gq-s0\n",
1686 | "# https://www.geeksforgeeks.org/confusion-matrix-machine-learning/\n",
1687 | "#https://stackoverflow.com/questions/30746460/how-to-interpret-scikits-learn-confusion-matrix-and-classification-report\n",
1688 | "from sklearn.metrics import confusion_matrix\n",
1689 | "cm = confusion_matrix(y_test, y_pred)\n",
1690 | "print(y_test.size)\n",
1691 | "ACC=( cm[0][0] + cm[1][1] ) / ( 117 )\n",
1692 | "print('Accuracy',ACC)\n",
1693 | "\n",
1694 | "print('Accuracy Score :',accuracy_score(y_test, y_pred)) \n",
1695 | "print('Report : ', classification_report(y_test, y_pred)) \n",
1696 | "print(confusion_matrix)\n",
1697 | "print('\\nConfussion matrix:\\n',confusion_matrix(y_test, y_pred))"
1698 | ],
1699 | "execution_count": 0,
1700 | "outputs": []
1701 | },
1702 | {
1703 | "cell_type": "code",
1704 | "metadata": {
1705 | "id": "FKhofH_7Rswy",
1706 | "colab_type": "code",
1707 | "colab": {}
1708 | },
1709 | "source": [
1710 | "# Visualizing Decision Trees\n",
1711 | "dot_data = StringIO()\n",
1712 | "export_graphviz(clf, out_file=dot_data, \n",
1713 | " filled=True, rounded=True,\n",
1714 | " special_characters=True,feature_names = feature_cols,class_names=['Not-submitted','Submitted'])\n",
1715 | "graph = pydotplus.graph_from_dot_data(dot_data.getvalue()) \n",
1716 | "graph.write_png('StudentNextSessionf.png')\n",
1717 | "Image(graph.create_png())"
1718 | ],
1719 | "execution_count": 0,
1720 | "outputs": []
1721 | },
1722 | {
1723 | "cell_type": "markdown",
1724 | "metadata": {
1725 | "id": "dDDTGM0Nkg1E",
1726 | "colab_type": "text"
1727 | },
1728 | "source": [
1729 | " **References**\n",
1730 | " \n",
1731 | "1. [1] Stock Price Prediction Using Python & Machine Learning\n",
1732 | " https://www.youtube.com/watch?v=QIUxPv5PJOY\n",
1733 | "\n",
1734 | "2. [2] Time-series data analysis using LSTM (Tutorial)\n",
1735 | "https://www.kaggle.com/amirrezaeian/time-series-data-analysis-using-lstm-tutorial\n",
1736 | "3. [3] Learn by example RNN/LSTM/GRU time series\n",
1737 | "https://www.kaggle.com/charel/learn-by-example-rnn-lstm-gru-time-series\n",
1738 | "4. [4] Stock Market Predictions with LSTM in Python\n",
1739 | "https://www.datacamp.com/community/tutorials/lstm-python-stock-market\n",
1740 | "5. [5] LSTM Time Series Prediction Tutorial using PyTorch in Python | Coronavirus Daily Cases Forecasting\n",
1741 | "https://www.youtube.com/watch?v=8A6TEjG2DNw\n",
1742 | "6. [6] LSTM Time Series Prediction Tutorial using PyTorch in Python | Coronavirus Daily Cases Forecasting\n",
1743 | "https://morioh.com/p/5a74f94cfd6b\n",
1744 | "7.[7] Pandas Dataframe: Plot Examples with Matplotlib and Pyplot\n",
1745 | "http://queirozf.com/entries/pandas-dataframe-plot-examples-with-matplotlib-pyplot\n",
1746 | "8.[8]Dataframe Visualization with Pandas Plot\n",
1747 | "https://kanoki.org/2019/09/16/dataframe-visualization-with-pandas-plot/\n",
1748 | "9.[9]How to Use Power Transforms for Time Series Forecast Data with Python\n",
1749 | "https://machinelearningmastery.com/power-transform-time-series-forecast-data-python/\n",
1750 | "10.[10] Time Series Forecasting with LSTMs for Daily Coronavirus Cases using PyTorch in Python\n",
1751 | "https://www.curiousily.com/posts/time-series-forecasting-with-lstm-for-daily-coronavirus-cases/\n",
1752 | "11. [11] Building COVID-19 interactive dashboard from Jupyter Notebook https://morioh.com/p/127b5a302cb1?fbclid=IwAR28dsncAPM184LyzEhJCMxsCx5im2X4XJp3gSULd9Tq70XTivsMH75piLg\n",
1753 | "12. [12] How to Calculate Precision, Recall, F1, and More for Deep Learning Models\n",
1754 | "https://machinelearningmastery.com/how-to-calculate-precision-recall-f1-and-more-for-deep-learning-models/?fbclid=IwAR30_eKuKXmIYbyiaMZdCDzhe9YPLaI-ATGjRj83U8mcjySuwikcaQt6Vfw\n",
1755 | "13.[13] Data ETL & Analysis on the global and Mexican datasets of the COVID-19 pandemic\n",
1756 | "https://github.com/PhantomInsights/covid-19\n",
1757 | "14.[14]Regression Models with Keras\n",
1758 | "https://colab.research.google.com/github/hussain0048/Deep-Learning-with-Keras/blob/master/DL0101EN-3-1-Regression-with-Keras-py-v1.0.ipynb#scrollTo=4ORZhKfduSrw\n",
1759 | "15.[15] Pandas: Find Rows Where Column/Field Is Null\n",
1760 | "https://dzone.com/articles/pandas-find-rows-where-columnfield-is-null\n",
1761 | "16. [16] Analysis and Predicting Stock Trends with Python\n",
1762 | "https://morioh.com/p/8e9d9d4161c5?f=5c21f93bc16e2556b555ab2f&fbclid=IwAR2oIByWVFfg-b7f1Phd3cZ84mwmp9LriMb0pobqdJa9TWV1-pK04YkHqH4\n",
1763 | "\n",
1764 | "\n",
1765 | "\n"
1766 | ]
1767 | }
1768 | ]
1769 | }
--------------------------------------------------------------------------------
/Implementation/5_3_2020_Covid_Prophet_Final.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "kernelspec": {
6 | "display_name": "Python 3",
7 | "language": "python",
8 | "name": "python3"
9 | },
10 | "language_info": {
11 | "codemirror_mode": {
12 | "name": "ipython",
13 | "version": 3
14 | },
15 | "file_extension": ".py",
16 | "mimetype": "text/x-python",
17 | "name": "python",
18 | "nbconvert_exporter": "python",
19 | "pygments_lexer": "ipython3",
20 | "version": "3.6.6"
21 | },
22 | "colab": {
23 | "name": " 5-3-2020 Covid_Prophet_Final.ipynb",
24 | "provenance": [],
25 | "collapsed_sections": [],
26 | "toc_visible": true,
27 | "machine_shape": "hm",
28 | "include_colab_link": true
29 | }
30 | },
31 | "cells": [
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {
35 | "id": "view-in-github",
36 | "colab_type": "text"
37 | },
38 | "source": [
39 | "
"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {
45 | "id": "FfcjS4CKTyAP"
46 | },
47 | "source": [
48 | "# **1-Introducton** \n",
49 | "\n",
50 | "Predicting confirmed cases of Convid-19 with Prophet"
51 | ]
52 | },
53 | {
54 | "cell_type": "markdown",
55 | "metadata": {
56 | "id": "r609ISbsmq2t"
57 | },
58 | "source": [
59 | "#**2-Importing necessary libraries**"
60 | ]
61 | },
62 | {
63 | "cell_type": "code",
64 | "metadata": {
65 | "id": "FxdLWHIJTyAU"
66 | },
67 | "source": [
68 | "import pandas as pd\n",
69 | "import numpy as np\n",
70 | "from fbprophet import Prophet\n",
71 | "import matplotlib.pyplot as plt\n",
72 | " \n",
73 | "plt.rcParams['figure.figsize']=(20,10)\n",
74 | "plt.style.use('ggplot')"
75 | ],
76 | "execution_count": 2,
77 | "outputs": []
78 | },
79 | {
80 | "cell_type": "code",
81 | "metadata": {
82 | "id": "5NeSSztObv-7"
83 | },
84 | "source": [
85 | "plt.rcParams['figure.figsize']=(20,10)\n",
86 | "plt.style.use('ggplot')"
87 | ],
88 | "execution_count": 3,
89 | "outputs": []
90 | },
91 | {
92 | "cell_type": "code",
93 | "metadata": {
94 | "id": "XhadCtyRcFFY"
95 | },
96 | "source": [
97 | "pd.plotting.register_matplotlib_converters()"
98 | ],
99 | "execution_count": 4,
100 | "outputs": []
101 | },
102 | {
103 | "cell_type": "code",
104 | "metadata": {
105 | "id": "-vcGxjHQGL1c"
106 | },
107 | "source": [
108 | "#[3]\n",
109 | "import warnings\n",
110 | "warnings.filterwarnings('ignore')\n",
111 | "\n",
112 | "import numpy as np\n",
113 | "import pandas as pd\n",
114 | "from scipy import stats\n",
115 | "import statsmodels.api as sm\n",
116 | "import matplotlib.pyplot as plt\n",
117 | "\n",
118 | "%matplotlib inline"
119 | ],
120 | "execution_count": 5,
121 | "outputs": []
122 | },
123 | {
124 | "cell_type": "code",
125 | "metadata": {
126 | "id": "d17uQ_kpKn5w"
127 | },
128 | "source": [
129 | "from fbprophet import Prophet\n",
130 | "\n",
131 | "import logging\n",
132 | "logging.getLogger().setLevel(logging.ERROR)"
133 | ],
134 | "execution_count": 6,
135 | "outputs": []
136 | },
137 | {
138 | "cell_type": "markdown",
139 | "metadata": {
140 | "id": "X5p8oL_STyAg"
141 | },
142 | "source": [
143 | "#**3-Import dataset**"
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "metadata": {
149 | "id": "4lsb_UGenA-Y",
150 | "outputId": "70bd3db4-797d-407c-88b1-0cf5182a48d2",
151 | "colab": {
152 | "base_uri": "https://localhost:8080/"
153 | }
154 | },
155 | "source": [
156 | "from google.colab import drive\n",
157 | "drive.mount('/content/drive')"
158 | ],
159 | "execution_count": 7,
160 | "outputs": [
161 | {
162 | "output_type": "stream",
163 | "text": [
164 | "Mounted at /content/drive\n"
165 | ],
166 | "name": "stdout"
167 | }
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "metadata": {
173 | "id": "RDKPEa7keRWE"
174 | },
175 | "source": [
176 | "data = pd.read_csv(\"/content/drive/My Drive/Datasets/Covid-19/data_cases1.csv\", usecols=['Date','Confirmed'],index_col='Date', parse_dates=True )\n",
177 | "data.head()"
178 | ],
179 | "execution_count": null,
180 | "outputs": []
181 | },
182 | {
183 | "cell_type": "code",
184 | "metadata": {
185 | "id": "_qRu1k2Dyt2O"
186 | },
187 | "source": [
188 | "data.head()"
189 | ],
190 | "execution_count": null,
191 | "outputs": []
192 | },
193 | {
194 | "cell_type": "code",
195 | "metadata": {
196 | "id": "t-E75RQRTyAx"
197 | },
198 | "source": [
199 | "data.shape"
200 | ],
201 | "execution_count": null,
202 | "outputs": []
203 | },
204 | {
205 | "cell_type": "markdown",
206 | "metadata": {
207 | "id": "R8BthJfITyBS"
208 | },
209 | "source": [
210 | "#**4-Data cleaning and feature engineering**"
211 | ]
212 | },
213 | {
214 | "cell_type": "code",
215 | "metadata": {
216 | "id": "Ns2tk6CCGzDo"
217 | },
218 | "source": [
219 | "df = data.reset_index()"
220 | ],
221 | "execution_count": 11,
222 | "outputs": []
223 | },
224 | {
225 | "cell_type": "code",
226 | "metadata": {
227 | "id": "WGxkU_bZ_eoq"
228 | },
229 | "source": [
230 | "df.head()"
231 | ],
232 | "execution_count": null,
233 | "outputs": []
234 | },
235 | {
236 | "cell_type": "code",
237 | "metadata": {
238 | "id": "wiEfm8xA9Cb4"
239 | },
240 | "source": [
241 | "#we get rid of possible duplicates and missing values in the data [3]\n",
242 | "df = df[['Date', 'Confirmed']].dropna().drop_duplicates()"
243 | ],
244 | "execution_count": 13,
245 | "outputs": []
246 | },
247 | {
248 | "cell_type": "code",
249 | "metadata": {
250 | "id": "fqj24WXrFwbV",
251 | "outputId": "8bd45a73-a772-48f3-c96f-c05f27829a71",
252 | "colab": {
253 | "base_uri": "https://localhost:8080/"
254 | }
255 | },
256 | "source": [
257 | "df.shape"
258 | ],
259 | "execution_count": 14,
260 | "outputs": [
261 | {
262 | "output_type": "execute_result",
263 | "data": {
264 | "text/plain": [
265 | "(1157, 2)"
266 | ]
267 | },
268 | "metadata": {
269 | "tags": []
270 | },
271 | "execution_count": 14
272 | }
273 | ]
274 | },
275 | {
276 | "cell_type": "code",
277 | "metadata": {
278 | "id": "8oKf0uV2GG02"
279 | },
280 | "source": [
281 | "#we need to convert Date to the datetime format because by default pandas treats this field as string-valued[3]\n",
282 | "df['Date'] = pd.to_datetime(df['Date'])"
283 | ],
284 | "execution_count": 15,
285 | "outputs": []
286 | },
287 | {
288 | "cell_type": "code",
289 | "metadata": {
290 | "id": "ijc8tkqbGqpE"
291 | },
292 | "source": [
293 | "df.head()"
294 | ],
295 | "execution_count": null,
296 | "outputs": []
297 | },
298 | {
299 | "cell_type": "code",
300 | "metadata": {
301 | "id": "-cnFzmAAHIWq"
302 | },
303 | "source": [
304 | "#Let's sort the dataframe by time and take a look at what we've got [3]\n",
305 | "df.sort_values(by=['Date']).head(n=3)"
306 | ],
307 | "execution_count": null,
308 | "outputs": []
309 | },
310 | {
311 | "cell_type": "code",
312 | "metadata": {
313 | "id": "vegTUwkq9kw8"
314 | },
315 | "source": [
316 | "#We will just trim our time series to keep only those rows that fall onto the period from March 10, 2020 to March 31, 2020[3]\n",
317 | "df = df[(df['Date'] > '2020-03-09') & (df['Date'] < '2020-04-01')].sort_values(by=['Date'])\n",
318 | "df.head(n=10)"
319 | ],
320 | "execution_count": null,
321 | "outputs": []
322 | },
323 | {
324 | "cell_type": "code",
325 | "metadata": {
326 | "id": "rahdPkyK-81A"
327 | },
328 | "source": [
329 | "#As we are going to predict the number of confirm Cases of Covid-19, we will aggregate and count unique Cases at each given point in time. We will name the corresponding new column Confirmed_Cases:\n",
330 | "aggr_df = df.groupby('Date')[['Confirmed']].count()\n",
331 | "aggr_df.columns = ['Confirmed_Cases']"
332 | ],
333 | "execution_count": 19,
334 | "outputs": []
335 | },
336 | {
337 | "cell_type": "code",
338 | "metadata": {
339 | "id": "K-av4_rg_pfa"
340 | },
341 | "source": [
342 | "aggr_df.head(n=3)\n"
343 | ],
344 | "execution_count": null,
345 | "outputs": []
346 | },
347 | {
348 | "cell_type": "code",
349 | "metadata": {
350 | "id": "8WPfYYLU_6dD"
351 | },
352 | "source": [
353 | "#In this practice, we are interested in the number of confirmed cases a day. But at this moment all our data is divided into irregular time intervals that are less than a day. \n",
354 | "#This is called a sub-daily time series.To fix this, we need to aggregate the Cases counts by \"bins\" of a date size. \n",
355 | "#In time series analysis, this process is referred to as resampling. And if we reduce the sampling rate of data it is often called downsampling.\n",
356 | "#Luckily, pandas has a built-in functionality for this task. We will resample our time index down to 1-day bins [3]\n",
357 | "daily_df = aggr_df.resample('D').apply(sum)\n",
358 | "daily_df.head(n=3)"
359 | ],
360 | "execution_count": null,
361 | "outputs": []
362 | },
363 | {
364 | "cell_type": "code",
365 | "metadata": {
366 | "id": "9n0GTxkvAeq5"
367 | },
368 | "source": [
369 | "weekly_df = daily_df.resample('W').apply(sum)"
370 | ],
371 | "execution_count": 22,
372 | "outputs": []
373 | },
374 | {
375 | "cell_type": "code",
376 | "metadata": {
377 | "id": "SUR6GRnOJp5T"
378 | },
379 | "source": [
380 | "weekly_df.head()"
381 | ],
382 | "execution_count": null,
383 | "outputs": []
384 | },
385 | {
386 | "cell_type": "code",
387 | "metadata": {
388 | "id": "lVCbk-vsAz-n"
389 | },
390 | "source": [
391 | "daily_df = daily_df.loc[daily_df.index >= '2020-03-10']\n",
392 | "daily_df.head(n=3)"
393 | ],
394 | "execution_count": null,
395 | "outputs": []
396 | },
397 | {
398 | "cell_type": "code",
399 | "metadata": {
400 | "id": "ZQLlg3g4OvWh"
401 | },
402 | "source": [
403 | "plt.figure(figsize=(16,8))\n",
404 | "plt.title('Daily Confirmed Cases of COVID-19 (World)')\n",
405 | "plt.plot(daily_df['Confirmed_Cases'])\n",
406 | "plt.xlabel('Date', fontsize=18)\n",
407 | "plt.ylabel('Confirmed Cases', fontsize=18)\n",
408 | "plt.show()"
409 | ],
410 | "execution_count": null,
411 | "outputs": []
412 | },
413 | {
414 | "cell_type": "markdown",
415 | "metadata": {
416 | "id": "C8ivtMFNTyEs"
417 | },
418 | "source": [
419 | "#**5- Modelling**\n",
420 | "\n",
421 | "Let's focus on predictig the confirmed cases of COVI-ID.Prophet's API is very similar to the one you can find in sklearn. First we create a model, then call the method fit, and, finally, make a forecast. The input to the method fit is a DataFrame with two columns:\n",
422 | "\n",
423 | "ds (datestamp) must be of type date or datetime.\n",
424 | "y is a numeric value we want to predict."
425 | ]
426 | },
427 | {
428 | "cell_type": "code",
429 | "metadata": {
430 | "id": "IVFBqHaJBM2J"
431 | },
432 | "source": [
433 | "#[3]\n",
434 | "df = daily_df.reset_index()\n",
435 | "df.columns = ['ds', 'y']\n",
436 | "df.tail(n=3)"
437 | ],
438 | "execution_count": null,
439 | "outputs": []
440 | },
441 | {
442 | "cell_type": "code",
443 | "metadata": {
444 | "id": "0_egvgIBTB2U"
445 | },
446 | "source": [
447 | "df.set_index('ds').y.plot().get_figure()"
448 | ],
449 | "execution_count": null,
450 | "outputs": []
451 | },
452 | {
453 | "cell_type": "code",
454 | "metadata": {
455 | "id": "m2sSEx8DLfGB"
456 | },
457 | "source": [
458 | "#To measure the quality of our forecast, we need to split our dataset into the historical part, which is the first and biggest slice of our data,\n",
459 | "# and the prediction part, which will be located at the end of the timeline. \n",
460 | "#We will remove the last 3 days from the dataset in order to use it later as a prediction target[3]\n",
461 | "prediction_size = 3\n",
462 | "train_df = df[:-prediction_size]\n",
463 | "train_df.tail(n=3)"
464 | ],
465 | "execution_count": null,
466 | "outputs": []
467 | },
468 | {
469 | "cell_type": "code",
470 | "metadata": {
471 | "id": "Yi-9PTvvMaOg"
472 | },
473 | "source": [
474 | "# now we create model [3]\n",
475 | "m = Prophet()\n",
476 | "m.fit(train_df);"
477 | ],
478 | "execution_count": null,
479 | "outputs": []
480 | },
481 | {
482 | "cell_type": "code",
483 | "metadata": {
484 | "id": "a_ki-3zQMxf9",
485 | "outputId": "c429c6f7-1b09-4972-9991-29d0041948ed",
486 | "colab": {
487 | "base_uri": "https://localhost:8080/",
488 | "height": 142
489 | }
490 | },
491 | "source": [
492 | "#[3]\n",
493 | "future = m.make_future_dataframe(periods=prediction_size)\n",
494 | "future.tail(n=3)"
495 | ],
496 | "execution_count": 30,
497 | "outputs": [
498 | {
499 | "output_type": "execute_result",
500 | "data": {
501 | "text/html": [
502 | "\n",
503 | "\n",
516 | "
\n",
517 | " \n",
518 | " \n",
519 | " | \n",
520 | " ds | \n",
521 | "
\n",
522 | " \n",
523 | " \n",
524 | " \n",
525 | " | 14 | \n",
526 | " 2020-03-24 | \n",
527 | "
\n",
528 | " \n",
529 | " | 15 | \n",
530 | " 2020-03-25 | \n",
531 | "
\n",
532 | " \n",
533 | " | 16 | \n",
534 | " 2020-03-26 | \n",
535 | "
\n",
536 | " \n",
537 | "
\n",
538 | "
"
539 | ],
540 | "text/plain": [
541 | " ds\n",
542 | "14 2020-03-24\n",
543 | "15 2020-03-25\n",
544 | "16 2020-03-26"
545 | ]
546 | },
547 | "metadata": {
548 | "tags": []
549 | },
550 | "execution_count": 30
551 | }
552 | ]
553 | },
554 | {
555 | "cell_type": "code",
556 | "metadata": {
557 | "id": "CTCGpSIMNM8X"
558 | },
559 | "source": [
560 | "#[3]\n",
561 | "forecast = m.predict(future)\n",
562 | "forecast.tail(n=3)"
563 | ],
564 | "execution_count": null,
565 | "outputs": []
566 | },
567 | {
568 | "cell_type": "code",
569 | "metadata": {
570 | "id": "qJSMTYcAOl4M",
571 | "outputId": "cbdbfb3e-0699-469c-9f33-2938a4106d99",
572 | "colab": {
573 | "base_uri": "https://localhost:8080/",
574 | "height": 204
575 | }
576 | },
577 | "source": [
578 | "#[1]\n",
579 | "forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()"
580 | ],
581 | "execution_count": 33,
582 | "outputs": [
583 | {
584 | "output_type": "execute_result",
585 | "data": {
586 | "text/html": [
587 | "\n",
588 | "\n",
601 | "
\n",
602 | " \n",
603 | " \n",
604 | " | \n",
605 | " ds | \n",
606 | " yhat | \n",
607 | " yhat_lower | \n",
608 | " yhat_upper | \n",
609 | "
\n",
610 | " \n",
611 | " \n",
612 | " \n",
613 | " | 12 | \n",
614 | " 2020-03-22 | \n",
615 | " 83.510020 | \n",
616 | " 56.517001 | \n",
617 | " 104.968454 | \n",
618 | "
\n",
619 | " \n",
620 | " | 13 | \n",
621 | " 2020-03-23 | \n",
622 | " 89.762552 | \n",
623 | " 66.425144 | \n",
624 | " 113.424199 | \n",
625 | "
\n",
626 | " \n",
627 | " | 14 | \n",
628 | " 2020-03-24 | \n",
629 | " 96.015084 | \n",
630 | " 74.384712 | \n",
631 | " 121.402555 | \n",
632 | "
\n",
633 | " \n",
634 | " | 15 | \n",
635 | " 2020-03-25 | \n",
636 | " 102.267617 | \n",
637 | " 76.591055 | \n",
638 | " 125.693865 | \n",
639 | "
\n",
640 | " \n",
641 | " | 16 | \n",
642 | " 2020-03-26 | \n",
643 | " 108.520149 | \n",
644 | " 83.544659 | \n",
645 | " 133.043532 | \n",
646 | "
\n",
647 | " \n",
648 | "
\n",
649 | "
"
650 | ],
651 | "text/plain": [
652 | " ds yhat yhat_lower yhat_upper\n",
653 | "12 2020-03-22 83.510020 56.517001 104.968454\n",
654 | "13 2020-03-23 89.762552 66.425144 113.424199\n",
655 | "14 2020-03-24 96.015084 74.384712 121.402555\n",
656 | "15 2020-03-25 102.267617 76.591055 125.693865\n",
657 | "16 2020-03-26 108.520149 83.544659 133.043532"
658 | ]
659 | },
660 | "metadata": {
661 | "tags": []
662 | },
663 | "execution_count": 33
664 | }
665 | ]
666 | },
667 | {
668 | "cell_type": "markdown",
669 | "metadata": {
670 | "id": "DPnDCm1jeFIp"
671 | },
672 | "source": [
673 | "#**6- Result Visualization**"
674 | ]
675 | },
676 | {
677 | "cell_type": "code",
678 | "metadata": {
679 | "id": "BB5Kty-_N7k1"
680 | },
681 | "source": [
682 | "#[3]forecasting\n",
683 | "m.plot(forecast);\n",
684 | "plt.title(\"Forecasting Covid-19 confirmed Cases(world) \")\n",
685 | "plt.show()"
686 | ],
687 | "execution_count": null,
688 | "outputs": []
689 | },
690 | {
691 | "cell_type": "code",
692 | "metadata": {
693 | "id": "Auutf8VWdchF"
694 | },
695 | "source": [
696 | "#[3]\n",
697 | "m.plot_components(forecast);\n",
698 | "plt.show()"
699 | ],
700 | "execution_count": null,
701 | "outputs": []
702 | },
703 | {
704 | "cell_type": "code",
705 | "metadata": {
706 | "id": "Jirxk0dDTs-n"
707 | },
708 | "source": [
709 | "# [1]\n",
710 | "df.set_index('ds', inplace=True)\n",
711 | "forecast.set_index('ds', inplace=True)"
712 | ],
713 | "execution_count": 36,
714 | "outputs": []
715 | },
716 | {
717 | "cell_type": "code",
718 | "metadata": {
719 | "id": "fnUxJ25aTztl"
720 | },
721 | "source": [
722 | "viz_df = daily_df.join(forecast[['yhat', 'yhat_lower','yhat_upper']], how = 'outer')"
723 | ],
724 | "execution_count": 37,
725 | "outputs": []
726 | },
727 | {
728 | "cell_type": "code",
729 | "metadata": {
730 | "id": "pgD7XbqwT_LV",
731 | "outputId": "0db294b6-f0e2-436a-e438-07f711201add",
732 | "colab": {
733 | "base_uri": "https://localhost:8080/",
734 | "height": 235
735 | }
736 | },
737 | "source": [
738 | "viz_df.head()"
739 | ],
740 | "execution_count": 38,
741 | "outputs": [
742 | {
743 | "output_type": "execute_result",
744 | "data": {
745 | "text/html": [
746 | "\n",
747 | "\n",
760 | "
\n",
761 | " \n",
762 | " \n",
763 | " | \n",
764 | " Confirmed_Cases | \n",
765 | " yhat | \n",
766 | " yhat_lower | \n",
767 | " yhat_upper | \n",
768 | "
\n",
769 | " \n",
770 | " | Date | \n",
771 | " | \n",
772 | " | \n",
773 | " | \n",
774 | " | \n",
775 | "
\n",
776 | " \n",
777 | " \n",
778 | " \n",
779 | " | 2020-03-10 | \n",
780 | " 17 | \n",
781 | " 8.479636 | \n",
782 | " -15.735117 | \n",
783 | " 31.833502 | \n",
784 | "
\n",
785 | " \n",
786 | " | 2020-03-11 | \n",
787 | " 24 | \n",
788 | " 14.732168 | \n",
789 | " -11.257902 | \n",
790 | " 38.105296 | \n",
791 | "
\n",
792 | " \n",
793 | " | 2020-03-12 | \n",
794 | " 28 | \n",
795 | " 20.984699 | \n",
796 | " -2.669664 | \n",
797 | " 46.315372 | \n",
798 | "
\n",
799 | " \n",
800 | " | 2020-03-13 | \n",
801 | " 30 | \n",
802 | " 27.237231 | \n",
803 | " 4.537930 | \n",
804 | " 51.516875 | \n",
805 | "
\n",
806 | " \n",
807 | " | 2020-03-14 | \n",
808 | " 37 | \n",
809 | " 33.489763 | \n",
810 | " 9.121017 | \n",
811 | " 57.230878 | \n",
812 | "
\n",
813 | " \n",
814 | "
\n",
815 | "
"
816 | ],
817 | "text/plain": [
818 | " Confirmed_Cases yhat yhat_lower yhat_upper\n",
819 | "Date \n",
820 | "2020-03-10 17 8.479636 -15.735117 31.833502\n",
821 | "2020-03-11 24 14.732168 -11.257902 38.105296\n",
822 | "2020-03-12 28 20.984699 -2.669664 46.315372\n",
823 | "2020-03-13 30 27.237231 4.537930 51.516875\n",
824 | "2020-03-14 37 33.489763 9.121017 57.230878"
825 | ]
826 | },
827 | "metadata": {
828 | "tags": []
829 | },
830 | "execution_count": 38
831 | }
832 | ]
833 | },
834 | {
835 | "cell_type": "code",
836 | "metadata": {
837 | "id": "TacZpRviVQlQ",
838 | "outputId": "bcbf0e0f-e8af-4977-f6e7-7104a1a079f0",
839 | "colab": {
840 | "base_uri": "https://localhost:8080/",
841 | "height": 595
842 | }
843 | },
844 | "source": [
845 | "viz_df[['Confirmed_Cases', 'yhat']].plot().get_figure()"
846 | ],
847 | "execution_count": 39,
848 | "outputs": [
849 | {
850 | "output_type": "execute_result",
851 | "data": {
852 | "image/png": "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vqO+JiEh4YhteDwe4uLiAGdqo9/vx7ZtUlJSWLRoUYvttXUK5KhRo/jyyy9b3PfCCy+QkZHBokWLsG2bY445BoBTTz2VN954g08++YQ777yT2bNnk5qayvTp03nuuecOa+f999/n888/5/333+e///u/ee2119oUmxACTGkx9jNzoGwvnp89gDVxStBtyto7rTj99NOpr6/n73//e9O23NxcUlNTeeedd/D7/ZSWlrJixQomTQr6IuQ2S05OZujQobz77ruAU3Bev349AFOmTOHtt98GnOJxay699FK++eYb/vWvfzVtW758ORs3bsTr9dKvXz88Hg9vvPEGfr8fgJ07d5KRkcG1117LNddcw9q1a5k8eTIrV64kL88Zgquurmbr1q1UVVVRUVHB2Wefzdy5c8nNzQ35/4UQPZXZtR378buhYj+eOx8OScKHbtLTDxfLsvjrX//KnDlzeO6554iLi2PIkCE89NBDVFVVce6552JZFg888AD9+vVjy5YtnRbbs88+y3333ce8efPw+XzMnDmTcePG8fDDD3Pbbbfx3HPPHbWQGx8fz8svv8ycOXOYM2cOMTExjBkzhocffphZs2Yxe/ZsXn/9dc4888ymTyPLli3jz3/+M9HR0SQmJjJv3jz69u3LM888w2233dY0zHT33XeTlJTEjTfeSF1dHcYY5syZ0+H/L0L0BGbLBuw/PgIxsXh++RusIZkha9sypkvctMocehOV6urqw4Y9RM8kP2shDjDfrcT+y2+hdzqeOx/CSu9/xGPd+mH3vHOWEEJEOnvZp5iX/wBDj8Fzx4NYKb1D/h6S9CPAhg0buOOOOw7aFhcXx3vvvRemiIQQh7I/fgvz2n/DmIl4fnYfVq+O+fQrwzsi7ORnLSKZMQbzxsuYj97EmjwN66b/xIqJadNrZXhHCCG6EeP3Y/7nWcwXn2DNuADr6tlYno5dc0ySvhBChIGpr8Oe/wSs+Qrrh1dh/fDqTllmXJK+EEJ0MlNdif3so7BlA9Y1t+A588JOe2+5OKudli1bdtACbG2xcOFC9uzZ00ERCSG6E7O/DPt398G2zVg3/7JTEz5I0u8Ur732GkVFReEOQwgRZqao0LnKtqQIzx0P4plyeqfHIEm/FU888cRB694//vjj5ObmUl1dzc0338z06dO5/fbbaZwB9cwzz3DhhRdy1llncffdd2OM4b333mPNmjXcfvvtnHvuudTU1ITr2xFChJEp2Ir923ugrhbPXY9hje28pVuak6TfiquuuorXX38dcG7U/s477zBw4EDWrVvHQw89xOLFiykoKGDlypUAXH/99XzwwQd8+umn1NTUsGjRIi6++GImTpzIs88+y6JFi4iPjw/ntySECAOzaR32k/dDbByeex7HyjoubLF0i0LuX78uIm9fbUjbzErrxb+fdOTLmwGGDh1KWloa69atY+/evYwbN460tLQjLp+8bNkynn/+eWpqati/fz+jRo066vo3QoiezXyfi/2Hh6BvP2fhtLS+YY2nWyT9cLr66qvRWlNcXMxVV10FtLx8cm1tLffffz8ffPABgwcP5qmnnqKuri5cYQshugCzbZOT8Puk47nrUazUtKO/qIN1i6R/tB55R7rgggt48skn8fl8/OlPf2LFihUtHteY4Pv06UNVVRXvv/8+F110EQCJiYlUVlZ2WsxCiPAzBVuwfz8XklPx/GfXSPjQTZJ+OMXGxjJ16lRSU1OJijrylXKpqalcc801nH322WRkZDBx4sSmfUop7r33Xnr16sU777wj4/pC9HBmRx720w9CQqJTtA3zkE5zsvbOUdi2zfnnn89f/vKXprtHidDqKj9rIULB7NruFG1jYvH88tdYGQM67L0CWXtHZu+0YvPmzUybNo3TTz9dEr4Q4qjMnp3YT/8KoqKdMfwOTPiBOurwjlLqReBioFhrPd7dNhe4GdjrHna/1voDd999wE2AH7hDa/1RB8TdKUaOHHnEe8gKIURzprgQ+6lfgTF4/usRrP6Dwh1Si9oypv8S8CzwyiHbn9FaP9l8g1JqLHAVMA4YBPxLKTVSa+0PQaxCCNElmZIiJ+H7GvD816+xBg4Nd0hHdNThHa31EqCsje3NBF7VWtdprfOALcDJgQTWRWoNohPIz1p0Z6Zsr5Pwa2ucefiDh4c7pFYFM3vndqXUdcDXwF1a633AYGB5s2N2utvazePx4PP5iI6WCUY9mc/nw+OR0pLonsz+Muyn/h9UVeC58xGsYSPCHdJRBZpRnwceAYz79SngxvY0oJSaDcwG0FqTnp5+0H5jDGVlZfh8vgBDFN1BTEwM/fv375R1xIUIJXt/GWXz5mJ599F7zu+JHX18uENqk4CSvta6aclIpdQLQOPNVncBzQezhrjbWmpj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\n",
853 | "text/plain": [
854 | ""
855 | ]
856 | },
857 | "metadata": {
858 | "tags": []
859 | },
860 | "execution_count": 39
861 | },
862 | {
863 | "output_type": "display_data",
864 | "data": {
865 | "image/png": "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vqO+JiEh4YhteDwe4uLiAGdqo9/vx7ZtUlJSWLRoUYvttXUK5KhRo/jyyy9b3PfCCy+QkZHBokWLsG2bY445BoBTTz2VN954g08++YQ777yT2bNnk5qayvTp03nuuecOa+f999/n888/5/333+e///u/ee2119oUmxACTGkx9jNzoGwvnp89gDVxStBtyto7rTj99NOpr6/n73//e9O23NxcUlNTeeedd/D7/ZSWlrJixQomTQr6IuQ2S05OZujQobz77ruAU3Bev349AFOmTOHtt98GnOJxay699FK++eYb/vWvfzVtW758ORs3bsTr9dKvXz88Hg9vvPEGfr8fgJ07d5KRkcG1117LNddcw9q1a5k8eTIrV64kL88Zgquurmbr1q1UVVVRUVHB2Wefzdy5c8nNzQ35/4UQPZXZtR378buhYj+eOx8OScKHbtLTDxfLsvjrX//KnDlzeO6554iLi2PIkCE89NBDVFVVce6552JZFg888AD9+vVjy5YtnRbbs88+y3333ce8efPw+XzMnDmTcePG8fDDD3Pbbbfx3HPPHbWQGx8fz8svv8ycOXOYM2cOMTExjBkzhocffphZs2Yxe/ZsXn/9dc4888ymTyPLli3jz3/+M9HR0SQmJjJv3jz69u3LM888w2233dY0zHT33XeTlJTEjTfeSF1dHcYY5syZ0+H/L0L0BGbLBuw/PgIxsXh++RusIZkha9sypkvctMocehOV6urqw4Y9RM8kP2shDjDfrcT+y2+hdzqeOx/CSu9/xGPd+mH3vHOWEEJEOnvZp5iX/wBDj8Fzx4NYKb1D/h6S9CPAhg0buOOOOw7aFhcXx3vvvRemiIQQh7I/fgvz2n/DmIl4fnYfVq+O+fQrwzsi7ORnLSKZMQbzxsuYj97EmjwN66b/xIqJadNrZXhHCCG6EeP3Y/7nWcwXn2DNuADr6tlYno5dc0ySvhBChIGpr8Oe/wSs+Qrrh1dh/fDqTllmXJK+EEJ0MlNdif3so7BlA9Y1t+A588JOe2+5OKudli1bdtACbG2xcOFC9uzZ00ERCSG6E7O/DPt398G2zVg3/7JTEz5I0u8Ur732GkVFReEOQwgRZqao0LnKtqQIzx0P4plyeqfHIEm/FU888cRB694//vjj5ObmUl1dzc0338z06dO5/fbbaZwB9cwzz3DhhRdy1llncffdd2OM4b333mPNmjXcfvvtnHvuudTU1ITr2xFChJEp2Ir923ugrhbPXY9hje28pVuak6TfiquuuorXX38dcG7U/s477zBw4EDWrVvHQw89xOLFiykoKGDlypUAXH/99XzwwQd8+umn1NTUsGjRIi6++GImTpzIs88+y6JFi4iPjw/ntySECAOzaR32k/dDbByeex7HyjoubLF0i0LuX78uIm9fbUjbzErrxb+fdOTLmwGGDh1KWloa69atY+/evYwbN460tLQjLp+8bNkynn/+eWpqati/fz+jRo066vo3QoiezXyfi/2Hh6BvP2fhtLS+YY2nWyT9cLr66qvRWlNcXMxVV10FtLx8cm1tLffffz8ffPABgwcP5qmnnqKuri5cYQshugCzbZOT8Puk47nrUazUtKO/qIN1i6R/tB55R7rgggt48skn8fl8/OlPf2LFihUtHteY4Pv06UNVVRXvv/8+F110EQCJiYlUVlZ2WsxCiPAzBVuwfz8XklPx/GfXSPjQTZJ+OMXGxjJ16lRSU1OJijrylXKpqalcc801nH322WRkZDBx4sSmfUop7r33Xnr16sU777wj4/pC9HBmRx720w9CQqJTtA3zkE5zsvbOUdi2zfnnn89f/vKXprtHidDqKj9rIULB7NruFG1jYvH88tdYGQM67L0CWXtHZu+0YvPmzUybNo3TTz9dEr4Q4qjMnp3YT/8KoqKdMfwOTPiBOurwjlLqReBioFhrPd7dNhe4GdjrHna/1voDd999wE2AH7hDa/1RB8TdKUaOHHnEe8gKIURzprgQ+6lfgTF4/usRrP6Dwh1Si9oypv8S8CzwyiHbn9FaP9l8g1JqLHAVMA4YBPxLKTVSa+0PQaxCCNElmZIiJ+H7GvD816+xBg4Nd0hHdNThHa31EqCsje3NBF7VWtdprfOALcDJgQTWRWoNohPIz1p0Z6Zsr5Pwa2ucefiDh4c7pFYFM3vndqXUdcDXwF1a633AYGB5s2N2utvazePx4PP5iI6WCUY9mc/nw+OR0pLonsz+Muyn/h9UVeC58xGsYSPCHdJRBZpRnwceAYz79SngxvY0oJSaDcwG0FqTnp5+0H5jDGVlZfh8vgBDFN1BTEwM/fv375R1xIUIJXt/GWXz5mJ599F7zu+JHX18uENqk4CSvta6aclIpdQLQOPNVncBzQezhrjbWmpj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\n",
866 | "text/plain": [
867 | ""
868 | ]
869 | },
870 | "metadata": {
871 | "tags": [],
872 | "needs_background": "light"
873 | }
874 | }
875 | ]
876 | },
877 | {
878 | "cell_type": "markdown",
879 | "metadata": {
880 | "id": "_3WYU3uraZOQ"
881 | },
882 | "source": [
883 | "#**7- Forecast quality evaluation** \n",
884 | "Let's evaluate the quality of the algorithm by calculating the error metrics for the last 30 days that we predicted. For this, we will need the observations yi and the corresponding predicted values y^i ."
885 | ]
886 | },
887 | {
888 | "cell_type": "code",
889 | "metadata": {
890 | "id": "V294mk5-PUcV"
891 | },
892 | "source": [
893 | "def make_comparison_dataframe(historical, forecast):\n",
894 | " \"\"\"Join the history with the forecast.\n",
895 | " \n",
896 | " The resulting dataset will contain columns 'yhat', 'yhat_lower', 'yhat_upper' and 'y'.\n",
897 | " \"\"\"\n",
898 | " return forecast.set_index('ds')[['yhat', 'yhat_lower', 'yhat_upper']].join(historical.set_index('ds'))"
899 | ],
900 | "execution_count": 40,
901 | "outputs": []
902 | },
903 | {
904 | "cell_type": "code",
905 | "metadata": {
906 | "id": "7rkQB64bPdTp"
907 | },
908 | "source": [
909 | "cmp_df = make_comparison_dataframe(df, forecast)\n",
910 | "cmp_df.tail(n=3)"
911 | ],
912 | "execution_count": null,
913 | "outputs": []
914 | },
915 | {
916 | "cell_type": "code",
917 | "metadata": {
918 | "id": "hHZkxBo2PvyI"
919 | },
920 | "source": [
921 | "def calculate_forecast_errors(df, prediction_size):\n",
922 | " \"\"\"Calculate MAPE and MAE of the forecast.\n",
923 | " \n",
924 | " Args:\n",
925 | " df: joined dataset with 'y' and 'yhat' columns.\n",
926 | " prediction_size: number of days at the end to predict.\n",
927 | " \"\"\"\n",
928 | " \n",
929 | " # Make a copy\n",
930 | " df = df.copy()\n",
931 | " \n",
932 | " # Now we calculate the values of e_i and p_i according to the formulas given in the article above.\n",
933 | " df['e'] = df['y'] - df['yhat']\n",
934 | " df['p'] = 100 * df['e'] / df['y']\n",
935 | " \n",
936 | " # Recall that we held out the values of the last `prediction_size` days\n",
937 | " # in order to predict them and measure the quality of the model. \n",
938 | " \n",
939 | " # Now cut out the part of the data which we made our prediction for.\n",
940 | " predicted_part = df[-prediction_size:]\n",
941 | " \n",
942 | " # Define the function that averages absolute error values over the predicted part.\n",
943 | " error_mean = lambda error_name: np.mean(np.abs(predicted_part[error_name]))\n",
944 | " \n",
945 | " # Now we can calculate MAPE and MAE and return the resulting dictionary of errors.\n",
946 | " return {'MAPE': error_mean('p'), 'MAE': error_mean('e')}\n"
947 | ],
948 | "execution_count": 42,
949 | "outputs": []
950 | },
951 | {
952 | "cell_type": "code",
953 | "metadata": {
954 | "id": "6lpRKrLhP4NQ",
955 | "outputId": "ac59aaa7-0ac1-41d7-9c17-d19c296134f7",
956 | "colab": {
957 | "base_uri": "https://localhost:8080/",
958 | "height": 51
959 | }
960 | },
961 | "source": [
962 | "for err_name, err_value in calculate_forecast_errors(cmp_df, prediction_size).items():\n",
963 | " print(err_name, err_value)"
964 | ],
965 | "execution_count": null,
966 | "outputs": [
967 | {
968 | "output_type": "stream",
969 | "text": [
970 | "MAPE 34.774518380154696\n",
971 | "MAE 55.0657164657149\n"
972 | ],
973 | "name": "stdout"
974 | }
975 | ]
976 | },
977 | {
978 | "cell_type": "markdown",
979 | "metadata": {
980 | "id": "HLConDmcvWW-"
981 | },
982 | "source": [
983 | "#**8- RMSE**"
984 | ]
985 | },
986 | {
987 | "cell_type": "code",
988 | "metadata": {
989 | "id": "3mn74pRGqITN"
990 | },
991 | "source": [
992 | "se = np.square(forecast.loc[:, 'yhat'] - df['y'])\n",
993 | "mse = np.mean(se)\n",
994 | "rmse = np.sqrt(mse)"
995 | ],
996 | "execution_count": 46,
997 | "outputs": []
998 | },
999 | {
1000 | "cell_type": "code",
1001 | "metadata": {
1002 | "id": "P3nGmOylu3nv",
1003 | "outputId": "d4b1e353-79a6-4435-99a0-c41b86a7ddbb",
1004 | "colab": {
1005 | "base_uri": "https://localhost:8080/"
1006 | }
1007 | },
1008 | "source": [
1009 | "print(rmse)"
1010 | ],
1011 | "execution_count": 47,
1012 | "outputs": [
1013 | {
1014 | "output_type": "stream",
1015 | "text": [
1016 | "29.077235826002735\n"
1017 | ],
1018 | "name": "stdout"
1019 | }
1020 | ]
1021 | },
1022 | {
1023 | "cell_type": "markdown",
1024 | "metadata": {
1025 | "id": "QmrbiUI8sjn8"
1026 | },
1027 | "source": [
1028 | "# **References** "
1029 | ]
1030 | },
1031 | {
1032 | "cell_type": "code",
1033 | "metadata": {
1034 | "id": "KZy09JqTtWPt"
1035 | },
1036 | "source": [
1037 | "#[1]Forecasting Time Series Data With Prophet I & II\n",
1038 | "# https://nextjournal.com/eric-brown/forecasting-with-prophet \n",
1039 | "#[2]Forecasting Time Series Data With Prophet IV\n",
1040 | "#https://nextjournal.com/eric-brown/forecasting-with-prophet-part-4\n",
1041 | "#[3]Time series analysis in Python\n",
1042 | "#https://mlcourse.ai/articles/topic9-part2-prophet/\n",
1043 | "#https://www.kaggle.com/kashnitsky/topic-9-part-2-time-series-with-facebook-prophet\n",
1044 | "#[4] Covid-19 Deaths Predictions (Time Series - Prophet) - DIY\n",
1045 | "#https://www.youtube.com/watch?v=zlFKgMnaDXk&feature=youtu.be&fbclid=IwAR3vSH3rUeeQRvhxSzADMlqK4CY06GaSbJSaeq-mAYfHXZb9E0M8Dlor4wU\n"
1046 | ],
1047 | "execution_count": null,
1048 | "outputs": []
1049 | }
1050 | ]
1051 | }
--------------------------------------------------------------------------------
/Implementation/5_13_2020_Covid_LSTM.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "kernelspec": {
6 | "display_name": "Python 3",
7 | "language": "python",
8 | "name": "python3"
9 | },
10 | "language_info": {
11 | "codemirror_mode": {
12 | "name": "ipython",
13 | "version": 3
14 | },
15 | "file_extension": ".py",
16 | "mimetype": "text/x-python",
17 | "name": "python",
18 | "nbconvert_exporter": "python",
19 | "pygments_lexer": "ipython3",
20 | "version": "3.6.6"
21 | },
22 | "colab": {
23 | "name": " 5-13-2020 Covid_LSTM.ipynb",
24 | "provenance": [],
25 | "collapsed_sections": [],
26 | "toc_visible": true,
27 | "machine_shape": "hm",
28 | "include_colab_link": true
29 | }
30 | },
31 | "cells": [
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {
35 | "id": "view-in-github",
36 | "colab_type": "text"
37 | },
38 | "source": [
39 | "
"
40 | ]
41 | },
42 | {
43 | "cell_type": "markdown",
44 | "metadata": {
45 | "id": "FfcjS4CKTyAP"
46 | },
47 | "source": [
48 | "# **1- Introduction** \n",
49 | "\n",
50 | "Predicting confirmed cases of Convid-19 with LSTM"
51 | ]
52 | },
53 | {
54 | "cell_type": "code",
55 | "metadata": {
56 | "id": "uTYReJPf9UFm",
57 | "outputId": "ccf747f0-ee30-4185-91e5-de0485b17e52",
58 | "colab": {
59 | "base_uri": "https://localhost:8080/"
60 | }
61 | },
62 | "source": [
63 | "!git clone https://github.com/hussain0048/Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System"
64 | ],
65 | "execution_count": 1,
66 | "outputs": [
67 | {
68 | "output_type": "stream",
69 | "text": [
70 | "Cloning into 'Machine-Learning-Driven-Approach-for-2019-nCoV-Warning-System'...\n",
71 | "fatal: could not read Username for 'https://github.com': No such device or address\n"
72 | ],
73 | "name": "stdout"
74 | }
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {
80 | "id": "85cNlo5f1-Z3"
81 | },
82 | "source": [
83 | "# **2- Import Nessary library**"
84 | ]
85 | },
86 | {
87 | "cell_type": "code",
88 | "metadata": {
89 | "id": "FxdLWHIJTyAU"
90 | },
91 | "source": [
92 | "import pandas as pd\n",
93 | "import numpy as np\n",
94 | "from fbprophet import Prophet\n",
95 | "import matplotlib.pyplot as plt\n",
96 | " \n",
97 | "plt.rcParams['figure.figsize']=(20,10)\n",
98 | "plt.style.use('ggplot')"
99 | ],
100 | "execution_count": 3,
101 | "outputs": []
102 | },
103 | {
104 | "cell_type": "code",
105 | "metadata": {
106 | "id": "5NeSSztObv-7"
107 | },
108 | "source": [
109 | "plt.rcParams['figure.figsize']=(20,10)\n",
110 | "plt.style.use('ggplot')"
111 | ],
112 | "execution_count": 4,
113 | "outputs": []
114 | },
115 | {
116 | "cell_type": "code",
117 | "metadata": {
118 | "id": "XhadCtyRcFFY"
119 | },
120 | "source": [
121 | "pd.plotting.register_matplotlib_converters()"
122 | ],
123 | "execution_count": 5,
124 | "outputs": []
125 | },
126 | {
127 | "cell_type": "code",
128 | "metadata": {
129 | "id": "-vcGxjHQGL1c"
130 | },
131 | "source": [
132 | "#[3]\n",
133 | "import warnings\n",
134 | "warnings.filterwarnings('ignore')\n",
135 | "\n",
136 | "import numpy as np\n",
137 | "import pandas as pd\n",
138 | "from scipy import stats\n",
139 | "import statsmodels.api as sm\n",
140 | "import matplotlib.pyplot as plt\n",
141 | "\n",
142 | "%matplotlib inline"
143 | ],
144 | "execution_count": 6,
145 | "outputs": []
146 | },
147 | {
148 | "cell_type": "code",
149 | "metadata": {
150 | "id": "d17uQ_kpKn5w"
151 | },
152 | "source": [
153 | "from fbprophet import Prophet\n",
154 | "\n",
155 | "import logging\n",
156 | "logging.getLogger().setLevel(logging.ERROR)"
157 | ],
158 | "execution_count": 7,
159 | "outputs": []
160 | },
161 | {
162 | "cell_type": "code",
163 | "metadata": {
164 | "id": "Ia255xaIs1iD"
165 | },
166 | "source": [
167 | "# LSTM\n",
168 | "import math\n",
169 | "import pandas_datareader as web\n",
170 | "import numpy as np\n",
171 | "import pandas as pd\n",
172 | "from sklearn.preprocessing import MinMaxScaler\n",
173 | "from keras.models import Sequential\n",
174 | "from keras.layers import Dense,LSTM\n",
175 | "import matplotlib.pyplot as plt\n",
176 | "plt.style.use('fivethirtyeight')"
177 | ],
178 | "execution_count": 8,
179 | "outputs": []
180 | },
181 | {
182 | "cell_type": "code",
183 | "metadata": {
184 | "id": "NwsfXTJk2R0M",
185 | "outputId": "e03f8c93-a8da-420e-b702-f430e02607b8",
186 | "colab": {
187 | "base_uri": "https://localhost:8080/"
188 | }
189 | },
190 | "source": [
191 | "from google.colab import drive\n",
192 | "drive.mount('/content/drive')"
193 | ],
194 | "execution_count": 9,
195 | "outputs": [
196 | {
197 | "output_type": "stream",
198 | "text": [
199 | "Mounted at /content/drive\n"
200 | ],
201 | "name": "stdout"
202 | }
203 | ]
204 | },
205 | {
206 | "cell_type": "markdown",
207 | "metadata": {
208 | "id": "X5p8oL_STyAg"
209 | },
210 | "source": [
211 | "# **3-Import dataset**"
212 | ]
213 | },
214 | {
215 | "cell_type": "code",
216 | "metadata": {
217 | "id": "RDKPEa7keRWE"
218 | },
219 | "source": [
220 | "df = pd.read_csv(\"/content/drive/My Drive/Datasets/Covid-19/data_cases1.csv\", usecols=['Date','Confirmed'],index_col='Date', parse_dates=True )\n",
221 | "df.head()"
222 | ],
223 | "execution_count": null,
224 | "outputs": []
225 | },
226 | {
227 | "cell_type": "code",
228 | "metadata": {
229 | "id": "_qRu1k2Dyt2O"
230 | },
231 | "source": [
232 | "df.head()"
233 | ],
234 | "execution_count": null,
235 | "outputs": []
236 | },
237 | {
238 | "cell_type": "code",
239 | "metadata": {
240 | "id": "t-E75RQRTyAx"
241 | },
242 | "source": [
243 | "df.shape"
244 | ],
245 | "execution_count": null,
246 | "outputs": []
247 | },
248 | {
249 | "cell_type": "markdown",
250 | "metadata": {
251 | "id": "R8BthJfITyBS"
252 | },
253 | "source": [
254 | "#**4-Data cleaning and feature engineering**"
255 | ]
256 | },
257 | {
258 | "cell_type": "code",
259 | "metadata": {
260 | "id": "Ns2tk6CCGzDo"
261 | },
262 | "source": [
263 | "df1 = df.reset_index()"
264 | ],
265 | "execution_count": 68,
266 | "outputs": []
267 | },
268 | {
269 | "cell_type": "code",
270 | "metadata": {
271 | "id": "WGxkU_bZ_eoq"
272 | },
273 | "source": [
274 | "df1.head()"
275 | ],
276 | "execution_count": null,
277 | "outputs": []
278 | },
279 | {
280 | "cell_type": "code",
281 | "metadata": {
282 | "id": "wiEfm8xA9Cb4"
283 | },
284 | "source": [
285 | "#we get rid of possible duplicates and missing values in the data [3]\n",
286 | "df1 = df1[['Date', 'Confirmed']].dropna().drop_duplicates()"
287 | ],
288 | "execution_count": 70,
289 | "outputs": []
290 | },
291 | {
292 | "cell_type": "code",
293 | "metadata": {
294 | "id": "fqj24WXrFwbV"
295 | },
296 | "source": [
297 | "df1.shape"
298 | ],
299 | "execution_count": null,
300 | "outputs": []
301 | },
302 | {
303 | "cell_type": "code",
304 | "metadata": {
305 | "id": "8oKf0uV2GG02"
306 | },
307 | "source": [
308 | "#we need to convert Date to the datetime format because by default pandas treats this field as string-valued[3]\n",
309 | "df1['Date'] = pd.to_datetime(df1['Date'])"
310 | ],
311 | "execution_count": 72,
312 | "outputs": []
313 | },
314 | {
315 | "cell_type": "code",
316 | "metadata": {
317 | "id": "ijc8tkqbGqpE"
318 | },
319 | "source": [
320 | "df1.head()"
321 | ],
322 | "execution_count": null,
323 | "outputs": []
324 | },
325 | {
326 | "cell_type": "code",
327 | "metadata": {
328 | "id": "-cnFzmAAHIWq"
329 | },
330 | "source": [
331 | "#Let's sort the dataframe by time and take a look at what we've got [3]\n",
332 | "df1.sort_values(by=['Date']).head(n=3)"
333 | ],
334 | "execution_count": null,
335 | "outputs": []
336 | },
337 | {
338 | "cell_type": "code",
339 | "metadata": {
340 | "id": "vegTUwkq9kw8"
341 | },
342 | "source": [
343 | "#We will just trim our time series to keep only those rows that fall onto the period from March 10, 2020 to March 31, 2020[3]\n",
344 | "df1 = df1[(df1['Date'] > '2020-03-09') & (df1['Date'] < '2020-04-01')].sort_values(by=['Date'])\n",
345 | "df1.head(n=10)"
346 | ],
347 | "execution_count": null,
348 | "outputs": []
349 | },
350 | {
351 | "cell_type": "code",
352 | "metadata": {
353 | "id": "rahdPkyK-81A"
354 | },
355 | "source": [
356 | "#As we are going to predict the number of confirm Cases of Covid-19, we will aggregate and count unique Cases at each given point in time. We will name the corresponding new column Confirmed_Cases:\n",
357 | "aggr_df = df1.groupby('Date')[['Confirmed']].count()\n",
358 | "aggr_df.columns = ['Confirmed_Cases']"
359 | ],
360 | "execution_count": 77,
361 | "outputs": []
362 | },
363 | {
364 | "cell_type": "code",
365 | "metadata": {
366 | "id": "K-av4_rg_pfa"
367 | },
368 | "source": [
369 | "aggr_df.head(n=3)\n"
370 | ],
371 | "execution_count": null,
372 | "outputs": []
373 | },
374 | {
375 | "cell_type": "code",
376 | "metadata": {
377 | "id": "8WPfYYLU_6dD"
378 | },
379 | "source": [
380 | "#In this practice, we are interested in the number of confirmed cases a day. But at this moment all our data is divided into irregular time intervals that are less than a day. \n",
381 | "#This is called a sub-daily time series.To fix this, we need to aggregate the Cases counts by \"bins\" of a date size. \n",
382 | "#In time series analysis, this process is referred to as resampling. And if we reduce the sampling rate of data it is often called downsampling.\n",
383 | "#Luckily, pandas has a built-in functionality for this task. We will resample our time index down to 1-day bins [3]\n",
384 | "daily_df = aggr_df.resample('D').apply(sum)\n",
385 | "daily_df.head(n=3)"
386 | ],
387 | "execution_count": null,
388 | "outputs": []
389 | },
390 | {
391 | "cell_type": "code",
392 | "metadata": {
393 | "id": "9n0GTxkvAeq5"
394 | },
395 | "source": [
396 | "weekly_df = df1.resample('W').apply(sum)"
397 | ],
398 | "execution_count": null,
399 | "outputs": []
400 | },
401 | {
402 | "cell_type": "code",
403 | "metadata": {
404 | "id": "SUR6GRnOJp5T",
405 | "outputId": "de7058f9-8c63-4574-9f99-7d16f1ad130a",
406 | "colab": {
407 | "base_uri": "https://localhost:8080/",
408 | "height": 164
409 | }
410 | },
411 | "source": [
412 | "weekly_df.head()"
413 | ],
414 | "execution_count": 24,
415 | "outputs": [
416 | {
417 | "output_type": "error",
418 | "ename": "NameError",
419 | "evalue": "ignored",
420 | "traceback": [
421 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
422 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
423 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mweekly_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhead\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
424 | "\u001b[0;31mNameError\u001b[0m: name 'weekly_df' is not defined"
425 | ]
426 | }
427 | ]
428 | },
429 | {
430 | "cell_type": "code",
431 | "metadata": {
432 | "id": "lVCbk-vsAz-n",
433 | "outputId": "10a05488-8331-4da1-9360-b60fd39a21cc",
434 | "colab": {
435 | "base_uri": "https://localhost:8080/",
436 | "height": 181
437 | }
438 | },
439 | "source": [
440 | "daily_df = daily_df.loc[daily_df.index >= '2020-03-10']\n",
441 | "daily_df.head(n=3)"
442 | ],
443 | "execution_count": 25,
444 | "outputs": [
445 | {
446 | "output_type": "error",
447 | "ename": "NameError",
448 | "evalue": "ignored",
449 | "traceback": [
450 | "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
451 | "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
452 | "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mdaily_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdaily_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mdaily_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m \u001b[0;34m>=\u001b[0m \u001b[0;34m'2020-03-10'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mdaily_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mhead\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
453 | "\u001b[0;31mNameError\u001b[0m: name 'daily_df' is not defined"
454 | ]
455 | }
456 | ]
457 | },
458 | {
459 | "cell_type": "code",
460 | "metadata": {
461 | "id": "ZQLlg3g4OvWh"
462 | },
463 | "source": [
464 | "plt.figure(figsize=(16,8))\n",
465 | "plt.title('Daily Confirmed Cases of COVID-19 (World)')\n",
466 | "plt.plot(daily_df['Confirmed_Cases'])\n",
467 | "plt.xlabel('Date', fontsize=18)\n",
468 | "plt.ylabel('Confirmed Cases', fontsize=18)\n",
469 | "plt.show()"
470 | ],
471 | "execution_count": null,
472 | "outputs": []
473 | },
474 | {
475 | "cell_type": "markdown",
476 | "metadata": {
477 | "id": "C8ivtMFNTyEs"
478 | },
479 | "source": [
480 | "#**5- Modelling**\n"
481 | ]
482 | },
483 | {
484 | "cell_type": "code",
485 | "metadata": {
486 | "id": "IVFBqHaJBM2J"
487 | },
488 | "source": [
489 | "#Lstm\n",
490 | "data=aggr_df.filter(['Confirmed'])"
491 | ],
492 | "execution_count": 79,
493 | "outputs": []
494 | },
495 | {
496 | "cell_type": "code",
497 | "metadata": {
498 | "id": "Uucawvui-7iT"
499 | },
500 | "source": [
501 | "dataset=aggr_df.values"
502 | ],
503 | "execution_count": 80,
504 | "outputs": []
505 | },
506 | {
507 | "cell_type": "code",
508 | "metadata": {
509 | "id": "BMJiPPce_C3A"
510 | },
511 | "source": [
512 | "training_data_len=math.ceil(len(dataset)*.8)"
513 | ],
514 | "execution_count": 81,
515 | "outputs": []
516 | },
517 | {
518 | "cell_type": "code",
519 | "metadata": {
520 | "id": "LqoNjyXg_qjc"
521 | },
522 | "source": [
523 | "training_data_len"
524 | ],
525 | "execution_count": null,
526 | "outputs": []
527 | },
528 | {
529 | "cell_type": "code",
530 | "metadata": {
531 | "id": "YgLle6F7_0DK"
532 | },
533 | "source": [
534 | "scaler=MinMaxScaler(feature_range=(0,1))"
535 | ],
536 | "execution_count": 83,
537 | "outputs": []
538 | },
539 | {
540 | "cell_type": "code",
541 | "metadata": {
542 | "id": "QUPaY-3DAE9v"
543 | },
544 | "source": [
545 | "scaled_data=scaler.fit_transform(dataset)"
546 | ],
547 | "execution_count": 84,
548 | "outputs": []
549 | },
550 | {
551 | "cell_type": "code",
552 | "metadata": {
553 | "id": "CQgo0uoxAZT9"
554 | },
555 | "source": [
556 | "scaled_data"
557 | ],
558 | "execution_count": null,
559 | "outputs": []
560 | },
561 | {
562 | "cell_type": "code",
563 | "metadata": {
564 | "id": "2TtxrK2kBS8F",
565 | "outputId": "87e86f76-7a27-476d-c702-a8b717dcb985",
566 | "colab": {
567 | "base_uri": "https://localhost:8080/"
568 | }
569 | },
570 | "source": [
571 | "# create the training dataset\n",
572 | "# create the scaled training dataset\n",
573 | "train_data=scaled_data[0:training_data_len,:]\n",
574 | "# split the data into x_train and y_train dataset\n",
575 | "x_train = []\n",
576 | "y_train = []\n",
577 | "\n",
578 | "for i in range (12, len(train_data)):\n",
579 | " x_train.append(train_data[i-12:i,0])\n",
580 | " y_train.append(train_data[i,0])\n",
581 | " if i<= 12:\n",
582 | " print(x_train)\n",
583 | " print(y_train)\n",
584 | " print()"
585 | ],
586 | "execution_count": 86,
587 | "outputs": [
588 | {
589 | "output_type": "stream",
590 | "text": [
591 | "[array([0. , 0.04458599, 0.07006369, 0.08280255, 0.12738854,\n",
592 | " 0.12101911, 0.15923567, 0.15286624, 0.15923567, 0.17197452,\n",
593 | " 0.1910828 , 0.21656051])]\n",
594 | "[0.624203821656051]\n",
595 | "\n"
596 | ],
597 | "name": "stdout"
598 | }
599 | ]
600 | },
601 | {
602 | "cell_type": "code",
603 | "metadata": {
604 | "id": "oZl7H0pBChBy",
605 | "outputId": "1e2b2a96-c815-4174-f808-9f137cddfc95",
606 | "colab": {
607 | "base_uri": "https://localhost:8080/"
608 | }
609 | },
610 | "source": [
611 | "# Convert the x_train and y_train to numpy arrays\n",
612 | "x_train, y_train = np.array(x_train), np.array(y_train)\n",
613 | "x_train"
614 | ],
615 | "execution_count": 87,
616 | "outputs": [
617 | {
618 | "output_type": "execute_result",
619 | "data": {
620 | "text/plain": [
621 | "array([[0. , 0.04458599, 0.07006369, 0.08280255, 0.12738854,\n",
622 | " 0.12101911, 0.15923567, 0.15286624, 0.15923567, 0.17197452,\n",
623 | " 0.1910828 , 0.21656051],\n",
624 | " [0.04458599, 0.07006369, 0.08280255, 0.12738854, 0.12101911,\n",
625 | " 0.15923567, 0.15286624, 0.15923567, 0.17197452, 0.1910828 ,\n",
626 | " 0.21656051, 0.62420382]])"
627 | ]
628 | },
629 | "metadata": {
630 | "tags": []
631 | },
632 | "execution_count": 87
633 | }
634 | ]
635 | },
636 | {
637 | "cell_type": "code",
638 | "metadata": {
639 | "id": "901KPDDeCpu5",
640 | "outputId": "380d8dd1-a08a-4a7c-e397-7a5832ac87d8",
641 | "colab": {
642 | "base_uri": "https://localhost:8080/"
643 | }
644 | },
645 | "source": [
646 | "# Reshap the data\n",
647 | "x_train=np.reshape(x_train, (x_train.shape[0], x_train.shape[1],1))\n",
648 | "x_train.shape"
649 | ],
650 | "execution_count": 88,
651 | "outputs": [
652 | {
653 | "output_type": "execute_result",
654 | "data": {
655 | "text/plain": [
656 | "(2, 12, 1)"
657 | ]
658 | },
659 | "metadata": {
660 | "tags": []
661 | },
662 | "execution_count": 88
663 | }
664 | ]
665 | },
666 | {
667 | "cell_type": "code",
668 | "metadata": {
669 | "id": "Qo5bwUE-Cz9g"
670 | },
671 | "source": [
672 | "# build the LSTM model\n",
673 | "model=Sequential()\n",
674 | "model.add(LSTM(40, return_sequences=True,input_shape=(x_train.shape[1],1)))\n",
675 | "model.add(LSTM(40, return_sequences=False))\n",
676 | "model.add(Dense(25))\n",
677 | "model.add(Dense(1))"
678 | ],
679 | "execution_count": 89,
680 | "outputs": []
681 | },
682 | {
683 | "cell_type": "code",
684 | "metadata": {
685 | "id": "Ph3rquB-DZsX",
686 | "outputId": "a754b201-7b40-4edc-81b9-41b542a57d36",
687 | "colab": {
688 | "base_uri": "https://localhost:8080/"
689 | }
690 | },
691 | "source": [
692 | "# train the model\n",
693 | "model.fit(x_train,y_train,batch_size=1,epochs=1)"
694 | ],
695 | "execution_count": 91,
696 | "outputs": [
697 | {
698 | "output_type": "stream",
699 | "text": [
700 | "2/2 [==============================] - 0s 6ms/step - loss: 0.4434\n"
701 | ],
702 | "name": "stdout"
703 | },
704 | {
705 | "output_type": "execute_result",
706 | "data": {
707 | "text/plain": [
708 | ""
709 | ]
710 | },
711 | "metadata": {
712 | "tags": []
713 | },
714 | "execution_count": 91
715 | }
716 | ]
717 | },
718 | {
719 | "cell_type": "code",
720 | "metadata": {
721 | "id": "Mxp-MSYPDOzz"
722 | },
723 | "source": [
724 | "# compile the model\n",
725 | "model.compile(optimizer='adam',loss='mean_squared_error')"
726 | ],
727 | "execution_count": 90,
728 | "outputs": []
729 | },
730 | {
731 | "cell_type": "code",
732 | "metadata": {
733 | "id": "I8b3sFhSEDiL"
734 | },
735 | "source": [
736 | "test_data=scaled_data[training_data_len -12:,:]\n",
737 | "x_test= []\n",
738 | "y_test = dataset[training_data_len:,:]\n",
739 | "for i in range(12, len(test_data)):\n",
740 | " x_test.append(test_data[i -12:i,0])"
741 | ],
742 | "execution_count": 92,
743 | "outputs": []
744 | },
745 | {
746 | "cell_type": "code",
747 | "metadata": {
748 | "id": "RuY3KUkGEOYA"
749 | },
750 | "source": [
751 | "x_test=np.array(x_test)"
752 | ],
753 | "execution_count": 93,
754 | "outputs": []
755 | },
756 | {
757 | "cell_type": "code",
758 | "metadata": {
759 | "id": "IrrrGaW1EQuf",
760 | "outputId": "8bc16ae1-9e25-4d7e-d53b-bed388093491",
761 | "colab": {
762 | "base_uri": "https://localhost:8080/"
763 | }
764 | },
765 | "source": [
766 | "x_test"
767 | ],
768 | "execution_count": 94,
769 | "outputs": [
770 | {
771 | "output_type": "execute_result",
772 | "data": {
773 | "text/plain": [
774 | "array([[0.07006369, 0.08280255, 0.12738854, 0.12101911, 0.15923567,\n",
775 | " 0.15286624, 0.15923567, 0.17197452, 0.1910828 , 0.21656051,\n",
776 | " 0.62420382, 0.72611465],\n",
777 | " [0.08280255, 0.12738854, 0.12101911, 0.15923567, 0.15286624,\n",
778 | " 0.15923567, 0.17197452, 0.1910828 , 0.21656051, 0.62420382,\n",
779 | " 0.72611465, 0.78343949],\n",
780 | " [0.12738854, 0.12101911, 0.15923567, 0.15286624, 0.15923567,\n",
781 | " 0.17197452, 0.1910828 , 0.21656051, 0.62420382, 0.72611465,\n",
782 | " 0.78343949, 0.89808917]])"
783 | ]
784 | },
785 | "metadata": {
786 | "tags": []
787 | },
788 | "execution_count": 94
789 | }
790 | ]
791 | },
792 | {
793 | "cell_type": "code",
794 | "metadata": {
795 | "id": "dLKwuQ2mEUY-"
796 | },
797 | "source": [
798 | "x_test=np.reshape(x_test,(x_test.shape[0], x_test.shape[1],1))"
799 | ],
800 | "execution_count": 95,
801 | "outputs": []
802 | },
803 | {
804 | "cell_type": "code",
805 | "metadata": {
806 | "id": "u2GibjoyEco3"
807 | },
808 | "source": [
809 | "predictions=model.predict(x_test)\n",
810 | "predictions=scaler.inverse_transform(predictions)"
811 | ],
812 | "execution_count": 96,
813 | "outputs": []
814 | },
815 | {
816 | "cell_type": "code",
817 | "metadata": {
818 | "id": "oCknKvIiDSvC"
819 | },
820 | "source": [
821 | "rmse=np.sqrt(np.mean(predictions - y_test)**2)"
822 | ],
823 | "execution_count": 97,
824 | "outputs": []
825 | },
826 | {
827 | "cell_type": "code",
828 | "metadata": {
829 | "id": "4UAIiiUzDStS",
830 | "outputId": "3446c8d6-c16c-49fb-eecf-bb3d06d0f811",
831 | "colab": {
832 | "base_uri": "https://localhost:8080/"
833 | }
834 | },
835 | "source": [
836 | "rmse"
837 | ],
838 | "execution_count": 98,
839 | "outputs": [
840 | {
841 | "output_type": "execute_result",
842 | "data": {
843 | "text/plain": [
844 | "130.11727078755698"
845 | ]
846 | },
847 | "metadata": {
848 | "tags": []
849 | },
850 | "execution_count": 98
851 | }
852 | ]
853 | },
854 | {
855 | "cell_type": "code",
856 | "metadata": {
857 | "id": "auMST9VMFXil"
858 | },
859 | "source": [
860 | "train=aggr_df[:training_data_len]\n",
861 | "valid=aggr_df[training_data_len:]"
862 | ],
863 | "execution_count": 100,
864 | "outputs": []
865 | },
866 | {
867 | "cell_type": "code",
868 | "metadata": {
869 | "id": "9U1h6R3DGG_4"
870 | },
871 | "source": [
872 | "valid['Predictions']=predictions"
873 | ],
874 | "execution_count": 101,
875 | "outputs": []
876 | },
877 | {
878 | "cell_type": "code",
879 | "metadata": {
880 | "id": "L0bIwuB0J-nn",
881 | "outputId": "1ac7531b-a6d0-4236-a2c7-61c51c05eaeb",
882 | "colab": {
883 | "base_uri": "https://localhost:8080/",
884 | "height": 173
885 | }
886 | },
887 | "source": [
888 | "valid.head()"
889 | ],
890 | "execution_count": 102,
891 | "outputs": [
892 | {
893 | "output_type": "execute_result",
894 | "data": {
895 | "text/html": [
896 | "\n",
897 | "\n",
910 | "
\n",
911 | " \n",
912 | " \n",
913 | " | \n",
914 | " Confirmed_Cases | \n",
915 | " Predictions | \n",
916 | "
\n",
917 | " \n",
918 | " | Date | \n",
919 | " | \n",
920 | " | \n",
921 | "
\n",
922 | " \n",
923 | " \n",
924 | " \n",
925 | " | 2020-03-24 | \n",
926 | " 140 | \n",
927 | " 26.088554 | \n",
928 | "
\n",
929 | " \n",
930 | " | 2020-03-25 | \n",
931 | " 158 | \n",
932 | " 27.168270 | \n",
933 | "
\n",
934 | " \n",
935 | " | 2020-03-26 | \n",
936 | " 174 | \n",
937 | " 28.391363 | \n",
938 | "
\n",
939 | " \n",
940 | "
\n",
941 | "
"
942 | ],
943 | "text/plain": [
944 | " Confirmed_Cases Predictions\n",
945 | "Date \n",
946 | "2020-03-24 140 26.088554\n",
947 | "2020-03-25 158 27.168270\n",
948 | "2020-03-26 174 28.391363"
949 | ]
950 | },
951 | "metadata": {
952 | "tags": []
953 | },
954 | "execution_count": 102
955 | }
956 | ]
957 | },
958 | {
959 | "cell_type": "code",
960 | "metadata": {
961 | "id": "S9o1cWAPG85L",
962 | "outputId": "e85abd2f-70b0-4105-ad29-aed877108e7d",
963 | "colab": {
964 | "base_uri": "https://localhost:8080/",
965 | "height": 468
966 | }
967 | },
968 | "source": [
969 | "plt.figure(figsize=(16,8))\n",
970 | "plt.title('Model')\n",
971 | "plt.xlabel('Date',fontsize=18)\n",
972 | "plt.ylabel('Confirmed Cases',fontsize=18)\n",
973 | "plt.plot(train['Confirmed_Cases'])\n",
974 | "plt.plot(valid[['Confirmed_Cases','Predictions']])\n",
975 | "plt.legend(['Train','Val','Predictions'],loc='lower right')"
976 | ],
977 | "execution_count": 103,
978 | "outputs": [
979 | {
980 | "output_type": "execute_result",
981 | "data": {
982 | "text/plain": [
983 | ""
984 | ]
985 | },
986 | "metadata": {
987 | "tags": []
988 | },
989 | "execution_count": 103
990 | },
991 | {
992 | "output_type": "display_data",
993 | "data": {
994 | "image/png": "iVBORw0KGgoAAAANSUhEUgAABCwAAAIdCAYAAAD25OyiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAgAElEQVR4nOzdeXhTZf7//1eSNt0XWrZSoAKWfXGoqGWRuowKOICIgvWrIi7jwowL6riMqPN1xIXfR+eDMyowbuAoi6hFQXADxBVBQAeRUqCsZSttWtqkbXK+f/AzGEJrgLQnCc/Hdc01nvs+Sd7prb3k5f2+j6WsrMwQAAAAAABACLGaXQAAAAAAAMDRCCwAAAAAAEDIIbAAAAAAAAAhh8ACAAAAAACEHAILAAAAAAAQcggsAAAAAABAyCGwAAAAEae4uFipqam69dZbQ+J9AADA8SOwAAAAJy01NVWpqalq1qyZtmzZUu99I0eO9N778ssvN2GFAAAg3BBYAACAoIiKipJhGHr99dePOb9161YtW7ZMUVFRTVwZAAAIRwQWAAAgKNLS0tSvXz/95z//UV1dnd/8zJkzZRiGLrnkEhOqAwAA4YbAAgAABM21116rPXv2aNGiRT7jdXV1euONN5STk6MePXrU+/qtW7fqtttuU/fu3dWiRQtlZ2dr3Lhx+vHHH495f0VFhR588EF1795drVq1Ur9+/fT888/LMIx6P8PpdGrq1KkaPHiwMjMz1aZNG+Xl5enll19u8HUAAKBpEVgAAICgGTVqlJKSkvzaQhYvXqySkhJdd9119b52zZo1Gjx4sN5880316tVLf/rTnzRw4EC9//77uvDCC/Xpp5/63O9yuTRixAj961//Umpqqm655RYNHDhQU6ZM0QMPPHDMz6ioqNCwYcP08MMPyzAM5efn6+qrr5bD4dDdd9+t22677eR/CAAAIChoIgUAAEGTkJCg0aNH67XXXtP27dvVrl07SdLrr7+uxMREjRo1SlOnTvV7nWEYuuWWW1ReXq5//etfys/P984tXbpUl112mW6++WatW7dO8fHxkqTnn39eq1ev1tChQzVr1ixZrYf/O8xdd92lvLy8Y9b34IMPatWqVXr00Ud15513esddLpeuueYavfnmmxo+fLiGDBkSrB8JAAA4QeywAAAAQXXdddfJ4/Fo1qxZkqSdO3fq448/1uWXX67ExMRjvuabb77Rhg0b1LdvX5+wQpLy8vJ06aWXav/+/Vq4cKF3/I033pDFYtFjjz3mDSskqX379vrjH//o9xkHDx7Um2++qd69e/uEFZIUExOjSZMmSZJmz559Yl8cAAAEFTssAABAUJ1xxhnq3bu33njjDd13332aOXOm3G53g+0ga9eulSSde+65x5zPy8vTggULtHbtWo0ePVoVFRXavHmzWrdurezsbL/7BwwY4De2atUq1dXVyWq1avLkyX7zvxwUunHjxoC+JwAAaFwEFgAAIOiuu+46TZw4UYsXL9asWbPUs2dP9e3bt977HQ6HJKlly5bHnG/VqpUkqby83Of+Fi1aHPP+Y71PaWmppMNnZaxZs6beWiorK+udAwAATYeWEAAAEHRXXHGF4uPjde+992rHjh0aN25cg/cnJydLkvbu3XvM+T179vjc98v/79u375j3H+t9fnnNzTffrLKysnr/t27dut/+ggAAoNERWAAAgKBLTk7WZZddpp07dyo+Pl5XXHFFg/f36dNHkvT5558fc37ZsmWSDrebSFJSUpI6duyoPXv2aNOmTX73f/HFF35jZ555pqxWq7766qvj+i4AAMAcBBYAAKBRPPjgg5o1a5bmzZunlJSUBu89++yz1aVLF61atcrv0Mtly5ZpwYIFSk9P19ChQ73jV199tQzD0KRJk+TxeLzj27Zt00svveT3Gc2bN9eYMWP0ww8/aPLkyd4zK35t586dnGEBAECI4AwLAADQKDIzM5WZmRnQvRaLRS+88IJGjhypW265Re+884569OihLVu2qKCgQHa7XS+++KL3kaaSNGHCBH3wwQdauHChBg0apAsvvFAOh0PvvPOOcnNztWjRIr/Pefrpp7V582Y99dRTmj17tvr3769WrVp5d2qsXLlSf//739W5c+eg/RwAAMCJIbAAAAAhoW/fvlq6dKmeeeYZLV26VJ988olSUlI0bNgwTZw4Ub179/a5PyYmRu+++66efPJJvfPOO3rxxRfVvn17TZw4UX/4wx+OGVgkJSXp/fff18yZMzV37ly9//77cjqdatGihbKysvTII4/osssua6qvDAAAGmApKyszzC4CAAAAAADg1zjDAgAAAAAAhBwCCwAAAAAAEHIILAAAAAAAQMghsAAAAAAAACGHwAIA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F3BgYRiG9zGmx1JZWSmbzXZcH96lSxdNnz693vmG5n4RHR2t/Px85efnH9dnAwAAAGgcH+9w6ublB1Xq8viMR1mkv/VL0a3dE2Sx8MhSAA0LONLMyMho8BEw69atU7t27YJSFAAAAIDw4/YYeny1Q1d8dMAvrGibYNOioS10W49EwgoAAQk4sBg4cKBWr16tzz//XIZhSJIsFotcLpfefPNNFRUVadCgQY1WKAAAAIDQtafKrZGL92vK2goZR839PjNGy4e3UL+WnFcBIHABt4Tk5eVp06ZNmjlzpubOnSvpcMvGoUOH5PF41L9/f51zzjmNVigAAACA0PT5bpduXFaqPdW+uyqsFumvfZN1Z69EWdlVAeA4BRxYSNKNN96ovn376ptvvtHu3bslSR06dFBubq5ycnIapUAAAAAAocljGHp2XaX+/r1DnqO2VbSKs2rG4DQNyogxpzgAYe+4AgtJ6tu3r/r27dsYtQAAAAAIE44aj25YWqqPdrr85s7NiNGMwc3UMu74DuUHgF876ecIVVRUaM+ePcGoBQAAAECYuPfrMr+wwiLp3j5JeueidMIKACct4B0WX375pTZt2qRrr73WO/b2229r8eLFkqSOHTvqzjvvVGxsbPCrBAAAABAyDjjdmre52mcsLcaqaec204Vt+fMAgOAIeIfF8uXL5fEcOURn69atWrx4sbKzszVo0CBt3bpVS5YsaZQiAQAAAISOD7Y55f7VmRXtE21aPrwFYQWAoAp4h8XevXt15plneq+/++47JSQk6K677lJUVJQsFou+++47DR8+vFEKBQAAABAaCrb67q7IPz1ebROP+3g8AGhQwDssqqurFRcX573esGGDunXrpqiow7+YsrKyVFpaGvwKAQAAAISMgy6Plu7yPbtixGlx9dwNACcu4MAiJSXFe7hmRUWFtm/fruzsbO+8y+WS1XrSZ3gCAAAACGELt1Wr7lftIF1SotStWbR5BQGIWAHv2+ratauWLl2qhIQE/fzzz7JYLOrVq5d3fs+ePUpNTW2UIgEAAACEhqPbQYazuwJAIwk4sBg+fLiKior09ttvS5KGDRum5s2bS5LcbrdWrVqlnJycxqkSAAAAgOnKXB59SjsIgCYScGCRlpamxx57TLt27VJcXJzS09O9czU1Nbr22mvVtm3bRikSAAAAgPk+3O5U7ZEHB+r0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m0pISNCPf/xjzZs3zzeO559/Xk899ZQOHDiguLg4nXvuuXrttddktQY3YgjrwALSuJ62ZgOLxGiTLutl15VZMZrQk5ACAAAAQMdT8e609nsuSXET17b6Ona7XS6XS5K0d+9evfHGG3rhhRcUHR0tm82mGTNmKDExUUuWLFGXLl20aNEizZw5U5988ol69OihTz/9VHfccYceeOABXXnlldq0aZMeeuihFp/znXfe0XXXXacFCxbo6aefltvt1nvvvSev16uXX35ZY8aM0Q9+8APdcsstzV7j888/14033qi77rpL1157rbZu3aoFCxYoISFBt99+u++8//mf/9F9992nefPmaf369brnnnt04YUXauTIkfrXv/6lu+66S88884wuvPBClZaWKjc3t9Xf01MhsAhzszJj9KtPynzbidEmXd47Rldmxmh8TxshBQAAAAC0o88++0xvvPGGxo0bJ0mqqanRwoULlZKSIkl6//33tW3bNuXn5/taOn71q19p7dq1WrJkiebPn6///d//1bhx43TXXXdJkvr166etW7fqpZdeavZ5H3vsMc2aNUu/+tWvfPu+853vSJJiY2NlNpuVkJDQYgvI008/rYsvvlj333+/73l37dqlv/zlL36BxcSJE3XbbbdJkm6//XYtXLhQ77//vkaOHKn9+/crLi5O06dPV0JCgqTaWRltIezvEtLZ9Yq3akq6TXP6xeq1yd2UPztNz4ztokt7MaMCAAAAANrDO++8o/T0dKWmpmrKlCm66KKL9Mc//lGS1LNnT19YIUlffPGFKisr1a9fP6Wnp/v+7NixQ7t375Yk7dy5UxdccIHfczTdburLL7/0hSRna+fOnSfdoGL06NE6dOiQysoaflE+dOhQv3N69Oiho0ePSpImTJigjIwMnXPOObr11lu1aNEinThxolXjag4zLDqA16d2D/UQAAAAAKDTuuiii/SXv/xFVqtVaWlpioqK8h1reqcQr9erlJQUrVmz5qTr1M9ICEeNFwpt/PXVHzMMQ1Lt15Cbm6vNmzdr48aNeuKJJ/Tb3/5W7777rtLS0oI6JgILAAAAAEDIBGNNiUA4nc6zvptkbGyssrOzAzr3nHPOUWFhocxmszIzM095zsCBA/Xpp5/67Wu63dTw4cP1/vvv64c//OEpj0dHR8vj8bR4jYEDB+qjjz7y27dlyxalp6efUZhitVo1btw4jRs3Tvfdd5/69eunt99+WzfeeGPA1wgELSEAAAAAAATJ+PHjdeGFF2rOnDlav3699uzZo48//li///3v9cEHH0iqXRdi48aN+tOf/qRdu3bpxRdf1MqVK1u87p133qlly5bp4Ycf1jfffKMdO3bo6aefVmVlpSSpd+/e2rJliw4dOqTi4uJTXuOnP/2pNm/erEceeUT5+fl67bXX9PTTT/vdAeR01q5dq2eeeUZffPGF9u3bp9dff13l5eUaMGBAwNcIFIEFAAAAAABBYjKZ9Nprr2ns2LGaP3++LrjgAt10003Kz8/3tUxccMEFevLJJ/Xcc8/p4osvVk5Oju69994Wrzt16lS9/PLLWr9+vS655BJdfvnl2rRpk8zm2rf1999/vw4cOKARI0aob9++p7zGueeeqxdeeEE5OTkaPXq0fvOb3+j//b//51tgMxAOh0OrVq3SlVdeqZEjR+qpp57SX//6V1100UUBXyNQppKSEiPoVwXOUF5envr37x/qYaCVqGPHRw0jA3WMDNQxMlDHyEAdg6O0tFQOhyNkz9+alhC0ztnWnhkWAAAAAAAg7BBYAAAAAACAsENgAQAAAAAAwg6BBQAAAAAACDsEFgAAAAAAIOwQWAAAAAAAgLBDYAEAAAAAaHNWq1UVFRUyDCPUQ0E7qqmpkdl8dtGDNchjAQAAAADgJHFxcaqurlZZWVlInr+srEyJiYkhee7OzGw2Kz4+/qweS2ABAAAAAGgXNptNNpstJM9dWFioXr16heS5cXZoCQEAAAAAAGGHwAIAAAAAAIQdAgsAAAAAABB2CCwAAAAAAEDYMZWUlHBPGQAAAAAAEFaYYQEAAAAAAMIOgQUAAAAAAAg7BBYAAAAAACDsEFgAAAAAAICwQ2ABAAAAAADCjjXUA0D7Wb16tbZu3aqCggJZrVZlZ2frqquuUnp6uu8cwzCUk5Oj3NxcVVZWKisrS3PmzPGdU1RUpJUrV2rnzp0qLS2Vw+HQBRdcoCuuuELR0dG+6xQXF2vRokX65ptvFB0drZEjR+qaa66R1dryX7nPPvtMy5cv19GjR5WcnKwrr7xS5513nu/4smXL9Nlnn+nYsWOyWq3q3bu3Zs2apX79+rV43VWrVmnbtm3av3+/ampq9Oyzz550zuLFi5Wfn6+DBw/K4XDo0UcfDej72p6oYfM1PHHihP7+97/r4MGDqqioUEJCgs455xx973vfU2xsbMDf4/ZAHVv+t3jrrbeetO8HP/iBxo8f3+K12xt1bL6Omzdv1gsvvHDKx95///3Kyspq8frtiTq2/O9xx44dWr58uQ4cOCCbzabRo0fre9/7niwWS0Df3/bSWesY6Jg7wmsciTq2NGZe50RGHaWO8zonXFjuvffe/wr1INA+Vq5cqTFjxuiKK67Q6NGj9e9//1urV6/WmDFjfP+I1q5dq7Vr12ru3Lm67LLLtGfPHq1evVqXXHKJrFarvv32Wx04cEDTp0/XFVdcoczMTK1atUpHjx7VOeecI0nyer167LHHZDabddttt2nYsGFavXq1jh07pmHDhjU7vl27dumvf/2rJk2apNmzZ8tisWjRokUaOnSounTpIkkqKSnRBRdcoMsuu0wXXnihjhw5orfeektjxoyRzWZr9to7duxQ79691atXL+Xl5WnmzJknnfPll19q0KBBcjgcOnr0qCZPntyab3eboIbN19DlcskwDF166aWaNm2aBgwYoPfee0+7d+/Wd7/73dZ+64OKOrb8bzEnJ0c33HCD5s6dq6lTp2rq1KnKzs4OuzdI1LH5Ovbo0UMTJ0701W/q1KkqKytTdXW1vv/978tkMrX22x801LH5Ou7fv1+PP/64Ro8ereuvv15Dhw7V+vXrdezYMQ0dOrS13/qg6qx1DGTMUsd4jSNRx5bGzOucyKij1HFe54QLAotOZPTo0erdu7cSExOVmJio4cOHa/ny5erXr5969OghwzC0cOFCTZkyRePGjfOds2rVKjkcDmVmZiolJUUjRoxQSkqK4uLilJqaqqioKG3cuFHTpk2TJH311VfasGGDfvnLXyotLU3JyclKTEzUihUrNGnSJEVFRZ1yfK+//roSExP1wx/+UAkJCRowYIDy8vJ04MABnX/++ZKkjIwMJScnKy4uTomJiRo4cKBycnI0ePBgpaSkNPu1Dxo0SH379lVlZaU+/fTTU75JGjZsmLKzs3XkyBHt2bMnLP8zp4bN1zA6OlqZmZlKSkpSbGyskpOTZRiGPv74Y02dOjVIFQgO6tjyv8WcnByNHj1aWVlZstvtstvtYfmfOHVsvo4Wi8VXO7vdLpPJpJdeekkTJkzQgAEDglSB4KCOzddxw4YNqqqq0u233664uDh1795d3bp1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\n",
995 | "text/plain": [
996 | ""
997 | ]
998 | },
999 | "metadata": {
1000 | "tags": []
1001 | }
1002 | }
1003 | ]
1004 | },
1005 | {
1006 | "cell_type": "markdown",
1007 | "metadata": {
1008 | "id": "QmrbiUI8sjn8"
1009 | },
1010 | "source": [
1011 | "# **References**\n",
1012 | "\n",
1013 | "[1]Forecasting Time Series Data With Prophet I & II\n",
1014 | "https://nextjournal.com/eric-brown/forecasting-with-prophet\n",
1015 | "\n",
1016 | "[2]Forecasting Time Series Data With Prophet IV\n",
1017 | "https://nextjournal.com/eric-brown/forecasting-with-prophet-part-4\n",
1018 | "\n",
1019 | "[3]Time series analysis in Python\n",
1020 | "https://mlcourse.ai/articles/topic9-part2-prophet/\n",
1021 | "\n",
1022 | "[4] https://www.kaggle.com/kashnitsky/topic-9-part-2-time-series-with-facebook-prophet\n",
1023 | "\n",
1024 | "[5] How To Predict Coronavirus (COVID-19) Cases Using Deep Learning in Python\n",
1025 | "https://laconicml.com/predict-coronavirus-cases-deep-learning/"
1026 | ]
1027 | }
1028 | ]
1029 | }
--------------------------------------------------------------------------------