{"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":"# Import libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \nimport tensorflow as tf\nfrom zipfile import ZipFile \nimport keras.backend as K\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport os\nimport torch\nimport torch.nn as nn\nimport pandas as pd\nimport os\nimport PIL\nimport skimage\nfrom skimage import io\nimport numpy as np\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as patches\nimport torchvision.transforms as transforms\nimport torch.optim as optim\nimport torchvision.transforms.functional as FT\nfrom torch.utils.data import DataLoader\nfrom tqdm import tqdm\nseed = 123\nimport cv2\nimport xml.etree.ElementTree as ET\ntorch.manual_seed(seed)\nfrom collections import Counter\nimport matplotlib.pyplot as plt\nimport os\nfrom glob import glob\nfrom tqdm import tqdm\nimport cv2\nimport torch\nimport torchvision\nimport torch.nn as nn\nimport torch\nfrom torch.utils.data import Dataset\nfrom torchvision import datasets\nfrom torchvision.transforms import ToTensor\nimport matplotlib.pyplot as plt\nfrom torch.utils.data import DataLoader, TensorDataset","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:32.687742Z","iopub.execute_input":"2022-12-16T08:27:32.688083Z","iopub.status.idle":"2022-12-16T08:27:39.486295Z","shell.execute_reply.started":"2022-12-16T08:27:32.688051Z","shell.execute_reply":"2022-12-16T08:27:39.48533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset Preparation","metadata":{}},{"cell_type":"code","source":"train_zip = \"/kaggle/input/carvana-image-masking-challenge/train.zip\"\nwith ZipFile(train_zip, 'r') as zip_: \n    zip_.extractall('/kaggle/working')","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:39.487872Z","iopub.execute_input":"2022-12-16T08:27:39.488231Z","iopub.status.idle":"2022-12-16T08:27:50.082031Z","shell.execute_reply.started":"2022-12-16T08:27:39.488191Z","shell.execute_reply":"2022-12-16T08:27:50.081036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_mask_zip = \"/kaggle/input/carvana-image-masking-challenge/train_masks.zip\"\nwith ZipFile(train_mask_zip, 'r') as zip_: \n    zip_.extractall('/kaggle/working')","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:50.083969Z","iopub.execute_input":"2022-12-16T08:27:50.084332Z","iopub.status.idle":"2022-12-16T08:27:51.656578Z","shell.execute_reply.started":"2022-12-16T08:27:50.084294Z","shell.execute_reply":"2022-12-16T08:27:51.655616Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Train set:  \", len(os.listdir(\"/kaggle/working/train\")))\nprint(\"Train masks:\", len(os.listdir(\"/kaggle/working/train_masks\")))","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:51.658288Z","iopub.execute_input":"2022-12-16T08:27:51.658709Z","iopub.status.idle":"2022-12-16T08:27:51.672249Z","shell.execute_reply.started":"2022-12-16T08:27:51.658664Z","shell.execute_reply":"2022-12-16T08:27:51.671449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"car_ids = []\npaths = []\nfor dirname, _, filenames in os.walk('/kaggle/working/train'):\n    for filename in filenames:\n        path = os.path.join(dirname, filename)    \n        paths.append(path)\n        \n        car_id = filename.split(\".\")[0]\n        car_ids.append(car_id)\n\nd = {\"id\": car_ids, \"car_path\": paths}\ndf = pd.DataFrame(data = d)\ndf = df.set_index('id')\ndf","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:51.673574Z","iopub.execute_input":"2022-12-16T08:27:51.67393Z","iopub.status.idle":"2022-12-16T08:27:51.717329Z","shell.execute_reply.started":"2022-12-16T08:27:51.673894Z","shell.execute_reply":"2022-12-16T08:27:51.716319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"car_ids = []\nmask_path = []\nfor dirname, _, filenames in os.walk('/kaggle/working/train_masks'):\n    for filename in filenames:\n        path = os.path.join(dirname, filename)\n        mask_path.append(path)\n        \n        car_id = filename.split(\".\")[0]\n        car_id = car_id.split(\"_mask\")[0]\n        car_ids.append(car_id)\n\n        \nd = {\"id\": car_ids,\"mask_path\": mask_path}\nmask_df = pd.DataFrame(data = d)\nmask_df = mask_df.set_index('id')\nmask_df","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:51.718844Z","iopub.execute_input":"2022-12-16T08:27:51.719209Z","iopub.status.idle":"2022-12-16T08:27:51.751476Z","shell.execute_reply.started":"2022-12-16T08:27:51.719171Z","shell.execute_reply":"2022-12-16T08:27:51.750438Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"mask_path\"] = mask_df[\"mask_path\"]\ndf","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:51.752986Z","iopub.execute_input":"2022-12-16T08:27:51.753342Z","iopub.status.idle":"2022-12-16T08:27:51.767633Z","shell.execute_reply.started":"2022-12-16T08:27:51.753303Z","shell.execute_reply":"2022-12-16T08:27:51.766623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = df[:1000]\nlen(df)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:14:13.213904Z","iopub.execute_input":"2022-12-16T10:14:13.214254Z","iopub.status.idle":"2022-12-16T10:14:13.220055Z","shell.execute_reply.started":"2022-12-16T10:14:13.214219Z","shell.execute_reply":"2022-12-16T10:14:13.219174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Now we will perform a simple augmentation of flipping an image and then normalize the image pixel in between 0 and 1","metadata":{}},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2022-12-16T08:27:51.787856Z","iopub.execute_input":"2022-12-16T08:27:51.788267Z","iopub.status.idle":"2022-12-16T08:27:51.804325Z","shell.execute_reply.started":"2022-12-16T08:27:51.78823Z","shell.execute_reply":"2022-12-16T08:27:51.803222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self,df):\n        self.df = df\n        self.transform = transforms.Compose([\n            transforms.ToTensor(),\n        \n        ])\n\n    def __len__(self):\n        return len(self.df)\n\n    def __getitem__(self, idx):\n        image_path = self.df.iloc[idx]['car_path']\n        mask_path = self.df.iloc[idx]['mask_path']\n        \n#         if self.transform:\n#             image = self.transform(image)\n#         if self.target_transform:\n#             label = self.target_transform(label)\n\n       \n        image = Image.open(image_path)\n        mask = Image.open(mask_path)\n        \n        image = image.resize((224, 224))\n        mask = mask.resize((224,224))\n        \n        \n        image = self.transform(image)\n        mask = self.transform(mask)\n        \n        return image, mask","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:48.554718Z","iopub.execute_input":"2022-12-16T10:15:48.555123Z","iopub.status.idle":"2022-12-16T10:15:48.56379Z","shell.execute_reply.started":"2022-12-16T10:15:48.555082Z","shell.execute_reply":"2022-12-16T10:15:48.562664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = CustomDataset(df)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:49.289149Z","iopub.execute_input":"2022-12-16T10:15:49.289501Z","iopub.status.idle":"2022-12-16T10:15:49.294512Z","shell.execute_reply.started":"2022-12-16T10:15:49.289463Z","shell.execute_reply":"2022-12-16T10:15:49.293456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset.__getitem__(0)\ndata_loader = DataLoader(\n     dataset=dataset,\n     batch_size=64,\n     shuffle=True,\n     drop_last=False\n)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:49.787091Z","iopub.execute_input":"2022-12-16T10:15:49.787436Z","iopub.status.idle":"2022-12-16T10:15:49.843649Z","shell.execute_reply.started":"2022-12-16T10:15:49.787401Z","shell.execute_reply":"2022-12-16T10:15:49.842739Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Block(nn.Module):\n    def __init__(self, in_ch, out_ch):\n        super().__init__()\n        self.conv1 = nn.Conv2d(in_ch, out_ch, 3)\n        self.relu  = nn.ReLU()\n        self.conv2 = nn.Conv2d(out_ch, out_ch, 3)\n    \n    def forward(self, x):\n        return self.conv2(self.relu(self.conv1(x)))\n\n\nclass Encoder(nn.Module):\n    def __init__(self, chs=(3,64,128,256,512,1024)):\n        super().__init__()\n        self.enc_blocks = nn.ModuleList([Block(chs[i], chs[i+1]) for i in range(len(chs)-1)])\n        self.pool       = nn.MaxPool2d(2)\n    \n    def forward(self, x):\n        ftrs = []\n        for block in self.enc_blocks:\n            x = block(x)\n            ftrs.append(x)\n            x = self.pool(x)\n        return ftrs\n\n\nclass Decoder(nn.Module):\n    def __init__(self, chs=(1024, 512, 256, 128, 64)):\n        super().__init__()\n        self.chs         = chs\n        self.upconvs    = nn.ModuleList([nn.ConvTranspose2d(chs[i], chs[i+1], 2, 2) for i in range(len(chs)-1)])\n        self.dec_blocks = nn.ModuleList([Block(chs[i], chs[i+1]) for i in range(len(chs)-1)]) \n        \n    def forward(self, x, encoder_features):\n        for i in range(len(self.chs)-1):\n            x        = self.upconvs[i](x)\n            enc_ftrs = self.crop(encoder_features[i], x)\n            x        = torch.cat([x, enc_ftrs], dim=1)\n            x        = self.dec_blocks[i](x)\n        return x\n    \n    def crop(self, enc_ftrs, x):\n        _, _, H, W = x.shape\n        enc_ftrs   = torchvision.transforms.CenterCrop([H, W])(enc_ftrs)\n        return enc_ftrs\n\n\nclass UNet(nn.Module):\n    def __init__(self, enc_chs=(3,64,128,256,512,1024), dec_chs=(1024, 512, 256, 128, 64), num_class=1, retain_dim=True, out_sz=(224,224)):\n        super().__init__()\n        self.encoder     = Encoder(enc_chs)\n        self.decoder     = Decoder(dec_chs)\n        self.head        = nn.Conv2d(dec_chs[-1], num_class, 1)\n        self.retain_dim  = retain_dim\n\n    def forward(self, x):\n        enc_ftrs = self.encoder(x)\n        out      = self.decoder(enc_ftrs[::-1][0], enc_ftrs[::-1][1:])\n        out      = self.head(out)\n        if self.retain_dim:\n            out = torch.nn.functional.interpolate(out,(224,224))\n        return out","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:49.9742Z","iopub.execute_input":"2022-12-16T10:15:49.974555Z","iopub.status.idle":"2022-12-16T10:15:49.989322Z","shell.execute_reply.started":"2022-12-16T10:15:49.974502Z","shell.execute_reply":"2022-12-16T10:15:49.988471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unet = UNet()\nx    = torch.randn(1, 3, 224, 224)\nunet(x).shape","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:50.189321Z","iopub.execute_input":"2022-12-16T10:15:50.189658Z","iopub.status.idle":"2022-12-16T10:15:50.627307Z","shell.execute_reply.started":"2022-12-16T10:15:50.189624Z","shell.execute_reply":"2022-12-16T10:15:50.626418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"criterion = nn.BCEWithLogitsLoss()\noptimizer = optim.Adam(unet.parameters(), lr=0.001)\nlr_scheduler = optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.595)\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n# device = \"cpu\"\nunet.to(device)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:50.628906Z","iopub.execute_input":"2022-12-16T10:15:50.629271Z","iopub.status.idle":"2022-12-16T10:15:50.670575Z","shell.execute_reply.started":"2022-12-16T10:15:50.629232Z","shell.execute_reply":"2022-12-16T10:15:50.669628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(data_loader)\nlen(df)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:50.672422Z","iopub.execute_input":"2022-12-16T10:15:50.672795Z","iopub.status.idle":"2022-12-16T10:15:50.678345Z","shell.execute_reply.started":"2022-12-16T10:15:50.672755Z","shell.execute_reply":"2022-12-16T10:15:50.677294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"losses = []\nfor epoch in range(5):\n    for j,(image, mask) in enumerate(data_loader):\n        image = image.type(torch.FloatTensor)\n        \n    \n\n        image = image.to(device)\n        mask = mask.to(device)\n\n        \n        out = unet(image)\n        \n#         print(out.dtype, mask.dtype)\n        \n        \n        \n        loss = criterion(mask ,out)\n        \n        losses.append(float(\"{:.4f}\".format(loss.item())))\n        \n        optimizer.zero_grad()\n        \n        loss.backward()\n        \n        \n        optimizer.step()\n        print(\"Loss at step of epoch \", epoch , j, float(\"{:.4f}\".format(loss.item())) )","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:15:50.680013Z","iopub.execute_input":"2022-12-16T10:15:50.68036Z","iopub.status.idle":"2022-12-16T10:20:58.523461Z","shell.execute_reply.started":"2022-12-16T10:15:50.680324Z","shell.execute_reply":"2022-12-16T10:20:58.522424Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(losses)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:20:58.524984Z","iopub.execute_input":"2022-12-16T10:20:58.525331Z","iopub.status.idle":"2022-12-16T10:20:58.667372Z","shell.execute_reply.started":"2022-12-16T10:20:58.525293Z","shell.execute_reply":"2022-12-16T10:20:58.666553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAINED_FILE = \"/kaggle/working/model.pth\"\ntorch.save(unet.state_dict(), TRAINED_FILE)\n","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:21:06.366276Z","iopub.execute_input":"2022-12-16T10:21:06.366667Z","iopub.status.idle":"2022-12-16T10:21:06.714178Z","shell.execute_reply.started":"2022-12-16T10:21:06.36663Z","shell.execute_reply":"2022-12-16T10:21:06.712871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_df = df[:50]\nnew_df","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:24:17.398159Z","iopub.execute_input":"2022-12-16T10:24:17.39852Z","iopub.status.idle":"2022-12-16T10:24:17.414811Z","shell.execute_reply.started":"2022-12-16T10:24:17.398483Z","shell.execute_reply":"2022-12-16T10:24:17.413822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"new_df.iloc[0]","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:24:17.700345Z","iopub.execute_input":"2022-12-16T10:24:17.700721Z","iopub.status.idle":"2022-12-16T10:24:17.710761Z","shell.execute_reply.started":"2022-12-16T10:24:17.700683Z","shell.execute_reply":"2022-12-16T10:24:17.709444Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = CustomDataset(new_df)\nloader = DataLoader(\n     dataset=ds,\n     batch_size=1,\n)\nlen(loader)","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:24:17.994261Z","iopub.execute_input":"2022-12-16T10:24:17.994605Z","iopub.status.idle":"2022-12-16T10:24:18.001552Z","shell.execute_reply.started":"2022-12-16T10:24:17.994568Z","shell.execute_reply":"2022-12-16T10:24:18.000435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unet.eval()\nfor i, (image, mask) in enumerate(loader):\n    image = image.to(device)\n    \n    out = unet(image)\n    print(out)\n    \n    \n    \n    out = out.squeeze(0).cpu().detach().numpy()\n    \n    print(out)\n    out = out.transpose(1,2,0)\n    print(out.shape)\n    plt.imshow(out, cmap = 'gray')","metadata":{"execution":{"iopub.status.busy":"2022-12-16T10:24:18.115905Z","iopub.execute_input":"2022-12-16T10:24:18.116193Z","iopub.status.idle":"2022-12-16T10:24:22.54352Z","shell.execute_reply.started":"2022-12-16T10:24:18.116164Z","shell.execute_reply":"2022-12-16T10:24:22.542566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"markdown","source":"We are going to use U-Net model. A U-Net consists of an encoder (downsampler) and decoder (upsampler). In-order to learn robust features, and reduce the number of trainable parameters, a pretrained model can be used as the encoder.The encoder will be a pretrained MobileNetV2 model which is prepared and ready to use in tf.keras.applications. ","metadata":{}},{"cell_type":"markdown","source":"# Train the Model","metadata":{}},{"cell_type":"markdown","source":"Let's observe how the model improves while it is training. To accomplish this task, a callback function is defined below.","metadata":{}}]}