{"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":"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","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-06-16T18:20:06.618339Z","iopub.execute_input":"2023-06-16T18:20:06.618696Z","iopub.status.idle":"2023-06-16T18:20:06.635576Z","shell.execute_reply.started":"2023-06-16T18:20:06.618667Z","shell.execute_reply":"2023-06-16T18:20:06.634437Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In this nootbok, I demostrated how to use UNet to perform the binary image segmentation task.\n\n## Steps:\n- Import Libaries\n- Load Data\n- Visualize the Sample Data\n- Define UNet Model\n- Training\n- Visualize Result","metadata":{}},{"cell_type":"markdown","source":"# Import Libaries","metadata":{}},{"cell_type":"code","source":"!pip install segmentation-models-pytorch\nimport segmentation_models_pytorch as smp\n","metadata":{"scrolled":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-06-16T18:20:06.637423Z","iopub.execute_input":"2023-06-16T18:20:06.638088Z","iopub.status.idle":"2023-06-16T18:20:30.704996Z","shell.execute_reply.started":"2023-06-16T18:20:06.638057Z","shell.execute_reply":"2023-06-16T18:20:30.704002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport random\n\nimport torch\nimport torch.nn as nn\nimport torch.optim as optim\nimport torchvision\nimport torchvision.utils as vutils\n\nfrom torch.optim.lr_scheduler import ReduceLROnPlateau, CosineAnnealingLR, StepLR, MultiStepLR, CyclicLR\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision import transforms as T, datasets as dset\nfrom sklearn.model_selection import train_test_split\nfrom matplotlib import pyplot as plt\n\nfrom zipfile import ZipFile\nfrom tqdm import tqdm\nfrom glob import glob\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:30.706649Z","iopub.execute_input":"2023-06-16T18:20:30.707031Z","iopub.status.idle":"2023-06-16T18:20:32.090621Z","shell.execute_reply.started":"2023-06-16T18:20:30.706976Z","shell.execute_reply":"2023-06-16T18:20:32.089582Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config","metadata":{}},{"cell_type":"code","source":"batch_size = 4\nn_iters = 10000\nepochs = 10\nlearning_rate = 0.0002\nn_workers = 2\n\n\nwidth = 256\nheight = 256\nchannels = 3\n\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n\nseed = 44\nrandom.seed(seed)\ntorch.manual_seed(seed)","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:32.094524Z","iopub.execute_input":"2023-06-16T18:20:32.094829Z","iopub.status.idle":"2023-06-16T18:20:32.171098Z","shell.execute_reply.started":"2023-06-16T18:20:32.094804Z","shell.execute_reply":"2023-06-16T18:20:32.169935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Data","metadata":{}},{"cell_type":"code","source":"# extract train data\nwith ZipFile('../input/carvana-image-masking-challenge/train.zip', 'r') as zf:\n    zf.extractall('../working')\n     \nwith ZipFile('../input/carvana-image-masking-challenge/train_masks.zip', 'r') as zf:\n    zf.extractall('../working')","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:32.172633Z","iopub.execute_input":"2023-06-16T18:20:32.172993Z","iopub.status.idle":"2023-06-16T18:20:41.830302Z","shell.execute_reply.started":"2023-06-16T18:20:32.172960Z","shell.execute_reply":"2023-06-16T18:20:41.829313Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":" class MyDataset(Dataset):\n    def __init__(self, root_dir: str, train=True, transforms=None):\n        super(MyDataset, self).__init__()\n        self.train = train\n        self.transforms = transforms\n        \n        file_path = root_dir + 'train/*.*'\n        file_mask_path = root_dir + 'train_masks/*.*'\n        \n        self.images = sorted(glob(file_path))\n        self.image_mask = sorted(glob(file_mask_path))\n        \n        # manually split the train/valid data\n        split_ratio = int(len(self.images) * 0.7)\n        if train:\n            self.images = self.images[:split_ratio]\n            self.image_mask = self.image_mask[:split_ratio]\n        else:\n            self.images = self.images[split_ratio:]\n            self.image_mask = self.image_mask[split_ratio:]\n        \n        \n    def __getitem__(self, index: int):\n        image = Image.open(self.images[index]).convert('RGB')\n        image_mask = Image.open(self.image_mask[index]).convert('L')\n\n        \n        if self.transforms:\n            image = self.transforms(image)\n            image_mask = self.transforms(image_mask)\n                        \n        return {'img': image, 'mask': image_mask}\n    \n    def __len__(self):\n        return len(self.images)\n    \n\ntransforms = T.Compose([\n    T.Resize((width, height)),\n    T.ToTensor(),\n#     T.Normalize(mean=[0.485, 0.456, 0.406],\n#                 std=[0.229, 0.224, 0.225]),\n#     T.RandomHorizontalFlip()\n])\ntrain_dataset = MyDataset(root_dir='../working/',\n                                 train=True,\n                                 transforms=transforms)\nval_dataset = MyDataset(root_dir='../working/',\n                                train=False,\n                                transforms=transforms)\n\ntrain_dataset_loader = DataLoader(dataset=train_dataset,\n                                 batch_size=batch_size,\n                                 shuffle=True,\n                                 num_workers=n_workers)\nval_dataset_loader = DataLoader(dataset=val_dataset,\n                                batch_size=batch_size,\n                                shuffle=True,\n                                num_workers=n_workers)\n\n        ","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:41.832936Z","iopub.execute_input":"2023-06-16T18:20:41.833632Z","iopub.status.idle":"2023-06-16T18:20:41.929520Z","shell.execute_reply.started":"2023-06-16T18:20:41.833597Z","shell.execute_reply":"2023-06-16T18:20:41.928629Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sample Data","metadata":{}},{"cell_type":"code","source":"samples = next(iter(train_dataset_loader))\n\nfig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, figsize=(12, 4))\nfig.tight_layout()\n\n\nax1.axis('off')\nax1.set_title('input image')\nax1.imshow(np.transpose(vutils.make_grid(samples['img'], padding=2).numpy(),\n                       (1, 2, 0)))\n\nax2.axis('off')\nax2.set_title('input mask')\nax2.imshow(np.transpose(vutils.make_grid(samples['mask'], padding=2).numpy(),\n                       (1, 2, 0)), cmap='gray')\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:41.931147Z","iopub.execute_input":"2023-06-16T18:20:41.931512Z","iopub.status.idle":"2023-06-16T18:20:43.324685Z","shell.execute_reply.started":"2023-06-16T18:20:41.931479Z","shell.execute_reply":"2023-06-16T18:20:43.323701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\n\n\nclass PositionalEncoding(nn.Module):\n    def __init__(self, d_model, height, width):\n        super().__init__()\n        self.height = height\n        self.width = width\n        self.pe = nn.Parameter(torch.randn(1, d_model, height, width))\n\n    def forward(self, x):\n        return x + self.pe[:, :, :x.size(2), :x.size(3)]\n\n\nclass TransformerEncoderLayer(nn.Module):\n    def __init__(self, d_model, nhead, dim_feedforward, dropout):\n        super().__init__()\n        self.self_attention = nn.MultiheadAttention(d_model, nhead)\n        self.feed_forward = nn.Sequential(\n            nn.Linear(d_model, dim_feedforward),\n            nn.ReLU(),\n            nn.Linear(dim_feedforward, d_model),\n        )\n        self.norm1 = nn.LayerNorm(d_model)\n        self.norm2 = nn.LayerNorm(d_model)\n        self.dropout = nn.Dropout(dropout)\n\n    def forward(self, src):\n        src2 = self.self_attention(src, src, src)[0]\n        src = src + self.dropout(src2)\n        src = self.norm1(src)\n        src2 = self.feed_forward(src)\n        src = src + self.dropout(src2)\n        src = self.norm2(src)\n        return src\n\n\nclass TransformerDecoderLayer(nn.Module):\n    def __init__(self, d_model, nhead, dim_feedforward, dropout):\n        super().__init__()\n        self.self_attention = nn.MultiheadAttention(d_model, nhead)\n        self.encoder_attention = nn.MultiheadAttention(d_model, nhead)\n        self.feed_forward = nn.Sequential(\n            nn.Linear(d_model, dim_feedforward),\n            nn.ReLU(),\n            nn.Linear(dim_feedforward, d_model),\n        )\n        self.norm1 = nn.LayerNorm(d_model)\n        self.norm2 = nn.LayerNorm(d_model)\n        self.norm3 = nn.LayerNorm(d_model)\n        self.dropout = nn.Dropout(dropout)\n\n    def forward(self, memory,tgt):\n        tgt2 = self.self_attention(tgt, tgt, tgt)[0]\n        tgt = tgt + self.dropout(tgt2)\n        tgt = self.norm1(tgt)\n        tgt2 = self.encoder_attention(tgt, memory, memory)[0]\n        tgt = tgt + self.dropout(tgt2)\n        tgt = self.norm2(tgt)\n        tgt2 = self.feed_forward(tgt)\n        tgt = tgt + self.dropout(tgt2)\n        tgt = self.norm3(tgt)\n        return tgt\n\nclass TransformerSegmentationModel(nn.Module):\n    def __init__(\n        self,\n        in_channels=3,\n        out_channels=64,\n        d_model=512,\n        nhead=8,\n        dim_feedforward=2048,\n        num_encoder_layers=6,\n        num_decoder_layers=6,\n        dropout=0.1,\n        height=256,\n        width=256,\n    ):\n        super().__init__()\n\n        self.encoder = nn.ModuleList(\n            [\n                TransformerEncoderLayer(d_model, nhead, dim_feedforward, dropout)\n                for _ in range(num_encoder_layers)\n            ]\n        )\n        self.decoder = nn.ModuleList(\n            [\n                TransformerDecoderLayer(d_model, nhead, dim_feedforward, dropout)\n                for _ in range(num_decoder_layers)\n            ]\n        )\n        self.positional_encoding = PositionalEncoding(d_model, height, width)\n        self.fc = nn.Conv2d(d_model, out_channels, kernel_size=1)\n\n    def forward(self, x):\n        x = self.positional_encoding(x)\n        for encoder_layer in self.encoder:\n            x = encoder_layer(x)\n        for decoder_layer in self.decoder:\n            x = decoder_layer(x, x)\n        x = self.fc(x)\n        return x\n","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:43.325956Z","iopub.execute_input":"2023-06-16T18:20:43.326332Z","iopub.status.idle":"2023-06-16T18:20:43.351573Z","shell.execute_reply.started":"2023-06-16T18:20:43.326292Z","shell.execute_reply":"2023-06-16T18:20:43.350636Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Mymodel(nn.Module):\n    def _enc_layer(self, in_channels, out_channels):\n        return nn.Sequential(\n            nn.Conv2d(in_channels, out_channels, kernel_size=(3, 3), padding=(1, 1)),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True),\n        )\n    \n    def _dec_layer(self, in_channels, out_channels):\n        return nn.Sequential(\n            nn.ConvTranspose2d(in_channels, out_channels, kernel_size=(3, 3), padding=(1, 1)),\n            nn.BatchNorm2d(out_channels),\n            nn.ReLU(inplace=True),\n        )\n  \n    def __init__(self):\n        super().__init__()\n\n        # encoder (downsampling)\n        # Each enc_conv/dec_conv block should look like this:\n        # nn.Sequential(\n        #     nn.Conv2d(...),\n        #     ... (2 or 3 conv layers with relu and batchnorm),\n        # )\n\n        self.enc_conv0 = nn.Sequential(self._enc_layer(3, 64))\n        self.pool0 = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True) # 256 -> 128\n        self.enc_conv1 = nn.Sequential(self._enc_layer(64, 128))\n        self.pool1 = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True) # 128 -> 64\n        self.enc_conv2 = nn.Sequential(self._enc_layer(128, 256))\n        self.pool2 = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True) # 64 -> 32\n        self.enc_conv3 = nn.Sequential(self._enc_layer(256, 512))\n        self.pool3 = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True) # 32 -> 16\n        \n        self.transformer = nn.Transformer()\n\n        # decoder (upsampling)\n        self.upsample0 = nn.MaxUnpool2d(kernel_size=2, stride=2) # 16 -> 32\n        self.dec_conv0 = nn.Sequential(self._dec_layer(512, 256))\n        self.upsample1 = nn.MaxUnpool2d(kernel_size=2, stride=2) # 32 -> 64\n        self.dec_conv1 = nn.Sequential(self._dec_layer(256, 128))\n        self.upsample2 = nn.MaxUnpool2d(kernel_size=2, stride=2) # 64 -> 128\n        self.dec_conv2 = nn.Sequential(self._dec_layer(128, 64))\n        self.upsample3 = nn.MaxUnpool2d(kernel_size=2, stride=2) # 128 -> 256\n        self.dec_conv3 = nn.Sequential(\n            self._dec_layer(64, 64),\n            nn.ConvTranspose2d(64, 1, kernel_size=(3, 3), padding=(1, 1)),\n            # nn.BatchNorm2d(1, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True),\n            # nn.ReLU(inplace=True)\n       )\n\n    '''def forward(self, x):\n        # encoder\n        e0, idx0 = self.pool0(self.enc_conv0(x))\n        e1, idx1 = self.pool1(self.enc_conv1(e0))\n        e2, idx2 = self.pool2(self.enc_conv2(e1))\n        e3, idx3 = self.pool3(self.enc_conv3(e2))\n\n        t1 = self.transformer(e3,e3)\n        \n        # decoder\n        d0 = self.dec_conv0(self.upsample0(e3, idx3))\n        d1 = self.dec_conv1(self.upsample1(d0, idx2))\n        d2 = self.dec_conv2(self.upsample2(d1, idx1))\n        d3 = self.dec_conv3(self.upsample3(d2, idx0))\n        d3 = F.sigmoid(d3)\n        return d3'''\n    def forward(self, x):\n        e0, idx0 = self.pool0(self.enc_conv0(x))\n        e1, idx1 = self.pool1(self.enc_conv1(e0))\n        e2, idx2 = self.pool2(self.enc_conv2(e1))\n        e3, idx3 = self.pool3(self.enc_conv3(e2))\n\n    # reshape the encoder output to match the expected dimensions of the transformer\n        b, c, h, w = e3.size()\n        e3 = e3.view(b, c, h * w).permute(2, 0, 1)  # reshape to (h*w, b, c)\n\n    # apply the transformer to the reshaped encoder output\n        t1 = self.transformer(e3, e3)\n\n    # reshape the transformer output back to the original shape\n        t1 = t1.permute(1, 2, 0).view(b, c, h, w)\n\n    # decoder\n        d0 = self.dec_conv0(self.upsample0(t1, idx3))\n        d1 = self.dec_conv1(self.upsample1(d0, idx2))\n        d2 = self.dec_conv2(self.upsample2(d1, idx1))\n        d3 = self.dec_conv3(self.upsample3(d2, idx0))\n        d3 = torch.sigmoid(d3)\n        return d3\n","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:43.353105Z","iopub.execute_input":"2023-06-16T18:20:43.353471Z","iopub.status.idle":"2023-06-16T18:20:43.373154Z","shell.execute_reply.started":"2023-06-16T18:20:43.353438Z","shell.execute_reply":"2023-06-16T18:20:43.372307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"It is a binary segmentation problem. We use *BCEWithLogitsLoss* loss function. You can change the loss function to *BCELoss* by adding sigmoid layer to the output.","metadata":{}},{"cell_type":"markdown","source":"# Metrics","metadata":{}},{"cell_type":"code","source":"def dice_score(pred: torch.Tensor, mask: torch.Tensor):\n    dice = (2 * (pred * mask).sum()) / (pred + mask).sum()\n    return np.mean(dice.cpu().numpy())\n\ndef iou_score(pred: torch.Tensor, mask: torch.Tensor):\n    intersection = torch.logical_and(pred, mask).sum()\n    union = torch.logical_or(pred, mask).sum()\n    iou = intersection.float() / union.float()\n    return iou\n\ndef pixel_accuracy(pred: torch.Tensor, mask: torch.Tensor):\n    correct = torch.eq(pred, mask).int()\n    return float(correct.sum()) / float(correct.numel())","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:43.376621Z","iopub.execute_input":"2023-06-16T18:20:43.377143Z","iopub.status.idle":"2023-06-16T18:20:43.388984Z","shell.execute_reply.started":"2023-06-16T18:20:43.377110Z","shell.execute_reply":"2023-06-16T18:20:43.388270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train","metadata":{}},{"cell_type":"code","source":"def plot_pred_img(samples, pred):\n    fig, (ax1, ax2, ax3) = plt.subplots(nrows=3, ncols=1, figsize=(12, 6))\n    fig.tight_layout()\n\n\n    ax1.axis('off')\n    ax1.set_title('input image')\n    ax1.imshow(np.transpose(vutils.make_grid(samples['img'], padding=2).numpy(),\n                           (1, 2, 0)))\n\n    ax2.axis('off')\n    ax2.set_title('input mask')\n    ax2.imshow(np.transpose(vutils.make_grid(samples['mask'], padding=2).numpy(),\n                           (1, 2, 0)), cmap='gray')\n    \n    ax3.axis('off')\n    ax3.set_title('predicted mask')\n    ax3.imshow(np.transpose(vutils.make_grid(pred, padding=2).cpu().numpy(),\n                           (1, 2, 0)), cmap='gray')\n\n    plt.show()\n    \n    \ndef plot_train_progress(model):\n#     model.eval()\n\n#     with torch.no_grad():\n    samples = next(iter(val_dataset_loader))\n    val_img = samples['img'].to(device)\n    val_mask = samples['mask'].to(device)\n\n    pred = model(val_img)\n\n\n    plot_pred_img(samples, pred.detach())","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:20:43.390202Z","iopub.execute_input":"2023-06-16T18:20:43.390756Z","iopub.status.idle":"2023-06-16T18:20:43.404870Z","shell.execute_reply.started":"2023-06-16T18:20:43.390724Z","shell.execute_reply":"2023-06-16T18:20:43.404240Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model, optimizer, criteration, scheduler=None):\n    train_losses = []\n    val_lossess = []\n    lr_rates = []\n    \n    # calculate train epochs\n    epochs = int(n_iters / (len(train_dataset) / batch_size))\n\n\n    for epoch in range(epochs):\n        model.train()        \n        train_total_loss = 0\n        train_iterations = 0\n        \n        for idx, img_mask in enumerate(tqdm(train_dataset_loader)):\n            train_iterations += 1\n            train_img = samples['img'].float().to(device)\n            train_mask = samples['mask'].float().to(device)\n            \n            optimizer.zero_grad()\n            # speed up the training\n            with torch.autocast(device_type='cuda'):\n                train_output_mask = model(train_img)\n                train_loss = criterion(train_output_mask, train_mask)\n                train_total_loss += train_loss.item()\n\n            train_loss.backward()\n            optimizer.step()\n\n\n\n        train_epoch_loss = train_total_loss / train_iterations\n        train_losses.append(train_epoch_loss)\n        \n        # evaluate mode\n        model.eval()\n        with torch.no_grad():\n            val_total_loss = 0\n            val_iterations = 0\n            scores = 0\n            scores_Iou = 0\n            \n\n            for vidx, img_mask in enumerate(tqdm(val_dataset_loader)):\n                val_iterations += 1\n                val_img = samples['img'].float().to(device)\n                val_mask = samples['mask'].float().to(device)\n\n                with torch.autocast(device_type='cuda'):\n                    pred = model(val_img)\n                    val_loss = criterion(pred, val_mask)\n                    val_total_loss += val_loss.item()\n                    scores += dice_score(pred, val_mask)\n                    scores_Iou += iou_score(pred, val_mask)\n                    \n\n\n            val_epoch_loss = val_total_loss / val_iterations\n            dice_coef_scroe = scores / val_iterations\n            scores_Iou_coeff = scores_Iou / val_iterations\n            \n\n            val_lossess.append(val_epoch_loss)           \n\n            #plot_train_progress(model)\n            print('epochs - {}/{} [{}/{}], dice score: {}, train loss: {}, val loss: {}, IOU Score :{}'.format(\n                epoch+1, epochs,\n                idx+1, len(train_dataset_loader),\n                dice_coef_scroe, train_epoch_loss, val_epoch_loss,scores_Iou_coeff\n            )) \n            \n        lr_rates.append(optimizer.param_groups[0]['lr'])\n        if scheduler:\n            scheduler.step() # decay learning rate\n            print('LR rate:', scheduler.get_last_lr())\n            \n    return {\n        'lr': lr_rates,\n        'train_loss': train_losses,\n        'valid_loss': val_lossess\n    }","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:55:47.351678Z","iopub.execute_input":"2023-06-16T18:55:47.352306Z","iopub.status.idle":"2023-06-16T18:55:47.367919Z","shell.execute_reply.started":"2023-06-16T18:55:47.352262Z","shell.execute_reply":"2023-06-16T18:55:47.366891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Mymodel().to(device)\ncriterion = nn.BCEWithLogitsLoss()\n# criterion = smp.losses.DiceLoss(mode='binary')\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\nhistory = train(model, optimizer, criterion)","metadata":{"execution":{"iopub.status.busy":"2023-06-16T18:55:47.753846Z","iopub.execute_input":"2023-06-16T18:55:47.754195Z","iopub.status.idle":"2023-06-16T19:39:13.249733Z","shell.execute_reply.started":"2023-06-16T18:55:47.754166Z","shell.execute_reply":"2023-06-16T19:39:13.248534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#accuracy\ndef pixel_accuracy(pred: torch.Tensor, mask: torch.Tensor):\n    correct = torch.eq(pred, val_mask).int()\n    return float(correct.sum()) / float(correct.numel())\n\ndef train_A(model, optimizer, criteration, scheduler=None):\n    train_losses = []\n    val_lossess = []\n    lr_rates = []\n    \n    # calculate train epochs\n    epochs = int(n_iters / (len(train_dataset) / batch_size))\n\n\n    for epoch in range(epochs):\n        model.train()        \n        train_total_loss = 0\n        train_iterations = 0\n        \n        for idx, img_mask in enumerate(tqdm(train_dataset_loader)):\n            train_iterations += 1\n            train_img = samples['img'].float().to(device)\n            train_mask = samples['mask'].float().to(device)\n            \n            optimizer.zero_grad()\n            # speed up the training\n            with torch.autocast(device_type='cuda'):\n                train_output_mask = model(train_img)\n                train_loss = criterion(train_output_mask, train_mask)\n                train_total_loss += train_loss.item()\n\n            train_loss.backward()\n            optimizer.step()\n\n\n\n        train_epoch_loss = train_total_loss / train_iterations\n        train_losses.append(train_epoch_loss)\n        \n        # evaluate mode\n        model.eval()\n        with torch.no_grad():\n            val_total_loss = 0\n            val_iterations = 0\n            scores_acc = 0\n\n            for vidx, img_mask in enumerate(tqdm(val_dataset_loader)):\n                val_iterations += 1\n                val_img = samples['img'].float().to(device)\n                val_mask = samples['mask'].float().to(device)\n                def pixel_accuracy(pred: torch.Tensor, mask: torch.Tensor):\n                    correct = torch.eq(pred, val_mask).int()\n                    return float(correct.sum()) / float(correct.numel())\n\n                with torch.autocast(device_type='cuda'):\n                    pred = model(val_img)\n                    scores_acc += pixel_accuracy(pred, val_mask)\n\n\n            scores_acc_coeff = scores_acc/ val_iterations\n                      \n\n            #plot_train_progress(model)\n            print('epochs - {}/{} [{}/{}], Accuracy : {}'.format(\n                epoch+1, epochs,\n                idx+1, len(train_dataset_loader),\n                scores_acc_coeff\n            )) \n            \n        lr_rates.append(optimizer.param_groups[0]['lr'])\n        if scheduler:\n            scheduler.step() # decay learning rate\n            print('LR rate:', scheduler.get_last_lr())\n            \n    return {\n        'lr': lr_rates,\n        'train_loss': train_losses,\n        'valid_loss': val_lossess\n    }","metadata":{"execution":{"iopub.status.busy":"2023-06-16T19:39:47.452480Z","iopub.execute_input":"2023-06-16T19:39:47.452906Z","iopub.status.idle":"2023-06-16T19:39:47.470871Z","shell.execute_reply.started":"2023-06-16T19:39:47.452870Z","shell.execute_reply":"2023-06-16T19:39:47.469986Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Mymodel().to(device)\ncriterion = nn.BCEWithLogitsLoss()\n# criterion = smp.losses.DiceLoss(mode='binary')\noptimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)\n\nhistory = train_A(model, optimizer, criterion)","metadata":{"execution":{"iopub.status.busy":"2023-06-16T19:41:09.176341Z","iopub.execute_input":"2023-06-16T19:41:09.176737Z","iopub.status.idle":"2023-06-16T20:26:26.710838Z","shell.execute_reply.started":"2023-06-16T19:41:09.176708Z","shell.execute_reply":"2023-06-16T20:26:26.709715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Result","metadata":{}},{"cell_type":"code","source":"plt.plot(history['train_loss'], label='constant LR train loss')\nplt.plot(history['valid_loss'], label='constant LR val loss')\nplt.xlabel('epoch')\nplt.ylabel('loss')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-16T20:26:42.589859Z","iopub.execute_input":"2023-06-16T20:26:42.590277Z","iopub.status.idle":"2023-06-16T20:26:42.900362Z","shell.execute_reply.started":"2023-06-16T20:26:42.590239Z","shell.execute_reply":"2023-06-16T20:26:42.899345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}