{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":11848,"databundleVersionId":862157,"sourceType":"competition"},{"sourceId":2061927,"sourceType":"datasetVersion","datasetId":1235849}],"dockerImageVersionId":30674,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"raw","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"markdown","source":"**This notebook about computer vision models with PyTorch**","metadata":{}},{"cell_type":"code","source":"import torch\nimport torchvision\ntorch.cuda.is_available()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:14.479288Z","iopub.execute_input":"2024-04-15T09:41:14.480262Z","iopub.status.idle":"2024-04-15T09:41:20.544817Z","shell.execute_reply.started":"2024-04-15T09:41:14.480227Z","shell.execute_reply":"2024-04-15T09:41:20.543938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Working with tensors**","metadata":{}},{"cell_type":"code","source":"# define tensor wit default data type\nx = torch.ones (2, 2)\nprint (x)\nprint (x.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.546359Z","iopub.execute_input":"2024-04-15T09:41:20.546757Z","iopub.status.idle":"2024-04-15T09:41:20.631415Z","shell.execute_reply.started":"2024-04-15T09:41:20.546731Z","shell.execute_reply":"2024-04-15T09:41:20.630577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# specify data type\nx = torch.ones (2, 2, dtype = torch.int8)\nprint (x)\nprint (x.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.632569Z","iopub.execute_input":"2024-04-15T09:41:20.632878Z","iopub.status.idle":"2024-04-15T09:41:20.638279Z","shell.execute_reply.started":"2024-04-15T09:41:20.632854Z","shell.execute_reply":"2024-04-15T09:41:20.637430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# change tensor data type\nx = torch.ones (1, dtype = torch.uint8)\n\nprint (x.dtype)\n\nx = x.type (torch.float)\nprint (x.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.640170Z","iopub.execute_input":"2024-04-15T09:41:20.640453Z","iopub.status.idle":"2024-04-15T09:41:20.648279Z","shell.execute_reply.started":"2024-04-15T09:41:20.640411Z","shell.execute_reply":"2024-04-15T09:41:20.647402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# converting tensors to NumPy arrays\nx = torch.rand (2, 2)\nprint (x)\nprint (x.dtype)\n\ny = x.numpy ()\nprint (y)\nprint (y.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.649304Z","iopub.execute_input":"2024-04-15T09:41:20.649581Z","iopub.status.idle":"2024-04-15T09:41:20.660640Z","shell.execute_reply.started":"2024-04-15T09:41:20.649553Z","shell.execute_reply":"2024-04-15T09:41:20.659643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# converting NumPy arrays to tensors\nimport numpy as np\n\nx = np.zeros ((2, 2), dtype = np.float32)\nprint (x)\nprint (x.dtype)\n\ny = torch.from_numpy (x)\nprint (x)\nprint (y.dtype)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.661869Z","iopub.execute_input":"2024-04-15T09:41:20.662169Z","iopub.status.idle":"2024-04-15T09:41:20.669878Z","shell.execute_reply.started":"2024-04-15T09:41:20.662143Z","shell.execute_reply":"2024-04-15T09:41:20.669106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# move tensors between devices\n\n# define a tensor\nx = torch.tensor ([1.5, 2])\nprint (x)\nprint (x.device)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.671006Z","iopub.execute_input":"2024-04-15T09:41:20.671570Z","iopub.status.idle":"2024-04-15T09:41:20.679464Z","shell.execute_reply.started":"2024-04-15T09:41:20.671520Z","shell.execute_reply":"2024-04-15T09:41:20.678586Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# move tensor onto GPU\ndevice = torch.device (\"cuda:0\")\nx = x.to (device)\nprint (x)\nprint (x.device)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:20.680604Z","iopub.execute_input":"2024-04-15T09:41:20.680860Z","iopub.status.idle":"2024-04-15T09:41:21.106772Z","shell.execute_reply.started":"2024-04-15T09:41:20.680838Z","shell.execute_reply":"2024-04-15T09:41:21.105788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# move tensor onto cpu\ndevice = torch.device ('cpu')\nx = x.to (device)\nprint (x)\nprint (x.device)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:21.107966Z","iopub.execute_input":"2024-04-15T09:41:21.108244Z","iopub.status.idle":"2024-04-15T09:41:21.114245Z","shell.execute_reply.started":"2024-04-15T09:41:21.108219Z","shell.execute_reply":"2024-04-15T09:41:21.113439Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Loading and processing data from PyTorch datasets - get the FashionMNIST dataset, it's not overused as MNIST**\nhttps://github.com/zalandoresearch/fashion-mnist","metadata":{}},{"cell_type":"code","source":"from torchvision import datasets\n\npath2data = 'FashionMNIST/raw/train-images-idx3-ubyte'\n\ntrain_data = torchvision.datasets.FashionMNIST(path2data, train = True, download=True)\n\nx_train, y_train = train_data.data, train_data.targets\nprint (x_train.shape)\nprint (y_train.shape)\n\nval_data = torchvision.datasets.FashionMNIST(path2data, train = False, download=True)\nx_val, y_val = val_data.data, val_data.targets\nprint (x_val.shape)\nprint (y_val.shape)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:21.118026Z","iopub.execute_input":"2024-04-15T09:41:21.118457Z","iopub.status.idle":"2024-04-15T09:41:22.438525Z","shell.execute_reply.started":"2024-04-15T09:41:21.118432Z","shell.execute_reply":"2024-04-15T09:41:22.437595Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Display images**","metadata":{}},{"cell_type":"code","source":"from torchvision import utils\nimport matplotlib.pyplot as plt\nimport numpy as np\n%matplotlib inline\n\n# adding a dimension to tensor to become B*C*H*H\nif len (x_train.shape) == 3:\n    x_train = x_train.unsqueeze (1)\nprint (x_train.shape)\n\nif len(x_val.shape) == 3:\n    x_val = x_val.unsqueeze (1)\n    \n# make a grid of 50 images, 8 images per row\nx_grid = utils.make_grid (x_train[:50], nrow = 8, padding = 2)\nprint (x_grid.shape)\n\n# function to display images\ndef show (img):\n    # convert tensor to numpy array\n    npimg = img.numpy ()\n    \n    # convert to H*W*C shape\n    npimg_tr = np.transpose (npimg, (1, 2, 0))\n    \n    # display images\n    plt.imshow (npimg_tr, interpolation = 'nearest')\n    \n# call function for display images\nshow (x_grid)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:22.440064Z","iopub.execute_input":"2024-04-15T09:41:22.440732Z","iopub.status.idle":"2024-04-15T09:41:22.707256Z","shell.execute_reply.started":"2024-04-15T09:41:22.440699Z","shell.execute_reply":"2024-04-15T09:41:22.706381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Data transformation**","metadata":{}},{"cell_type":"code","source":"from torchvision import transforms\n\n# loading FashionMNIST training dataset\ntrain_data = torchvision.datasets.FashionMNIST(path2data, train = True, download=True)\n\n# define transformations\ndata_transform = transforms.Compose([transforms.RandomHorizontalFlip(p=1),\n                                    transforms.RandomVerticalFlip(p=1),\n                                    transforms.ToTensor(),\n                                    ])\n\n# get a sample image from training dataset\nimg = train_data[0][0]\n\n# tranform sample image\nimg_tr=data_transform(img)\n\n# convert tensor to numpy array\nimg_tr_np=img_tr.numpy()\n\n# show original and transformed images\nplt.subplot(1,2,1)\nplt.imshow(img,cmap = \"gray\")\nplt.title(\"original\")\nplt.subplot(1,2,2)\nplt.imshow(img_tr_np[0],cmap = \"gray\");\nplt.title(\"transformed\")","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:22.708666Z","iopub.execute_input":"2024-04-15T09:41:22.709074Z","iopub.status.idle":"2024-04-15T09:41:23.211712Z","shell.execute_reply.started":"2024-04-15T09:41:22.709041Z","shell.execute_reply":"2024-04-15T09:41:23.210867Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define transformations\ndata_transform = transforms.Compose([\n                                        transforms.RandomHorizontalFlip(1),\n                                        transforms.RandomVerticalFlip(1),\n                                        transforms.ToTensor(),])\n\n# Loading MNIST training data with on-the-fly transformations\ntrain_data = torchvision.datasets.FashionMNIST(path2data, train = True, download = True,\ntransform = data_transform )\n\n# wrap tensors into a dataset\nfrom torch.utils.data import TensorDataset\n\ntrain_ds = TensorDataset (x_train, y_train)\nval_ds = TensorDataset (x_val, y_val)\n\nfor x, y in train_ds:\n    print (x.shape, y.item ())\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.213233Z","iopub.execute_input":"2024-04-15T09:41:23.213676Z","iopub.status.idle":"2024-04-15T09:41:23.287585Z","shell.execute_reply.started":"2024-04-15T09:41:23.213642Z","shell.execute_reply":"2024-04-15T09:41:23.286660Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# iterate over dataset\nfrom torch.utils.data import DataLoader\n\n# create a data loader from dataset\ntrain_dl = DataLoader (train_ds, batch_size = 8)\nval_dl = DataLoader (val_ds, batch_size = 8)\n\n# iterate over batches\nfor xb, yb in train_dl:\n    print (xb.shape)\n    print (yb.shape)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.288721Z","iopub.execute_input":"2024-04-15T09:41:23.289003Z","iopub.status.idle":"2024-04-15T09:41:23.297452Z","shell.execute_reply.started":"2024-04-15T09:41:23.288979Z","shell.execute_reply":"2024-04-15T09:41:23.296567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Building the models**","metadata":{}},{"cell_type":"code","source":"from torch import nn\n\n# input tensor dimension 64*1000\ninput_tensor = torch.randn (64, 1000)\n\n# linear layer with 1000 inputs and 100 outputs\nlinear_layer = nn.Linear (1000, 100)\n\n# output of the linear layer \noutput = linear_layer (input_tensor)\nprint (output.size ())","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.298364Z","iopub.execute_input":"2024-04-15T09:41:23.298627Z","iopub.status.idle":"2024-04-15T09:41:23.349370Z","shell.execute_reply.started":"2024-04-15T09:41:23.298604Z","shell.execute_reply":"2024-04-15T09:41:23.348556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define models using nn.Sequential\n\nfrom torch import nn\n\n# define a two layer model\nmodel = nn.Sequential (nn.Linear (4, 5),\n                      nn.ReLU (), # ReLU is not shown in the figure.\n                      nn.Linear (5, 1),)\nprint (model)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.350612Z","iopub.execute_input":"2024-04-15T09:41:23.351184Z","iopub.status.idle":"2024-04-15T09:41:23.357246Z","shell.execute_reply.started":"2024-04-15T09:41:23.351141Z","shell.execute_reply":"2024-04-15T09:41:23.356255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define models using nn.Module\n\nimport torch.nn.functional as F\n\nclass Net (nn.Module):\n    def __init__ (self):\n        super (Net, self).__init__()\n        self.conv1 = nn.Conv2d (1, 8, 5, 1)\n        self.conv2 = nn.Conv2d (8, 16, 5, 1)\n        self.fc1 = nn.Linear (4*4*16, 100)\n        self.fc2 = nn.Linear (100, 10)\n        \n    def forward (self, x):\n        x = F.relu (self.conv1 (x))\n        x = F.max_pool2d (x, 2, 2)\n        x = F.relu (self.conv2 (x))\n        x = F.max_pool2d (x, 2, 2)\n        x = x.view (-1, 4*4*16)\n        x = F.relu (self.fc1 (x))\n        x = self.fc2 (x)\n        return F.log_softmax (x, dim = 1)\n    \nmodel = Net ()\nprint (model)\n    ","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.358527Z","iopub.execute_input":"2024-04-15T09:41:23.358797Z","iopub.status.idle":"2024-04-15T09:41:23.369060Z","shell.execute_reply.started":"2024-04-15T09:41:23.358774Z","shell.execute_reply":"2024-04-15T09:41:23.368253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# move model to device\ndevice = torch.device ('cuda:0')\nmodel.to(device)\nprint (next (model.parameters ()).device)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.370085Z","iopub.execute_input":"2024-04-15T09:41:23.370344Z","iopub.status.idle":"2024-04-15T09:41:23.381401Z","shell.execute_reply.started":"2024-04-15T09:41:23.370322Z","shell.execute_reply":"2024-04-15T09:41:23.380575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# show model summary\n!pip install torchsummary\nfrom torchsummary import summary\n\nsummary (model, input_size = (1, 28, 28))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:23.382618Z","iopub.execute_input":"2024-04-15T09:41:23.382929Z","iopub.status.idle":"2024-04-15T09:41:37.284802Z","shell.execute_reply.started":"2024-04-15T09:41:23.382903Z","shell.execute_reply":"2024-04-15T09:41:37.283627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the negative log likelihood loss\nloss_func = nn.NLLLoss (reduction = \"sum\")\n\nfor xb, yb in train_dl:\n    # move batch to cuda device\n    xb = xb.type (torch.float).to(device)\n    yb = yb.to(device)\n    \n    # get model output\n    out = model (xb)\n    \n    # calculate loss value\n    loss = loss_func (out, yb)\n    print (loss.item ())\n    break\n    \n# compute gradients \nloss.backward ()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:37.286568Z","iopub.execute_input":"2024-04-15T09:41:37.286950Z","iopub.status.idle":"2024-04-15T09:41:37.568349Z","shell.execute_reply.started":"2024-04-15T09:41:37.286909Z","shell.execute_reply":"2024-04-15T09:41:37.567402Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch import optim\n\n# define Adam optimizer\nopt = optim.Adam (model.parameters (), lr = 1e-4)\n\n# update model parameters\nopt.step ()\n\n# set gradients to zero\nopt.zero_grad ()\n\n# training and validation\ndef metrics_batch (target, output):\n    # obtain output class\n    pred = output.argmax (dim = 1, keepdim = True)\n    \n    # compare output class with target class\n    corrects = pred.eq (target.view_as (pred)).sum().item()\n    return corrects\n\ndef loss_batch (loss_func, xb, yb, yb_h, opt = None):\n    # obtain loss\n    loss = loss_func (yb_h, yb)\n    \n    # obtain performance metric\n    metric_b = metrics_batch (yb, yb_h)\n    \n    if opt is not None:\n        loss.backward()\n        opt.step()\n        opt.zero_grad ()\n        \n    return loss.item (), metric_b\n\ndef loss_epoch (model, loss_func, dataset_dl, opt = None):\n    loss = 0.0\n    metric = 0.0\n    len_data = len (dataset_dl.dataset)\n    for xb, yb in dataset_dl:\n        xb = xb.type (torch.float).to(device)\n        yb = yb.to(device)\n        \n        # obtain model output\n        yb_h = model (xb)\n        \n        loss_b, metric_b = loss_batch (loss_func, xb, yb, yb_h, opt)\n        loss += loss_b\n        if metric_b is not None:\n            metric += metric_b\n    loss/=len_data\n    metric/=len_data\n    return loss, metric\n\ndef train_val (epochs, model, loss_func, opt, train_dl, val_dl):\n    for epoch in range (epochs):\n        model.train ()\n        train_loss, train_metric = loss_epoch (model, loss_func, train_dl, opt)\n        \n        model.eval ()\n        with torch.no_grad ():\n            val_loss, val_metric = loss_epoch (model, loss_func, val_dl)\n            \n        accuracy = 100*val_metric\n        print (\"epoch: %d, train loss: %.6f, val_loss: %.6f, accuracy: %.2f\" %(epoch, train_loss, val_loss, accuracy))\n        \n# call train_val function\nnum_epochs = 5\ntrain_val (num_epochs, model, loss_func, opt, train_dl, val_dl)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:41:37.569598Z","iopub.execute_input":"2024-04-15T09:41:37.569881Z","iopub.status.idle":"2024-04-15T09:42:59.634447Z","shell.execute_reply.started":"2024-04-15T09:41:37.569858Z","shell.execute_reply":"2024-04-15T09:42:59.633516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Working with labels**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\n\npath2csv = '/kaggle/input/histopathologic-cancer-detection/train_labels.csv'\nlabels_df = pd.read_csv (path2csv)\nlabels_df.head ()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:42:59.635719Z","iopub.execute_input":"2024-04-15T09:42:59.636006Z","iopub.status.idle":"2024-04-15T09:43:01.091491Z","shell.execute_reply.started":"2024-04-15T09:42:59.635981Z","shell.execute_reply":"2024-04-15T09:43:01.090474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print (labels_df ['label'].value_counts ())","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:01.092888Z","iopub.execute_input":"2024-04-15T09:43:01.093236Z","iopub.status.idle":"2024-04-15T09:43:01.106431Z","shell.execute_reply.started":"2024-04-15T09:43:01.093204Z","shell.execute_reply":"2024-04-15T09:43:01.105435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%matplotlib inline\nlabels_df['label'][0:300].hist();","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:01.107676Z","iopub.execute_input":"2024-04-15T09:43:01.107964Z","iopub.status.idle":"2024-04-15T09:43:01.389454Z","shell.execute_reply.started":"2024-04-15T09:43:01.107939Z","shell.execute_reply":"2024-04-15T09:43:01.388581Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pylab as plt\nfrom PIL import Image, ImageDraw\nimport os\n%matplotlib inline\n\n# data is stored here\npath2train = '/kaggle/input/histopathologic-cancer-detection/train'\n\n# show images in gray-scale\ncolor = False\n\n# get ids for images\nIds = labels_df.loc [labels_df ['label']==1]['id'].values\n\nplt.rcParams ['figure.figsize'] = (10.0, 10.0)\nplt.subplots_adjust (wspace = 0, hspace = 0)\nnrows, ncols = 3, 3\nfor i, id_ in enumerate (Ids [:nrows*ncols]):\n    full_filenames = os.path.join (path2train, id_ +'.tif')\n    \n    # load image\n    img = Image.open (full_filenames)\n    \n    # draw a 32*32 rectangle\n    draw = ImageDraw.Draw (img)\n    draw.rectangle (((32, 32), (64, 64)), outline = \"green\")\n    \n    plt.subplot (nrows, ncols, i + 1)\n    if color is True:\n        plt.imshow (np.array (img))\n    else:\n        plt.imshow (np.array (img)[:,:, 0], cmap = \"gray\")\n    plt.axis (\"off\")","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:01.390942Z","iopub.execute_input":"2024-04-15T09:43:01.391671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print (\"image shape:\", np.array (img).shape)\nprint (\"pixel values range from %s to %s\" %(np.min(img), np.max (img)))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:02.209389Z","iopub.execute_input":"2024-04-15T09:43:02.209686Z","iopub.status.idle":"2024-04-15T09:43:02.215254Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Create a cusstom dataset**","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import Dataset\nimport torchvision.transforms as transforms\n\n# fix torch random seed\ntorch.manual_seed (0)\n\nclass histoCancerDataset (Dataset):\n    def __init__ (self, data_dir, transform, data_type = \"train\"):\n        path2data = os.path.join (data_dir, data_type)\n        filenames = os.listdir (path2data)\n        self.full_filenames = [os.path.join (path2data, f) for f in filenames]\n        csv_filename = data_type + \"_labels.csv\"\n        path2csvLabels = os.path.join (data_dir, csv_filename)\n        labels_df = pd.read_csv (path2csvLabels)\n        \n        labels_df.set_index (\"id\", inplace = True)\n        \n        self.labels = [labels_df.loc [filename [:-4]].values[0] for filename in filenames]\n        self.transform = transform\n        \n    def __len__ (self):\n        return len (self.full_filenames)\n    \n    def __getitem__ (self, idx):\n        image = Image.open (self.full_filenames [idx])\n        image = self.transform (image)\n        return image, self.labels  [idx]\n    \ndata_transformer = transforms.Compose ([transforms.ToTensor ()])\ndata_dir = \"/kaggle/input/histopathologic-cancer-detection\"\nhisto_dataset = histoCancerDataset (data_dir, data_transformer, \"train\")\nprint (len (histo_dataset))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:02.216388Z","iopub.execute_input":"2024-04-15T09:43:02.216667Z","iopub.status.idle":"2024-04-15T09:43:13.085719Z","shell.execute_reply.started":"2024-04-15T09:43:02.216644Z","shell.execute_reply":"2024-04-15T09:43:13.084742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# load an image \nimg, label = histo_dataset [9]\nprint (img.shape, torch.min (img), torch.max (img))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.092769Z","iopub.execute_input":"2024-04-15T09:43:13.093071Z","iopub.status.idle":"2024-04-15T09:43:13.109660Z","shell.execute_reply.started":"2024-04-15T09:43:13.093045Z","shell.execute_reply":"2024-04-15T09:43:13.108837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Split the dataset**","metadata":{}},{"cell_type":"code","source":"from torch.utils.data import random_split\n\nlen_histo = len (histo_dataset)\nlen_train = int (0.8 * len_histo)\nlen_val = len_histo-len_train\n\ntrain_ds, val_ds = random_split (histo_dataset, [len_train, len_val])\n\nprint (\"train dataset length:\", len (train_ds))\nprint (\"validation dataset length:\", len (val_ds))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.110615Z","iopub.execute_input":"2024-04-15T09:43:13.110872Z","iopub.status.idle":"2024-04-15T09:43:13.136715Z","shell.execute_reply.started":"2024-04-15T09:43:13.110849Z","shell.execute_reply":"2024-04-15T09:43:13.135896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get the image from the training dataset\n\nfor x, y in train_ds:\n    print (x.shape, y)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.137727Z","iopub.execute_input":"2024-04-15T09:43:13.137993Z","iopub.status.idle":"2024-04-15T09:43:13.148323Z","shell.execute_reply.started":"2024-04-15T09:43:13.137970Z","shell.execute_reply":"2024-04-15T09:43:13.147477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get the image from the validation dataset\n\nfor x, y in val_ds:\n    print (x.shape, y)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.149488Z","iopub.execute_input":"2024-04-15T09:43:13.149777Z","iopub.status.idle":"2024-04-15T09:43:13.159969Z","shell.execute_reply.started":"2024-04-15T09:43:13.149754Z","shell.execute_reply":"2024-04-15T09:43:13.159118Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get a few samples from training dataset\nfrom torchvision import utils\n\nnp.random.seed (0)\n\ndef show (img, y, color = False):\n    # conver tensor to numpy array\n    npimg = img.numpy ()\n    # convert to H*W*C shape\n    npimg_tr = np.transpose (npimg, (1, 2, 0))\n    if color == False:\n        npimg_tr = npimg_tr [:, :, 0]\n        plt.imshow (npimg_tr, interpolation = 'nearest', cmap = 'gray')\n    else:\n        # display images\n        plt.imshow (npimg_tr, interpolation = 'nearest')\n    plt.title (\"label: \"+ str (y))\n    \ngrid_size = 4\nrnd_inds = np.random.randint (0, len (train_ds), grid_size)\nprint (\"image indices:\", rnd_inds)\n\nx_grid_train = [train_ds [i][0] for i in rnd_inds]\ny_grid_train = [train_ds [i][1] for i in rnd_inds]\n\nx_grid_train = utils.make_grid (x_grid_train, nrow = 4, padding = 2)\nprint (x_grid_train.shape)\n\nplt.rcParams ['figure.figsize'] = (10.0, 5)\nshow (x_grid_train, y_grid_train)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.161295Z","iopub.execute_input":"2024-04-15T09:43:13.161677Z","iopub.status.idle":"2024-04-15T09:43:13.446457Z","shell.execute_reply.started":"2024-04-15T09:43:13.161652Z","shell.execute_reply":"2024-04-15T09:43:13.445500Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get a few samples from validation dataset\ngrid_size = 4\nrnd_inds = np.random.randint (0, len (val_ds), grid_size)\nprint (\"image indices:\", rnd_inds)\n\nx_grid_val = [val_ds [i][0] for i in range (grid_size)]\ny_grid_val = [val_ds [i][1] for i in range (grid_size)]\n\nx_grid_val = utils.make_grid (x_grid_val, nrow = 4, padding = 2)\nprint (x_grid_val.shape)\n\nshow (x_grid_val, y_grid_val)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.447571Z","iopub.execute_input":"2024-04-15T09:43:13.447838Z","iopub.status.idle":"2024-04-15T09:43:13.782003Z","shell.execute_reply.started":"2024-04-15T09:43:13.447814Z","shell.execute_reply":"2024-04-15T09:43:13.781099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Transforming the data**","metadata":{}},{"cell_type":"code","source":"train_transformer = transforms.Compose ([\n    transforms.RandomHorizontalFlip (p = 0.5),\n    transforms.RandomVerticalFlip (p = 0.5),\n    transforms.RandomRotation (45),\n    transforms.RandomResizedCrop (96, scale = (0.8, 1.0), ratio = (1.0, 1.0)),\n    transforms.ToTensor ()\n])\n\nval_transformer = transforms.Compose ([transforms.ToTensor ()])\n\n# overwrite the transform functions\ntrain_ds.transform = train_transformer\nval_ds.transform = val_transformer\n\n# creating dataloaders\nfrom torch.utils.data import DataLoader\ntrain_dl = DataLoader (train_ds, batch_size = 32, shuffle = True)\nval_dl = DataLoader (val_ds, batch_size = 64, shuffle = False)\n\n# extract a batch from training data\nfor x, y in train_dl:\n    print (x.shape)\n    print (y.shape)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:13.783256Z","iopub.execute_input":"2024-04-15T09:43:13.783597Z","iopub.status.idle":"2024-04-15T09:43:14.052682Z","shell.execute_reply.started":"2024-04-15T09:43:13.783564Z","shell.execute_reply":"2024-04-15T09:43:14.051598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# get the data from the valuidation dataloader\nfor x, y in val_dl:\n    print (x.shape)\n    print (y.shape)\n    break","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:14.053933Z","iopub.execute_input":"2024-04-15T09:43:14.054235Z","iopub.status.idle":"2024-04-15T09:43:14.541323Z","shell.execute_reply.started":"2024-04-15T09:43:14.054208Z","shell.execute_reply":"2024-04-15T09:43:14.540300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Building the classification model**","metadata":{}},{"cell_type":"code","source":"# get labels for validation dataset\ny_val = [y for _, y in val_ds]\n\ndef accuracy (labels, out):\n    return np.sum (out == labels) / float (len (labels))\n\n# accuracy all zero predictions\nacc_all_zeros = accuracy (y_val, np.zeros_like (y_val))\nprint (\"accuracy all zero prediction: %.2f\" %acc_all_zeros)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:43:14.542663Z","iopub.execute_input":"2024-04-15T09:43:14.543447Z","iopub.status.idle":"2024-04-15T09:48:25.720607Z","shell.execute_reply.started":"2024-04-15T09:43:14.543412Z","shell.execute_reply":"2024-04-15T09:48:25.719580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# accuracy all ones predictions\nacc_all_ones = accuracy (y_val, np.ones_like (y_val))\nprint (\"accuracy all one prediction: %.2f\" %acc_all_ones)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.722053Z","iopub.execute_input":"2024-04-15T09:48:25.722778Z","iopub.status.idle":"2024-04-15T09:48:25.735386Z","shell.execute_reply.started":"2024-04-15T09:48:25.722732Z","shell.execute_reply":"2024-04-15T09:48:25.734233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# accuracy all random predictions\nacc_random = accuracy (y_val, np.random.randint (2, size = len (y_val)))\nprint (\"accuracy random prediction: %2f\" %acc_random)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.736553Z","iopub.execute_input":"2024-04-15T09:48:25.736824Z","iopub.status.idle":"2024-04-15T09:48:25.752481Z","shell.execute_reply.started":"2024-04-15T09:48:25.736793Z","shell.execute_reply":"2024-04-15T09:48:25.751596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch.nn as nn\n\n# helper function for calculating the output size of a CNN layer\ndef findConv2dOutShape (H_in, W_in, conv, pool = 2):\n    # get conv arguments\n    kernel_size = conv.kernel_size\n    stride = conv.stride\n    padding = conv.padding \n    dilation = conv.dilation\n    \n    H_out = np.floor ((H_in + 2 * padding [0] -\n                      dilation[0] * (kernel_size[0] - 1)- 1) /stride [0] + 1)\n    W_out = np.floor ((W_in + 2 * padding [1] - dilation[1] * \n                      (kernel_size [1] - 1)-1) / stride [1] + 1)\n    if pool:\n        H_out /= pool\n        W_out /= pool\n    return int (H_out), int (W_out)\n\n# provide the example\nconv1 = nn.Conv2d (3, 8, kernel_size = 3)\nh, w = findConv2dOutShape (96, 96, conv1)\nprint (h, w)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.753665Z","iopub.execute_input":"2024-04-15T09:48:25.753933Z","iopub.status.idle":"2024-04-15T09:48:25.762791Z","shell.execute_reply.started":"2024-04-15T09:48:25.753909Z","shell.execute_reply":"2024-04-15T09:48:25.761834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define the Net class\nclass Net (nn.Module):\n    def __init__ (self, params):\n        super (Net, self).__init__()\n        C_in, H_in, W_in = params ['input_shape']\n        init_f = params ['initial_filters']\n        num_fc1 = params ['num_fc1']\n        num_classes = params ['num_classes']\n        self.dropout_rate = params ['dropout_rate']\n        self.conv1 = nn.Conv2d (C_in, init_f, kernel_size = 3)\n        h, w = findConv2dOutShape (H_in, W_in, self.conv1)\n        self.conv2 = nn.Conv2d (init_f, 2 * init_f, kernel_size = 3)\n        h, w = findConv2dOutShape (h, w, self.conv2)\n        self.conv3 = nn.Conv2d (2 * init_f, 4 * init_f, kernel_size = 3)\n        h, w = findConv2dOutShape (h, w, self.conv3)\n        self.conv4 = nn.Conv2d (4 * init_f, 8 * init_f, kernel_size = 3)\n        h, w = findConv2dOutShape (h, w, self.conv4)\n        # compute the flatten size\n        self.num_flatten = h * w * 8 * init_f\n        self.fc1 = nn.Linear (self.num_flatten, num_fc1)\n        self.fc2 = nn.Linear (num_fc1, num_classes)\n        \n    # define the forward function\n    def forward (self, x):\n        x = F.relu (self.conv1 (x))\n        x = F.max_pool2d (x, 2, 2)\n        x = F.relu (self.conv2(x))\n        x = F.max_pool2d (x, 2, 2)\n        x = F.relu (self.conv3(x))\n        x = F.max_pool2d (x, 2, 2)\n        x = F.relu (self.conv4(x))\n        x = F.max_pool2d (x, 2, 2)\n        x = x.view (-1, self.num_flatten)\n        x = F.relu (self.fc1 (x))\n        x = F.dropout (x, self.dropout_rate, training = self.training)\n        x = self.fc2 (x)\n        return F.log_softmax (x, dim = 1)\n    \n# dict to define model parameters\nparams_model = {\n    \"input_shape\": (3, 96, 96),\n    \"initial_filters\": 8,\n    \"num_fc1\": 100,\n    \"dropout_rate\": 0.25,\n    \"num_classes\": 2,\n}\n\n# create the model\ncnn_model = Net (params_model)\n\n# move model to gpu device\nif torch.cuda.is_available ():\n    device = torch.device ('cuda')\n    cnn_model = cnn_model.to (device)\n\nprint (cnn_model)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.764011Z","iopub.execute_input":"2024-04-15T09:48:25.764265Z","iopub.status.idle":"2024-04-15T09:48:25.782549Z","shell.execute_reply.started":"2024-04-15T09:48:25.764243Z","shell.execute_reply":"2024-04-15T09:48:25.781723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchsummary import summary\nsummary (cnn_model, input_size = (3, 96, 96), device = device.type)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.783733Z","iopub.execute_input":"2024-04-15T09:48:25.784613Z","iopub.status.idle":"2024-04-15T09:48:25.823095Z","shell.execute_reply.started":"2024-04-15T09:48:25.784580Z","shell.execute_reply":"2024-04-15T09:48:25.822225Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Define the loss function**","metadata":{}},{"cell_type":"code","source":"loss_func = nn.NLLLoss (reduction = 'sum')\n\n# fix random seed\ntorch.manual_seed (0)\n\nn, c = 8, 2\ny = torch.randn (n, c, requires_grad = True)\nls_F = nn.LogSoftmax (dim = 1)\ny_out = ls_F (y)\nprint (y_out.shape)\n\ntarget = torch.randint (c, size = (n, ))\nprint (target.shape)\n\nloss = loss_func (y_out, target)\nprint (loss.item ())","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.824103Z","iopub.execute_input":"2024-04-15T09:48:25.824377Z","iopub.status.idle":"2024-04-15T09:48:25.834352Z","shell.execute_reply.started":"2024-04-15T09:48:25.824352Z","shell.execute_reply":"2024-04-15T09:48:25.833427Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# compute the gradients\nloss.backward ()\nprint (y.data)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.835430Z","iopub.execute_input":"2024-04-15T09:48:25.835780Z","iopub.status.idle":"2024-04-15T09:48:25.841987Z","shell.execute_reply.started":"2024-04-15T09:48:25.835756Z","shell.execute_reply":"2024-04-15T09:48:25.841068Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Define the optimizer**","metadata":{}},{"cell_type":"code","source":"from torch import optim\n\nopt = optim.Adam (cnn_model.parameters (), lr = 3e-4)\n\n# get the learning rate\ndef get_lr (opt):\n    for param_group in opt.param_groups:\n        return param_group ['lr']\n\ncurrent_lr = get_lr (opt)\nprint ('current lr = {}'.format (current_lr))","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.843231Z","iopub.execute_input":"2024-04-15T09:48:25.843568Z","iopub.status.idle":"2024-04-15T09:48:25.850220Z","shell.execute_reply.started":"2024-04-15T09:48:25.843497Z","shell.execute_reply":"2024-04-15T09:48:25.849337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# define a learning scheduler\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau\n\nlr_scheduler = ReduceLROnPlateau (opt, mode = 'min', factor = 0.5, patience = 20, verbose = 1)\n\nfor i in range (100):\n    lr_scheduler.step (1)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.851343Z","iopub.execute_input":"2024-04-15T09:48:25.851608Z","iopub.status.idle":"2024-04-15T09:48:25.859667Z","shell.execute_reply.started":"2024-04-15T09:48:25.851585Z","shell.execute_reply":"2024-04-15T09:48:25.858860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Training and evaluation of the model**","metadata":{}},{"cell_type":"code","source":"# function to count the number of correct predictions per batch\ndef metrics_batch (output, target):\n    # get output class\n    pred = output.argmax (dim = 1, keepdim = True)\n    # compare output class with target class\n    corrects = pred.eq (target.view_as (pred)).sum ().item ()\n    return corrects\n\n# function to compute the loss value per batch\ndef loss_batch (loss_func, output, target, opt = None):\n    loss = loss_func (output, target)\n    with torch.no_grad ():\n        metric_b = metrics_batch (output, target)\n    if opt is not None:\n        opt.zero_grad ()\n        loss.backward ()\n        opt.step ()\n    return loss.item (), metric_b\n\n# function to compute the loss value and performance metric for an epoch\ndef loss_epoch (model, loss_func, dataset_dl, sanity_check = False, opt = None):\n    running_loss = 0.0\n    running_metric = 0.0\n    len_data = len (dataset_dl.dataset)\n    \n    for xb, yb in dataset_dl:\n        # move batch to device\n        xb = xb.to (device)\n        yb = yb.to (device)\n        # get model output\n        output = model (xb)\n        # get loss per batch\n        loss_b, metric_b = loss_batch (loss_func, output, yb, opt)\n        # update running loss\n        running_loss += loss_b\n        # update running metric\n        if metric_b is not None:\n            running_metric += metric_b\n        # break the loop in case of sanity check\n        if sanity_check is True:\n            break\n            \n    # average loss value\n    loss = running_loss / float (len_data)\n    # avearge metric value\n    metric = running_metric / float (len_data)\n    return loss, metric\n\n# train and validation function\ndef train_val (model, params):\n    # extract model parameters\n    num_epochs = params [\"num_epochs\"]\n    loss_func = params [\"loss_func\"]\n    opt = params [\"optimizer\"]\n    train_dl = params [\"train_dl\"]\n    val_dl = params [\"val_dl\"]\n    sanity_check = params [\"sanity_check\"]\n    lr_scheduler = params [\"lr_scheduler\"]\n    path2weights = params [\"path2weights\"]\n    \n    # history of loss values of each epoch\n    loss_history = {\"train\": [], \"val\": [], }\n    # history of metric values in each epoch\n    metric_history = {\"train\": [], \"val\": [], }\n    \n    # a deep copy of weights for the best performing model\n    best_model_wts = copy.deepcopy (model.state_dict ())\n    \n    # initialize best loss to a large value\n    best_loss = float ('inf')\n    \n    # loop that will calculate the training loss over an epoch\n    for epoch in range (num_epochs):\n        # get current learning rate\n        current_lr = get_lr (opt)\n        print ('Epoch {}/{}, current lr = {}'.format (epoch, num_epochs - 1, current_lr))\n        \n        # train model on training dataset\n        model.train ()\n        train_loss, train_metric = loss_epoch (model, loss_func, train_dl, sanity_check, opt)\n        \n        # collect loss and metric for training dataset\n        loss_history [\"train\"].append (train_loss)\n        metric_history[\"train\"].append (train_metric)\n        \n        # evaluate the model on validation dataset\n        model.eval ()\n        with torch.no_grad ():\n            val_loss, val_metric = loss_epoch (model, loss_func, val_dl, sanity_check)\n        \n        # collect loss and metric for validation dataset\n        loss_history [\"val\"].append (val_loss)\n        metric_history [\"val\"].append (val_metric)\n        \n        # store best model\n        if val_loss < best_loss:\n            best_loss = val_loss\n            best_model_wts = copy.deepcopy (model.state_dict ())\n            \n            # store weights into a local file\n            torch.save (model.state_dict (), path2weights)\n            print ('Copied best model weights')\n            \n        # learning rate schedule\n        lr_scheduler.step (val_loss)\n        if current_lr != get_lr (opt):\n            print (\"Loading best model weights\")\n            model.load_state_dict (best_model_wts)\n            \n        print (\"train_loss: %.6f, dev_loss: %.6f, accuracy: %.2f\" %(train_loss, val_loss, 100 * val_metric))\n        print (\"-\" * 10)\n    \n    # load best model weights\n    model.load_state_dict (best_model_wts)\n    return model, loss_history, metric_history\n\nimport copy\nloss_func = nn.NLLLoss (reduction = \"sum\")\nopt = optim.Adam (cnn_model.parameters (), lr = 3e-4)\nlr_scheduler = ReduceLROnPlateau (opt, mode = \"min\", factor = 0.5, patience = 20, verbose = 1)\n\nparams_train = {\n    \"num_epochs\": 100,\n    \"optimizer\": opt,\n    \"loss_func\": loss_func,\n    \"train_dl\": train_dl,\n    \"val_dl\": val_dl,\n    \"sanity_check\": True,\n    \"lr_scheduler\": lr_scheduler,\n    \"path2weights\": \"/kaggle/working/FashionMNIST/weights.pt\",\n}\n\n# train and validate the model\ncnn_model, loss_hist, metric_hist = train_val (cnn_model, params_train)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:48:25.863167Z","iopub.execute_input":"2024-04-15T09:48:25.863490Z","iopub.status.idle":"2024-04-15T09:49:00.059967Z","shell.execute_reply.started":"2024-04-15T09:48:25.863467Z","shell.execute_reply":"2024-04-15T09:49:00.059065Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Plot the progress of learning**","metadata":{}},{"cell_type":"code","source":"# train validation progress\nnum_epochs = params_train ['num_epochs']\n\n# plot loss progress\nplt.title (\"Train-Validation Loss\")\nplt.plot (range (1, num_epochs + 1), loss_hist [\"train\"], label = \"train\")\nplt.plot (range (1, num_epochs + 1), loss_hist [\"val\"], label = \"val\")\nplt.ylabel (\"Loss\")\nplt.xlabel (\"Training Epochs\")\nplt.legend ()\nplt.show ()\n\n# plot accuracy progress\nplt.title (\"Train-Validation Accuracy\")\nplt.plot (range (1, num_epochs + 1), metric_hist [\"train\"], label = \"train\")\nplt.plot (range (1, num_epochs + 1), metric_hist [\"val\"], label = \"val\")\nplt.ylabel (\"Accuracy\")\nplt.xlabel (\"Training Epochs\")\nplt.legend ()\nplt.grid ()\nplt.show ()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:49:00.061303Z","iopub.execute_input":"2024-04-15T09:49:00.061719Z","iopub.status.idle":"2024-04-15T09:49:00.661198Z","shell.execute_reply.started":"2024-04-15T09:49:00.061683Z","shell.execute_reply":"2024-04-15T09:49:00.660213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import copy\n\nloss_func = nn.NLLLoss (reduction = 'sum')\nopt = optim.Adam (cnn_model.parameters (), lr = 3e-4)\nlr_scheduler = ReduceLROnPlateau (opt, mode = 'min', factor = 0.5, patience = 20, verbose = 1)\n\nparams_train = {\n    \"num_epochs\": 2, \n    \"optimizer\": opt,\n    \"loss_func\": loss_func,\n    \"train_dl\": train_dl,\n    \"val_dl\": val_dl,\n    \"sanity_check\": False,\n    \"lr_scheduler\": lr_scheduler,\n    \"path2weights\": \"/kaggle/working/FashionMNIST/weights.pt\",\n}\n\n# train and validate the model\ncnn_model, loss_hist, metric_hist = train_val (cnn_model, params_train)","metadata":{"execution":{"iopub.status.busy":"2024-04-15T09:49:00.662300Z","iopub.execute_input":"2024-04-15T09:49:00.662584Z","iopub.status.idle":"2024-04-15T10:20:46.190682Z","shell.execute_reply.started":"2024-04-15T09:49:00.662549Z","shell.execute_reply":"2024-04-15T10:20:46.189679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train-validation progress\nnum_epochs = params_train [\"num_epochs\"]\n\n# plot loss progress\nplt.title ('Train-Val Loss')\nplt.plot (range (1, num_epochs + 1), loss_hist ['train'], label = 'train')\nplt.plot (range (1, num_epochs + 1), loss_hist ['val'], label = 'val')\nplt.ylabel ('Loss')\nplt.xlabel ('Training Epochs')\nplt.legend ()\nplt.show ()\n\n# plot accuracy progress\nplt.title ('Train-Val Accuracy')\nplt.plot (range (1, num_epochs + 1), metric_hist ['train'], label = 'train')\nplt.plot (range (1, num_epochs + 1), metric_hist ['val'], label = 'val')\nplt.ylabel ('Accuracy')\nplt.xlabel ('Training Epochs')\nplt.legend ()\nplt.show ()","metadata":{"execution":{"iopub.status.busy":"2024-04-15T10:25:57.914727Z","iopub.execute_input":"2024-04-15T10:25:57.915566Z","iopub.status.idle":"2024-04-15T10:25:58.471342Z","shell.execute_reply.started":"2024-04-15T10:25:57.915520Z","shell.execute_reply":"2024-04-15T10:25:58.470445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision import datasets\nimport torchvision.transforms as transforms\nimport os\n\n# path to store \npath2data = '/kaggle/working/data'\n\n# define transformation\ndata_transformer = transforms.Compose ([transforms.ToTensor ()])\n\n# loading data\ntrain_ds = datasets.STL10 (path2data, split = 'train', download = True, transform = data_transformer)\n\n# print out data shape\nprint (train_ds.data.shape)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T18:38:18.252212Z","iopub.execute_input":"2024-04-19T18:38:18.253075Z","iopub.status.idle":"2024-04-19T18:38:23.817407Z","shell.execute_reply.started":"2024-04-19T18:38:18.253038Z","shell.execute_reply":"2024-04-19T18:38:23.816463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import collections \n\n# get labels \ny_train = [y for _, y in train_ds]\n\n# count labels\ncounter_train = collections.Counter (y_train)\nprint (counter_train)","metadata":{"execution":{"iopub.status.busy":"2024-04-19T18:39:29.273523Z","iopub.execute_input":"2024-04-19T18:39:29.273809Z","iopub.status.idle":"2024-04-19T18:39:30.947772Z","shell.execute_reply.started":"2024-04-19T18:39:29.273784Z","shell.execute_reply":"2024-04-19T18:39:30.946818Z"},"trusted":true},"execution_count":null,"outputs":[]}]}