├── 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 | "\"Open" 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 | "\"Open" 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 | " \n", 521 | " \n", 522 | " \n", 523 | " \n", 524 | " \n", 525 | " \n", 526 | " \n", 527 | " \n", 528 | " \n", 529 | " \n", 530 | " \n", 531 | " \n", 532 | " \n", 533 | " \n", 534 | " \n", 535 | " \n", 536 | " \n", 537 | "
ds
142020-03-24
152020-03-25
162020-03-26
\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 | " \n", 606 | " \n", 607 | " \n", 608 | " \n", 609 | " \n", 610 | " \n", 611 | " \n", 612 | " \n", 613 | " \n", 614 | " \n", 615 | " \n", 616 | " \n", 617 | " \n", 618 | " \n", 619 | " \n", 620 | " \n", 621 | " \n", 622 | " \n", 623 | " \n", 624 | " \n", 625 | " \n", 626 | " \n", 627 | " \n", 628 | " \n", 629 | " \n", 630 | " \n", 631 | " \n", 632 | " \n", 633 | " \n", 634 | " \n", 635 | " \n", 636 | " \n", 637 | " \n", 638 | " \n", 639 | " \n", 640 | " \n", 641 | " \n", 642 | " \n", 643 | " \n", 644 | " \n", 645 | " \n", 646 | " \n", 647 | " \n", 648 | "
dsyhatyhat_loweryhat_upper
122020-03-2283.51002056.517001104.968454
132020-03-2389.76255266.425144113.424199
142020-03-2496.01508474.384712121.402555
152020-03-25102.26761776.591055125.693865
162020-03-26108.52014983.544659133.043532
\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 | " \n", 765 | " \n", 766 | " \n", 767 | " \n", 768 | " \n", 769 | " \n", 770 | " \n", 771 | " \n", 772 | " \n", 773 | " \n", 774 | " \n", 775 | " \n", 776 | " \n", 777 | " \n", 778 | " \n", 779 | " \n", 780 | " \n", 781 | " \n", 782 | " \n", 783 | " \n", 784 | " \n", 785 | " \n", 786 | " \n", 787 | " \n", 788 | " \n", 789 | " \n", 790 | " \n", 791 | " \n", 792 | " \n", 793 | " \n", 794 | " \n", 795 | " \n", 796 | " \n", 797 | " \n", 798 | " \n", 799 | " \n", 800 | " \n", 801 | " \n", 802 | " \n", 803 | " \n", 804 | " \n", 805 | " \n", 806 | " \n", 807 | " \n", 808 | " \n", 809 | " \n", 810 | " \n", 811 | " \n", 812 | " \n", 813 | " \n", 814 | "
Confirmed_Casesyhatyhat_loweryhat_upper
Date
2020-03-10178.479636-15.73511731.833502
2020-03-112414.732168-11.25790238.105296
2020-03-122820.984699-2.66966446.315372
2020-03-133027.2372314.53793051.516875
2020-03-143733.4897639.12101757.230878
\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 | "\"Open" 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 | " \n", 915 | " \n", 916 | " \n", 917 | " \n", 918 | " \n", 919 | " \n", 920 | " \n", 921 | " \n", 922 | " \n", 923 | " \n", 924 | " \n", 925 | " \n", 926 | " \n", 927 | " \n", 928 | " \n", 929 | " \n", 930 | " \n", 931 | " \n", 932 | " \n", 933 | " \n", 934 | " \n", 935 | " \n", 936 | " \n", 937 | " \n", 938 | " \n", 939 | " \n", 940 | "
Confirmed_CasesPredictions
Date
2020-03-2414026.088554
2020-03-2515827.168270
2020-03-2617428.391363
\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+/fTTU75JGjZsmLKzs3XkyBHt2bMnLP8zp4bN1zA6OlqZmZlKSkpSbGyskpOTZRiGPv74Y02dOjVIFQgO6tjyv8WcnByNHj1aWVlZstvtstvtYfmfOHVsvo4Wi8VXO7vdLpPJpJdeekkTJkzQgAEDglSB4KCOzddxw4YNqqqq0u233664uDh1795d3bp10xtvvKFJkyad9jeY7amz1jGQMUsd4zWORB1bGjOvcyKjjlLHeZ0TLljDohNzOp0yDMM3jayoqEilpaUaMmSI75zo6GgNGDBAu3btavE6jaeiffvtt+rRo4e6du3q2zd06FC53W7t3bu32et8++23J/3GZujQoc0+t9vtVm5urmJiYtS7d++Wv9gIRQ2bV1JSoq1bt4bdm6NToY4nW7x4sRYsWKCHH35YGzdulNfrDcp12xJ1bN6nn36qmpoajRkzJqjXbQvU0f9aTV/wR0VFyeVytTjmcNCZ69h0zB0ZdWy+jrzO6dh17Iivc0IlfKJxtLvFixerV69e6tu3rySptLRUkpSYmOh3XmJioo4fP37KaxQXF2vdunWaPn26b19paelJ14iPj5fZbPY9x6mUlpYqISHBb19CQoLKysr89n3xxRd69tlnVVNTI4fDoQULFpz0fJ0FNTzZ3/72N33xxReqqanR8OHDdeONNwblum2JOvqbNWuWBg4cKJvNpm+++Uavv/66ysvLdcUVV7T62m2JOjZv06ZNGjZsmBwOR1Cv2xaoY4OhQ4fqnXfe0YcffqgLLrhAZWVlWrlypaTaN0vhrLPW8VRj7sio48l15HVOx69jR32dEyoEFp3UkiVLlJ+fr3vuuUdm89lNtCkrK9Of//xnDR48WFOmTAn4ccXFxfr1r3/t254+fbouv/zygB8/aNAgPfjggzpx4oQ2bdqkhQsX6t5771VSUpJeeuklffTRR75zn3rqqYCv29FQw1P7j//4D82YMUMFBQVaunSplixZorlz557RNdoTdTxZ4/+we/fuLa/Xq9WrV4f1f+TUsXkHDx7Url27NG/evDN+bHujjv6GDh2qq6++WosWLdLzzz8vq9WqK664Qnl5eWf9/WkPnbWOZzvmcEUdTz1mXud0/Dp2xNc5oURg0QktWbJEn3zyie68804lJyf79tf/5qusrEzdunXz7S8rKzvpt2KlpaX67//+b6Wnp+uWW27xW0DN4XAoPz/f7/zy8nJ5vV45HA4lJSXpwQcf9B2Li4vzPe7EiRN+jztx4sRJSabNZlNKSopSUlLUt29fPfDAA/rnP/+pK664QrNmzdKll156Nt+WDoUaNs/hcMjhcCgtLU1xcXH64x//qMsvv9xvumC4oI6BycrKUlVVlcrKysJyNhV1bNmmTZvUtWvXsFuksSnqeGpTp07VlClTVFpaqtjYWBUXF2vp0qXq3r37WV2vrXXWOrY05o6IOjZfR17nREYdGwv31zmhFr7xONrE4sWL9fHHH+vOO+9UWlqa37Hu3bvL4XBo+/btvn0ul0t5eXm+KVxS7TTQxx9/XGlpabr11ltPWiSmflGnY8eO+fZt375dVqtVffr0kcVi8f3jr1+Upv5xjZ+7/nGNn/tUDMOQy+WSVDuVrPG1IxE1DJxhGJJqew/DDXUM3P79+xUVFaWYmJhWXactUMeWuVwubdmyRRdffHFY/0aeOrbMZDIpKSlJ0dHR+vjjj9W1a1f16dPnjK/T1jprHU835o6GOgZeR17nREYdw/l1TjjgLiGdyCuvvKItW7bo9ttvV9euXVVdXa3q6mpJktVqlclkksfj0dq1a5Wamiqv16vXXntNpaWluuGGG2S1WlVSUqLHHntMDodDc+fOldvt9l0nOjpaJpNJycnJ2rp1q77++mtlZGTo4MGDWrRokUaNGuV3f+OmkpKStGLFClmtVsXHx2vTpk364IMPNHfuXHXp0kVVVVVauXKlbDabvF6vjh49qmXLlik/P1+zZ89uMZEsLi5WUVGR9u3bp+3bt+vcc89VaWmpbDabb5XzwsJCFRcXKz8/XwcOHNCgQYNUWlqquLi4sHmhTQ2br+EXX3yhb7/9VmazWTU1NcrPz9fixYuVkpLitzJzOKCOLdfx3//+t6xWq5xOp7Zu3eq7jVjjW4KFA+rY8s9USfrkk0/0ySef6KabbgrbRQCpY8t1fPvtt2W323XixAnl5uZq9erVuvHGG9WzZ8/gFqKVOmsdAxmz1DFe40jUsaUx8zoncurYUV7nhAtTSUmJEepBoH3ceuutp9w/Y8YM363MDMNQTk6OcnNzVVFRoezsbM2ZM0fp6emSpM2bN+uFF1445XUeeeQR3xTR4uJivfLKK9q5c6eioqI0atQoXX311c3eXqjeZ599pmXLluno0aNKTk7W9773Pd8PnOrqav3973/X7t27VVFRobi4OGVmZuqyyy5TdnZ2i9d97rnntGXLlpP233XXXRo4cKAk6bHHHtO///3vFr+uUKOGzddw+/btWr58uQ4fPiy3260uXbpoxIgRmj59ui9RDxfUsfk6fvXVV1q6dKkKCwtlGIaSk5M1ZswYTZgwIex+a0gdW/6ZKtX+XI2Ojtb8+fNbvF4oUceW6/j4449r3759crvdysjI0IwZMzRs2LAWrxsKnbWOgY65I7zGkahjS2PmdU6DjlzHjvQ6J1wQWAAAAAAAgLATPnPAAAAAAAAA6hBYAAAAAACAsENgAQAAAAAAwg6BBQAAAAAACDsEFgAAAAAAIOwQWAAAAAAAgLBDYAEAAAAAAMKONdQDAAAAncPOnTv1+OOP+7ZNJpNiYmKUlJSkPn36aOTIkRo6dKhMJtNZXX/fvn36/PPPddFFF6l79+7BGjYAAAgRAgsAANCuRo4cqWHDhskwDDmdThUUFOhf//qXtmzZosGDB+vHP/6xYmNjz/i6+/fvV05OjgYOHEhgAQBABCCwAAAA7ap379668MIL/fZde+21euONN7R+/Xo9++yzmj9/fohGBwAAwgWBBQAACDmz2axrr71Wu3fv1ldffaW8vDz1799fJSUlWrdunXbs2KFjx46ppqZGycnJGj16tC699FKZzbXLca1YsUI5OTmS5Nd2Mnr0aN18882SJJfLpXXr1umjjz7S0aNHFRUVpf79+2vWrFnq3bt3+3/RAACgRQQWAAAgbIwZM0b5+fnatm2b+vfvrwMHDmjr1q0aMWKEUlJS5PF49NVXX2np0qUqKirS3LlzJUnnnXeeSktLlZubq8suu0xpaWmSpOTkZEmS2+3WX/7yF+3atUsXXnihJk6cqKqqKm3atEl/+MMfdPfddyszMzNUXzYAADgFAgsAABA2MjIyJEkFBQWSpAEDBuiRRx7xW4hz8uTJ+sc//qFNmzZpxowZSkpKUkZGhrKzs5Wbm6shQ4Zo4MCBftd97733tHPnTs2fP1/f+c53fPvHjx+v//qv/9Lrr7+uu+++ux2+QgAAEChuawoAAMJGTEyMJKmqqkqSFB0d7Qsr3G63KioqdOLECQ0dOlSGYWjv3r0BXffDDz9Ujx491KdPH504ccL3x+12a/DgwcrPz1dNTU3bfFEAAOCsMMMCAACEjfqgoj648Hg8WrNmjbZs2aKjR4/KMAy/8ysqKgK67pEjR1RTU6Nf/OIXzZ5TXl6url27nuXIAQBAsBFYAACAsHHgwAFJUmpqqiTptdde07vvvqsLLrhAl19+uRISEmSxWLRv3z69+eabJwUYzTEMQ+np6br22mubPSchIaH1XwAAAAgaAgsAABA2/vnPf0qShg8fLqm2lWPAgAG67bbb/M4rLCw86bGN17loKiUlReXl5Ro0aJDvziIAACC88T82AAAIOa/Xq9dff135+fkaNmyY+vXrJ6n2dqdNZ1FUV1frnXfeOekaNptN0qnbREaPHq3S0lKtX7/+lM9fVlbW2i8BAAAEGTMsAABAu9q3b58+/PBDSZLT6dSRI0f0/9u7Y9RUojAMw98UEiWNhCxgSGW0sxBi7NyIBJfgMoK9e0glCClDIKaxsBKzgoAgiJAykCIgXG5xAxfCFM/TDRxm4JQv5/yzXq+z3+/TbrczHo9Pa7vdbp6fnzObzXJ9fZ3j8ZiXl5ecn5//9d6yLFMURRaLRT4+PnJ2dpbLy8tcXV1lOBxms9nk4eEh2+02rVYrjUYj+/0+2+02tVotk8nk1/YAAPi34nA4/OzyJwDAf3h7e8v9/f3puSiK1Ov1NJvNlGWZXq/3xy9Hk+/TFPP5PKvVKsfjMRcXFxkMBinLMtPpNKPRKLe3t6f1y+Uyj4+P2e12+fz8zM3NTe7u7pJ8D/B8enrK6+tr3t/fk+T07X6/n06n8wu7AAD8lGABAAAAVI4ZFgAAAEDlCBYAAABA5QgWAAAAQOUIFgAAAEDlCBYAAABA5QgWAAAAQOUIFgAAAEDlCBYAAABA5QgWAAAAQOUIFgAAAEDlfAF6u4e5ryGM4QAAAABJRU5ErkJggg==\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 | } --------------------------------------------------------------------------------