{"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":13451,"databundleVersionId":1188070,"sourceType":"competition"}],"dockerImageVersionId":30664,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","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","execution":{"iopub.status.busy":"2024-03-03T12:59:18.227652Z","iopub.execute_input":"2024-03-03T12:59:18.227956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport numpy as np\nfrom scipy.ndimage import rotate\n\nclass ToTensor2D(object):\n    \"\"\"Convert a PIL image or numpy array to a PyTorch tensor.\"\"\"\n\n    def __init__(self, labeled=True):\n        self.labeled = labeled\n\n    def __call__(self, sample):\n        rdict = {}\n        input_data = sample['input']\n\n        ret_input = input_data.transpose(2, 0, 1)  # Pytorch supports N x C x X_dim x Y_dim\n        ret_input = torch.from_numpy(ret_input).float()\n        rdict['input'] = ret_input\n\n        if self.labeled:\n            gt_data = sample['gt']\n            if gt_data is not None:\n                ret_gt = torch.tensor(gt_data).float()\n\n                rdict['gt'] = ret_gt\n        sample.update(rdict)\n        return sample\n\nclass RandomRotation2D(object):\n    \"\"\"Make a rotation of the volume's values.\n    :param degrees: Maximum rotation's degrees.\n    \"\"\"\n\n    def __init__(self, degrees, axis=0, labeled=True, segment=True):\n        self.degrees = degrees\n        self.labeled = labeled\n        self.segment = segment\n        self.order = 0 if self.segment == True else 5\n\n    @staticmethod\n    def get_params(degrees):  # Get random theta value for rotation\n        angle = np.random.uniform(degrees[0], degrees[1])\n        return angle\n\n    def __call__(self, sample):\n        rdict = {}\n        input_data = sample['input']\n        if len(sample['input'].shape) != 3:  # C x X_dim x Y_dim \n            raise ValueError(\"Input of RandomRotation2D should be a 3 dimensionnal tensor.\")\n\n        angle = self.get_params(self.degrees)\n\n        input_rotated = np.zeros(input_data.shape, dtype=input_data.dtype)\n\n        gt_data = sample['gt'] if self.labeled else None\n        # gt_rotated = np.zeros(gt_data.shape, dtype=gt_data.dtype) if self.labeled else None\n\n        # Rotation angle chosen at random and rotation happens only on XY plane for both image and label.\n        # for sh in range(input_data.shape[2]):\n        input_rotated[:, :, 0] = rotate(input_data[:, :, 0], float(angle), reshape=False, order=self.order,\n                                            mode='nearest')\n\n            # if self.labeled:\n                # gt_rotated[:, :, sh, 0] = rotate(gt_data[:, :, sh, 0], float(angle), reshape=False, order=self.order,\n                #                                  mode='nearest')\n                # gt_rotated[:, :, sh, 1] = rotate(gt_data[:, :, sh, 1], float(angle), reshape=False, order=self.order,\n                #                                  mode='nearest')\n                # gt_rotated = (gt_rotated > 0.6).astype(float)\n\n        # Update the dictionary with transformed image and labels\n        rdict['input'] = input_rotated\n\n        # if self.labeled:\n            # rdict['gt'] = gt_rotated\n        sample.update(rdict)\n        return sample","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:28:26.330321Z","iopub.execute_input":"2024-03-08T14:28:26.33071Z","iopub.status.idle":"2024-03-08T14:28:26.34407Z","shell.execute_reply.started":"2024-03-08T14:28:26.330679Z","shell.execute_reply":"2024-03-08T14:28:26.343024Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"[[1,2],\n [3,4]]","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:09:04.958036Z","iopub.execute_input":"2024-03-08T14:09:04.95841Z","iopub.status.idle":"2024-03-08T14:09:04.964435Z","shell.execute_reply.started":"2024-03-08T14:09:04.958369Z","shell.execute_reply":"2024-03-08T14:09:04.963425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"[[1,2],\n [3,5]]","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:09:58.215014Z","iopub.execute_input":"2024-03-08T14:09:58.215788Z","iopub.status.idle":"2024-03-08T14:09:58.221954Z","shell.execute_reply.started":"2024-03-08T14:09:58.215749Z","shell.execute_reply":"2024-03-08T14:09:58.221016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#1 2 3 4\n# 1  2  2.5 3   4","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:19:47.693243Z","iopub.execute_input":"2024-03-08T14:19:47.69403Z","iopub.status.idle":"2024-03-08T14:19:47.697901Z","shell.execute_reply.started":"2024-03-08T14:19:47.693999Z","shell.execute_reply":"2024-03-08T14:19:47.696969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(54 - 0)/(255-0)","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:24:15.823642Z","iopub.execute_input":"2024-03-08T14:24:15.824362Z","iopub.status.idle":"2024-03-08T14:24:15.830258Z","shell.execute_reply.started":"2024-03-08T14:24:15.824332Z","shell.execute_reply":"2024-03-08T14:24:15.829219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(0 -0 )/(255-0)","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:24:40.446916Z","iopub.execute_input":"2024-03-08T14:24:40.447618Z","iopub.status.idle":"2024-03-08T14:24:40.453718Z","shell.execute_reply.started":"2024-03-08T14:24:40.447586Z","shell.execute_reply":"2024-03-08T14:24:40.452707Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import pandas as pd","metadata":{"execution":{"iopub.status.busy":"2024-03-15T13:51:34.687941Z","iopub.execute_input":"2024-03-15T13:51:34.688282Z","iopub.status.idle":"2024-03-15T13:51:35.039118Z","shell.execute_reply.started":"2024-03-15T13:51:34.688256Z","shell.execute_reply":"2024-03-15T13:51:35.038165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data = pd.read_csv('/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv')","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:25:20.914115Z","iopub.execute_input":"2024-03-15T14:25:20.914832Z","iopub.status.idle":"2024-03-15T14:25:23.814629Z","shell.execute_reply.started":"2024-03-15T14:25:20.914797Z","shell.execute_reply":"2024-03-15T14:25:23.813724Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data.head(10)","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:25:28.276841Z","iopub.execute_input":"2024-03-15T14:25:28.277175Z","iopub.status.idle":"2024-03-15T14:25:28.286502Z","shell.execute_reply.started":"2024-03-15T14:25:28.277151Z","shell.execute_reply":"2024-03-15T14:25:28.285522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data[['ID', 'Image', 'Diagnosis']] = gt_data['ID'].str.split('_', expand=True)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:21:57.011542Z","iopub.execute_input":"2024-03-15T14:21:57.012369Z","iopub.status.idle":"2024-03-15T14:22:09.491996Z","shell.execute_reply.started":"2024-03-15T14:21:57.012335Z","shell.execute_reply":"2024-03-15T14:22:09.491002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data = gt_data[['Image', 'Diagnosis', 'Label']]\n","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:23:26.492764Z","iopub.execute_input":"2024-03-15T14:23:26.493379Z","iopub.status.idle":"2024-03-15T14:23:35.710475Z","shell.execute_reply.started":"2024-03-15T14:23:26.49335Z","shell.execute_reply":"2024-03-15T14:23:35.709443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data.drop_duplicates(inplace=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data['Image'] = 'ID_' + gt_data['Image']\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:24:37.065806Z","iopub.execute_input":"2024-03-15T14:24:37.066153Z","iopub.status.idle":"2024-03-15T14:24:37.288233Z","shell.execute_reply.started":"2024-03-15T14:24:37.066125Z","shell.execute_reply":"2024-03-15T14:24:37.287171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gt_data = gt_data.pivot(index='Image', columns='Diagnosis', values='Label').reset_index()\n\n","metadata":{"execution":{"iopub.status.busy":"2024-03-15T14:24:57.81201Z","iopub.execute_input":"2024-03-15T14:24:57.812656Z","iopub.status.idle":"2024-03-15T14:24:57.827243Z","shell.execute_reply.started":"2024-03-15T14:24:57.812622Z","shell.execute_reply":"2024-03-15T14:24:57.826139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.utils.data import Dataset,DataLoader\nimport nibabel as nib\nimport skimage.transform as skiform\nimport numpy as np\nimport pydicom as dicom\nimport pandas as pd\n\nclass ICH_Reader(Dataset):\n    def __init__(self,img_paths,gt_data,size=64,transform=None):\n        self.image_paths = img_paths\n        self.data = gt_data\n        self.transform = transform\n        self.size =size\n    def __getitem__(self,index):\n        image =  dicom.dcmread(self.image_paths[index])\n        image = image.pixel_array\n        \n        # windowing to the image\n#         image[image<L_HU] = L_HU\n#         image[image>H_HU] = H_HU\n        \n        image = skiform.resize(image,(self.size,)*2,order=1,preserve_range=True)\n        gt =  np.array(self.data.loc[self.image_paths[index][-16:-4], ['epidural', 'intraparenchymal', 'intraventricular', 'subarachnoid', 'subdural', 'any']]).astype(np.float16)\n        # 64x64\n        # 6x1\n        image -=image.min()\n        image /=image.max() + 1e-7\n\n\n        image = np.expand_dims(image,axis=-1)\n        # 64x64x1 \n\n        data_dict = {}\n        data_dict['input'] = image \n        data_dict['gt'] = gt\n        if(self.transform!=None):\n            self.transform(data_dict)\n        return data_dict\n    def __len__(self):\n        return len(self.image_paths)","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:28:29.233878Z","iopub.execute_input":"2024-03-08T14:28:29.234235Z","iopub.status.idle":"2024-03-08T14:28:29.803676Z","shell.execute_reply.started":"2024-03-08T14:28:29.234205Z","shell.execute_reply":"2024-03-08T14:28:29.802687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\nclass ResNet2DBasicBlock(nn.Module):\n    def __init__(self, input_channels, output_channels, stride=1, downsample=None):\n        super().__init__()\n        self.downsample = downsample\n\n        self.conv1 = nn.Conv2d(input_channels, output_channels, kernel_size=3, stride=stride, padding=1)\n        self.bn1 = nn.BatchNorm2d(output_channels)\n        self.relu = nn.ReLU(inplace=True)\n\n        self.conv2 = nn.Conv2d(output_channels, output_channels, kernel_size=3, padding=1)\n        self.bn2 = nn.BatchNorm2d(output_channels)\n\n    def forward(self, x):\n        identity = x\n\n        out = self.conv1(x)\n        out = self.bn1(out)\n        out = self.relu(out)\n\n        out = self.conv2(out)\n        out = self.bn2(out)\n\n        if self.downsample:\n            identity = self.downsample(x)\n            \n        out += identity\n        out = self.relu(out)\n        return out\n    \nclass ResNet2D(nn.Module):\n    def __init__(self, image_channels):\n        super().__init__()\n        self.in_channels = 64\n\n        self.conv1 = nn.Conv2d(image_channels, self.in_channels, kernel_size=7, stride=2, padding=3)\n        self.bn1 = nn.BatchNorm2d(self.in_channels)\n        self.relu = nn.ReLU(inplace=True)\n        self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)\n\n        self.layer1 = self._make_layer(64, 64, 2, stride=1)\n        self.layer2 = self._make_layer(64, 128, 2, stride=2)\n        self.layer3 = self._make_layer(128, 256, 2, stride=2)\n        self.layer4 = self._make_layer(256, 512, 2, stride=2)\n        # self.layer5 = self._make_layer(512, 1024, 2, stride=2)\n        # self.layer6 = self._make_layer(1024, 2048, 2, stride=2)\n\n    def _make_layer(self, in_channels, output_channels, blocks, stride=1):\n        downsample = None\n        if stride != 1:\n            downsample = nn.Sequential(\n                nn.Conv2d(in_channels, output_channels, kernel_size=1, stride=stride),\n                nn.BatchNorm2d(output_channels),\n            )\n        \n        layers = []\n        layers.append(\n            ResNet2DBasicBlock(\n                self.in_channels,\n                output_channels, \n                stride,\n                downsample\n            )\n        )\n        self.in_channels = output_channels\n\n        for _ in range(1, blocks):\n            layers.append(\n                ResNet2DBasicBlock(\n                    self.in_channels,\n                    output_channels,\n                )\n            )\n        \n        return nn.Sequential(*layers)\n    \n    def forward(self, x):\n\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.relu(x)\n        x = self.maxpool(x)\n\n        x = self.layer1(x)\n        x = self.layer2(x)\n        x = self.layer3(x)\n        x = self.layer4(x)\n        # x = self.layer5(x)\n        # x = self.layer6(x)\n\n        return x\n\n\nclass Classifier(nn.Module):\n\n    def __init__(self, input_channels, output_channels):\n        super().__init__()\n\n        self.layer1 = nn.Sequential(\n            nn.Linear(input_channels, input_channels // 2),\n            nn.ReLU(inplace=True)\n        )\n\n        self.layer2 = nn.Sequential(\n            nn.Linear(input_channels // 2, input_channels // 4),\n            nn.ReLU(inplace=True)\n        )\n\n        self.layer3 = nn.Linear(input_channels // 4, output_channels)\n\n        self.fc = nn.Sequential()\n        self.fc.add_module('layer1', self.layer1)\n        self.fc.add_module('layer2', self.layer2)\n        self.fc.add_module('layer3', self.layer3)\n\n        self.activation = nn.Sigmoid()\n    \n    def forward(self, x):\n        out = self.fc(x)\n        out = self.activation(out)\n        return out\n\nclass ResNetClassifier(nn.Module):\n    def __init__(self,in_channels,out_channels):\n        super().__init__()\n        self.encoder = ResNet2D(in_channels)\n        self.classifier = Classifier(2048,out_channels) \n\n    def forward(self,x): \n        out = self.encoder(x)\n        out = torch.flatten(out,1,-1)\n        out = self.classifier(out)\n        return out","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:28:41.884868Z","iopub.execute_input":"2024-03-08T14:28:41.885425Z","iopub.status.idle":"2024-03-08T14:28:41.909757Z","shell.execute_reply.started":"2024-03-08T14:28:41.885378Z","shell.execute_reply":"2024-03-08T14:28:41.908792Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pwd\n","metadata":{"execution":{"iopub.status.busy":"2024-03-03T13:10:46.853296Z","iopub.execute_input":"2024-03-03T13:10:46.853654Z","iopub.status.idle":"2024-03-03T13:10:47.80675Z","shell.execute_reply.started":"2024-03-03T13:10:46.853622Z","shell.execute_reply":"2024-03-03T13:10:47.805609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport glob\nimport json\n\nnp.random.seed(0)\n\nimg_paths = np.array(glob.glob('/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train/*dcm'))[:100]\n\npermutation = np.random.choice(len(img_paths),len(img_paths),replace=False).astype(np.int32)\n\nimg_paths = img_paths[permutation].tolist()\n\n# train val test split 0.7 0.1 0.2\ndata_split = {'train_imgs':img_paths[:int(0.7*len(img_paths))],\n              'val_imgs':img_paths[int(0.7*len(img_paths)):int(0.8*len(img_paths))],\n              'test_imgs':img_paths[int(0.8*len(img_paths)):],}\n\n\n\nwith open('data_split.json', 'w') as f:\n    json.dump(data_split, f)","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:28:46.546359Z","iopub.execute_input":"2024-03-08T14:28:46.546754Z","iopub.status.idle":"2024-03-08T14:28:54.971733Z","shell.execute_reply.started":"2024-03-08T14:28:46.546725Z","shell.execute_reply":"2024-03-08T14:28:54.970807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#W = W - lr*(dL/dW)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport matplotlib.pyplot as plt\nfrom torchvision import transforms\nfrom torch.utils.data import DataLoader\nimport torch.optim as optim\nfrom tqdm import tqdm\nimport numpy as np\nimport json\nimport pandas as pd\nimport os\n\ntrain_transforms = transforms.Compose([\n            RandomRotation2D([10,10]),\n            ToTensor2D(True)])\n\nval_transforms = transforms.Compose([ToTensor2D(True)])\n\n\ndevice = 'cuda:0'\ncriterion = nn.BCELoss().to(device)\n \ndata = json.load(open('data_split.json'))\n\ncsv_path = '/kaggle/input/rsna-intracranial-hemorrhage-detection/rsna-intracranial-hemorrhage-detection/stage_2_train.csv'\ngt_data = pd.read_csv(csv_path)\n\n#######################################################################################\n# Adapted from https://www.kaggle.com/code/taindow/pytorch-resnext-101-32x8d-benchmark/notebook\n    \ngt_data[['ID', 'Image', 'Diagnosis']] = gt_data['ID'].str.split('_', expand=True)\ngt_data = gt_data[['Image', 'Diagnosis', 'Label']]\ngt_data.drop_duplicates(inplace=True)\ngt_data = gt_data.pivot(index='Image', columns='Diagnosis', values='Label').reset_index()\ngt_data['Image'] = 'ID_' + gt_data['Image']\ngt_data.set_index('Image',inplace=True)\n\n########################################################################################\n\n\ndatadict_train = ICH_Reader(data['train_imgs'],gt_data,transform=train_transforms)\ndatadict_val = ICH_Reader(data['val_imgs'],gt_data,transform=val_transforms)\n#datadict_test\n\ntrainloader = DataLoader(datadict_train, batch_size=16, shuffle=True)\nvalloader = DataLoader(datadict_val, batch_size=1, shuffle=False)\n# testloader\n\n# model = UNet(in_channels=1,out_channels=2,init_features=32).to(device)\n# model_name = 'UNet'\n\nmodel = ResNetClassifier(in_channels=1,out_channels=6).to(device)\nmodel_name = 'ResNet'\n\noptimizer = optim.Adam(model.parameters(), lr = 1e-4, eps = 0.0001)\nscheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer,factor=0.5,patience=10,min_lr = 2e-5,mode='min')\n\nnum_epochs = 200\n\ntrain_losses = []\nval_losses = []\nbest_loss = np.inf\nmin_epoch = 0\n\n#############\n# Train Loop \n#############\nos.makedirs('./models',exist_ok=True)\nos.makedirs('./losses',exist_ok=True)\n\nfor epoch in range(0,num_epochs):\n    torch.cuda.empty_cache()\n\n    epoch_loss = 0\n\n    model.train()\n\n    with tqdm(range(len(trainloader))) as pbar:\n        for i, data in zip(pbar, trainloader):\n            torch.cuda.empty_cache()\n            err = 0\n            image = data['input'].to(device)\n\n            output = model.forward(image) # forward\n            label = data['gt'].to(device)\n            err = criterion(output,label) # how poorly model formed compared clinician's output\n\n            model.zero_grad()\n            err.backward() #backward\n            optimizer.step() #update the parameters\n            pbar.set_postfix(Train_Loss = np.round(err.cpu().detach().numpy().item(), 5))\n            pbar.update(0)\n            epoch_loss += err.item()\n            del image\n            del label\n            del err\n\n\n        train_losses.append([epoch_loss/len(trainloader)])\n        print('Training Loss at epoch {} is : Total {}'.format(epoch,*train_losses[-1]))\n\n    epoch_loss = 0\n    model.eval()\n    with tqdm(range(len(valloader))) as pbar:\n        for i, data in zip(pbar, valloader):\n            torch.cuda.empty_cache()\n            err = 0\n            with torch.no_grad():\n                image = data['input'].to(device)\n                output = model.forward(image) #forward\n                label = data['gt'].to(device)\n                \n                err = criterion(output,label)\n                #acc\n                #f1\n                \n                del image\n                del label\n\n            pbar.set_postfix(Val_Loss = np.round(err.cpu().detach().numpy().item(), 5))\n            pbar.update(0)\n            epoch_loss += err.item()\n            del err\n\n        val_losses.append([epoch_loss/len(valloader)])\n        print('Validation Loss at epoch {} is : Total {}'.format(epoch,*val_losses[-1]))\n    \n    scheduler.step(*val_losses[-1])\n\n    if(epoch_loss<best_loss):\n            best_loss = epoch_loss\n            torch.save({\n            'epoch': epoch,\n            'model_state_dict': model.state_dict(),\n            'optimizer_state_dict': optimizer.state_dict(),\n            'loss': epoch_loss,\n            'lr_scheduler_state_dict':scheduler.state_dict(),\n            }, './models/'+model_name+'_state_dict_best_loss'+str(epoch)+'.pth')\n    else:\n            pass\n            # early_stopping_counter-=1\n\n    np.save('./losses/'+model_name+'_loss.npy', [train_losses,val_losses])\n    \n    if(epoch%10==0):\n        torch.save({\n        'epoch': epoch,\n        'model_state_dict': model.state_dict(),\n        'optimizer_state_dict': optimizer.state_dict(),\n        'loss': epoch_loss,\n        'lr_scheduler_state_dict':scheduler.state_dict(),\n        }, './models/'+model_name+'_state_dict'+str(epoch)+'.pth')\n\ntorch.save({\n    'epoch': epoch,\n    'model_state_dict': model.state_dict(),\n    'optimizer_state_dict': optimizer.state_dict(),\n    'loss': epoch_loss,\n    'lr_scheduler_state_dict':scheduler.state_dict(),\n    }, './models/'+model_name+'_state_dict'+str(epoch)+'.pth')","metadata":{"execution":{"iopub.status.busy":"2024-03-08T14:28:54.973573Z","iopub.execute_input":"2024-03-08T14:28:54.974033Z","iopub.status.idle":"2024-03-08T14:30:02.881627Z","shell.execute_reply.started":"2024-03-08T14:28:54.974001Z","shell.execute_reply":"2024-03-08T14:30:02.880122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#sum of all the correctly classified samples/total num of samples","metadata":{},"execution_count":null,"outputs":[]}]}