{"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":"!pip install segmentation_models_pytorch --quiet","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-24T13:45:24.823683Z","iopub.execute_input":"2023-05-24T13:45:24.824591Z","iopub.status.idle":"2023-05-24T13:45:46.896191Z","shell.execute_reply.started":"2023-05-24T13:45:24.824543Z","shell.execute_reply":"2023-05-24T13:45:46.895167Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import csv\nfrom torch import nn\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nimport numpy as np\nimport random\nfrom random import randrange, shuffle\nfrom matplotlib import pyplot as plt\nimport matplotlib.patches as patches\nfrom torchvision import transforms\nfrom torchvision.transforms.functional import rotate\nimport torchvision\nimport cv2\nimport time, glob\nimport PIL\nimport pandas as pd \nimport torch.utils.data as data\nfrom tqdm import tqdm\nimport csv\nfrom segmentation_models_pytorch.encoders import get_preprocessing_fn\nimport segmentation_models_pytorch as smp\nfrom segmentation_models_pytorch import utils\nimport glob\nfrom tqdm import tqdm\n\nROOT_DIR = \"../input/airbus-ship-detection\"\n","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:16:59.087965Z","iopub.execute_input":"2023-05-21T17:16:59.088323Z","iopub.status.idle":"2023-05-21T17:16:59.100256Z","shell.execute_reply.started":"2023-05-21T17:16:59.088294Z","shell.execute_reply":"2023-05-21T17:16:59.099503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\" Read CSV File \"\"\"\n\nmasks = pd.read_csv(f\"{ROOT_DIR}/train_ship_segmentations_v2.csv\")\nmasks.head()","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:18:06.867136Z","iopub.execute_input":"2023-05-21T17:18:06.867516Z","iopub.status.idle":"2023-05-21T17:18:07.159258Z","shell.execute_reply.started":"2023-05-21T17:18:06.867489Z","shell.execute_reply":"2023-05-21T17:18:07.158220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# RLE\n\n    - encoder\n    - decoder ","metadata":{}},{"cell_type":"code","source":"def rle_encoder(image_mask):\n    \n    \"\"\" Change from 2d to 1d (x_size*y_size, 1) \n        for example: [[1, 2] , [3, 4]] -> [1,2,3,4] \n    \n    \"\"\"\n    size = image_mask.shape[0]*image_mask.shape[1]\n\n    \"\"\" Transpose operation \"\"\"\n    image_mask = image_mask.T\n    image_mask = image_mask.reshape(size)\n    result = \"\"\n    pointer = 0\n    count = 0\n    for pointer in range(size):\n\n        if image_mask[pointer]:\n            count += 1\n        elif count > 0:\n            result += f\"{pointer-count + 1} {count} \"\n            count = 0\n\n    return result if len(result) > 0 else np.nan\n\n\ndef rle_decoder(encodedPixels:list,shape:tuple):\n    x_size = shape[0]\n    y_size = shape[1]\n    img_mask = np.zeros(x_size*y_size, dtype=np.uint8)\n    \n    for encoded in encodedPixels:\n        mask_list = encoded.split()\n        \n        for inx in range(0,len(mask_list),2):\n            location = int(mask_list[inx]) - 1\n            length = int(mask_list[inx+1])\n            for l in range(location,location+length):\n                try:\n                    img_mask[l] = 1;\n                except IndexError as e:\n                    print(l)\n                    print(location,location+length)\n                    raise e\n            \n    \"\"\" Change from 1d to 2d (x_size,y_size) \n        for example: [1,2,3,4] - > [[1, 2] , [3, 4]]\n    \n    \"\"\"\n    img_mask = img_mask.reshape((x_size,y_size))\n    \n    \"\"\" Transpose operation \"\"\"\n    img_mask = img_mask.T\n\n    return img_mask","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:18:09.356295Z","iopub.execute_input":"2023-05-21T17:18:09.356876Z","iopub.status.idle":"2023-05-21T17:18:09.367680Z","shell.execute_reply.started":"2023-05-21T17:18:09.356836Z","shell.execute_reply":"2023-05-21T17:18:09.366417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<b>Testing for an encoder and decoder that work correctly for submission.<b>","metadata":{}},{"cell_type":"code","source":"image_encode = masks.loc[masks['ImageId'] == \"000155de5.jpg\"]['EncodedPixels'].values\nprint(f\"CSV Encoder: {image_encode[0][:150]}\")\nprint(f\"RLE Encoder: {rle_encoder(rle_decoder(image_encode,(768,768)))[:150]}\")","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:21:00.567985Z","iopub.execute_input":"2023-05-21T17:21:00.568330Z","iopub.status.idle":"2023-05-21T17:21:01.046386Z","shell.execute_reply.started":"2023-05-21T17:21:00.568305Z","shell.execute_reply":"2023-05-21T17:21:01.045193Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masks = pd.read_csv(f\"{ROOT_DIR}/train_ship_segmentations_v2.csv\") \n\nSHIP_EXIEST = 10000\nNO_SHIP = 2000\n\nnotNan_masks = masks.loc[~masks['EncodedPixels'].isna()]\nnan_masks = masks.loc[masks['EncodedPixels'].isna()]\n\npaths = list(notNan_masks.ImageId.array[:6800]) #+ list(nan_masks.ImageId.array[:NO_SHIP])\n\nprint(len(paths))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# DataSet Object","metadata":{}},{"cell_type":"code","source":"class AirbusShipDataset(Dataset):\n    \n    def __init__(self, root_paths,paths, labels_csv=None, transform=None,train=True,size=224,preprocessing_fn=None):\n        self.root_paths = root_paths\n        self.paths = paths\n\n        if labels_csv:\n            self.masks = pd.read_csv(labels_csv)\n            self.masks = masks[~masks.EncodedPixels.isna()] \n        else:\n            self.masks = pd.DataFrame()\n        self.transform = transform\n        self.train = train\n        self.size = size\n\n        self.preprocessing_fn = preprocessing_fn\n\n    def __len__(self):\n        return len(self.paths)\n    \n    def getranditem(self):\n        ImageId = self.paths[randrange(self.__len__())]\n         \n        if not self.masks.empty:\n            img_masks = self.masks.loc[self.masks['ImageId'] == ImageId, 'EncodedPixels'].tolist()\n\n            all_masks = rle_decoder(img_masks, (768, 768))\n        \n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n\n        return image, all_masks\n\n        \n    \n    def __getitem__(self, idx):\n\n        ImageId = self.paths[idx]\n\n        if not self.masks.empty:\n            img_masks = self.masks.loc[self.masks['ImageId'] == ImageId, 'EncodedPixels'].tolist()\n\n            all_masks = rle_decoder(img_masks, (768, 768))\n\n            all_masks = cv2.resize(all_masks, (224, 224))\n\n        \n        img_path = f\"{ROOT_DIR}/{self.root_paths}/{ImageId}\"\n        image = cv2.imread(img_path)\n        image = cv2.resize(image,(self.size,self.size))\n        image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)\n\n        #image = self.preprocessing_fn(image)\n\n        if self.train:\n             image = transforms.ToPILImage()(image)\n\n        if self.transform:\n             image = self.transform(image)\n        \n\n\n        \n        if not self.train:\n            #return image.transpose([2, 0, 1]).astype(np.float32), ImageId\n            return image.transpose([2, 0, 1]).astype(np.float32), ImageId\n\n        \n        #return image.transpose([2, 0, 1]).astype(np.float32), all_masks\n        return image, all_masks","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:21:02.512522Z","iopub.execute_input":"2023-05-21T17:21:02.512878Z","iopub.status.idle":"2023-05-21T17:21:02.521579Z","shell.execute_reply.started":"2023-05-21T17:21:02.512852Z","shell.execute_reply":"2023-05-21T17:21:02.520896Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ENCODER = 'resnet18'\nENCODER_WEIGHTS = 'imagenet'\nCLASSES = ['ships']\nACTIVATION = 'sigmoid' # could be None for logits or 'softmax2d' for multicalss segmentation\nDEVICE = 'cuda' if torch.cuda.is_available() else 'cpu'\n\nLOAD_MODEL = False\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\ntrain_transform = transforms.Compose([transforms.RandomHorizontalFlip(),\n                                        transforms.RandomRotation((-120, 120)),\n                                        transforms.ToTensor(),\n                                        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])\n\ntrainAirbusShipDataset = AirbusShipDataset(\"train_v2\",\n                                           paths, \n                                           f\"{ROOT_DIR}/train_ship_segmentations_v2.csv\", \n                                           transform =train_transform,\n                                           train=True,\n                                           preprocessing_fn=preprocessing_fn)\ntrainLoaderAirbusShipDataset = torch.utils.data.DataLoader(trainAirbusShipDataset, batch_size=64, shuffle=True, num_workers=0)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Images","metadata":{}},{"cell_type":"code","source":"print(f\"Images\")\nfig, axs = plt.subplots(4, 2,figsize=(10, 15))\nfor img_indx in range(4):\n  img, mask = trainAirbusShipDataset.getranditem()\n  axs[img_indx][0].imshow(img, cmap=\"gray\")\n  axs[img_indx][0].set_xlabel(f\"Input\")\n  axs[img_indx][1].imshow(mask, cmap=\"gray\")\n  axs[img_indx][1].set_xlabel(f\"Mask\")\nfor ax in axs.flat:\n  ax.set(xticks=[], yticks=[], ylabel='')\n\nimg, _ = trainAirbusShipDataset.getranditem()\nprint(f\"Shape: {img.shape}\")","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:23:25.828742Z","iopub.execute_input":"2023-05-21T17:23:25.829080Z","iopub.status.idle":"2023-05-21T17:23:25.836245Z","shell.execute_reply.started":"2023-05-21T17:23:25.829057Z","shell.execute_reply":"2023-05-21T17:23:25.834631Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# UNet","metadata":{}},{"cell_type":"code","source":"\nprint(f\"DEVICE: {DEVICE}\")\n\nif LOAD_MODEL:\n    print(f\"Load Model UNet\")\n    model = torch.load('./best_model.pth')\nelse:\n    print(f\"Create Model UNet\")\n    model = smp.FPN(encoder_depth = 5,\n        encoder_name=ENCODER, \n        encoder_weights=ENCODER_WEIGHTS, \n        classes=len(CLASSES), \n        activation=ACTIVATION,\n    )\n\npreprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)\nloss = utils.losses.DiceLoss()\nmetrics = [\n    smp.utils.metrics.IoU(threshold=0.5),\n]\n\noptimizer = torch.optim.Adam([ \n    dict(params=model.parameters(), lr=0.0001),\n])\n\ntrain_epoch = smp.utils.train.TrainEpoch(model, \n                                        loss=loss, \n                                        metrics=metrics, \n                                        optimizer=optimizer,\n                                        device=DEVICE,\n                                        verbose=True,)","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:23:27.883221Z","iopub.execute_input":"2023-05-21T17:23:27.883657Z","iopub.status.idle":"2023-05-21T17:23:28.409391Z","shell.execute_reply.started":"2023-05-21T17:23:27.883623Z","shell.execute_reply":"2023-05-21T17:23:28.407947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train & Validation","metadata":{}},{"cell_type":"code","source":"max_score = 0\n\nfor i in range(0, 3):\n    \n    print('\\nEpoch: {}'.format(i))\n    train_logs = train_epoch.run(trainLoaderAirbusShipDataset)\n    #valid_logs = valid_epoch.run(valid_loader)\n    \n    # do something (save model, change lr, etc.)\n    if max_score < train_logs['iou_score']:\n        max_score = train_logs['iou_score']\n        torch.save(model, './best_model.pth')\n        print('Model saved!')\n        \n    if i == 4:\n        optimizer.param_groups[0]['lr'] = 1e-5\n        print('Decrease decoder learning rate to 1e-5!')","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:23:31.441117Z","iopub.execute_input":"2023-05-21T17:23:31.441526Z","iopub.status.idle":"2023-05-21T17:23:31.449388Z","shell.execute_reply.started":"2023-05-21T17:23:31.441494Z","shell.execute_reply":"2023-05-21T17:23:31.448256Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Test & Submission","metadata":{}},{"cell_type":"code","source":"\ntest_path = [path.split(\"/\")[-1] for path in glob.glob(f\"{ROOT_DIR}/test_v2/*\")]\ntestAirbusShipDataset = AirbusShipDataset(\"test_v2\",test_path, None, transform =None,train=False,preprocessing_fn=preprocessing_fn)\ntestLoaderAirbusShipDataset = torch.utils.data.DataLoader(testAirbusShipDataset, batch_size=64, shuffle=False, num_workers=0)","metadata":{"execution":{"iopub.status.busy":"2023-05-21T17:23:33.601954Z","iopub.execute_input":"2023-05-21T17:23:33.602326Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = []\nthreshold = 0.5\n\nwith torch.no_grad():\n    device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    for batch_idx, (images, paths) in enumerate(testLoaderAirbusShipDataset):\n        images = images.to(device)\n        predictions = train_epoch.model(images)\n        predictions[predictions >= threshold] = 1\n        predictions[predictions < threshold] = 0\n\n        for pred,path in zip(predictions,paths):\n            img_array = pred.squeeze().cpu().numpy()\n            submission.append({\"ImageId\":path,\"EncodedPixels\":rle_encoder(img_array)})\n\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(f\"Images\")\nfig, axs = plt.subplots(4, 2,figsize=(10, 15))\ncount = 0\nfor img in submission[10:14]:\n    image = cv2.imread(f\"{ROOT_DIR}/test_v2/{img['ImageId']}\")\n    axs[count][0].imshow(image)\n    axs[count][0].set_xlabel(f\"Test\")\n    axs[count][1].imshow(rle_decoder([img['EncodedPixels']],(768,768)), cmap=\"gray\")\n    axs[count][1].set_xlabel(f\"Predicte\")\n    count += 1\nfor ax in axs.flat:\n    ax.set(xticks=[], yticks=[], ylabel='')","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predict = pd.DataFrame(submission)\npredict.to_csv('submission.csv', index=False)","metadata":{},"execution_count":null,"outputs":[]}]}