diff --git a/01 Introduction/Google_Colab_Tutorial.ipynb b/01 Introduction/Google_Colab_Tutorial.ipynb
new file mode 100644
index 0000000..0257bc1
--- /dev/null
+++ b/01 Introduction/Google_Colab_Tutorial.ipynb
@@ -0,0 +1,299 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "name": "Google Colab Tutorial",
+ "provenance": [],
+ "collapsed_sections": [],
+ "toc_visible": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ }
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ca2CpPPUvO-h"
+ },
+ "source": [
+ "# **Google Colab Tutorial**\n",
+ "\n",
+ "\n",
+ "Should you have any question, contact TA via
ntu-ml-2021spring-ta@googlegroups.com\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "xIN7RF4wjgHk"
+ },
+ "source": [
+ "
\r\n",
+ "\r\n",
+ "What is Colaboratory?
\r\n",
+ "\r\n",
+ "Colaboratory, or \"Colab\" for short, allows you to write and execute Python in your browser, with \r\n",
+ "- Zero configuration required\r\n",
+ "- Free access to GPUs\r\n",
+ "- Easy sharing\r\n",
+ "\r\n",
+ "Whether you're a **student**, a **data scientist** or an **AI researcher**, Colab can make your work easier. Watch [Introduction to Colab](https://www.youtube.com/watch?v=inN8seMm7UI) to learn more, or just get started below!\r\n",
+ "\r\n",
+ "You can type python code in the code block, or use a leading exclamation mark ! to change the code block to bash environment to execute linux code."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "IrAxlhp3VBMD"
+ },
+ "source": [
+ "To utilize the free GPU provided by google, click on \"Runtime\"(執行階段) -> \"Change Runtime Type\"(變更執行階段類型). There are three options under \"Hardward Accelerator\"(硬體加速器), select \"GPU\". \r\n",
+ "* Doing this will restart the session, so make sure you change to the desired runtime before executing any code.\r\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "CLUWxZKbvQpx"
+ },
+ "source": [
+ "import torch\n",
+ "torch.cuda.is_available() # is GPU available\n",
+ "# Outputs True if running with GPU"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "EAM_tPQAELh0"
+ },
+ "source": [
+ "**1. Download Files via google drive**\n",
+ "\n",
+ " A file stored in Google Drive has the following sharing link:\n",
+ "\n",
+ " https://drive.google.com/open?id=1duQU7xqXRsOSPYeOR0zLiSA8g_LCFzoV\n",
+ " \n",
+ " The random string after \"open?id=\" is the **file_id**
\n",
+ "![](https://i.imgur.com/33SW1WZ.png)\n",
+ "\n",
+ " It is possible to download the file via Colab knowing the **file_id**, using the following command.\n",
+ "\n",
+ "\n",
+ "\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "XztYEj0oD7J3"
+ },
+ "source": [
+ "# Download the file with file_id \"1duQU7xqXRsOSPYeOR0zLiSA8g_LCFzoV\", and rename it to Minori.jpg\n",
+ "!gdown --id '1duQU7xqXRsOSPYeOR0zLiSA8g_LCFzoV' --output Minori.jpg"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "Gg3T23LXG-eL"
+ },
+ "source": [
+ "# List all the files under the working directory\n",
+ "!ls"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "38dcGQujOVWM"
+ },
+ "source": [
+ "Exclamation mark (!) starts a new shell, does the operations, and then kills that shell, while percentage (%) affects the process associated with the notebook"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "dOQxjfAZAsys"
+ },
+ "source": [
+ "It can be seen that `Minori.jpg` is saved the the current working directory. \r\n",
+ "\r\n",
+ "The working space is temporary, once you close the browser, the file will be gone.\r\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "wLUPcHuNHF8u"
+ },
+ "source": [
+ "Clicking on the folder icon will give you the visuallization of the file structure\n",
+ "
\n",
+ " ![image.png](data:image/png;base64,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)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "MXp98PijHkrk"
+ },
+ "source": [
+ "There should be a file named `Minori.jpg`, if you do not see it, click the icon in the middle (refresh button)
\n",
+ " ![](https://i.imgur.com/CNBTH23.png)\n",
+ "
\n",
+ "You can double click on the file to view the image.\n",
+ "\n",
+ "\n",
+ " \n",
+ "![](https://i.imgur.com/h2PLMrq.png)\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "k_gmTo9NKtu9"
+ },
+ "source": [
+ "**2. Mounting Google Drive**\n",
+ "\n",
+ " One advantage of using google colab is that connection with other google services such as Google Drive is simple. By mounting google drive, the working files can be stored permanantly. After executing the following code block, log in to the google account and copy the authentication code to the input box to finish the process."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "ImETTQKkL2l4"
+ },
+ "source": [
+ "from google.colab import drive # Import a library named google.colab\n",
+ "drive.mount('/content/drive', force_remount=True) # mount the content to the directory `/content/drive`"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "BmvzTF5IJ6TL"
+ },
+ "source": [
+ "from google.colab import drive\n",
+ "drive.mount('/content/drive')"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "AkmayCmGMD03"
+ },
+ "source": [
+ "After mounting the drive, the content of the google drive will be under a directory named `MyDrive`, check the file structure for such a folder to confirm the execution of the code."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "kDrO_DjBMW5D"
+ },
+ "source": [
+ "There is also an icon for mounting google drive. The icon will automatically generate the code above.\n",
+ "\n",
+ "![](https://i.imgur.com/hM9Jgi7.png) \n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "UhKhwipoMvXF"
+ },
+ "source": [
+ "After mounting the drive, all the chnages will be synced with the google drive.\n",
+ "Since models could be quite large, make sure that your google drive has enough space. You can apply for a gsuite drive which has unlimited space using your studentID (until 2022/07). \n",
+ "https://www.cc.ntu.edu.tw/chinese/services/serv_i06.asp\n",
+ "http://www.cc.ntu.edu.tw/english/spotlight/2016/a105038.asp"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "UT0TEPRS7KF6"
+ },
+ "source": [
+ "%cd /content/drive/MyDrive \r\n",
+ "#change directory to google drive\r\n",
+ "!mkdir ML2021 #make a directory named ML2021\r\n",
+ "%cd ./ML2021 \r\n",
+ "#change directory to ML2021"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Oj13Q58QerAx"
+ },
+ "source": [
+ "Use bash command pwd to output the current directory"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "-S8l1-ReepkS"
+ },
+ "source": [
+ "!pwd #output the current directory"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "qSSvrDaBiDrP"
+ },
+ "source": [
+ "Repeat the downloading process, this time, the file will be stored permanently in your google drive."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "b39YMYicASvP"
+ },
+ "source": [
+ "# Download the file with file_id \"1duQU7xqXRsOSPYeOR0zLiSA8g_LCFzoV\", and rename it to Minori.jpg\r\n",
+ "!gdown --id '1duQU7xqXRsOSPYeOR0zLiSA8g_LCFzoV' --output Minori.jpg"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "D0URgikZXl5I"
+ },
+ "source": [
+ "TA will provide the homework data using code similar to the code above. The data could also be stored in the google drive and loaded from there."
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/01 Introduction/ML2021Spring_HW1.ipynb b/01 Introduction/ML2021Spring_HW1.ipynb
new file mode 100644
index 0000000..94b7712
--- /dev/null
+++ b/01 Introduction/ML2021Spring_HW1.ipynb
@@ -0,0 +1,874 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "name": "ML2021Spring - HW1.ipynb",
+ "provenance": [],
+ "collapsed_sections": [],
+ "toc_visible": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ },
+ "accelerator": "GPU"
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "mz0_QVkxCrX3"
+ },
+ "source": [
+ "# **Homework 1: COVID-19 Cases Prediction (Regression)**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "ZeZnPAiwDRWG"
+ },
+ "source": [
+ "Author: Heng-Jui Chang\n",
+ "\n",
+ "Slides: https://github.com/ga642381/ML2021-Spring/blob/main/HW01/HW01.pdf \n",
+ "Video: TBA\n",
+ "\n",
+ "Objectives:\n",
+ "* Solve a regression problem with deep neural networks (DNN).\n",
+ "* Understand basic DNN training tips.\n",
+ "* Get familiar with PyTorch.\n",
+ "\n",
+ "If any questions, please contact the TAs via TA hours, NTU COOL, or email.\n"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "Jx3x1nDkG-Uy"
+ },
+ "source": [
+ "# **Download Data**\n",
+ "\n",
+ "\n",
+ "If the Google drive links are dead, you can download data from [kaggle](https://www.kaggle.com/c/ml2021spring-hw1/data), and upload data manually to the workspace."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "tMj55YDKG6ch",
+ "outputId": "fc40ecc9-4756-48b1-d5c6-c169a8b453b2"
+ },
+ "source": [
+ "tr_path = 'covid.train.csv' # path to training data\n",
+ "tt_path = 'covid.test.csv' # path to testing data\n",
+ "\n",
+ "!gdown --id '19CCyCgJrUxtvgZF53vnctJiOJ23T5mqF' --output covid.train.csv\n",
+ "!gdown --id '1CE240jLm2npU-tdz81-oVKEF3T2yfT1O' --output covid.test.csv"
+ ],
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "text": [
+ "Downloading...\n",
+ "From: https://drive.google.com/uc?id=19CCyCgJrUxtvgZF53vnctJiOJ23T5mqF\n",
+ "To: /content/covid.train.csv\n",
+ "100% 2.00M/2.00M [00:00<00:00, 31.7MB/s]\n",
+ "Downloading...\n",
+ "From: https://drive.google.com/uc?id=1CE240jLm2npU-tdz81-oVKEF3T2yfT1O\n",
+ "To: /content/covid.test.csv\n",
+ "100% 651k/651k [00:00<00:00, 10.2MB/s]\n"
+ ],
+ "name": "stdout"
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "wS_4-77xHk44"
+ },
+ "source": [
+ "# **Import Some Packages**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "k-onQd4JNA5H"
+ },
+ "source": [
+ "# PyTorch\n",
+ "import torch\n",
+ "import torch.nn as nn\n",
+ "from torch.utils.data import Dataset, DataLoader\n",
+ "\n",
+ "# For data preprocess\n",
+ "import numpy as np\n",
+ "import csv\n",
+ "import os\n",
+ "\n",
+ "# For plotting\n",
+ "import matplotlib.pyplot as plt\n",
+ "from matplotlib.pyplot import figure\n",
+ "\n",
+ "myseed = 42069 # set a random seed for reproducibility\n",
+ "torch.backends.cudnn.deterministic = True\n",
+ "torch.backends.cudnn.benchmark = False\n",
+ "np.random.seed(myseed)\n",
+ "torch.manual_seed(myseed)\n",
+ "if torch.cuda.is_available():\n",
+ " torch.cuda.manual_seed_all(myseed)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "BtE3b6JEH7rw"
+ },
+ "source": [
+ "# **Some Utilities**\n",
+ "\n",
+ "You do not need to modify this part."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "FWMT3uf1NGQp"
+ },
+ "source": [
+ "def get_device():\n",
+ " ''' Get device (if GPU is available, use GPU) '''\n",
+ " return 'cuda' if torch.cuda.is_available() else 'cpu'\n",
+ "\n",
+ "def plot_learning_curve(loss_record, title=''):\n",
+ " ''' Plot learning curve of your DNN (train & dev loss) '''\n",
+ " total_steps = len(loss_record['train'])\n",
+ " x_1 = range(total_steps)\n",
+ " x_2 = x_1[::len(loss_record['train']) // len(loss_record['dev'])]\n",
+ " figure(figsize=(6, 4))\n",
+ " plt.plot(x_1, loss_record['train'], c='tab:red', label='train')\n",
+ " plt.plot(x_2, loss_record['dev'], c='tab:cyan', label='dev')\n",
+ " plt.ylim(0.0, 5.)\n",
+ " plt.xlabel('Training steps')\n",
+ " plt.ylabel('MSE loss')\n",
+ " plt.title('Learning curve of {}'.format(title))\n",
+ " plt.legend()\n",
+ " plt.show()\n",
+ "\n",
+ "\n",
+ "def plot_pred(dv_set, model, device, lim=35., preds=None, targets=None):\n",
+ " ''' Plot prediction of your DNN '''\n",
+ " if preds is None or targets is None:\n",
+ " model.eval()\n",
+ " preds, targets = [], []\n",
+ " for x, y in dv_set:\n",
+ " x, y = x.to(device), y.to(device)\n",
+ " with torch.no_grad():\n",
+ " pred = model(x)\n",
+ " preds.append(pred.detach().cpu())\n",
+ " targets.append(y.detach().cpu())\n",
+ " preds = torch.cat(preds, dim=0).numpy()\n",
+ " targets = torch.cat(targets, dim=0).numpy()\n",
+ "\n",
+ " figure(figsize=(5, 5))\n",
+ " plt.scatter(targets, preds, c='r', alpha=0.5)\n",
+ " plt.plot([-0.2, lim], [-0.2, lim], c='b')\n",
+ " plt.xlim(-0.2, lim)\n",
+ " plt.ylim(-0.2, lim)\n",
+ " plt.xlabel('ground truth value')\n",
+ " plt.ylabel('predicted value')\n",
+ " plt.title('Ground Truth v.s. Prediction')\n",
+ " plt.show()"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "39U_XFX6KOoj"
+ },
+ "source": [
+ "# **Preprocess**\n",
+ "\n",
+ "We have three kinds of datasets:\n",
+ "* `train`: for training\n",
+ "* `dev`: for validation\n",
+ "* `test`: for testing (w/o target value)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "TQ-MdwpLL7Dt"
+ },
+ "source": [
+ "## **Dataset**\n",
+ "\n",
+ "The `COVID19Dataset` below does:\n",
+ "* read `.csv` files\n",
+ "* extract features\n",
+ "* split `covid.train.csv` into train/dev sets\n",
+ "* normalize features\n",
+ "\n",
+ "Finishing `TODO` below might make you pass medium baseline."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "0zlpIp9ANJRU"
+ },
+ "source": [
+ "class COVID19Dataset(Dataset):\n",
+ " ''' Dataset for loading and preprocessing the COVID19 dataset '''\n",
+ " def __init__(self,\n",
+ " path,\n",
+ " mode='train',\n",
+ " target_only=False):\n",
+ " self.mode = mode\n",
+ "\n",
+ " # Read data into numpy arrays\n",
+ " with open(path, 'r') as fp:\n",
+ " data = list(csv.reader(fp))\n",
+ " data = np.array(data[1:])[:, 1:].astype(float)\n",
+ " \n",
+ " if not target_only:\n",
+ " feats = list(range(93))\n",
+ " else:\n",
+ " # TODO: Using 40 states & 2 tested_positive features (indices = 57 & 75)\n",
+ " pass\n",
+ "\n",
+ " if mode == 'test':\n",
+ " # Testing data\n",
+ " # data: 893 x 93 (40 states + day 1 (18) + day 2 (18) + day 3 (17))\n",
+ " data = data[:, feats]\n",
+ " self.data = torch.FloatTensor(data)\n",
+ " else:\n",
+ " # Training data (train/dev sets)\n",
+ " # data: 2700 x 94 (40 states + day 1 (18) + day 2 (18) + day 3 (18))\n",
+ " target = data[:, -1]\n",
+ " data = data[:, feats]\n",
+ " \n",
+ " # Splitting training data into train & dev sets\n",
+ " if mode == 'train':\n",
+ " indices = [i for i in range(len(data)) if i % 10 != 0]\n",
+ " elif mode == 'dev':\n",
+ " indices = [i for i in range(len(data)) if i % 10 == 0]\n",
+ " \n",
+ " # Convert data into PyTorch tensors\n",
+ " self.data = torch.FloatTensor(data[indices])\n",
+ " self.target = torch.FloatTensor(target[indices])\n",
+ "\n",
+ " # Normalize features (you may remove this part to see what will happen)\n",
+ " self.data[:, 40:] = \\\n",
+ " (self.data[:, 40:] - self.data[:, 40:].mean(dim=0, keepdim=True)) \\\n",
+ " / self.data[:, 40:].std(dim=0, keepdim=True)\n",
+ "\n",
+ " self.dim = self.data.shape[1]\n",
+ "\n",
+ " print('Finished reading the {} set of COVID19 Dataset ({} samples found, each dim = {})'\n",
+ " .format(mode, len(self.data), self.dim))\n",
+ "\n",
+ " def __getitem__(self, index):\n",
+ " # Returns one sample at a time\n",
+ " if self.mode in ['train', 'dev']:\n",
+ " # For training\n",
+ " return self.data[index], self.target[index]\n",
+ " else:\n",
+ " # For testing (no target)\n",
+ " return self.data[index]\n",
+ "\n",
+ " def __len__(self):\n",
+ " # Returns the size of the dataset\n",
+ " return len(self.data)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "AlhTlkE7MDo3"
+ },
+ "source": [
+ "## **DataLoader**\n",
+ "\n",
+ "A `DataLoader` loads data from a given `Dataset` into batches.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "hlhLk5t6MBX3"
+ },
+ "source": [
+ "def prep_dataloader(path, mode, batch_size, n_jobs=0, target_only=False):\n",
+ " ''' Generates a dataset, then is put into a dataloader. '''\n",
+ " dataset = COVID19Dataset(path, mode=mode, target_only=target_only) # Construct dataset\n",
+ " dataloader = DataLoader(\n",
+ " dataset, batch_size,\n",
+ " shuffle=(mode == 'train'), drop_last=False,\n",
+ " num_workers=n_jobs, pin_memory=True) # Construct dataloader\n",
+ " return dataloader"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "SGuycwR0MeQB"
+ },
+ "source": [
+ "# **Deep Neural Network**\n",
+ "\n",
+ "`NeuralNet` is an `nn.Module` designed for regression.\n",
+ "The DNN consists of 2 fully-connected layers with ReLU activation.\n",
+ "This module also included a function `cal_loss` for calculating loss.\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "49-uXYovOAI0"
+ },
+ "source": [
+ "class NeuralNet(nn.Module):\n",
+ " ''' A simple fully-connected deep neural network '''\n",
+ " def __init__(self, input_dim):\n",
+ " super(NeuralNet, self).__init__()\n",
+ "\n",
+ " # Define your neural network here\n",
+ " # TODO: How to modify this model to achieve better performance?\n",
+ " self.net = nn.Sequential(\n",
+ " nn.Linear(input_dim, 64),\n",
+ " nn.ReLU(),\n",
+ " nn.Linear(64, 1)\n",
+ " )\n",
+ "\n",
+ " # Mean squared error loss\n",
+ " self.criterion = nn.MSELoss(reduction='mean')\n",
+ "\n",
+ " def forward(self, x):\n",
+ " ''' Given input of size (batch_size x input_dim), compute output of the network '''\n",
+ " return self.net(x).squeeze(1)\n",
+ "\n",
+ " def cal_loss(self, pred, target):\n",
+ " ''' Calculate loss '''\n",
+ " # TODO: you may implement L2 regularization here\n",
+ " return self.criterion(pred, target)"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "DvFWVjZ5Nvga"
+ },
+ "source": [
+ "# **Train/Dev/Test**"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "MAM8QecJOyqn"
+ },
+ "source": [
+ "## **Training**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "lOqcmYzMO7jB"
+ },
+ "source": [
+ "def train(tr_set, dv_set, model, config, device):\n",
+ " ''' DNN training '''\n",
+ "\n",
+ " n_epochs = config['n_epochs'] # Maximum number of epochs\n",
+ "\n",
+ " # Setup optimizer\n",
+ " optimizer = getattr(torch.optim, config['optimizer'])(\n",
+ " model.parameters(), **config['optim_hparas'])\n",
+ "\n",
+ " min_mse = 1000.\n",
+ " loss_record = {'train': [], 'dev': []} # for recording training loss\n",
+ " early_stop_cnt = 0\n",
+ " epoch = 0\n",
+ " while epoch < n_epochs:\n",
+ " model.train() # set model to training mode\n",
+ " for x, y in tr_set: # iterate through the dataloader\n",
+ " optimizer.zero_grad() # set gradient to zero\n",
+ " x, y = x.to(device), y.to(device) # move data to device (cpu/cuda)\n",
+ " pred = model(x) # forward pass (compute output)\n",
+ " mse_loss = model.cal_loss(pred, y) # compute loss\n",
+ " mse_loss.backward() # compute gradient (backpropagation)\n",
+ " optimizer.step() # update model with optimizer\n",
+ " loss_record['train'].append(mse_loss.detach().cpu().item())\n",
+ "\n",
+ " # After each epoch, test your model on the validation (development) set.\n",
+ " dev_mse = dev(dv_set, model, device)\n",
+ " if dev_mse < min_mse:\n",
+ " # Save model if your model improved\n",
+ " min_mse = dev_mse\n",
+ " print('Saving model (epoch = {:4d}, loss = {:.4f})'\n",
+ " .format(epoch + 1, min_mse))\n",
+ " torch.save(model.state_dict(), config['save_path']) # Save model to specified path\n",
+ " early_stop_cnt = 0\n",
+ " else:\n",
+ " early_stop_cnt += 1\n",
+ "\n",
+ " epoch += 1\n",
+ " loss_record['dev'].append(dev_mse)\n",
+ " if early_stop_cnt > config['early_stop']:\n",
+ " # Stop training if your model stops improving for \"config['early_stop']\" epochs.\n",
+ " break\n",
+ "\n",
+ " print('Finished training after {} epochs'.format(epoch))\n",
+ " return min_mse, loss_record"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "0hSd4Bn3O2PL"
+ },
+ "source": [
+ "## **Validation**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "yrxrD3YsN3U2"
+ },
+ "source": [
+ "def dev(dv_set, model, device):\n",
+ " model.eval() # set model to evalutation mode\n",
+ " total_loss = 0\n",
+ " for x, y in dv_set: # iterate through the dataloader\n",
+ " x, y = x.to(device), y.to(device) # move data to device (cpu/cuda)\n",
+ " with torch.no_grad(): # disable gradient calculation\n",
+ " pred = model(x) # forward pass (compute output)\n",
+ " mse_loss = model.cal_loss(pred, y) # compute loss\n",
+ " total_loss += mse_loss.detach().cpu().item() * len(x) # accumulate loss\n",
+ " total_loss = total_loss / len(dv_set.dataset) # compute averaged loss\n",
+ "\n",
+ " return total_loss"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "g0pdrhQAO41L"
+ },
+ "source": [
+ "## **Testing**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "aSBMRFlYN5tB"
+ },
+ "source": [
+ "def test(tt_set, model, device):\n",
+ " model.eval() # set model to evalutation mode\n",
+ " preds = []\n",
+ " for x in tt_set: # iterate through the dataloader\n",
+ " x = x.to(device) # move data to device (cpu/cuda)\n",
+ " with torch.no_grad(): # disable gradient calculation\n",
+ " pred = model(x) # forward pass (compute output)\n",
+ " preds.append(pred.detach().cpu()) # collect prediction\n",
+ " preds = torch.cat(preds, dim=0).numpy() # concatenate all predictions and convert to a numpy array\n",
+ " return preds"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "SvckkF5dvf0j"
+ },
+ "source": [
+ "# **Setup Hyper-parameters**\n",
+ "\n",
+ "`config` contains hyper-parameters for training and the path to save your model."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "NPXpdumwPjE7"
+ },
+ "source": [
+ "device = get_device() # get the current available device ('cpu' or 'cuda')\n",
+ "os.makedirs('models', exist_ok=True) # The trained model will be saved to ./models/\n",
+ "target_only = False # TODO: Using 40 states & 2 tested_positive features\n",
+ "\n",
+ "# TODO: How to tune these hyper-parameters to improve your model's performance?\n",
+ "config = {\n",
+ " 'n_epochs': 3000, # maximum number of epochs\n",
+ " 'batch_size': 270, # mini-batch size for dataloader\n",
+ " 'optimizer': 'SGD', # optimization algorithm (optimizer in torch.optim)\n",
+ " 'optim_hparas': { # hyper-parameters for the optimizer (depends on which optimizer you are using)\n",
+ " 'lr': 0.001, # learning rate of SGD\n",
+ " 'momentum': 0.9 # momentum for SGD\n",
+ " },\n",
+ " 'early_stop': 200, # early stopping epochs (the number epochs since your model's last improvement)\n",
+ " 'save_path': 'models/model.pth' # your model will be saved here\n",
+ "}"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "6j1eOV3TOH-j"
+ },
+ "source": [
+ "# **Load data and model**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "eNrYBMmePLKm",
+ "outputId": "fcd4f175-4f7e-4306-f33c-5f8285f11dce"
+ },
+ "source": [
+ "tr_set = prep_dataloader(tr_path, 'train', config['batch_size'], target_only=target_only)\n",
+ "dv_set = prep_dataloader(tr_path, 'dev', config['batch_size'], target_only=target_only)\n",
+ "tt_set = prep_dataloader(tt_path, 'test', config['batch_size'], target_only=target_only)"
+ ],
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "text": [
+ "Finished reading the train set of COVID19 Dataset (2430 samples found, each dim = 93)\n",
+ "Finished reading the dev set of COVID19 Dataset (270 samples found, each dim = 93)\n",
+ "Finished reading the test set of COVID19 Dataset (893 samples found, each dim = 93)\n"
+ ],
+ "name": "stdout"
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "id": "FHylSirLP9oh"
+ },
+ "source": [
+ "model = NeuralNet(tr_set.dataset.dim).to(device) # Construct model and move to device"
+ ],
+ "execution_count": null,
+ "outputs": []
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "sX2B_zgSOPTJ"
+ },
+ "source": [
+ "# **Start Training!**"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "id": "GrEbUxazQAAZ",
+ "outputId": "f4f3bd74-2d97-4275-b69f-6609976b91f9"
+ },
+ "source": [
+ "model_loss, model_loss_record = train(tr_set, dv_set, model, config, device)"
+ ],
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "text": [
+ "Saving model (epoch = 1, loss = 74.9742)\n",
+ "Saving model (epoch = 2, loss = 50.5313)\n",
+ "Saving model (epoch = 3, loss = 29.1148)\n",
+ "Saving model (epoch = 4, loss = 15.8134)\n",
+ "Saving model (epoch = 5, loss = 9.5430)\n",
+ "Saving model (epoch = 6, loss = 6.8086)\n",
+ "Saving model (epoch = 7, loss = 5.3892)\n",
+ "Saving model (epoch = 8, loss = 4.5267)\n",
+ "Saving model (epoch = 9, loss = 3.9454)\n",
+ "Saving model (epoch = 10, loss = 3.5560)\n",
+ "Saving model (epoch = 11, loss = 3.2303)\n",
+ "Saving model (epoch = 12, loss = 2.9920)\n",
+ "Saving model (epoch = 13, loss = 2.7737)\n",
+ "Saving model (epoch = 14, loss = 2.6181)\n",
+ "Saving model (epoch = 15, loss = 2.3987)\n",
+ "Saving model (epoch = 16, loss = 2.2712)\n",
+ "Saving model (epoch = 17, loss = 2.1349)\n",
+ "Saving model (epoch = 18, loss = 2.0210)\n",
+ "Saving model (epoch = 19, loss = 1.8848)\n",
+ "Saving model (epoch = 20, loss = 1.7999)\n",
+ "Saving model (epoch = 21, loss = 1.7510)\n",
+ "Saving model (epoch = 22, loss = 1.6787)\n",
+ "Saving model (epoch = 23, loss = 1.6450)\n",
+ "Saving model (epoch = 24, loss = 1.6030)\n",
+ "Saving model (epoch = 26, loss = 1.5052)\n",
+ "Saving model (epoch = 27, loss = 1.4486)\n",
+ "Saving model (epoch = 28, loss = 1.4069)\n",
+ "Saving model (epoch = 29, loss = 1.3733)\n",
+ "Saving model (epoch = 30, loss = 1.3533)\n",
+ "Saving model (epoch = 31, loss = 1.3335)\n",
+ "Saving model (epoch = 32, loss = 1.3011)\n",
+ "Saving model (epoch = 33, loss = 1.2711)\n",
+ "Saving model (epoch = 35, loss = 1.2331)\n",
+ "Saving model (epoch = 36, loss = 1.2235)\n",
+ "Saving model (epoch = 38, loss = 1.2180)\n",
+ "Saving model (epoch = 39, loss = 1.2018)\n",
+ "Saving model (epoch = 40, loss = 1.1651)\n",
+ "Saving model (epoch = 42, loss = 1.1631)\n",
+ "Saving model (epoch = 43, loss = 1.1394)\n",
+ "Saving model (epoch = 46, loss = 1.1129)\n",
+ "Saving model (epoch = 47, loss = 1.1107)\n",
+ "Saving model (epoch = 49, loss = 1.1091)\n",
+ "Saving model (epoch = 50, loss = 1.0838)\n",
+ "Saving model (epoch = 52, loss = 1.0692)\n",
+ "Saving model (epoch = 53, loss = 1.0681)\n",
+ "Saving model (epoch = 55, loss = 1.0537)\n",
+ "Saving model (epoch = 60, loss = 1.0457)\n",
+ "Saving model (epoch = 61, loss = 1.0366)\n",
+ "Saving model (epoch = 63, loss = 1.0359)\n",
+ "Saving model (epoch = 64, loss = 1.0111)\n",
+ "Saving model (epoch = 69, loss = 1.0072)\n",
+ "Saving model (epoch = 72, loss = 0.9760)\n",
+ "Saving model (epoch = 76, loss = 0.9672)\n",
+ "Saving model (epoch = 79, loss = 0.9584)\n",
+ "Saving model (epoch = 80, loss = 0.9526)\n",
+ "Saving model (epoch = 82, loss = 0.9494)\n",
+ "Saving model (epoch = 83, loss = 0.9426)\n",
+ "Saving model (epoch = 88, loss = 0.9398)\n",
+ "Saving model (epoch = 89, loss = 0.9223)\n",
+ "Saving model (epoch = 95, loss = 0.9111)\n",
+ "Saving model (epoch = 98, loss = 0.9034)\n",
+ "Saving model (epoch = 101, loss = 0.9014)\n",
+ "Saving model (epoch = 105, loss = 0.9011)\n",
+ "Saving model (epoch = 106, loss = 0.8933)\n",
+ "Saving model (epoch = 110, loss = 0.8893)\n",
+ "Saving model (epoch = 117, loss = 0.8867)\n",
+ "Saving model (epoch = 118, loss = 0.8867)\n",
+ "Saving model (epoch = 121, loss = 0.8790)\n",
+ "Saving model (epoch = 126, loss = 0.8642)\n",
+ "Saving model (epoch = 130, loss = 0.8627)\n",
+ "Saving model (epoch = 137, loss = 0.8616)\n",
+ "Saving model (epoch = 139, loss = 0.8534)\n",
+ "Saving model (epoch = 147, loss = 0.8467)\n",
+ "Saving model (epoch = 154, loss = 0.8463)\n",
+ "Saving model (epoch = 155, loss = 0.8408)\n",
+ "Saving model (epoch = 167, loss = 0.8354)\n",
+ "Saving model (epoch = 176, loss = 0.8314)\n",
+ "Saving model (epoch = 191, loss = 0.8267)\n",
+ "Saving model (epoch = 200, loss = 0.8212)\n",
+ "Saving model (epoch = 226, loss = 0.8190)\n",
+ "Saving model (epoch = 230, loss = 0.8144)\n",
+ "Saving model (epoch = 244, loss = 0.8136)\n",
+ "Saving model (epoch = 258, loss = 0.8095)\n",
+ "Saving model (epoch = 269, loss = 0.8076)\n",
+ "Saving model (epoch = 285, loss = 0.8064)\n",
+ "Saving model (epoch = 330, loss = 0.8055)\n",
+ "Saving model (epoch = 347, loss = 0.8053)\n",
+ "Saving model (epoch = 359, loss = 0.7992)\n",
+ "Saving model (epoch = 410, loss = 0.7989)\n",
+ "Saving model (epoch = 442, loss = 0.7966)\n",
+ "Saving model (epoch = 447, loss = 0.7966)\n",
+ "Saving model (epoch = 576, loss = 0.7958)\n",
+ "Saving model (epoch = 596, loss = 0.7929)\n",
+ "Saving model (epoch = 600, loss = 0.7893)\n",
+ "Saving model (epoch = 683, loss = 0.7825)\n",
+ "Saving model (epoch = 878, loss = 0.7817)\n",
+ "Saving model (epoch = 904, loss = 0.7794)\n",
+ "Saving model (epoch = 931, loss = 0.7790)\n",
+ "Saving model (epoch = 951, loss = 0.7781)\n",
+ "Saving model (epoch = 965, loss = 0.7771)\n",
+ "Saving model (epoch = 1018, loss = 0.7717)\n",
+ "Saving model (epoch = 1168, loss = 0.7653)\n",
+ "Saving model (epoch = 1267, loss = 0.7645)\n",
+ "Saving model (epoch = 1428, loss = 0.7644)\n",
+ "Saving model (epoch = 1461, loss = 0.7635)\n",
+ "Saving model (epoch = 1484, loss = 0.7629)\n",
+ "Saving model (epoch = 1493, loss = 0.7590)\n",
+ "Finished training after 1694 epochs\n"
+ ],
+ "name": "stdout"
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 295
+ },
+ "id": "hsNO9nnXQBvP",
+ "outputId": "1626def6-94c7-4a87-9447-d939f827c8eb"
+ },
+ "source": [
+ "plot_learning_curve(model_loss_record, title='deep model')"
+ ],
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "display_data",
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "