{"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":"Base: [IC2RGW:PyTorch Baseline Train&Inference](https://www.kaggle.com/code/myso1987/ic2rgw-pytorch-baseline-train-inference)","metadata":{}},{"cell_type":"markdown","source":"# Libraries","metadata":{}},{"cell_type":"code","source":"import sys\nsys.path.append(\"../input/pretrained-models-pytorch\")\nsys.path.append(\"../input/efficientnet-pytorch\")\nsys.path.append(\"/kaggle/input/smp-github/segmentation_models.pytorch-master\")\nsys.path.append(\"/kaggle/input/timm-pretrained-resnest/resnest/\")\nimport segmentation_models_pytorch as smp\nimport torch\nimport os\nimport matplotlib.pyplot as plt\nfrom tqdm.notebook import tqdm\nimport numpy as np\nimport pandas as pd\nimport torch.nn as nn\nfrom timm.scheduler import CosineLRScheduler\nimport copy\nimport wandb\nimport time\nimport torchvision.transforms as T","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":3.421775,"end_time":"2023-05-15T00:35:16.571754","exception":false,"start_time":"2023-05-15T00:35:13.149979","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:25.617732Z","iopub.execute_input":"2023-08-09T23:18:25.618117Z","iopub.status.idle":"2023-08-09T23:18:31.561431Z","shell.execute_reply.started":"2023-08-09T23:18:25.618079Z","shell.execute_reply":"2023-08-09T23:18:31.558206Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utilities","metadata":{}},{"cell_type":"code","source":"def get_device():\n    device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n    print(f\"Using {device} device\")\n    return device\n\ndevice = get_device()","metadata":{"papermill":{"duration":0.064303,"end_time":"2023-05-15T00:35:16.6412","exception":false,"start_time":"2023-05-15T00:35:16.576897","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:31.569467Z","iopub.execute_input":"2023-08-09T23:18:31.569847Z","iopub.status.idle":"2023-08-09T23:18:31.616135Z","shell.execute_reply.started":"2023-08-09T23:18:31.569809Z","shell.execute_reply":"2023-08-09T23:18:31.614223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Config","metadata":{}},{"cell_type":"code","source":"class CFG:\n    # Data\n    base_dir = \"../input/google-research-identify-contrails-reduce-global-warming\"\n    train_path = os.path.join(base_dir,\"train\")\n    val_path = os.path.join(base_dir,\"validation\")","metadata":{"papermill":{"duration":0.012225,"end_time":"2023-05-15T00:35:16.658379","exception":false,"start_time":"2023-05-15T00:35:16.646154","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:31.617332Z","iopub.execute_input":"2023-08-09T23:18:31.617728Z","iopub.status.idle":"2023-08-09T23:18:31.628588Z","shell.execute_reply.started":"2023-08-09T23:18:31.617695Z","shell.execute_reply":"2023-08-09T23:18:31.627471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"markdown","source":"### Reference\n[Visualizing Contrails](https://www.kaggle.com/code/inversion/visualizing-contrails)","metadata":{}},{"cell_type":"code","source":"_T14_BOUNDS = (243, 303)\n_CLOUD_TOP_TDIFF_BOUNDS = (-4, 5)\n_TDIFF_BOUNDS = (-4, 2)\n\ndef normalize_range(data, bounds):\n    \"\"\"Maps data to the range [0, 1].\"\"\"\n    return (data - bounds[0]) / (bounds[1] - bounds[0])\n\nclass Dataset(torch.utils.data.Dataset):\n    def __init__(self, data_path, image_size, mode='train'):\n        self.data_path = data_path\n        self.file_name = os.listdir(data_path)\n        self.mode = mode\n        self.image_size = image_size\n        if self.image_size != 256:\n            self.resize_image = T.transforms.Resize(image_size)\n        \n    def __len__(self):\n        return len(self.file_name)\n\n    def __getitem__(self, i):\n        band08 = np.load(os.path.join(self.data_path, self.file_name[i], 'band_08.npy'))\n        band11 = np.load(os.path.join(self.data_path, self.file_name[i], 'band_11.npy'))\n        band14 = np.load(os.path.join(self.data_path, self.file_name[i], 'band_14.npy'))\n        band15 = np.load(os.path.join(self.data_path, self.file_name[i], 'band_15.npy'))\n        \n        r = normalize_range(band15 - band14, _TDIFF_BOUNDS)\n        g = normalize_range(band14 - band11, _CLOUD_TOP_TDIFF_BOUNDS)\n        b = normalize_range(band14, _T14_BOUNDS)\n        n = (band08 - 230) / 20\n        x = np.transpose(np.stack([r, g, b, n], axis=2)[:,:,:,4],(2,0,1))\n        x_big = np.array(self.resize_image(torch.tensor(x)))\n            \n        if self.mode == 'train':\n            y = np.load(os.path.join(self.data_path, self.file_name[i], 'human_pixel_masks.npy')).astype(np.float32).transpose(2,0,1)\n        elif self.mode == 'test':\n            y = self.file_name[i]\n        \n        return x_big, x, y","metadata":{"papermill":{"duration":0.017522,"end_time":"2023-05-15T00:35:16.699306","exception":false,"start_time":"2023-05-15T00:35:16.681784","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:31.631851Z","iopub.execute_input":"2023-08-09T23:18:31.632802Z","iopub.status.idle":"2023-08-09T23:18:31.658894Z","shell.execute_reply.started":"2023-08-09T23:18:31.632748Z","shell.execute_reply":"2023-08-09T23:18:31.65808Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_size = 384\ndataset = Dataset(CFG.train_path, image_size)\nbig, a, b = dataset[3]\nprint(a.shape)\n\nplt.figure(figsize=(12, 6))\nax = plt.subplot(1, 2, 1)\nax.imshow(np.transpose(a[:3],(1,2,0)))\nax = plt.subplot(1, 2, 2)\nax.imshow(np.transpose(b,(1,2,0)), interpolation='none') \nplt.show()","metadata":{"papermill":{"duration":0.911202,"end_time":"2023-05-15T00:35:17.615302","exception":false,"start_time":"2023-05-15T00:35:16.7041","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:31.660186Z","iopub.execute_input":"2023-08-09T23:18:31.661139Z","iopub.status.idle":"2023-08-09T23:18:32.633556Z","shell.execute_reply.started":"2023-08-09T23:18:31.661101Z","shell.execute_reply":"2023-08-09T23:18:32.632725Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class EnsembleModel(nn.Module):\n    def __init__(self, model_list):\n        super().__init__()\n        self.model = nn.ModuleList()\n        for model_name in model_list:\n            _model =torch.load('/kaggle/input/contrail-models/' + model_name)\n            _model.cuda()\n            _model.eval()\n            self.model.append(_model)\n    \n    def forward(self,x):\n        output=[]\n        for m in self.model:\n            if image_size == 256:\n                output.append(m(x))\n            elif image_size != 256:\n                output.append(torch.nn.functional.interpolate(m(x), size=256, mode='bilinear')) # Mod tuned \n        output=torch.stack(output,dim=0)#.mean(0)\n        return output.mean(axis=0)\n\nclass MultiScaleEnsembleModel(nn.Module):\n    def __init__(self, model_list, small_models_first):\n        super().__init__()\n        self.model = nn.ModuleList()\n        self.small_models_first = small_models_first\n        for model_name in model_list:\n            _model =torch.load('/kaggle/input/contrail-models/' + model_name)\n            _model.cuda()\n            _model.eval()\n            self.model.append(_model)\n    \n    def forward(self, x, x_big):\n        output=[]\n        for m in range(len(self.model)):\n            c_model = self.model[m]\n            if m < self.small_models_first:\n                #print('small')\n                output.append(c_model(x))\n            else:\n                #print('big')\n                output.append(torch.nn.functional.interpolate(c_model(x_big), size=256, mode='bilinear')*1.3) \n        output=torch.stack(output,dim=0)#.mean(0)\n        return output.mean(axis=0) #[None,:,:,0] #.mean(axis=0)\n    \nmodel_list = ['model_648.pth','model_653.pth','model_654.pth','model_646.pth','model_649.pth','model_650.pth','model_638_over.pth', 'model_650_over.pth',\n              'model_653_big.pth','model_659_big.pth','model_661_big.pth','model_6612_big.pth']\nbest_model = MultiScaleEnsembleModel(model_list, small_models_first=8) \n# 256: ['model_648.pth','model_653.pth','model_654.pth','model_646.pth','model_649.pth','model_650.pth','model_638_over.pth', 'model_650_over.pth']\n# 384: ['model_653_big.pth','model_659_big.pth','model_661_big.pth','model_6613_big.pth']\nsigmoid = nn.Sigmoid()","metadata":{"papermill":{"duration":6.104629,"end_time":"2023-05-15T00:35:23.727688","exception":false,"start_time":"2023-05-15T00:35:17.623059","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:18:32.634524Z","iopub.execute_input":"2023-08-09T23:18:32.634903Z","iopub.status.idle":"2023-08-09T23:19:10.57812Z","shell.execute_reply.started":"2023-08-09T23:18:32.634867Z","shell.execute_reply":"2023-08-09T23:19:10.577076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Eval Check","metadata":{}},{"cell_type":"code","source":"class Dice(nn.Module):\n    def __init__(self, weight=None, size_average=True):\n        super(Dice, self).__init__()\n        self.sigmoid = nn.Sigmoid()\n    def forward(self, inputs, targets, smooth=1, th=0.5):\n        with torch.no_grad():\n            inputs = self.sigmoid(inputs) > th\n            inputs = inputs.view(-1)\n            targets = targets.view(-1)\n            intersection = (inputs * targets).sum()                            \n            dice = (2.*intersection + smooth)/(inputs.sum() + targets.sum() + smooth)  \n        return dice, intersection.item(), inputs.sum().item(), targets.sum().item()\ndice = Dice()","metadata":{"papermill":{"duration":0.018966,"end_time":"2023-05-15T00:35:23.758237","exception":false,"start_time":"2023-05-15T00:35:23.739271","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-08-09T23:19:10.580112Z","iopub.execute_input":"2023-08-09T23:19:10.580705Z","iopub.status.idle":"2023-08-09T23:19:10.5904Z","shell.execute_reply.started":"2023-08-09T23:19:10.580669Z","shell.execute_reply":"2023-08-09T23:19:10.588479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if False:\n    batch_size = 8 # CARE TO ADJUST IN TEST TOO!\n    val_dataset = Dataset(CFG.val_path, image_size=image_size, mode='train')  # band away and mode to val\n    val_loader = torch.utils.data.DataLoader(val_dataset, batch_size=batch_size, shuffle=True, num_workers=2, drop_last=False, pin_memory=True)\n    \n    outputs = []\n    labels = []\n    device = 'cuda'\n    with torch.no_grad():\n        for i_val, (X_big, X, y) in enumerate(tqdm(val_loader)):\n            X = X.to(device).float()\n            X_big = X_big.to(device).float()\n            y = y.to(device).float()\n            pred = best_model(X, X_big)                     #best_model\n            outputs.append(pred)\n            labels.append(y)\n    all_preds = torch.cat(outputs)\n    all_labels = torch.cat(labels)\n    outputs = 0\n    best = 0\n    for i in range(1,100):\n        th = i * 0.01\n        dice_temp, _, pred_sum, _ = dice(all_preds, all_labels, th=th)\n        #print(dice_temp,pred_sum, th)\n        if dice_temp > best:\n            best = dice_temp\n    print(best)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T23:31:24.877627Z","iopub.execute_input":"2023-08-09T23:31:24.877996Z","iopub.status.idle":"2023-08-09T23:31:24.888892Z","shell.execute_reply.started":"2023-08-09T23:31:24.877965Z","shell.execute_reply":"2023-08-09T23:31:24.887663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict and submit","metadata":{}},{"cell_type":"markdown","source":"### Reference\n[Contrails - RLE Submission](https://www.kaggle.com/code/inversion/contrails-rle-submission)","metadata":{}},{"cell_type":"code","source":"def rle_encode(x, fg_val=1):\n    \"\"\"\n    Args:\n        x:  numpy array of shape (height, width), 1 - mask, 0 - background\n    Returns: run length encoding as list\n    \"\"\"\n    dots = np.where(\n        x.T.flatten() == fg_val)[0]  # .T sets Fortran order down-then-right\n    run_lengths = []\n    prev = -2\n    for b in dots:\n        if b > prev + 1:\n            run_lengths.extend((b + 1, 0))\n        run_lengths[-1] += 1\n        prev = b\n    return run_lengths\n\n\ndef list_to_string(x):\n    \"\"\"\n    Converts list to a string representation\n    Empty list returns '-'\n    \"\"\"\n    if x: # non-empty list\n        s = str(x).replace(\"[\", \"\").replace(\"]\", \"\").replace(\",\", \"\")\n    else:\n        s = '-'\n    return s\n\ndef rle_decode(mask_rle, shape=(256, 256)):\n    '''\n    mask_rle: run-length as string formatted (start length)\n              empty predictions need to be encoded with '-'\n    shape: (height, width) of array to return \n    Returns numpy array, 1 - mask, 0 - background\n    '''\n    img = np.zeros(shape[0]*shape[1], dtype=np.uint8)\n    if mask_rle != '-': \n        s = mask_rle.split()\n        starts, lengths = [np.asarray(x, dtype=int) for x in (s[0:][::2], s[1:][::2])]\n        starts -= 1\n        ends = starts + lengths\n        for lo, hi in zip(starts, ends):\n            img[lo:hi] = 1\n    return img.reshape(shape, order='F')  # Needed to align to RLE direction","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-08-09T23:31:26.216973Z","iopub.execute_input":"2023-08-09T23:31:26.217657Z","iopub.status.idle":"2023-08-09T23:31:26.229561Z","shell.execute_reply.started":"2023-08-09T23:31:26.217622Z","shell.execute_reply":"2023-08-09T23:31:26.228203Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_recs = os.listdir(os.path.join(CFG.base_dir,\"test\"))\nprint(test_recs)","metadata":{"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-08-09T23:31:26.871382Z","iopub.execute_input":"2023-08-09T23:31:26.871695Z","iopub.status.idle":"2023-08-09T23:31:26.878819Z","shell.execute_reply.started":"2023-08-09T23:31:26.871668Z","shell.execute_reply":"2023-08-09T23:31:26.877662Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_size = 8\ntest_dataset = Dataset('/kaggle/input/google-research-identify-contrails-reduce-global-warming/test', image_size=image_size, mode='test')\ntest_loader = torch.utils.data.DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=2, drop_last=False)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T23:31:27.861825Z","iopub.execute_input":"2023-08-09T23:31:27.862799Z","iopub.status.idle":"2023-08-09T23:31:27.868836Z","shell.execute_reply.started":"2023-08-09T23:31:27.86276Z","shell.execute_reply":"2023-08-09T23:31:27.867829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"threshold = 0.75\nsubmission = pd.read_csv('/kaggle/input/google-research-identify-contrails-reduce-global-warming/sample_submission.csv', index_col='record_id')\nwith torch.no_grad():\n    for X_big, X, rec in test_loader:\n        X = X.to(device)\n        X_big = X_big.to(device)\n        pred = best_model(X, X_big)\n        pred = sigmoid(pred)\n        pred = pred[:,0,:,:].cpu().detach().numpy().copy()\n        mask = np.zeros((len(rec), 256, 256))\n        mask[pred>=threshold] = 1    \n        for file_id, file_name in enumerate(rec):\n            submission.loc[int(file_name), 'encoded_pixels'] = list_to_string(rle_encode(mask[file_id,:,:])) #filename\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T23:31:30.147338Z","iopub.execute_input":"2023-08-09T23:31:30.147696Z","iopub.status.idle":"2023-08-09T23:31:31.351315Z","shell.execute_reply.started":"2023-08-09T23:31:30.147667Z","shell.execute_reply":"2023-08-09T23:31:31.349987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-08-09T23:31:33.84531Z","iopub.execute_input":"2023-08-09T23:31:33.845739Z","iopub.status.idle":"2023-08-09T23:31:33.853115Z","shell.execute_reply.started":"2023-08-09T23:31:33.845707Z","shell.execute_reply":"2023-08-09T23:31:33.852004Z"},"trusted":true},"execution_count":null,"outputs":[]}]}