{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":"nvidiaTeslaT4","dataSources":[{"sourceId":8988371,"sourceType":"datasetVersion","datasetId":5413423},{"sourceId":87339,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":73367,"modelId":98225},{"sourceId":91082,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":76357,"modelId":101037}],"dockerImageVersionId":30733,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install torch torchvision torchaudio","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:18.518161Z","iopub.execute_input":"2024-08-09T07:47:18.518425Z","iopub.status.idle":"2024-08-09T07:47:32.093091Z","shell.execute_reply.started":"2024-08-09T07:47:18.518401Z","shell.execute_reply":"2024-08-09T07:47:32.091955Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install torchsummary","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:32.094309Z","iopub.execute_input":"2024-08-09T07:47:32.094696Z","iopub.status.idle":"2024-08-09T07:47:44.479597Z","shell.execute_reply.started":"2024-08-09T07:47:32.094661Z","shell.execute_reply":"2024-08-09T07:47:44.478491Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torchsummary import summary\nimport torchvision.transforms.functional as TF\nimport torchvision\nfrom torchvision.models import ResNet50_Weights\nfrom torchvision import models\nimport matplotlib.pyplot as plt\nimport torchvision.transforms as transforms\nfrom PIL import Image\nimport numpy as np","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:44.482349Z","iopub.execute_input":"2024-08-09T07:47:44.482726Z","iopub.status.idle":"2024-08-09T07:47:49.131642Z","shell.execute_reply.started":"2024-08-09T07:47:44.482691Z","shell.execute_reply":"2024-08-09T07:47:49.130673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class ConvBlock(nn.Module):\n    \"\"\"\n    Helper module that consists of a Conv -> BN -> ReLU\n    \"\"\"\n\n    def __init__(self, in_channels, out_channels, padding=1, kernel_size=3, stride=1, with_nonlinearity=True):\n        super().__init__()\n        self.conv = nn.Conv2d(in_channels, out_channels, padding=padding, kernel_size=kernel_size, stride=stride)\n        self.bn = nn.BatchNorm2d(out_channels)\n        self.relu = nn.ReLU()\n        self.with_nonlinearity = with_nonlinearity\n\n    def forward(self, x):\n        x = self.conv(x)\n        x = self.bn(x)\n        if self.with_nonlinearity:\n            x = self.relu(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:49.137348Z","iopub.execute_input":"2024-08-09T07:47:49.137652Z","iopub.status.idle":"2024-08-09T07:47:49.144727Z","shell.execute_reply.started":"2024-08-09T07:47:49.137627Z","shell.execute_reply":"2024-08-09T07:47:49.143770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Bridge(nn.Module):\n    \"\"\"\n    This is the middle layer of the UNet which just consists of some\n    \"\"\"\n\n    def __init__(self, in_channels, out_channels):\n        super().__init__()\n        self.bridge = nn.Sequential(\n            ConvBlock(in_channels, out_channels),\n            ConvBlock(out_channels, out_channels)\n        )\n\n    def forward(self, x):\n        return self.bridge(x)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:49.145822Z","iopub.execute_input":"2024-08-09T07:47:49.146083Z","iopub.status.idle":"2024-08-09T07:47:49.154845Z","shell.execute_reply.started":"2024-08-09T07:47:49.146061Z","shell.execute_reply":"2024-08-09T07:47:49.153889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class UpBlockForUNetWithResNet50(nn.Module):\n    \"\"\"\n    Up block that encapsulates one up-sampling step which consists of Upsample -> ConvBlock -> ConvBlock\n    \"\"\"\n\n    def __init__(self, in_channels, out_channels, up_conv_in_channels=None, up_conv_out_channels=None,\n                 upsampling_method=\"conv_transpose\"):\n        super().__init__()\n\n        if up_conv_in_channels == None:\n            up_conv_in_channels = in_channels\n        if up_conv_out_channels == None:\n            up_conv_out_channels = out_channels\n\n        if upsampling_method == \"conv_transpose\":\n            self.upsample = nn.ConvTranspose2d(up_conv_in_channels, up_conv_out_channels, kernel_size=2, stride=2)\n        elif upsampling_method == \"bilinear\":\n            self.upsample = nn.Sequential(\n                nn.Upsample(mode='bilinear', scale_factor=2),\n                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1)\n            )\n        self.conv_block_1 = ConvBlock(in_channels, out_channels)\n        self.conv_block_2 = ConvBlock(out_channels, out_channels)\n\n    def forward(self, up_x, down_x):\n        \"\"\"\n\n        :param up_x: this is the output from the previous up block\n        :param down_x: this is the output from the down block\n        :return: upsampled feature map\n        \"\"\"\n        x = self.upsample(up_x)\n        x = torch.cat([x, down_x], 1)\n        x = self.conv_block_1(x)\n        x = self.conv_block_2(x)\n        return x","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:49.155957Z","iopub.execute_input":"2024-08-09T07:47:49.156314Z","iopub.status.idle":"2024-08-09T07:47:49.166774Z","shell.execute_reply.started":"2024-08-09T07:47:49.156277Z","shell.execute_reply":"2024-08-09T07:47:49.165851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class UNetWithResnet50Encoder(nn.Module):\n    DEPTH = 6\n\n    def __init__(self, n_classes=2):\n        super().__init__()\n        resnet = torchvision.models.resnet.resnet50(weights=ResNet50_Weights.DEFAULT)\n        down_blocks = []\n        up_blocks = []\n        self.input_block = nn.Sequential(*list(resnet.children()))[:3]\n        self.input_pool = list(resnet.children())[3]\n        for bottleneck in list(resnet.children()):\n            if isinstance(bottleneck, nn.Sequential):\n                down_blocks.append(bottleneck)\n        self.down_blocks = nn.ModuleList(down_blocks)\n        self.bridge = Bridge(2048, 2048)\n        up_blocks.append(UpBlockForUNetWithResNet50(2048, 1024))\n        up_blocks.append(UpBlockForUNetWithResNet50(1024, 512))\n        up_blocks.append(UpBlockForUNetWithResNet50(512, 256))\n        up_blocks.append(UpBlockForUNetWithResNet50(in_channels=128 + 64, out_channels=128,\n                                                    up_conv_in_channels=256, up_conv_out_channels=128))\n        up_blocks.append(UpBlockForUNetWithResNet50(in_channels=64 + 3, out_channels=64,\n                                                    up_conv_in_channels=128, up_conv_out_channels=64))\n\n        self.up_blocks = nn.ModuleList(up_blocks)\n\n        self.out = nn.Conv2d(64, 1, kernel_size=1, stride=1)\n\n    def forward(self, x, with_output_feature_map=False):\n        pre_pools = dict()\n        pre_pools[f\"layer_0\"] = x\n        x = self.input_block(x)\n        pre_pools[f\"layer_1\"] = x\n        x = self.input_pool(x)\n\n        for i, block in enumerate(self.down_blocks, 2):\n            x = block(x)\n            if i == (UNetWithResnet50Encoder.DEPTH - 1):\n                continue\n            pre_pools[f\"layer_{i}\"] = x\n\n        x = self.bridge(x)\n\n        for i, block in enumerate(self.up_blocks, 1):\n            key = f\"layer_{UNetWithResnet50Encoder.DEPTH - 1 - i}\"\n            x = block(x, pre_pools[key])\n        output_feature_map = x\n        x = self.out(x)\n        del pre_pools\n        if with_output_feature_map:\n            return x, output_feature_map\n        else:\n            return x","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:49.169364Z","iopub.execute_input":"2024-08-09T07:47:49.169981Z","iopub.status.idle":"2024-08-09T07:47:49.182731Z","shell.execute_reply.started":"2024-08-09T07:47:49.169946Z","shell.execute_reply":"2024-08-09T07:47:49.181888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = UNetWithResnet50Encoder()\ninp = torch.rand((2, 3, 512, 512))\nout = model(inp)\nprint(out.shape)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:47:49.183653Z","iopub.execute_input":"2024-08-09T07:47:49.183916Z","iopub.status.idle":"2024-08-09T07:47:58.222465Z","shell.execute_reply.started":"2024-08-09T07:47:49.183882Z","shell.execute_reply":"2024-08-09T07:47:58.221430Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Split Image","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def split_image(image_path, tile_size):\n#     \"\"\"\n#     Splits an image into smaller tiles of the specified size.\n\n#     :param image_path: Path to the input image.\n#     :param tile_size: Size of each tile (tile_size x tile_size).\n#     :return: List of image tiles.\n#     \"\"\"\n#     image = Image.open(image_path)\n#     image_np = np.array(image)\n    \n#     tiles = []\n#     height, width = image_np.shape[:2]\n    \n#     for y in range(0, height, tile_size):\n#         for x in range(0, width, tile_size):\n#             tile = image_np[y:y+tile_size, x:x+tile_size]\n#             tiles.append(Image.fromarray(tile))\n    \n#     return tiles","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:02:15.774554Z","iopub.execute_input":"2024-08-07T16:02:15.774915Z","iopub.status.idle":"2024-08-07T16:02:15.779609Z","shell.execute_reply.started":"2024-08-07T16:02:15.774888Z","shell.execute_reply":"2024-08-07T16:02:15.778527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def split_images(image_paths, label_paths, tile_size):\n#     \"\"\"\n#     Splits a list of input images and their corresponding labels into smaller tiles.\n\n#     :param image_paths: List of paths to the input images.\n#     :param label_paths: List of paths to the label images.\n#     :param tile_size: Size of each tile (tile_size x tile_size).\n#     :return: Tuple containing lists of image tiles and label tiles.\n#     \"\"\"\n#     all_image_tiles = []\n#     all_label_tiles = []\n\n#     for image_path, label_path in zip(image_paths, label_paths):\n#         image_tiles = split_image(image_path, tile_size)\n#         label_tiles = split_image(label_path, tile_size)\n        \n#         all_image_tiles.extend(image_tiles)\n#         all_label_tiles.extend(label_tiles)\n    \n#     return all_image_tiles, all_label_tiles","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:02:15.780643Z","iopub.execute_input":"2024-08-07T16:02:15.780914Z","iopub.status.idle":"2024-08-07T16:02:15.791849Z","shell.execute_reply.started":"2024-08-07T16:02:15.780890Z","shell.execute_reply":"2024-08-07T16:02:15.791019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# label_paths = ['img/label/Caugiay_1.1.png', 'img/label/Caugiay_1.2.png', 'img/label/Caugiay_1.3.png']\n# image_paths = ['img/normal/Caugiay_1.1.png', 'img/normal/Caugiay_1.2.png', 'img/normal/Caugiay_1.3.png']\n# tile_size = 512\n\n# image_tiles, label_tiles = split_images(image_paths, label_paths, tile_size)\n\n","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:02:15.793134Z","iopub.execute_input":"2024-08-07T16:02:15.793508Z","iopub.status.idle":"2024-08-07T16:02:15.800679Z","shell.execute_reply.started":"2024-08-07T16:02:15.793445Z","shell.execute_reply":"2024-08-07T16:02:15.799828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import os\n\n# # Create the dataset directory if it doesn't exist\n# dataset_dir = 'dataset'\n# os.makedirs(dataset_dir, exist_ok=True)\n\n# # Create subdirectories for images and labels\n# images_dir = os.path.join(dataset_dir, 'images')\n# labels_dir = os.path.join(dataset_dir, 'labels')\n# os.makedirs(images_dir, exist_ok=True)\n# os.makedirs(labels_dir, exist_ok=True)\n\n# # Save the image tiles\n# for i, tile in enumerate(image_tiles):\n#     tile = tile.convert(\"RGB\")  # Convert to RGB before saving\n#     tile.save(os.path.join(images_dir, f'image_tile_{i}.jpg'))\n\n# # Save the label tiles\n# for i, tile in enumerate(label_tiles):\n#     tile = tile.convert(\"RGB\")  # Convert to RGB before saving\n#     tile.save(os.path.join(labels_dir, f'label_tile_{i}.jpg'))","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:02:15.801631Z","iopub.execute_input":"2024-08-07T16:02:15.801887Z","iopub.status.idle":"2024-08-07T16:02:15.810263Z","shell.execute_reply.started":"2024-08-07T16:02:15.801865Z","shell.execute_reply":"2024-08-07T16:02:15.808973Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load dataset","metadata":{}},{"cell_type":"code","source":"import os\nimport torch\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn.model_selection import train_test_split\nimport numpy as np","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:26.602120Z","iopub.execute_input":"2024-08-09T07:48:26.603137Z","iopub.status.idle":"2024-08-09T07:48:27.253356Z","shell.execute_reply.started":"2024-08-09T07:48:26.603093Z","shell.execute_reply":"2024-08-09T07:48:27.252603Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_dir = '/kaggle/input/rooftop/dataset/images'\nlabels_dir = '/kaggle/input/rooftop/dataset/labels'\n\n# List all image and label files\nall_images = sorted(os.listdir(images_dir))\nall_labels = sorted(os.listdir(labels_dir))\n\n# Split into train and temp (remaining) sets (80/20)\ntrain_images, temp_images = train_test_split(all_images, test_size=0.2, random_state=42)\ntrain_labels, temp_labels = train_test_split(all_labels, test_size=0.2, random_state=42)\n\n# Split temp into validation and test sets (50/50 of remaining 20%)\nval_images, test_images = train_test_split(temp_images, test_size=0.5, random_state=42)\nval_labels, test_labels = train_test_split(temp_labels, test_size=0.5, random_state=42)\n\n# Output the number of files in each set\nprint(f\"Training set: {len(train_images)} images\")\nprint(f\"Validation set: {len(val_images)} images\")\nprint(f\"Test set: {len(test_images)} images\")\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:37.599781Z","iopub.execute_input":"2024-08-09T07:48:37.600352Z","iopub.status.idle":"2024-08-09T07:48:38.299812Z","shell.execute_reply.started":"2024-08-09T07:48:37.600308Z","shell.execute_reply":"2024-08-09T07:48:38.298499Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, image_dir, label_dir, file_list, transform=None):\n        self.image_dir = image_dir\n        self.label_dir = label_dir\n        self.file_list = file_list\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.file_list)\n\n    def __getitem__(self, idx):\n        image_file = self.file_list[idx]\n        label_file = image_file.replace('image', 'label')  \n        image_path = os.path.join(self.image_dir, image_file)\n        label_path = os.path.join(self.label_dir, label_file)\n        image = Image.open(image_path).convert(\"RGB\")\n        label = Image.open(label_path).convert(\"L\") \n\n        if self.transform:\n            image = self.transform(image)\n            label = self.transform(label)\n\n        return image, label\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:38.545414Z","iopub.execute_input":"2024-08-09T07:48:38.546332Z","iopub.status.idle":"2024-08-09T07:48:38.554459Z","shell.execute_reply.started":"2024-08-09T07:48:38.546288Z","shell.execute_reply":"2024-08-09T07:48:38.553263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def display_images_and_labels(image_filenames, label_filenames, num_samples=2):\n    fig, axs = plt.subplots(num_samples, 2, figsize=(10, 5*num_samples))\n    for i in range(num_samples):\n        # Load image and label\n        img_path = os.path.join(images_dir, image_filenames[i])\n        lbl_path = os.path.join(labels_dir, label_filenames[i])\n        \n        img = Image.open(img_path)\n        lbl = Image.open(lbl_path)\n        \n        # Display image and label\n        axs[i, 0].imshow(np.array(img))\n        axs[i, 0].set_title('Image')\n        axs[i, 0].axis('off')\n\n        axs[i, 1].imshow(np.array(lbl))\n        axs[i, 1].set_title('Label')\n        axs[i, 1].axis('off')\n\n    plt.tight_layout()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:38.592310Z","iopub.execute_input":"2024-08-09T07:48:38.593103Z","iopub.status.idle":"2024-08-09T07:48:38.603143Z","shell.execute_reply.started":"2024-08-09T07:48:38.593067Z","shell.execute_reply":"2024-08-09T07:48:38.601991Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_labels = [f'label_tile_{i.split(\"_\")[-1]}' for i in train_images]\ndisplay_images_and_labels(train_images, train_labels, num_samples=2)\n\nvalidation_labels = [f'label_tile_{i.split(\"_\")[-1]}' for i in val_images]\ndisplay_images_and_labels(val_images, val_labels, num_samples=2)\n\ntest_labels = [f'label_tile_{i.split(\"_\")[-1]}' for i in test_images]\ndisplay_images_and_labels(test_images, test_labels, num_samples=2)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:38.605504Z","iopub.execute_input":"2024-08-09T07:48:38.605866Z","iopub.status.idle":"2024-08-09T07:48:41.157767Z","shell.execute_reply.started":"2024-08-09T07:48:38.605834Z","shell.execute_reply":"2024-08-09T07:48:41.156766Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform = transforms.Compose([\n    transforms.ToTensor(),\n    # Add more transformations here if necessary\n])\n\n# Create datasets\ntrain_dataset = CustomDataset(image_dir=images_dir, label_dir=labels_dir, file_list=train_images, transform=transform)\nval_dataset = CustomDataset(image_dir=images_dir, label_dir=labels_dir, file_list=val_images, transform=transform)\ntest_dataset = CustomDataset(image_dir=images_dir, label_dir=labels_dir, file_list=test_images, transform=transform)\n\n# Create DataLoaders\ntrain_loader = DataLoader(train_dataset, batch_size=8, shuffle=True, num_workers=4)\nval_loader = DataLoader(val_dataset, batch_size=8, shuffle=True, num_workers=4)\ntest_loader = DataLoader(test_dataset, batch_size=8, shuffle=False, num_workers=4)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:41.159112Z","iopub.execute_input":"2024-08-09T07:48:41.159473Z","iopub.status.idle":"2024-08-09T07:48:41.168173Z","shell.execute_reply.started":"2024-08-09T07:48:41.159427Z","shell.execute_reply":"2024-08-09T07:48:41.167223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\ndef check_dataloader(data_loader, num_samples=2):\n    for i, (images, labels) in enumerate(data_loader):\n        if i >= num_samples:\n            break\n        print(f'Sample batch {i+1}:')\n        for j in range(min(images.size(0), 2)):  # Limiting to at most 2 images per batch\n            img = transforms.ToPILImage()(images[j])\n            lbl = transforms.ToPILImage()(labels[j])\n            \n            fig, axs = plt.subplots(1, 2, figsize=(10, 5))\n            axs[0].imshow(img)\n            axs[0].set_title('Image')\n            axs[0].axis('off')\n            \n            axs[1].imshow(lbl, cmap='gray')\n            axs[1].set_title('Label')\n            axs[1].axis('off')\n            \n            plt.show()\n\n# Check train loader\ncheck_dataloader(train_loader, num_samples=1)\n\n\n# Check test loader\ncheck_dataloader(val_loader, num_samples=1)\n\n# Check test loader\ncheck_dataloader(test_loader, num_samples=1)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:41.169306Z","iopub.execute_input":"2024-08-09T07:48:41.169658Z","iopub.status.idle":"2024-08-09T07:48:45.784210Z","shell.execute_reply.started":"2024-08-09T07:48:41.169629Z","shell.execute_reply":"2024-08-09T07:48:45.783321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train model","metadata":{}},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torch.optim as optim\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:45.787202Z","iopub.execute_input":"2024-08-09T07:48:45.787680Z","iopub.status.idle":"2024-08-09T07:48:45.792397Z","shell.execute_reply.started":"2024-08-09T07:48:45.787641Z","shell.execute_reply":"2024-08-09T07:48:45.791490Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\nmodel = UNetWithResnet50Encoder().to(device)\n\n# model.load_state_dict(torch.load('/kaggle/input/mse-loss-unet/pytorch/default/1/4_batch_MSE_30_epochs.pth'))\n# model.to(device)\n\n# Định nghĩa criterion và optimizer như trước\ncriterion = nn.BCEWithLogitsLoss() \n# criterion = nn.MSELoss()\n\n\noptimizer = optim.Adam(model.parameters(), lr=0.0001)\n# optimizer = optim.SGD(model.parameters(), lr=0.01, momentum=0.9, weight_decay=1e-4)","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:45.793749Z","iopub.execute_input":"2024-08-09T07:48:45.794383Z","iopub.status.idle":"2024-08-09T07:48:47.942260Z","shell.execute_reply.started":"2024-08-09T07:48:45.794340Z","shell.execute_reply":"2024-08-09T07:48:47.941289Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:47.943462Z","iopub.execute_input":"2024-08-09T07:48:47.943763Z","iopub.status.idle":"2024-08-09T07:48:47.947823Z","shell.execute_reply.started":"2024-08-09T07:48:47.943738Z","shell.execute_reply":"2024-08-09T07:48:47.946896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score\nfrom torch.nn.functional import softmax","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:47.949096Z","iopub.execute_input":"2024-08-09T07:48:47.949431Z","iopub.status.idle":"2024-08-09T07:48:47.956819Z","shell.execute_reply.started":"2024-08-09T07:48:47.949401Z","shell.execute_reply":"2024-08-09T07:48:47.955921Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Hàm tính toán IoU\ndef compute_iou(preds, labels, num_classes):\n    ious = []\n    for i in range(num_classes):\n        pred_i = (preds == i).astype(np.float32)\n        label_i = (labels == i).astype(np.float32)\n        \n        intersection = np.sum(pred_i * label_i)\n        union = np.sum(pred_i) + np.sum(label_i) - intersection\n        \n        iou = intersection / (union + 1e-6)  # Thêm epsilon để tránh chia cho 0\n        ious.append(iou)\n    \n    return np.mean(ious)\n\nnum_classes = 2  # Số lớp phân loại","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:47.958067Z","iopub.execute_input":"2024-08-09T07:48:47.958416Z","iopub.status.idle":"2024-08-09T07:48:47.966111Z","shell.execute_reply.started":"2024-08-09T07:48:47.958385Z","shell.execute_reply":"2024-08-09T07:48:47.965271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\nnum_epochs = 30\ntrain_losses = []\nval_losses = []\ntrain_f1_scores = []\nval_f1_scores = []\ntrain_ious = []\nval_ious = []\n\nfor epoch in range(num_epochs):\n    model.train()\n    running_train_loss = 0.0\n    all_train_preds = []\n    all_train_labels = []\n    \n    for images, labels in train_loader:\n        images, labels = images.to(device), labels.to(device)\n        \n        optimizer.zero_grad()\n        outputs = model(images)\n        loss = criterion(outputs, labels)\n        loss.backward()\n        optimizer.step()\n         \n        running_train_loss += loss.item() * images.size(0)\n        all_train_preds.append(outputs.cpu())\n        all_train_labels.append(labels.cpu())\n    \n    epoch_train_loss = running_train_loss / len(train_loader.dataset)\n    train_losses.append(epoch_train_loss)\n\n    # Tính toán IoU và F1 Score cho tập huấn luyện\n    all_train_preds = torch.cat(all_train_preds)\n    all_train_labels = torch.cat(all_train_labels)\n    all_train_preds = all_train_preds.detach().numpy()  # Không cần sigmoid vì BCE đã bao gồm sigmoid\n    all_train_labels = all_train_labels.detach().numpy()\n    threshold = 0.5\n    binary_train_preds = (all_train_preds > threshold).astype(np.float32)\n    binary_train_labels = (all_train_labels > threshold).astype(np.float32)\n    train_iou = compute_iou(binary_train_preds, binary_train_labels, num_classes)\n    train_f1 = f1_score(binary_train_labels.flatten(), binary_train_preds.flatten())\n    train_ious.append(train_iou)\n    train_f1_scores.append(train_f1)\n\n    model.eval()\n    running_val_loss = 0.0\n    all_val_preds = []\n    all_val_labels = []\n    \n    with torch.no_grad():\n        for images, labels in val_loader:\n            images, labels = images.to(device), labels.to(device)\n            \n            outputs = model(images)\n            loss = criterion(outputs, labels)\n            \n            running_val_loss += loss.item() * images.size(0)\n            all_val_preds.append(outputs.cpu())\n            all_val_labels.append(labels.cpu())\n    \n    epoch_val_loss = running_val_loss / len(val_loader.dataset)\n    val_losses.append(epoch_val_loss)\n\n    # Tính toán IoU và F1 Score cho tập xác thực\n    all_val_preds = torch.cat(all_val_preds)\n    all_val_labels = torch.cat(all_val_labels)\n    all_val_preds = all_val_preds.detach().numpy() \n    all_val_labels = all_val_labels.detach().numpy()\n    binary_val_preds = (all_val_preds > threshold).astype(np.float32)\n    binary_val_labels = (all_val_labels > threshold).astype(np.float32)\n    val_iou = compute_iou(binary_val_preds, binary_val_labels, num_classes)\n    val_f1 = f1_score(binary_val_labels.flatten(), binary_val_preds.flatten())\n    val_ious.append(val_iou)\n    val_f1_scores.append(val_f1)\n\n    # In ra kết quả\n    print(f'Epoch {epoch+1}/{num_epochs}, '\n          f'Train Loss: {epoch_train_loss:.4f}, Train IOU: {train_iou:.4f}, Train F1: {train_f1:.4f}, '\n          f'Val Loss: {epoch_val_loss:.4f}, Val IOU: {val_iou:.4f}, Val F1: {val_f1:.4f}')\n    \n    if (epoch + 1) % 10 == 0:\n        filename = f'/kaggle/working/unet_model_BCE_{epoch + 1}_epochs.pth'\n        torch.save(model.state_dict(), filename)\n        print(f'Model saved as {filename}')\n\n    torch.cuda.empty_cache()\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T07:48:47.967323Z","iopub.execute_input":"2024-08-09T07:48:47.967645Z","iopub.status.idle":"2024-08-09T12:04:11.248259Z","shell.execute_reply.started":"2024-08-09T07:48:47.967622Z","shell.execute_reply":"2024-08-09T12:04:11.246959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(range(1, num_epochs + 1), train_losses, marker='o', label='Train Loss')\nplt.plot(range(1, num_epochs + 1), val_losses, marker='x', label='Validation Loss', linestyle='--')\n\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.title('Training and Validation Loss Over Epochs')\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:11:52.253960Z","iopub.execute_input":"2024-08-09T12:11:52.254247Z","iopub.status.idle":"2024-08-09T12:11:52.532889Z","shell.execute_reply.started":"2024-08-09T12:11:52.254221Z","shell.execute_reply":"2024-08-09T12:11:52.532009Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(range(1, num_epochs + 1), train_f1_scores, marker='o', label='Train F1 Score')\nplt.plot(range(1, num_epochs + 1), val_f1_scores, marker='x', label='Validation F1 Score', linestyle='--')\n\nplt.xlabel('Epoch')\nplt.ylabel('F1 Score')\nplt.title('Training and Validation F1 Score Over Epochs')\nplt.legend()\nplt.grid(True)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:08:30.142099Z","iopub.execute_input":"2024-08-09T12:08:30.142382Z","iopub.status.idle":"2024-08-09T12:08:30.467678Z","shell.execute_reply.started":"2024-08-09T12:08:30.142351Z","shell.execute_reply":"2024-08-09T12:08:30.466795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(range(1, num_epochs + 1), train_ious, marker='o', label='Train IoU')\nplt.plot(range(1, num_epochs + 1), val_ious, marker='x', label='Validation IoU', linestyle='--')\n\nplt.xlabel('Epoch')\nplt.ylabel('IoU')\nplt.title('Training and Validation IoU Over Epochs')\nplt.legend()\nplt.grid(True)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:08:30.468904Z","iopub.execute_input":"2024-08-09T12:08:30.469221Z","iopub.status.idle":"2024-08-09T12:08:30.787092Z","shell.execute_reply.started":"2024-08-09T12:08:30.469195Z","shell.execute_reply":"2024-08-09T12:08:30.786233Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.eval()\n\n# Collect predictions and labels\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():\n    for images, labels in val_loader:\n        images, labels = images.to(device), labels.to(device)\n        outputs = model(images)\n        \n        all_preds.append(outputs.cpu())\n        all_labels.append(labels.cpu())\n\n# Concatenate all predictions and labels\nall_preds = torch.cat(all_preds)\nall_labels = torch.cat(all_labels)\n\n# Apply sigmoid activation to the predictions\nall_preds = all_preds.sigmoid().numpy()  # Apply sigmoid activation\n\n# Convert predictions to binary\nthreshold = 0.6\nbinary_preds = (all_preds > threshold).astype(np.float32)\nbinary_labels = (all_labels.numpy() > threshold).astype(np.float32)\n\n# Calculate accuracy and F1 score\naccuracy = accuracy_score(binary_labels.flatten(), binary_preds.flatten())\nf1 = f1_score(binary_labels.flatten(), binary_preds.flatten())\nprecision = precision_score(binary_labels.flatten(), binary_preds.flatten())\nrecall = recall_score(binary_labels.flatten(), binary_preds.flatten())\n\nprint(f'Accuracy: {accuracy:.4f}')\nprint(f'F1 Score: {f1:.4f}')\nprint(f'Precision: {precision:.4f}')\nprint(f'Recall: {recall:.4f}')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:08:30.788144Z","iopub.execute_input":"2024-08-09T12:08:30.788406Z","iopub.status.idle":"2024-08-09T12:09:35.526580Z","shell.execute_reply.started":"2024-08-09T12:08:30.788383Z","shell.execute_reply":"2024-08-09T12:09:35.525371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\niou = compute_iou(binary_preds, binary_labels, num_classes)\nprint(f'IOU: {iou:.4f}')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:09:35.528424Z","iopub.execute_input":"2024-08-09T12:09:35.528852Z","iopub.status.idle":"2024-08-09T12:09:35.927260Z","shell.execute_reply.started":"2024-08-09T12:09:35.528809Z","shell.execute_reply":"2024-08-09T12:09:35.926285Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom torchvision.utils import save_image\nimport numpy as np\nfrom sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score\n\n# Directory to save the outputs and true images\noutput_dir = '/kaggle/working/outputs'\nos.makedirs(output_dir, exist_ok=True)\n\n# Directory to save the original images and true labels\nimage_dir = '/kaggle/working/original_images'\nlabel_dir = '/kaggle/working/true_labels'\nos.makedirs(image_dir, exist_ok=True)\nos.makedirs(label_dir, exist_ok=True)\n\nmodel.eval()  # Set the model to evaluation mode\n\n# Initialize lists to store predictions and labels\nall_preds = []\nall_labels = []\n\nwith torch.no_grad():  # Disable gradient computation\n    for i, (images, labels) in enumerate(test_loader):\n        images, labels = images.to(device), labels.to(device)  # Uncomment if using GPU\n        \n        outputs = model(images)\n        outputs = torch.sigmoid(outputs)  # Apply sigmoid activation function\n        \n        # Apply threshold to obtain binary masks\n        threshold = 0.5\n        binary_outputs = (outputs > threshold).float()\n\n        # Save original images, true labels, and output images\n        for j in range(images.size(0)):  # For each image in the batch\n            # Save original image\n            original_image = images[j].cpu()  # Move to CPU if necessary\n            original_path = os.path.join(image_dir, f'image_{i * len(images) + j}.png')\n            save_image(original_image, original_path)\n\n            # Save true label\n            true_label = labels[j].cpu()  # Move to CPU if necessary\n            true_label_path = os.path.join(label_dir, f'label_{i * len(images) + j}.png')\n            save_image(true_label, true_label_path)\n\n            # Save output image\n            output_image = binary_outputs[j].cpu()  # Move to CPU if necessary\n            output_path = os.path.join(output_dir, f'output_{i * len(images) + j}.png')\n            save_image(output_image, output_path)\n\n            # Collect predictions and labels for metric calculation\n            all_preds.append(binary_outputs[j].cpu().numpy())\n            all_labels.append(labels[j].cpu().numpy())","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:44:00.314940Z","iopub.execute_input":"2024-08-09T12:44:00.315815Z","iopub.status.idle":"2024-08-09T12:44:34.660122Z","shell.execute_reply.started":"2024-08-09T12:44:00.315782Z","shell.execute_reply":"2024-08-09T12:44:34.659041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Concatenate all predictions and labels\nall_preds = np.concatenate(all_preds, axis=0)\nall_labels = np.concatenate(all_labels, axis=0)\n\n# Flatten arrays for metric calculation\nall_preds_flat = all_preds.flatten()\nall_labels_flat = all_labels.flatten()\n\n# Convert predictions to binary if not already\nbinary_preds = (all_preds_flat > 0.5).astype(np.float32)\nbinary_labels = (all_labels_flat > 0.5).astype(np.float32)\n\n# Calculate metrics\naccuracy = accuracy_score(binary_labels, binary_preds)\nf1 = f1_score(binary_labels, binary_preds)\nprecision = precision_score(binary_labels, binary_preds)\nrecall = recall_score(binary_labels, binary_preds)\n\nprint(f'Accuracy: {accuracy:.4f}')\nprint(f'F1 Score: {f1:.4f}')\nprint(f'Precision: {precision:.4f}')\nprint(f'Recall: {recall:.4f}')\n\n# Compute IoU\ndef compute_iou(preds, labels, num_classes):\n    ious = []\n    for i in range(num_classes):\n        pred_i = (preds == i).astype(np.float32)\n        label_i = (labels == i).astype(np.float32)\n        \n        intersection = np.sum(pred_i * label_i)\n        union = np.sum(pred_i) + np.sum(label_i) - intersection\n        \n        iou = intersection / (union + 1e-6)  # Add epsilon to avoid division by zero\n        ious.append(iou)\n    \n    return np.mean(ious)\n\nnum_classes = 2\niou = compute_iou(binary_preds, binary_labels, num_classes)\nprint(f'IoU: {iou:.4f}')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:45:37.922846Z","iopub.execute_input":"2024-08-09T12:45:37.923610Z","iopub.status.idle":"2024-08-09T12:47:19.616994Z","shell.execute_reply.started":"2024-08-09T12:45:37.923567Z","shell.execute_reply":"2024-08-09T12:47:19.616023Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_files = os.listdir('/kaggle/working/outputs')\nprint(f'Number of files in {output_dir}: {len(output_files)}')","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:47:19.619032Z","iopub.execute_input":"2024-08-09T12:47:19.619432Z","iopub.status.idle":"2024-08-09T12:47:19.625261Z","shell.execute_reply.started":"2024-08-09T12:47:19.619397Z","shell.execute_reply":"2024-08-09T12:47:19.624368Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def visualize_images(image_indices, image_dir, label_dir, output_dir):\n    num_images = len(image_indices)\n    fig, axes = plt.subplots(num_images, 3, figsize=(15, num_images * 5))\n    \n    if num_images == 1:\n        axes = np.expand_dims(axes, axis=0)  # Convert single subplot to 2D array\n    \n    for i, idx in enumerate(image_indices):\n        original_path = os.path.join(image_dir, f'image_{idx}.png')\n        true_label_path = os.path.join(label_dir, f'label_{idx}.png')\n        output_path = os.path.join(output_dir, f'output_{idx}.png')\n        \n        original_image = plt.imread(original_path)\n        true_label = plt.imread(true_label_path)\n        output_image = plt.imread(output_path)\n        \n        axes[i, 0].imshow(original_image, cmap='gray')\n        axes[i, 0].set_title(f'Original Image {idx}')\n        axes[i, 0].axis('off')\n\n        axes[i, 1].imshow(true_label, cmap='gray')\n        axes[i, 1].set_title(f'True Label {idx}')\n        axes[i, 1].axis('off')\n\n        axes[i, 2].imshow(output_image, cmap='gray')\n        axes[i, 2].set_title(f'Prediction {idx}')\n        axes[i, 2].axis('off')\n\n    plt.tight_layout()\n    plt.show()\n\n\nbatch_size = 8\nvisualize_images(\n    image_indices=range(batch_size*3),  \n    image_dir=image_dir,\n    label_dir=label_dir,\n    output_dir=output_dir\n)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-09T12:47:19.626668Z","iopub.execute_input":"2024-08-09T12:47:19.627374Z","iopub.status.idle":"2024-08-09T12:47:32.719183Z","shell.execute_reply.started":"2024-08-09T12:47:19.627337Z","shell.execute_reply":"2024-08-09T12:47:32.717472Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test","metadata":{}},{"cell_type":"code","source":"\n# # Alternatively, load the entire model\n# model = torch.load('/kaggle/working/unet_model_full.pth')\n# model.to(device)  # Move the model to the appropriate device (CPU or GPU)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:06:52.475120Z","iopub.status.idle":"2024-08-07T16:06:52.475484Z","shell.execute_reply.started":"2024-08-07T16:06:52.475307Z","shell.execute_reply":"2024-08-07T16:06:52.475321Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.eval()  # Set the model to evaluation mode\n# with torch.no_grad():\n#     # Test with some sample data or check the outputs\n#     sample_output = model(test_images[0].to(device))","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:06:52.477039Z","iopub.status.idle":"2024-08-07T16:06:52.477423Z","shell.execute_reply.started":"2024-08-07T16:06:52.477248Z","shell.execute_reply":"2024-08-07T16:06:52.477263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def load_image(file_path):\n#     image = Image.open(file_path).convert('RGB')\n#     return np.array(image)\n\n# # Choose a sample test image and its corresponding label\n# sample_image_file = test_images[0]\n# sample_image_path = os.path.join(images_dir, sample_image_file)\n# sample_label_file = sample_image_file.replace('.png', '.png')  # Adjust if necessary\n# sample_label_path = os.path.join(labels_dir, sample_label_file)\n\n# # Load the sample image and label\n# sample_image = load_image(sample_image_path)\n# sample_label = load_image(sample_label_path)\n\n# # Load the model output corresponding to this sample image\n# output_file = f'output_{0}.png'  # Adjust if necessary\n# output_path = os.path.join(output_dir, output_file)\n# output_image = Image.open(output_path)\n\n# # Plot the sample image, label, and output\n# plt.figure(figsize=(15, 5))\n\n# plt.subplot(1, 3, 1)\n# plt.title('Test Image')\n# plt.imshow(sample_image)\n# plt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2024-08-07T16:06:52.479173Z","iopub.status.idle":"2024-08-07T16:06:52.479595Z","shell.execute_reply.started":"2024-08-07T16:06:52.479372Z","shell.execute_reply":"2024-08-07T16:06:52.479387Z"},"trusted":true},"execution_count":null,"outputs":[]}]}