{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# TODO's:\n* [ ] balance train_df with sklearn\n* [x] replace next two rows with sorted image names\n* [x] quality control - check for missing images in both variables\n* [ ] balance train_df with sklearn\n* [ ] balance batches (n, n) {0, 1} with Pytorch Samplers\n* [x] crop train and test images to 32 x 32 (from center)\n* [ ] multiply loss.item() by batch_size (because default reduction value in Loss function is mean)\n* [x] replace next two rows with sorted image names\n* [x] quality control - check for missing images in both variables \n* [x] make bigger batch size for validation","metadata":{}},{"cell_type":"markdown","source":"# Hello there!\nThis is my almost first try to create a notebook. The main reason for this is because I have never seen the guides, where is NN building was described ","metadata":{}},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\n\nfrom collections import Counter\nfrom tqdm.notebook import tqdm\n\nimport matplotlib.pyplot as plt\nfrom PIL import Image, ImageDraw\nimport torch\nimport torch.nn as nn\nfrom torchvision import utils\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.transforms as transforms\nfrom torch.utils.data import random_split\nfrom torch.cuda.amp import autocast\n\nimport gc\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-01-02T20:26:38.921641Z","iopub.execute_input":"2023-01-02T20:26:38.922619Z","iopub.status.idle":"2023-01-02T20:26:40.939121Z","shell.execute_reply.started":"2023-01-02T20:26:38.922518Z","shell.execute_reply":"2023-01-02T20:26:40.937676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Constants region\nDATA_DIR = \"../input/histopathologic-cancer-detection/\"\nTRAIN_LABELS = 'train_labels.csv'\n\nCENTER_SIZE = 32\nBATCH_SIZE = 64\nVALIDATION_BATCH_SIZE = 512","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:26:40.940960Z","iopub.execute_input":"2023-01-02T20:26:40.941573Z","iopub.status.idle":"2023-01-02T20:26:40.948082Z","shell.execute_reply.started":"2023-01-02T20:26:40.941533Z","shell.execute_reply":"2023-01-02T20:26:40.946759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Before running this cell on Kaggle.com, don't forget to change data_dir to kaggle_data_dir\ntrain_df: pd.DataFrame = pd.read_csv(DATA_DIR + TRAIN_LABELS)\nprint(train_df.info())\nprint(train_df.head())","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:40.950100Z","iopub.execute_input":"2023-01-02T20:26:40.951344Z","iopub.status.idle":"2023-01-02T20:26:41.532224Z","shell.execute_reply.started":"2023-01-02T20:26:40.951291Z","shell.execute_reply":"2023-01-02T20:26:41.531274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Check for duplicated values","metadata":{}},{"cell_type":"code","source":"print(train_df[train_df['id'].duplicated(keep=False)])","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.535135Z","iopub.execute_input":"2023-01-02T20:26:41.535816Z","iopub.status.idle":"2023-01-02T20:26:41.586113Z","shell.execute_reply.started":"2023-01-02T20:26:41.535781Z","shell.execute_reply":"2023-01-02T20:26:41.584950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Check if dataset is balanced","metadata":{}},{"cell_type":"code","source":"Counter(train_df['label'])","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.588000Z","iopub.execute_input":"2023-01-02T20:26:41.588651Z","iopub.status.idle":"2023-01-02T20:26:41.655731Z","shell.execute_reply.started":"2023-01-02T20:26:41.588615Z","shell.execute_reply":"2023-01-02T20:26:41.653179Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see, it is not balanced. Let's fix it. I choose to UNDERsample dataset because I don't know how to synthesis new values for images.","metadata":{}},{"cell_type":"code","source":"normal = train_df.loc[train_df['label'] == 0]\nmalignant = train_df.loc[train_df['label'] == 1]\n\nprint(set(Counter(normal['id']).values()))\nprint(set(Counter(malignant['id']).values()))","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.658143Z","iopub.execute_input":"2023-01-02T20:26:41.659172Z","iopub.status.idle":"2023-01-02T20:26:41.815848Z","shell.execute_reply.started":"2023-01-02T20:26:41.659132Z","shell.execute_reply":"2023-01-02T20:26:41.813308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"balance_size = len(malignant)","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.819992Z","iopub.execute_input":"2023-01-02T20:26:41.820276Z","iopub.status.idle":"2023-01-02T20:26:41.827991Z","shell.execute_reply.started":"2023-01-02T20:26:41.820249Z","shell.execute_reply":"2023-01-02T20:26:41.826760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal = normal.to_numpy()\nmalignant = malignant.to_numpy()\nprint(normal.shape, malignant.shape)","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.831806Z","iopub.execute_input":"2023-01-02T20:26:41.832076Z","iopub.status.idle":"2023-01-02T20:26:41.852091Z","shell.execute_reply.started":"2023-01-02T20:26:41.832052Z","shell.execute_reply":"2023-01-02T20:26:41.851124Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"normal = normal[:balance_size, :]","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.853742Z","iopub.execute_input":"2023-01-02T20:26:41.854442Z","iopub.status.idle":"2023-01-02T20:26:41.858955Z","shell.execute_reply.started":"2023-01-02T20:26:41.854405Z","shell.execute_reply":"2023-01-02T20:26:41.857941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(set(Counter(normal[:, 0]).values()))\nprint(set(Counter(malignant[:, 0]).values()))\nnormal_and_malignant = np.insert(normal, np.arange(len(normal)), malignant, axis=0)\nbalanced_train_df = pd.DataFrame(normal_and_malignant, columns=['id', 'label'])\nprint(balanced_train_df)","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.864576Z","iopub.execute_input":"2023-01-02T20:26:41.865347Z","iopub.status.idle":"2023-01-02T20:26:41.932315Z","shell.execute_reply.started":"2023-01-02T20:26:41.865279Z","shell.execute_reply":"2023-01-02T20:26:41.931192Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class HistopathologicCancerDS(Dataset):\n    def __init__(self,dataframe: pd.DataFrame, data_dir: str = DATA_DIR, dataset_type: str = \"train\", transform=None):\n        self.transform = transform\n        image_directory: str = os.path.join(data_dir, dataset_type)\n        image_names: list[str] = sorted(os.listdir(image_directory))\n        \n        sorted_df = dataframe.sort_values('id')\n        sorted_id_list = sorted_df['id'].to_numpy().tolist()\n        sorted_id_list = [x + '.tif' for x in sorted_id_list]\n        if sorted_id_list != image_names:\n            print(\"Dataframe and image directory contain different image names. Trying to find intersection between them.\")\n            intersected_image_names = np.intersect1d(sorted_id_list, image_names)\n            print(\"Intersection completed\")\n\n        self.abs_image_path = np.array([os.path.join(image_directory, image_name) for image_name in intersected_image_names])\n        image_names = list(map(lambda x: x[:-4], intersected_image_names))\n        self.labels = sorted_df[sorted_df['id'].isin(image_names)]['label'].to_numpy()\n        \n        print(\"Dataset is ready for use.\")\n        \n    def __len__(self):\n        return len(self.abs_image_path)\n    \n    def __getitem__(self, index):\n        with Image.open(self.abs_image_path[index]) as image:\n            transformed_image = self.transform(image)\n        return transformed_image, self.labels[index]\n        ","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.936187Z","iopub.execute_input":"2023-01-02T20:26:41.936562Z","iopub.status.idle":"2023-01-02T20:26:41.951723Z","shell.execute_reply.started":"2023-01-02T20:26:41.936519Z","shell.execute_reply":"2023-01-02T20:26:41.950579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_transformer = transforms.Compose([transforms.CenterCrop(CENTER_SIZE),\n                                     transforms.ToTensor(),\n                                     transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.954405Z","iopub.execute_input":"2023-01-02T20:26:41.955052Z","iopub.status.idle":"2023-01-02T20:26:41.966280Z","shell.execute_reply.started":"2023-01-02T20:26:41.955011Z","shell.execute_reply":"2023-01-02T20:26:41.965398Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = HistopathologicCancerDS(dataframe=balanced_train_df, transform=ds_transformer)","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:26:41.968022Z","iopub.execute_input":"2023-01-02T20:26:41.968699Z","iopub.status.idle":"2023-01-02T20:27:02.020031Z","shell.execute_reply.started":"2023-01-02T20:26:41.968661Z","shell.execute_reply":"2023-01-02T20:27:02.018716Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(dataset))","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:27:02.021813Z","iopub.execute_input":"2023-01-02T20:27:02.022348Z","iopub.status.idle":"2023-01-02T20:27:02.028722Z","shell.execute_reply.started":"2023-01-02T20:27:02.022288Z","shell.execute_reply":"2023-01-02T20:27:02.027635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample, label = dataset[0]\nprint(sample.shape, label)","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:27:02.030415Z","iopub.execute_input":"2023-01-02T20:27:02.031280Z","iopub.status.idle":"2023-01-02T20:27:02.065419Z","shell.execute_reply.started":"2023-01-02T20:27:02.031238Z","shell.execute_reply":"2023-01-02T20:27:02.064460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_len = len(dataset)\ntrain_size = int(0.9 * ds_len)\nvalidation_size = ds_len - train_size","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:27:02.066890Z","iopub.execute_input":"2023-01-02T20:27:02.067497Z","iopub.status.idle":"2023-01-02T20:27:02.072624Z","shell.execute_reply.started":"2023-01-02T20:27:02.067461Z","shell.execute_reply":"2023-01-02T20:27:02.071422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds, validation_ds = random_split(dataset, [train_size, validation_size])","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.074303Z","iopub.execute_input":"2023-01-02T20:27:02.074686Z","iopub.status.idle":"2023-01-02T20:27:02.095734Z","shell.execute_reply.started":"2023-01-02T20:27:02.074654Z","shell.execute_reply":"2023-01-02T20:27:02.094743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#TODO: make with class balance\nprint(f\"train dataset size: {len(train_ds)}, validation dataset size: {len(validation_ds)}\")\nprint(train_ds[0])","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.098743Z","iopub.execute_input":"2023-01-02T20:27:02.099013Z","iopub.status.idle":"2023-01-02T20:27:02.125076Z","shell.execute_reply.started":"2023-01-02T20:27:02.098988Z","shell.execute_reply":"2023-01-02T20:27:02.123895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plotting function\ndef image2plot(image) -> None:\n    image = image.numpy()\n    channel_last_image = np.transpose(image, (1, 2, 0))\n    plt.imshow(channel_last_image)","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.126705Z","iopub.execute_input":"2023-01-02T20:27:02.127045Z","iopub.status.idle":"2023-01-02T20:27:02.133404Z","shell.execute_reply.started":"2023-01-02T20:27:02.127011Z","shell.execute_reply":"2023-01-02T20:27:02.131036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_transformation = transforms.Compose([transforms.CenterCrop(CENTER_SIZE),\n                                           transforms.ToTensor(),\n                                           transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])\nvalidation_transformation = transforms.Compose([transforms.CenterCrop(CENTER_SIZE),\n                                                transforms.ToTensor(),\n                                                transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])\n                                               ])","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.135148Z","iopub.execute_input":"2023-01-02T20:27:02.135525Z","iopub.status.idle":"2023-01-02T20:27:02.145441Z","shell.execute_reply.started":"2023-01-02T20:27:02.135490Z","shell.execute_reply":"2023-01-02T20:27:02.144600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"random_train_sample, random_train_label = train_ds[np.random.randint(0, len(train_ds))]\nimage2plot(random_train_sample)\nprint(f\"label: {random_train_label}\")","metadata":{"execution":{"iopub.status.busy":"2023-01-02T20:27:02.147189Z","iopub.execute_input":"2023-01-02T20:27:02.148030Z","iopub.status.idle":"2023-01-02T20:27:02.368181Z","shell.execute_reply.started":"2023-01-02T20:27:02.147941Z","shell.execute_reply":"2023-01-02T20:27:02.367261Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dl = DataLoader(train_ds, batch_size=BATCH_SIZE, shuffle=True)\nvalidation_dl = DataLoader(validation_ds, batch_size=VALIDATION_BATCH_SIZE, shuffle=True)","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.369700Z","iopub.execute_input":"2023-01-02T20:27:02.370041Z","iopub.status.idle":"2023-01-02T20:27:02.375691Z","shell.execute_reply.started":"2023-01-02T20:27:02.370007Z","shell.execute_reply":"2023-01-02T20:27:02.374380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Helper function for evaluate shape after sequential module\ndef eval_shape(height, width, model, pool=0):\n    for layer in model.modules():\n        if isinstance(layer, nn.Conv2d) or isinstance(layer, nn.MaxPool2d):\n            kernel_size=layer.kernel_size\n            stride=layer.stride\n            padding=layer.padding\n            dilation=layer.dilation\n            if isinstance(layer, nn.Conv2d):\n                height = np.floor((height + 2 * padding[0] - dilation[0] * (kernel_size[0] - 1) - 1) / stride[0] + 1)\n                width = np.floor((width + 2 * padding[1] - dilation[1] * (kernel_size[1] - 1) - 1) / stride[1] + 1)\n            elif isinstance(layer, nn.MaxPool2d):\n                    height = np.floor((height + 2 * padding - dilation * (kernel_size - 1) - 1) / stride + 1)\n                    width = np.floor((width + 2 * padding - dilation * (kernel_size - 1) - 1) / stride + 1)\n            print(f\"layer {layer}: h: {height}, w: {width}\")\n    if pool:\n        height /= pool\n        width /= pool\n    return int(height),int(width)","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.377548Z","iopub.execute_input":"2023-01-02T20:27:02.377887Z","iopub.status.idle":"2023-01-02T20:27:02.390269Z","shell.execute_reply.started":"2023-01-02T20:27:02.377853Z","shell.execute_reply":"2023-01-02T20:27:02.389370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#TODO: (Done) build all NN step by step:\n#TODO: implement conv with relu module to make NN code more readable","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.393043Z","iopub.execute_input":"2023-01-02T20:27:02.393338Z","iopub.status.idle":"2023-01-02T20:27:02.400451Z","shell.execute_reply.started":"2023-01-02T20:27:02.393297Z","shell.execute_reply":"2023-01-02T20:27:02.399470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ConvWithReLU(nn.Module):\n    def __init__(self, in_channels: int, out_channels: int, kernel_size: int = 3, stride: int = 1):\n        super(ConvWithReLU, self).__init__()\n        self.block = nn.Sequential(nn.Conv2d(in_channels, out_channels, kernel_size, stride),\n                                   nn.ReLU())\n    def forward(self, x):\n        return self.block(x)\n","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.401739Z","iopub.execute_input":"2023-01-02T20:27:02.402301Z","iopub.status.idle":"2023-01-02T20:27:02.411065Z","shell.execute_reply.started":"2023-01-02T20:27:02.402268Z","shell.execute_reply":"2023-01-02T20:27:02.410079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CancerDetector(nn.Module):\n    def __init__(self):\n        super(CancerDetector, self).__init__()\n        self.conv_block = nn.Sequential(\n            ConvWithReLU(3, 32, 7),\n            ConvWithReLU(32, 64, 5),\n            ConvWithReLU(64, 128)\n        )\n        self.relu = nn.ReLU()\n        self.sigmoid = nn.Sigmoid()\n        h, w = eval_shape(32, 32, self.conv_block)\n        self.size = h * w\n        self.fc1 = nn.Linear(128 * self.size, 512)\n        self.fc2 = nn.Linear(512, 1)\n\n    def forward(self, x):\n        x = self.conv_block(x)\n        x = torch.flatten(x, 1)\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.fc2(x)\n#         x = self.sigmoid(x)\n        return x","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.412284Z","iopub.execute_input":"2023-01-02T20:27:02.413150Z","iopub.status.idle":"2023-01-02T20:27:02.423459Z","shell.execute_reply.started":"2023-01-02T20:27:02.413109Z","shell.execute_reply":"2023-01-02T20:27:02.422495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataloaders = {\n    'train': train_dl,\n    'validation': validation_dl\n}","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.424659Z","iopub.execute_input":"2023-01-02T20:27:02.425029Z","iopub.status.idle":"2023-01-02T20:27:02.434552Z","shell.execute_reply.started":"2023-01-02T20:27:02.424990Z","shell.execute_reply":"2023-01-02T20:27:02.433661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.optim import Adam\n\nclassifier = CancerDetector()\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = classifier.to(device)\noptimizer = Adam(model.parameters(), lr=1e-4)\ncriteria = nn.BCEWithLogitsLoss()","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:02.440015Z","iopub.execute_input":"2023-01-02T20:27:02.440263Z","iopub.status.idle":"2023-01-02T20:27:05.626395Z","shell.execute_reply.started":"2023-01-02T20:27:02.440240Z","shell.execute_reply":"2023-01-02T20:27:05.625382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stats = {\n    'train': {\n        'loss': [],\n        'accuracy': []\n    },\n    'validation': {\n        'loss': [],\n        'accuracy': []\n    }\n}","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:05.627707Z","iopub.execute_input":"2023-01-02T20:27:05.628444Z","iopub.status.idle":"2023-01-02T20:27:05.634275Z","shell.execute_reply.started":"2023-01-02T20:27:05.628398Z","shell.execute_reply":"2023-01-02T20:27:05.633222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_epoch(model,\n              dataloader,\n              criteria,\n              optimizer=None,\n              device=device):\n    running_loss = 0.0\n    running_accuracy = 0.0\n    number_of_samples = 0\n    for i, data in enumerate(tqdm(dataloader, desc='Batches')):\n        x, y = data\n        x = x.half().to(device)\n        y = y.to(device).float()\n        \n        sample_size = x.size(0)\n        \n        if optimizer:\n            optimizer.zero_grad()\n            \n        with autocast():\n            output = model(x).reshape(-1)\n            loss = criteria(output, y)\n        output = torch.sigmoid(output)\n        y = y.int()\n        output = (output >= 0.5) * 1\n        \n#         print(f\"output: {output}\"\n#               f\"target: {y}\")\n        \n        running_accuracy += torch.sum(output == y).item()\n        running_loss += float(loss.item() * sample_size)\n        number_of_samples += sample_size\n\n        if optimizer:\n            loss.backward()\n            optimizer.step()\n            \n        if torch.cuda.is_available():\n            del x, output, loss\n            gc.collect()\n            with torch.cuda.device(device):\n                torch.cuda.empty_cache()\n        \n    loss = running_loss / len(dataloader.dataset)\n    accuracy = running_accuracy / number_of_samples\n    return loss, accuracy","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:05.635834Z","iopub.execute_input":"2023-01-02T20:27:05.636164Z","iopub.status.idle":"2023-01-02T20:27:05.649603Z","shell.execute_reply.started":"2023-01-02T20:27:05.636130Z","shell.execute_reply":"2023-01-02T20:27:05.648643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model,\n          dataloaders,\n          criteria,\n          optimizer,\n          device,\n          epochs,\n          stats=stats):\n    print(\"Epochs\")\n    for epoch in tqdm(range(epochs), desc=\"Epochs\"):\n        avg_train_loss, avg_train_accuracy = one_epoch(model, dataloaders['train'], criteria, optimizer)\n        stats['train']['loss'].append(avg_train_loss)\n        stats['train']['accuracy'].append(avg_train_accuracy)\n        print(f\"Training average loss - {avg_train_loss}, average accuracy - {avg_train_accuracy}\")\n\n        with torch.no_grad():\n            avg_valid_loss, avg_valid_accuracy = one_epoch(model, dataloaders['validation'], criteria)\n        stats['validation']['loss'].append(avg_valid_loss)\n        stats['validation']['accuracy'].append(avg_valid_accuracy)\n        print(f\"Validation loss - {avg_valid_loss},  accuracy - {avg_valid_accuracy}\")\n","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:05.652289Z","iopub.execute_input":"2023-01-02T20:27:05.652750Z","iopub.status.idle":"2023-01-02T20:27:05.662288Z","shell.execute_reply.started":"2023-01-02T20:27:05.652704Z","shell.execute_reply":"2023-01-02T20:27:05.661362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train(model, dataloaders, criteria, optimizer, device, epochs=5)","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T20:27:05.663617Z","iopub.execute_input":"2023-01-02T20:27:05.664036Z","iopub.status.idle":"2023-01-02T21:45:30.668988Z","shell.execute_reply.started":"2023-01-02T20:27:05.664002Z","shell.execute_reply":"2023-01-02T21:45:30.664577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2)\nax1.plot(stats['train']['loss'], color='b', label='train')\nax1.plot(stats['validation']['loss'], color='g', label='validation')\nax1.set_title('Loss')\n\nax2.plot(stats['train']['accuracy'], color='b', label='train')\nax2.plot(stats['validation']['accuracy'], color='g', label='validation')\nax2.set_title('Accuracy')\n\nplt.legend()\nplt.show()\n","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2023-01-02T21:45:30.670262Z","iopub.execute_input":"2023-01-02T21:45:30.671038Z","iopub.status.idle":"2023-01-02T21:45:30.946122Z","shell.execute_reply.started":"2023-01-02T21:45:30.671000Z","shell.execute_reply":"2023-01-02T21:45:30.945271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), \"./HCD-v3-3CONV\")","metadata":{"execution":{"iopub.status.busy":"2023-01-02T21:45:30.947581Z","iopub.execute_input":"2023-01-02T21:45:30.947917Z","iopub.status.idle":"2023-01-02T21:45:31.251857Z","shell.execute_reply.started":"2023-01-02T21:45:30.947883Z","shell.execute_reply":"2023-01-02T21:45:31.250887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}