{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":6927,"databundleVersionId":45059,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-08-10T03:54:28.696043Z","iopub.execute_input":"2024-08-10T03:54:28.696389Z","iopub.status.idle":"2024-08-10T03:54:29.060448Z","shell.execute_reply.started":"2024-08-10T03:54:28.696357Z","shell.execute_reply":"2024-08-10T03:54:29.059551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Define the path to the .zip file\nzip_file_path = '/kaggle/input/carvana-image-masking-challenge/train.zip'\n\n# Define the directory to extract the contents\nextract_dir = '/kaggle/data/'\n\n# Create the directory if it doesn't exist\nif not os.path.exists(extract_dir):\n    os.makedirs(extract_dir)\n\n# Unzip the file\nwith zipfile.ZipFile(zip_file_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_dir)\n\n# Verify extraction\nos.listdir(extract_dir)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-10T03:59:17.375644Z","iopub.execute_input":"2024-08-10T03:59:17.376272Z","iopub.status.idle":"2024-08-10T03:59:22.432170Z","shell.execute_reply.started":"2024-08-10T03:59:17.376241Z","shell.execute_reply":"2024-08-10T03:59:22.429663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Define the path to the .zip file\nzip_file_path = '/kaggle/input/carvana-image-masking-challenge/train_masks.zip'\n\n# Define the directory to extract the contents\nextract_dir = '/kaggle/data/'\n\n# Create the directory if it doesn't exist\nif not os.path.exists(extract_dir):\n    os.makedirs(extract_dir)\n\n# Unzip the file\nwith zipfile.ZipFile(zip_file_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_dir)\n\n# Verify extraction\n\nos.listdir(extract_dir)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:00:09.900501Z","iopub.execute_input":"2024-08-10T04:00:09.901094Z","iopub.status.idle":"2024-08-10T04:00:10.578984Z","shell.execute_reply.started":"2024-08-10T04:00:09.901061Z","shell.execute_reply":"2024-08-10T04:00:10.578083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Define the path to the .zip file\nzip_file_path = '/kaggle/input/carvana-image-masking-challenge/test.zip'\n\n# Define the directory to extract the contents\nextract_dir = '/kaggle/data/test_images'\n\n# Create the directory if it doesn't exist\nif not os.path.exists(extract_dir):\n    os.makedirs(extract_dir)\n\n# Unzip the file\nwith zipfile.ZipFile(zip_file_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_dir)\n\n# Verify extraction\n\nos.listdir(extract_dir)\n","metadata":{"execution":{"iopub.status.busy":"2024-08-10T02:15:46.240988Z","iopub.execute_input":"2024-08-10T02:15:46.241804Z","iopub.status.idle":"2024-08-10T02:18:20.170146Z","shell.execute_reply.started":"2024-08-10T02:15:46.241771Z","shell.execute_reply":"2024-08-10T02:18:20.169255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nimport torchvision.transforms as transforms\n\nclass DoubleConv(nn.Module):\n  def __init__(self, in_channels, out_channels):\n    super(DoubleConv, self).__init__()\n    self.conv = nn.Sequential(\n        nn.Conv2d(in_channels, out_channels, 3, 1, 1, bias=False),\n        nn.BatchNorm2d(out_channels),\n        nn.ReLU(inplace=True),\n        nn.Conv2d(out_channels, out_channels, 3, 1, 1, bias=False),\n        nn.BatchNorm2d(out_channels),\n        nn.ReLU(inplace=True),\n    )\n\n  def forward(self, x):\n    return self.conv(x)\n\nclass UNET(nn.Module):\n  def __init__(self, in_channels=3, out_channels=1, features=[64, 128, 256, 512]):\n    super(UNET, self).__init__()\n    self.ups = nn.ModuleList()\n    self.downs = nn.ModuleList()\n    self.pool = nn.MaxPool2d(kernel_size=2, stride=2)\n\n    for feature in features:\n      self.downs.append(DoubleConv(in_channels, feature))\n      in_channels = feature\n\n    for feature in reversed(features):\n      self.ups.append(\n          nn.ConvTranspose2d(\n              feature*2, feature, kernel_size=2, stride=2,\n          )\n      )\n      self.ups.append(DoubleConv(feature*2, feature))\n\n    self.bottleneck = DoubleConv(features[-1], features[-1]*2)\n    self.final_conv = nn.Conv2d(features[0], out_channels, kernel_size=1)\n  def forward(self, x):\n    skip_connections = []\n\n    for down in self.downs:\n      x = down(x)\n      skip_connections.append(x)\n      x = self.pool(x)\n\n    x = self.bottleneck(x)\n    skip_connections = skip_connections[::-1]\n    for idx in range(0, len(self.ups), 2):\n      x = self.ups[idx](x)\n      skip_connection = skip_connections[idx//2]\n      if x.shape != skip_connection.shape:\n        x = transforms.functional.resize(x, size=skip_connection.shape[2:])\n      concat_skip = torch.cat((skip_connection, x), dim=1)\n      x = self.ups[idx+1](concat_skip)\n\n    return self.final_conv(x)","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:00:40.976459Z","iopub.execute_input":"2024-08-10T04:00:40.977105Z","iopub.status.idle":"2024-08-10T04:00:46.183434Z","shell.execute_reply.started":"2024-08-10T04:00:40.977073Z","shell.execute_reply":"2024-08-10T04:00:46.182674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test():\n  x = torch.randn((3, 1, 161, 161))\n  model = UNET(in_channels=1, out_channels=1)\n  preds = model(x)\n  print(preds.shape)\n  print(x.shape)\n  assert preds.shape == x.shape\ntest()","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:00:50.675871Z","iopub.execute_input":"2024-08-10T04:00:50.676364Z","iopub.status.idle":"2024-08-10T04:00:52.204335Z","shell.execute_reply.started":"2024-08-10T04:00:50.676326Z","shell.execute_reply":"2024-08-10T04:00:52.203290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom PIL import Image\nfrom torch.utils.data import Dataset\nimport numpy as np\n\nclass CarvanaDataset(Dataset):\n  def __init__(self, image_dir, mask_dir, transform=None):\n    self.image_dir = image_dir\n    self.mask_dir = mask_dir\n    self.transform = transform\n    self.images = os.listdir(image_dir)\n  def __len__(self):\n    return len(self.images)\n  def __getitem__(self, index):\n    img_path = os.path.join(self.image_dir, self.images[index])\n    mask_path = os.path.join(self.mask_dir, self.images[index].replace(\".jpg\", \"_mask.gif\"))\n    image = np.array(Image.open(img_path).convert(\"RGB\"))\n    mask = np.array(Image.open(mask_path).convert(\"L\"), dtype=np.float32)\n    mask[mask == 255.0] = 1.0\n    if self.transform is not None:\n      augmentations = self.transform(image=image, mask=mask)\n      image = augmentations[\"image\"]\n      mask = augmentations[\"mask\"]\n    return image, mask","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:00:55.104139Z","iopub.execute_input":"2024-08-10T04:00:55.104465Z","iopub.status.idle":"2024-08-10T04:00:55.113307Z","shell.execute_reply.started":"2024-08-10T04:00:55.104442Z","shell.execute_reply":"2024-08-10T04:00:55.112292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchvision\nfrom torch.utils.data import DataLoader\n\ndef save_checkpoint(state, filename=\"my_checkpoint.pth.tar\"):\n  print(\"=> Saving checkpoint\")\n  torch.save(state, filename)\n\ndef load_checkpoint(checkpoint, model):\n  print(\"=> Loading checkpoint\")\n  model.load_state_dict(checkpoint[\"state_dict\"])\n\ndef get_loaders(\n    train_dir,\n    train_maskdir,\n    val_dir,\n    val_maskdir,\n    batch_size,\n    train_transform,\n    val_transform,\n    num_workers=4,\n    pin_memory=True,\n):\n\n  train_ds = CarvanaDataset(\n      image_dir=train_dir,\n      mask_dir=train_maskdir,\n      transform=train_transform,\n  )\n\n  from torch.utils.data import random_split\n\n# Define the split sizes\n  val_size = int(0.2 * len(train_ds))  # 20% of the dataset for validation\n  train_size = len(train_ds) - val_size  # 80% for training\n\n# Split the dataset\n  train_ds, val_ds = random_split(train_ds, [train_size, val_size])\n  import os\n\n# Define the paths for the directories\n  test_image_dir = '/kaggle/data/test'\n  test_mask_dir = '/kaggle/data/test_masks'\n\n# Create directories if they don't exist\n  os.makedirs(test_image_dir, exist_ok=True)\n  os.makedirs(test_mask_dir, exist_ok=True)\n  from shutil import copyfile\n\n# Assuming val_ds is your validation dataset obtained from the random_split method\n  for idx in range(len(val_ds)):\n    # Get the original index in the full dataset\n    original_idx = val_ds.indices[idx]\n\n    # Get the paths from the dataset class\n    img_path = os.path.join(val_ds.dataset.image_dir, val_ds.dataset.images[original_idx])\n    mask_path = os.path.join(val_ds.dataset.mask_dir, val_ds.dataset.images[original_idx].replace(\".jpg\", \"_mask.gif\"))\n\n    # Define the destination paths\n    dest_image_path = os.path.join(test_image_dir, os.path.basename(img_path))\n    dest_mask_path = os.path.join(test_mask_dir, os.path.basename(mask_path))\n\n    # Copy the files to the destination directories\n    copyfile(img_path, dest_image_path)\n    copyfile(mask_path, dest_mask_path)\n\n  train_loader = DataLoader(\n      train_ds,\n      batch_size=batch_size,\n      num_workers=num_workers,\n      pin_memory=pin_memory,\n      shuffle=True,\n  )\n  val_ds = CarvanaDataset(\n      image_dir= test_image_dir,\n      mask_dir=test_mask_dir,\n      transform=val_transform,\n  )\n  val_loader = DataLoader(\n      val_ds,\n      batch_size=batch_size,\n      num_workers=num_workers,\n      pin_memory=pin_memory,\n      shuffle=False,\n  )\n  return train_loader, val_loader\n\ndef check_accuracy(loader, model, device=\"cuda\"):\n  num_correct = 0\n  num_pixels = 0\n  dice_score = 0\n  model.eval()\n\n  with torch.no_grad():\n    for x, y in loader:\n      x = x.to(device)\n      y = y.to(device).unsqueeze(1)\n      preds = torch.sigmoid(model(x))\n      preds = (preds > 0.5).float()\n      num_correct += (preds == y).sum()\n      num_pixels += torch.numel(preds)\n      dice_score += (2 * (preds * y).sum()) / (\n          (preds + y).sum() + 1e-8\n      )\n  print(f\"Got {num_correct}/{num_pixels} with acc {num_correct/num_pixels*100:.2f}\")\n  print(f\"Dice score: {dice_score/len(loader)}\")\n  model.train()\n\ndef save_predictions_as_imgs(\n    loader, model, folder=\"/kaggle/data/saved_images/\", device=\"cuda\"\n):\n  model.eval()\n  for idx, (x, y) in enumerate(loader):\n    x = x.to(device=device)\n    with torch.no_grad():\n      preds = torch.sigmoid(model(x))\n      preds = (preds > 0.5).float()\n    torchvision.utils.save_image(\n        preds, f\"{folder}/pred_{idx}.png\"\n    )\n    torchvision.utils.save_image(y.unsqueeze(1), f\"{folder}{idx}.png\")\n\n  model.train()","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:35:36.251909Z","iopub.execute_input":"2024-08-10T04:35:36.252273Z","iopub.status.idle":"2024-08-10T04:35:36.272122Z","shell.execute_reply.started":"2024-08-10T04:35:36.252245Z","shell.execute_reply":"2024-08-10T04:35:36.271206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.mkdir(\"/kaggle/data/saved_images\")","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:55:37.800742Z","iopub.execute_input":"2024-08-10T04:55:37.801125Z","iopub.status.idle":"2024-08-10T04:55:37.805916Z","shell.execute_reply.started":"2024-08-10T04:55:37.801093Z","shell.execute_reply":"2024-08-10T04:55:37.804752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\nfrom tqdm import tqdm\nimport torch.nn as nn\nimport torch.optim as optim\n# from utils import (\n#     load_checkpoint,\n#     save_checkpoint,\n#     get_loaders,\n#     check_accuracy,\n#     save_predictions_as_imgs,\n# )\n\n#hyperparameters etc\nLEARNING_RATE = 1e-4\nDEVICE = \"cuda\" if torch.cuda.is_available() else \"cpu\"\nBATCH_SIZE=16\nNUM_EPOCHS = 3\nNUM_WORKERS = 2\nIMAGE_HEIGHT = 160\nIMAGE_WIDTH = 240\nPIN_MEMORY = True\nLOAD_MODEL = False\nTRAIN_IMG_DIR = \"/kaggle/data/train\"\nTRAIN_MASK_DIR = \"/kaggle/data/train_masks\"\nVAL_IMG_DIR = \"/kaggle/data/test\"\nVAL_MASK_DIR = \"/kaggle/data/test_masks\"\n\ndef train_fn(loader, model, optimizer, loss_fn, scaler):\n  loop = tqdm(loader)\n  for batch_idx, (data, targets) in enumerate(loop):\n    data = data.to(device=DEVICE)\n    targets = targets.float().unsqueeze(1).to(device=DEVICE)\n    with torch.cuda.amp.autocast():\n      predictions = model(data)\n      loss = loss_fn(predictions, targets)\n    optimizer.zero_grad()\n    scaler.scale(loss).backward()\n    scaler.step(optimizer)\n    scaler.update()\n\n    loop.set_postfix(loss=loss.item())\n\ndef main():\n  train_transform = A.Compose(\n      [\n          A.Resize(height=IMAGE_HEIGHT, width=IMAGE_WIDTH),\n          A.Rotate(limit=35, p=1.0),\n          A.HorizontalFlip(p=0.5),\n          A.VerticalFlip(p=0.1),\n          A.Normalize(mean=[0.0, 0.0, 0.0], std=[1.0, 1.0, 1.0], max_pixel_value=255.0),\n          ToTensorV2(),\n      ]\n  )\n  val_transform = A.Compose(\n      [\n          A.Resize(height=IMAGE_HEIGHT, width=IMAGE_WIDTH),\n          A.Normalize(mean=[0.0, 0.0, 0.0], std=[1.0, 1.0, 1.0], max_pixel_value=255.0),\n          ToTensorV2(),\n      ]\n  )\n  model = UNET(in_channels=3, out_channels=1).to(DEVICE)\n  loss_fn = nn.BCEWithLogitsLoss()\n  optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE)\n  train_loader, val_loader= get_loaders(\n      TRAIN_IMG_DIR,\n      TRAIN_MASK_DIR,\n      VAL_IMG_DIR,\n      VAL_MASK_DIR,\n      BATCH_SIZE,\n      train_transform,\n      val_transform,\n      NUM_WORKERS,\n      PIN_MEMORY,\n\n  )\n\n  if LOAD_MODEL:\n    load_checkpoint(torch.load(\"my_checkpoint.pth.tar\"), model)\n  #check_accuracy(val_loader, model, device=DEVICE)\n  scaler=torch.cuda.amp.GradScaler()\n  for epoch in range(NUM_EPOCHS):\n    train_fn(train_loader, model, optimizer, loss_fn, scaler)\n    checkpoint={\n        \"state_dict\": model.state_dict(),\n        \"optimizer\": optimizer.state_dict(),\n    }\n    save_checkpoint(checkpoint)\n    check_accuracy(val_loader, model, device=DEVICE)\n    save_predictions_as_imgs(val_loader, model, folder=\"/kaggle/data/saved_images/\", device=DEVICE)\n\n  model.eval()\nif __name__ == \"__main__\":\n  main()","metadata":{"execution":{"iopub.status.busy":"2024-08-10T04:36:08.091592Z","iopub.execute_input":"2024-08-10T04:36:08.091954Z","iopub.status.idle":"2024-08-10T04:43:17.062099Z","shell.execute_reply.started":"2024-08-10T04:36:08.091926Z","shell.execute_reply":"2024-08-10T04:43:17.061040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}