{"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":"%%bash\n#rm -rf *.oof\n#rm -rf gt*.oof\n#rm -rf /kaggle/working/r50delr5e4dlr1e3focal512f5dedup_0.oof","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.801257Z","iopub.execute_input":"2023-08-09T21:58:47.801637Z","iopub.status.idle":"2023-08-09T21:58:47.814404Z","shell.execute_reply.started":"2023-08-09T21:58:47.801606Z","shell.execute_reply":"2023-08-09T21:58:47.813347Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import yaml\n\nfrom easydict import EasyDict as edict","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.816651Z","iopub.execute_input":"2023-08-09T21:58:47.817684Z","iopub.status.idle":"2023-08-09T21:58:47.822228Z","shell.execute_reply.started":"2023-08-09T21:58:47.817648Z","shell.execute_reply":"2023-08-09T21:58:47.821235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from pathlib import Path\nimport os,joblib\nimport random\nimport math\nimport gc\nfrom collections import defaultdict\n\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport cv2\n\nimport torch\nfrom torch import nn\nfrom torchvision import transforms\nfrom torch.utils.data import Dataset, DataLoader\nimport albumentations as A\nimport torch.nn.functional as F\n\nfrom PIL import Image\nfrom tqdm.notebook import tqdm\nfrom transformers import get_cosine_schedule_with_warmup\nfrom tqdm.auto import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-08-09T21:58:47.833191Z","iopub.execute_input":"2023-08-09T21:58:47.833471Z","iopub.status.idle":"2023-08-09T21:58:47.840749Z","shell.execute_reply.started":"2023-08-09T21:58:47.833447Z","shell.execute_reply":"2023-08-09T21:58:47.839741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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\")\nimport segmentation_models_pytorch as smp\n\nprint(f\"Segmentation Models version: {smp.__version__}\")","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.846149Z","iopub.execute_input":"2023-08-09T21:58:47.847009Z","iopub.status.idle":"2023-08-09T21:58:47.858462Z","shell.execute_reply.started":"2023-08-09T21:58:47.846981Z","shell.execute_reply":"2023-08-09T21:58:47.857422Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    cv_check = False\n    batch_size = 16\n    seed = 42\n    thr = 0.5\n    \n    seg_model = \"Unet++\"\n    encoder = \"efficientnet-b7\"\n    pretrained = False\n    weights = None\n    classes = ['contrail']\n    activation = None\n    in_chans = 3\n    n_folds = 7\n    \n    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\n    \n    image_size = 512\n    \n    model_ckpt_dir = \"/kaggle/input/eb7elr5e4dlr1e3focal512f5dedup\"\n    \nclass Paths:\n    data = \"/kaggle/input/google-research-identify-contrails-reduce-global-warming\"\n    data_root = \"/kaggle/input/google-research-identify-contrails-reduce-global-warming/test/\"\n    train_root = '/kaggle/input/contrails-dataset-ash-color/contrails/'\n    model_dirs1 = [\n        \"/kaggle/input/gr-icrgw-model-7folds/efficientnet-b5-7folds/efficientnet-b5-7folds\",\n        \"/kaggle/input/gr-icrgw-model-7folds/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s\", \n    ] \n    model_dirs = [\n        \"/kaggle/input/eb7elr5e4dlr1e3focal512f7dedupplr1\",\n        \"/kaggle/input/eb6elr5e4dlr1e3focal512f7dedupplr1\",\n        \"/kaggle/input/eb4elr5e4dlr1e3focal512f7dedupplr1\",\n        \"/kaggle/input/gr-icrgw-model-7folds/efficientnet-b5-7folds/efficientnet-b5-7folds\", # xiaoyi,\n        \"/kaggle/input/gr-icrgw-model-7folds/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s\"\n    ]","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.860698Z","iopub.execute_input":"2023-08-09T21:58:47.861463Z","iopub.status.idle":"2023-08-09T21:58:47.871679Z","shell.execute_reply.started":"2023-08-09T21:58:47.861426Z","shell.execute_reply":"2023-08-09T21:58:47.870498Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def dice_coef(y_true, y_pred, thr=0.5, epsilon=0.001):\n    y_true = y_true.flatten()\n    y_pred = (y_pred>thr).astype(np.float32).flatten()\n    inter = (y_true*y_pred).sum()\n    den = y_true.sum() + y_pred.sum()\n    dice = ((2*inter+epsilon)/(den+epsilon))\n    return dice","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.8783Z","iopub.execute_input":"2023-08-09T21:58:47.879607Z","iopub.status.idle":"2023-08-09T21:58:47.88797Z","shell.execute_reply.started":"2023-08-09T21:58:47.879581Z","shell.execute_reply":"2023-08-09T21:58:47.886956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_parquet(\"/kaggle/input/gricrgw-splits/dedup-fold-splits-7f.parquet\")\ntrain_df[\"path\"] = Paths.train_root + train_df[\"record_id\"].astype(str)+ '.npy'\ntrain_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.890197Z","iopub.execute_input":"2023-08-09T21:58:47.891397Z","iopub.status.idle":"2023-08-09T21:58:47.934777Z","shell.execute_reply.started":"2023-08-09T21:58:47.891331Z","shell.execute_reply":"2023-08-09T21:58:47.933508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_cfg(cfg_path: str):\n    with open(cfg_path, \"r\") as f:\n        cfg = edict(yaml.safe_load(f))\n    return cfg\n\n\n\ndef set_seed(seed=1234):\n    random.seed(seed)\n    np.random.seed(seed)\n    os.environ[\"PYTHONHASHSEED\"] = str(seed)\n    \n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = False\n    torch.backends.cudnn.benchmark = True","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.937411Z","iopub.execute_input":"2023-08-09T21:58:47.937795Z","iopub.status.idle":"2023-08-09T21:58:47.944323Z","shell.execute_reply.started":"2023-08-09T21:58:47.937741Z","shell.execute_reply":"2023-08-09T21:58:47.943196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(Config.seed)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.946364Z","iopub.execute_input":"2023-08-09T21:58:47.946807Z","iopub.status.idle":"2023-08-09T21:58:47.962703Z","shell.execute_reply.started":"2023-08-09T21:58:47.946731Z","shell.execute_reply":"2023-08-09T21:58:47.961918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Data Preparation","metadata":{}},{"cell_type":"code","source":"filenames = os.listdir(Paths.data_root)\ntest_df = pd.DataFrame(filenames, columns=[\"record_id\"])\n\ntest_df[\"path\"] = Paths.data_root + test_df[\"record_id\"].astype(str)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.965215Z","iopub.execute_input":"2023-08-09T21:58:47.966185Z","iopub.status.idle":"2023-08-09T21:58:47.976238Z","shell.execute_reply.started":"2023-08-09T21:58:47.966155Z","shell.execute_reply":"2023-08-09T21:58:47.974974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.977734Z","iopub.execute_input":"2023-08-09T21:58:47.978076Z","iopub.status.idle":"2023-08-09T21:58:47.990334Z","shell.execute_reply.started":"2023-08-09T21:58:47.978047Z","shell.execute_reply":"2023-08-09T21:58:47.98909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_size_transform(\n    cfg\n):\n    return A.Compose([\n        A.Resize(cfg.model.image_size, cfg.model.image_size, interpolation=cv2.INTER_LANCZOS4, always_apply=True)\n    ])","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:47.992239Z","iopub.execute_input":"2023-08-09T21:58:47.992592Z","iopub.status.idle":"2023-08-09T21:58:47.999086Z","shell.execute_reply.started":"2023-08-09T21:58:47.992534Z","shell.execute_reply":"2023-08-09T21:58:47.997989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ContrailsDataset(torch.utils.data.Dataset):\n    def __init__(self, df, cfg, transform=None):\n        self.df = df\n        self.cfg = cfg\n        self.transform = transform\n        self.transform_size = get_size_transform(cfg)\n    \n    def read_record(self, directory):\n        record_data = {}\n        for x in [\n            \"band_11\", \n            \"band_14\", \n            \"band_15\"\n        ]:\n\n            record_data[x] = np.load(os.path.join(directory, x + \".npy\"))\n\n        return record_data\n\n    def normalize_range(self, data, bounds):\n        \"\"\"Maps data to the range [0, 1].\"\"\"\n        return (data - bounds[0]) / (bounds[1] - bounds[0])\n    \n    def get_false_color(self, record_data):\n        _T11_BOUNDS = (243, 303)\n        _CLOUD_TOP_TDIFF_BOUNDS = (-4, 5)\n        _TDIFF_BOUNDS = (-4, 2)\n        \n        N_TIMES_BEFORE = 4\n\n        r = self.normalize_range(record_data[\"band_15\"] - record_data[\"band_14\"], _TDIFF_BOUNDS)\n        g = self.normalize_range(record_data[\"band_14\"] - record_data[\"band_11\"], _CLOUD_TOP_TDIFF_BOUNDS)\n        b = self.normalize_range(record_data[\"band_14\"], _T11_BOUNDS)\n        false_color = np.clip(np.stack([r, g, b], axis=2), 0, 1)\n        img = false_color[..., N_TIMES_BEFORE]\n\n        return img\n    \n    def __getitem__(self, index):\n        row = self.df.iloc[index]\n        con_path = row.path\n        data = self.read_record(con_path)    \n        \n        img = self.get_false_color(data)\n        \n        if self.transform is not None:\n            img = self.transform(image=img)[\"image\"]\n        \n        \n        if self.cfg.model.image_size != 256:\n            img = self.transform_size(image=img)[\"image\"]\n        \n        img = torch.tensor(img)\n        img = img.permute(2, 0, 1)\n            \n        return img.float()\n    \n    def __len__(self):\n        return len(self.df)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.066258Z","iopub.execute_input":"2023-08-09T21:58:48.066542Z","iopub.status.idle":"2023-08-09T21:58:48.079463Z","shell.execute_reply.started":"2023-08-09T21:58:48.066519Z","shell.execute_reply":"2023-08-09T21:58:48.078541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform_size = A.Compose(\n    [\n        A.Resize(\n            Config.image_size,\n            Config.image_size,\n            interpolation=cv2.INTER_LANCZOS4,\n            always_apply=True,\n        )\n    ]\n) \n\nclass ContrailsDatasetVal(torch.utils.data.Dataset):\n    def __init__(self, df,cfg, train=True, transform=None):\n        self.df = df\n        self.trn = train\n        self.transform = transform\n        self.cfg = cfg\n\n    def __getitem__(self, index):\n        row = self.df.iloc[index]\n        con_path = row.path\n        con = np.load(str(con_path))\n\n        img = con[..., :-1]\n        label = con[..., -1]\n\n        img = img.astype(np.float32)\n        label = label.astype(np.float32)\n\n        if self.transform is not None: \n            augmented = self.transform(image=img, mask=label)\n            img = augmented[\"image\"]\n            label = augmented[\"mask\"]\n\n        if self.cfg.model.image_size != 256:\n            img = transform_size(image=img)[\"image\"]\n\n        img = torch.tensor(img)\n        label = torch.tensor(label)\n\n        img = img.permute(2, 0, 1)\n\n        return img.float(), label.float()\n\n    def __len__(self):\n        return len(self.df)\n    \n    \nclass ContrailsDatasetVal2(torch.utils.data.Dataset):\n    def __init__(self, df, train=True, transform=None):\n        \n        self.df = df\n        self.trn = train\n        self.transform = transform\n    \n    def __getitem__(self, index):\n        row = self.df.iloc[index]\n        con_path = row.path\n        con = np.load(str(con_path))\n        \n        img = con[..., :-1]\n        label = con[..., -1]\n        \n        img = img.astype(np.float32)\n        label = label.astype(np.float32) \n        \n        if self.transform is not None:\n            img = self.transform(image=img)[\"image\"]\n                \n        if Config.image_size != 256:\n            img = transform_size(image=img)[\"image\"]\n        \n        img = torch.tensor(img)\n        label = torch.tensor(label)\n        \n        img = img.permute(2, 0, 1)\n            \n        return img.float(), label.float()\n    \n    def __len__(self):\n        return len(self.df) \n","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.088611Z","iopub.execute_input":"2023-08-09T21:58:48.089609Z","iopub.status.idle":"2023-08-09T21:58:48.104831Z","shell.execute_reply.started":"2023-08-09T21:58:48.089577Z","shell.execute_reply":"2023-08-09T21:58:48.103837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"SEG_MODEL_MAP = {\n    \"Unet\": smp.Unet,\n    \"Unet++\": smp.UnetPlusPlus,\n    \"MAnet\": smp.MAnet,\n    \"Linknet\": smp.Linknet,\n    \"FPN\": smp.FPN,\n    \"PSPNet\": smp.PSPNet,\n    \"PAN\": smp.PAN,\n    \"DeepLabV3\": smp.DeepLabV3,\n    \"DeepLabV3+\": smp.DeepLabV3Plus,\n}\n\n\nclass SegModel(nn.Module):\n    def __init__(self, cfg):\n        super().__init__()\n        self.cfg = cfg\n        self.model = SEG_MODEL_MAP[cfg.model.seg_model](\n            encoder_name=cfg.model.encoder,\n            encoder_weights=None,\n            decoder_use_batchnorm=True,\n            classes=len(cfg.model.classes),\n            activation=cfg.model.activation,\n        )\n\n    def forward(self, imgs):\n        x = imgs\n        logits = self.model(x)\n        if self.cfg.model.image_size != 256:\n            logits = F.interpolate(logits, size=(256, 256), mode=\"nearest-exact\")\n        return logits.view(-1, 256, 256)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.121276Z","iopub.execute_input":"2023-08-09T21:58:48.123193Z","iopub.status.idle":"2023-08-09T21:58:48.131283Z","shell.execute_reply.started":"2023-08-09T21:58:48.123169Z","shell.execute_reply":"2023-08-09T21:58:48.130232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.set_grad_enabled(False)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.162222Z","iopub.execute_input":"2023-08-09T21:58:48.162892Z","iopub.status.idle":"2023-08-09T21:58:48.168816Z","shell.execute_reply.started":"2023-08-09T21:58:48.162868Z","shell.execute_reply":"2023-08-09T21:58:48.167833Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_predictions_oof(\n    df,\n    model_dir,\n    transform=None,\n    batch_size=32,\n    num_workers=2,\n    num_folds=5,\n    cfg=None,\n    device=torch.device(\"cuda\"),\n    train_df=train_df\n):\n    if cfg is None:\n        cfg = load_cfg(f\"{model_dir}/cfg.yaml\") \n    tag = model_dir[(model_dir.rfind(\"/\")+1):] \n    tag = tag+\"_tta\"  if transform is not None else tag\n    print(tag)\n    for fold in range(0,1):#range(num_folds):\n        model_ckpt = f\"{model_dir}/model-fold{fold}.pth\"\n        data = torch.load(model_ckpt, map_location=torch.device('cpu')) \n        train_ds = ContrailsDatasetVal(train_df[train_df.fold==fold], cfg, transform=transform)\n        val_dl = DataLoader(train_ds, batch_size=Config.batch_size, shuffle=False, num_workers=num_workers, drop_last=False) \n        \n        if \"state_dict\" in data:\n            state_dict = data[\"state_dict\"]\n        else:\n            state_dict = data\n        if \"val_dice\" in data:\n            print(\"val_dice\",data[\"val_dice\"])\n            \n        preds = [] \n        # Only testing Fold 0     \n        if not os.path.exists(f\"{tag}_{fold}.oof\") and fold ==0:   \n            model = SegModel(cfg).to(device)\n            model.load_state_dict(state_dict)\n            model.eval()\n            gt=[]\n            preds_cv = []\n            pbar_val = tqdm(val_dl, total=len(val_dl), desc=f'Fold {fold}')   \n            \n            for X,y in pbar_val: \n                X = X.to(device) \n                gt.append(y.cpu().numpy())\n                preds_ = model(X).sigmoid()\n                preds_cv.append(preds_.cpu().numpy())     \n            if transform is not None:\n                print(\"transforming back =>\")\n                preds_cv=np.concatenate(preds_cv,axis=0)\n                for i in range(preds_cv.shape[0]):\n                    preds_cv[i] = transform(image=preds_cv[i])[\"image\"]    \n                joblib.dump(preds_cv,f\"{tag}_{fold}.oof\")\n            else:    \n                joblib.dump(np.concatenate(preds_cv,axis=0),f\"{tag}_{fold}.oof\")\n            if not os.path.exists(f\"gt_{fold}.oof\") and transform is None:\n                print(\"Saving GT =>\")\n                joblib.dump(np.concatenate(gt),f\"gt_{fold}.oof\")\n            del gt,preds_cv,pbar_val;gc.collect()\n            del model\n        preds = joblib.load(f\"{tag}_{fold}.oof\")\n        if fold ==0:   \n            print(preds.shape)\n            print(\"dice calc\",dice_coef(joblib.load(f\"gt_{fold}.oof\"),preds))     \n        \n        torch.cuda.empty_cache()\n        gc.collect()  \n    return preds","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.283219Z","iopub.execute_input":"2023-08-09T21:58:48.285424Z","iopub.status.idle":"2023-08-09T21:58:48.302611Z","shell.execute_reply.started":"2023-08-09T21:58:48.285383Z","shell.execute_reply":"2023-08-09T21:58:48.30171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class SegNetV(nn.Module):\n    def __init__(self, cfg):\n        super(SegNetV, self).__init__()\n\n        self.cfg = cfg\n        self.training = True\n\n        if cfg.net.lower() == \"unet\":\n            self.model = smp.Unet(\n                encoder_name=cfg.encoder,\n                encoder_weights=cfg.weights,\n                decoder_use_batchnorm=True,\n                classes=len(cfg.classes),\n                activation=cfg.activation,\n            )\n        elif cfg.net.lower() == 'deeplabv3':\n            self.model = smp.DeepLabV3(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                #decoder_use_batchnorm=True\n                )\n        elif cfg.net.lower() == \"deeplabv3plus\":\n            self.model = smp.DeepLabV3Plus(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                #decoder_use_batchnorm=True\n                )\n        elif cfg.net.lower() == 'unetplusplus':\n            self.model = smp.UnetPlusPlus(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                decoder_use_batchnorm=True\n                )\n        else:\n            raise Exception(\"error net name\")\n\n        self.loss_fn = [smp.losses.DiceLoss(mode='binary'),smp.losses.FocalLoss(mode=\"binary\")]\n\n    def forward(self, imgs, targets):\n        #print('imgs:',imgs.shape, ' targets:',targets.shape)\n        x = imgs\n        y = targets\n\n        if Config.image_size != 256:\n            x = torch.nn.functional.interpolate(x,\n                                                size=Config.image_size,\n                                                mode='bilinear'\n                                               )\n        logits = self.model(x)\n        if Config.image_size != 256:\n            logits = torch.nn.functional.interpolate(logits,\n                                                size=256,\n                                                mode='bilinear'\n                                               )\n        loss = 0\n        for fn in self.loss_fn:\n            loss += fn(logits,y) \n        loss /= len(self.loss_fn) \n\n        return logits.sigmoid(),y ","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.315678Z","iopub.execute_input":"2023-08-09T21:58:48.316667Z","iopub.status.idle":"2023-08-09T21:58:48.331006Z","shell.execute_reply.started":"2023-08-09T21:58:48.316619Z","shell.execute_reply":"2023-08-09T21:58:48.329926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_preds(_type,encoder,net, ckpt,df,transform=None):\n    print(f\"Getting Preds for [{_type}] \")  \n    torch.set_grad_enabled(False) \n    i=0\n    ground_truths = []\n    mdl_cv_preds = [] \n    Config.encoder= encoder\n    Config.net= net  \n    for fold in range(1,2):  \n        mdl_nm = _type+\"_\"+ckpt[(ckpt.rfind(\"/\")+1):] \n        outfile=f\"{mdl_nm}_{fold}.npy\" \n        print(\"File \",outfile)\n        f= fold-1\n        if not os.path.exists(outfile): \n            valid_dl = DataLoader(ContrailsDatasetVal2( df[df.fold == f].reset_index(drop=True),train=False,transform=transform), batch_size=32, num_workers = 3)\n            gc.collect()\n            print(f\"Infer val model [{ckpt}] fold [{f}]\")\n            model = SegNetV(Config)\n            model.load_state_dict(torch.load(f\"{ckpt}{fold}.pth\", map_location=\"cpu\"))\n            torch.set_grad_enabled(False)\n            Config.encoder=encoder\n            Config.net=net\n            model = model.to(Config.device).eval()\n            preds = []\n            gp = []\n            pbar = tqdm(enumerate(valid_dl), total=len(valid_dl), desc='Valid')  \n            for step, (X, y) in pbar:\n                X, y = X.to(Config.device), y.to(Config.device) \n                y_hat,y_t = model(X,y)  \n                gp.append(y_t.cpu().detach().numpy()) \n                preds.append(y_hat.cpu().detach().numpy())\n            p=np.concatenate(preds,axis=0)    \n            if transform is not None:\n                print(\"DeAug\")\n                for _pc in range(p.shape[0]):\n                    p[_pc] = transform(image=p[_pc])[\"image\"]    \n            joblib.dump(p, outfile) \n            del model,valid_dl,y_hat,X,y,preds,pbar;gc.collect()\n            torch.cuda.empty_cache() \n        else: \n            print(f\"Load val model [{ckpt}] fold [{f}]\")\n            p=joblib.load(outfile) \n        gt = joblib.load(f\"gt_0.oof\")   \n        print(p.shape,gt.shape)\n        print(\"dice : \",dice_coef(gt,p))   \n        i+=1  \n    gc.collect() \n    return p","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.333233Z","iopub.execute_input":"2023-08-09T21:58:48.333586Z","iopub.status.idle":"2023-08-09T21:58:48.350141Z","shell.execute_reply.started":"2023-08-09T21:58:48.333556Z","shell.execute_reply":"2023-08-09T21:58:48.349073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_predictions(\n    df,\n    model_dir,\n    transform=None,\n    batch_size=32,\n    num_workers=2,\n    num_folds=Config.n_folds,\n    cfg=None,\n    device=torch.device(\"cuda\")\n):\n    if cfg is None:\n        cfg = load_cfg(f\"{model_dir}/cfg.yaml\")\n    test_ds = ContrailsDataset(df, cfg, transform=transform)\n    test_dl = DataLoader(test_ds, batch_size=batch_size, shuffle=False, num_workers=num_workers, drop_last=False, pin_memory=True)\n    \n    preds = None\n    for fold in range(num_folds):\n        model_ckpt = f\"{model_dir}/model-fold{fold}.pth\"\n        data = torch.load(model_ckpt, map_location=torch.device('cpu'))\n        if \"state_dict\" in data:\n            state_dict = data[\"state_dict\"]\n        else:\n            state_dict = data\n        if \"val_dice\" in data:\n            print(data[\"val_dice\"])\n        model = SegModel(cfg).to(device)\n        model.load_state_dict(state_dict)\n        model.eval()\n        fold_preds = []\n        pbar = tqdm(test_dl, total=len(test_dl), desc=f'Fold {fold}')\n        for X in pbar: \n            X = X.to(device)\n            fold_preds.append(model(X).sigmoid().cpu().numpy())\n        del model\n        torch.cuda.empty_cache()\n        gc.collect()\n        \n        # use in-place average to save memory\n        fold_preds = np.concatenate(fold_preds, axis=0) / num_folds\n        if preds is None:\n            preds = fold_preds\n        else:\n            preds += fold_preds\n            del fold_preds\n            gc.collect()\n    if transform is not None:\n        for i in range(len(preds)):\n            preds[i] = transform(image=preds[i])[\"image\"]\n    print(preds.shape)        \n    return preds","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.361694Z","iopub.execute_input":"2023-08-09T21:58:48.362489Z","iopub.status.idle":"2023-08-09T21:58:48.374944Z","shell.execute_reply.started":"2023-08-09T21:58:48.362457Z","shell.execute_reply":"2023-08-09T21:58:48.373977Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class SegNetX(nn.Module):\n    def __init__(self, cfg):\n        super(SegNetX, self).__init__()\n\n        self.cfg = cfg\n        self.training = True\n\n        if cfg.net.lower() == \"unet\":\n            self.model = smp.Unet(\n                encoder_name=cfg.encoder,\n                encoder_weights=cfg.weights,\n                decoder_use_batchnorm=True,\n                classes=len(cfg.classes),\n                activation=cfg.activation,\n            )\n            print('unet')\n        elif cfg.net.lower() == 'deeplabv3':\n            self.model = smp.DeepLabV3(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                #decoder_use_batchnorm=True\n                )\n            print('deeplabv3')\n        elif cfg.net.lower() == \"deeplabv3plus\":\n            self.model = smp.DeepLabV3Plus(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                #decoder_use_batchnorm=True\n                )\n            print(\"deeplabv3+\")\n        elif cfg.net.lower() == 'unetplusplus':\n            self.model = smp.UnetPlusPlus(\n                encoder_name =cfg.encoder,\n                encoder_weights=cfg.weights,    # use `imagenet` pre-trained weights for encoder initialization\n                in_channels=3,                  # model input channels (1 for gray-scale images, 3 for RGB, etc.)\n                classes=len(cfg.classes),        # model output channels (number of classes in your dataset)\n                activation=cfg.activation,\n                decoder_use_batchnorm=True\n                )\n            print('unet++')\n        else:\n            raise Exception(\"error net name\")\n\n        self.loss_fn = [smp.losses.DiceLoss(mode='binary'),smp.losses.FocalLoss(mode=\"binary\")]\n\n    def forward(self, imgs):\n        #print('imgs:',imgs.shape, ' targets:',targets.shape)\n        x = imgs\n\n        logits = self.model(x)\n        if Config.image_size != 256:\n            logits = torch.nn.functional.interpolate(logits,\n                                                size=256,\n                                                mode='bilinear'\n                                               )\n\n        return logits.sigmoid()\n    \nclass ContrailsDatasetX(torch.utils.data.Dataset):\n    def __init__(self, df, train=True):\n        \n        self.df = df\n        self.trn = train\n    \n    def read_record(self, directory):\n        record_data = {}\n        for x in [\n            \"band_11\", \n            \"band_14\", \n            \"band_15\"\n        ]:\n\n            record_data[x] = np.load(os.path.join(directory, x + \".npy\"))\n\n        return record_data\n\n    def normalize_range(self, data, bounds):\n        \"\"\"Maps data to the range [0, 1].\"\"\"\n        return (data - bounds[0]) / (bounds[1] - bounds[0])\n    \n    def get_false_color(self, record_data):\n        _T11_BOUNDS = (243, 303)\n        _CLOUD_TOP_TDIFF_BOUNDS = (-4, 5)\n        _TDIFF_BOUNDS = (-4, 2)\n        \n        N_TIMES_BEFORE = 4\n\n        r = self.normalize_range(record_data[\"band_15\"] - record_data[\"band_14\"], _TDIFF_BOUNDS)\n        g = self.normalize_range(record_data[\"band_14\"] - record_data[\"band_11\"], _CLOUD_TOP_TDIFF_BOUNDS)\n        b = self.normalize_range(record_data[\"band_14\"], _T11_BOUNDS)\n        false_color = np.clip(np.stack([r, g, b], axis=2), 0, 1)\n        img = false_color[..., N_TIMES_BEFORE]\n\n        return img\n    \n    def __getitem__(self, index):\n        row = self.df.iloc[index]\n        con_path = row.path\n        data = self.read_record(con_path)    \n        \n        img = self.get_false_color(data)\n        \n        if Config.image_size != 256:\n            img = transform_size(image=img)[\"image\"]\n        \n        img = torch.tensor(img)\n        img = img.permute(2, 0, 1)\n            \n        return img.float()\n    \n    def __len__(self):\n        return len(self.df)\n    \ndef get_preds_x(encoder,net,ckpt,df):  \n    test_ds = ContrailsDatasetX(df, train=False)\n    test_dl = DataLoader(test_ds, batch_size=16, num_workers = 2)\n    pbar = tqdm(test_dl, total=len(test_dl), desc='Test')\n    res = np.zeros((len(df), 1, 256, 256), dtype=np.float32)\n    Config.encoder= encoder\n    Config.net= net\n    for fold in range(1,Config.n_folds+1): \n        print(f\"Infer model [{ckpt}]:[{encoder}]:[{net}] fold [{fold}]\")\n        model = SegNetX(Config)\n        model.load_state_dict(torch.load(f\"{ckpt}{fold}.pth\", map_location=\"cpu\"))\n        model = model.to(Config.device).eval()\n        preds = []\n        for X in pbar:\n            X = X.to(Config.device)\n            y_hat = model(X).cpu().numpy()\n            preds.append(y_hat)\n        res += np.concatenate(preds, axis=0)  / Config.n_folds\n        del model, X, y_hat, preds\n        torch.cuda.empty_cache()\n        gc.collect()\n    print(res.shape)    \n    return res   ","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.385265Z","iopub.execute_input":"2023-08-09T21:58:48.386004Z","iopub.status.idle":"2023-08-09T21:58:48.412132Z","shell.execute_reply.started":"2023-08-09T21:58:48.385958Z","shell.execute_reply":"2023-08-09T21:58:48.411064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TTA","metadata":{}},{"cell_type":"code","source":"weights = np.array(\n    [0.10255835, 0.08839665, 0.12786484, 0.27137265, 0.2740991, 0.00275234, 0.13295609],\n    dtype=np.float32\n)\n\nwt=[0.3644355499749288,  0.3436631823556348,  0.7333105477390083,   0.15310520982601403]\nwt={'w0': 0.25610933708712014, 'w1': 0.5683481112631084, 'w2': 0.23354139270190638, 'w3': 0.7102059923835478, 'w4': 0.9499089596751146, 'w5': 0.021071553912667497, 'w6': 0.14554201363770572}.values()\nwt={'w0': 0.7087279133465924, 'w1': 0.5710576233674167, 'w2': 0.3540131539974304, 'w3': 0.6460780475008275, 'w4': 0.45016115472459267, 'w5': 0.2610667298124468}.values()\nwt={'w0': 0.999750200690668, 'w1': 0.8893568253564371, 'w2': 0.5512604409317351, 'w3': 0.7988369794301058, 'w4': 0.2787395150664705, 'w5': 0.44071004727391117, 'w6': 0.20650110000310667, 'w7': 0.8375445463333401}.values()\nweights = np.array( [c/(sum(wt)) for c in wt] ,  dtype=np.float32 )\nprint(weights)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.496614Z","iopub.execute_input":"2023-08-09T21:58:48.497423Z","iopub.status.idle":"2023-08-09T21:58:48.507037Z","shell.execute_reply.started":"2023-08-09T21:58:48.497393Z","shell.execute_reply":"2023-08-09T21:58:48.50587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hflip = A.HorizontalFlip(p=1.0)","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.50932Z","iopub.execute_input":"2023-08-09T21:58:48.510209Z","iopub.status.idle":"2023-08-09T21:58:48.523614Z","shell.execute_reply.started":"2023-08-09T21:58:48.510175Z","shell.execute_reply":"2023-08-09T21:58:48.522627Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Paths.model_dirs","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.525464Z","iopub.execute_input":"2023-08-09T21:58:48.526355Z","iopub.status.idle":"2023-08-09T21:58:48.537716Z","shell.execute_reply.started":"2023-08-09T21:58:48.526321Z","shell.execute_reply":"2023-08-09T21:58:48.536788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if Config.cv_check:    \n    # Calculating OOF\n    model_cv_preds =[]\n    i = 0\n    for model_dir in Paths.model_dirs:\n        if model_dir.split(\"/\")[-1].startswith(\"efficientnet-b5-7folds\"): \n            model_cv_preds.append(np.squeeze(get_preds(\"raw\",'efficientnet-b5','unetplusplus', \"/kaggle/input/gr-icrgw-model-7folds/efficientnet-b5-7folds/efficientnet-b5-7folds/efficientnet-b5_fold_\",train_df,transform=None), axis=1))\n        elif  model_dir.split(\"/\")[-1].startswith(\"tu-tf_efficientnetv2_s\"):\n            model_cv_preds.append(np.squeeze(get_preds(\"raw\",'tu-tf_efficientnetv2_s','unetplusplus', \"/kaggle/input/gr-icrgw-model-7folds/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s_fold_\",train_df,transform=None), axis=1))\n            #get_preds(\"flip\",'efficientnet-b5','unetplusplus', \"/kaggle/input/gr-icrgw-model-7folds/efficientnet-b5-7folds/efficientnet-b5-7folds/efficientnet-b5_fold_\",train_df,transform=hflip)\n        else:    \n            model_cv_preds.append(get_predictions_oof(test_df, model_dir, transform=None, batch_size=16)) \n            i += 1\n            #tta\n            if not model_dir.split(\"/\")[-1].startswith(\"r50\"):\n                model_cv_preds.append(get_predictions_oof(test_df, model_dir, transform=hflip, batch_size=16))\n                i += 1 ","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.540244Z","iopub.execute_input":"2023-08-09T21:58:48.541201Z","iopub.status.idle":"2023-08-09T21:58:48.55173Z","shell.execute_reply.started":"2023-08-09T21:58:48.54117Z","shell.execute_reply":"2023-08-09T21:58:48.550743Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Via Optuna \nimport optuna \noptuna.logging.set_verbosity(optuna.logging.WARNING)\n\ndef optunaOpt(n_trials=20,direction=\"maximize\") : \n    ground_truths = joblib.load(\"gt_0.oof\")\n    \n    def run(trials): \n        threshold=trials.suggest_float(\"threshold\", 0.01,0.6) \n        weights = [] \n        for _i in range(len(model_cv_preds)):\n            weights.append(trials.suggest_float(f\"w{_i}\", 0, 1.0))\n        w = [weights[i]/sum(weights) for i in range(len(model_cv_preds))]   \n        \n        p = model_cv_preds[0] *w[0]\n        for i in range(len(model_cv_preds)-1):\n            p += model_cv_preds[i+1]*w[i+1] \n        val_dice = dice_coef(ground_truths, p, threshold)  \n        return val_dice  \n    \n    study = optuna.create_study(sampler=optuna.samplers.TPESampler(seed=42),\n                                direction=direction,\n                                study_name=f\"thres-study\")\n    study.optimize(run, n_trials)\n    print('\\n Best Trial:')\n    print(study.best_trial)\n    print('\\n Best value')\n    print(study.best_value)\n    print('\\n Best Threshold Optuna:')\n    print(study.best_params)\n    print('\\n weights:')\n    #print([study.best_params.keys()])\n    return study   \n\nif Config.cv_check:    \n    optunaOpt(n_trials=1000) \n\"\"\"\nBest value\n0.6913259631777158\n\n Best Threshold Optuna:\n{'threshold': 0.44908161888481496, 'w0': 0.7087279133465924, 'w1': 0.5710576233674167, 'w2': 0.3540131539974304, 'w3': 0.6460780475008275, 'w4': 0.45016115472459267, 'w5': 0.2610667298124468}\n\"\"\"\n\"\"\"\n Best value\n0.6926716598756955\n\n Best Threshold Optuna:\n{'threshold': 0.44726427329207186, 'w0': 0.999750200690668, 'w1': 0.8893568253564371, 'w2': 0.5512604409317351, 'w3': 0.7988369794301058, 'w4': 0.2787395150664705, 'w5': 0.44071004727391117, 'w6': 0.20650110000310667, 'w7': 0.8375445463333401}\n\n\"\"\"","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:48.553256Z","iopub.execute_input":"2023-08-09T21:58:48.554585Z","iopub.status.idle":"2023-08-09T21:58:49.06578Z","shell.execute_reply.started":"2023-08-09T21:58:48.554555Z","shell.execute_reply":"2023-08-09T21:58:49.064723Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preds = None\ni = 0\nfor model_dir in Paths.model_dirs:\n    if model_dir.split(\"/\")[-1].startswith(\"efficientnet-b5-7folds\"): \n        preds += np.squeeze(get_preds_x('efficientnet-b5','unetplusplus', \"/kaggle/input/gr-icrgw-model-7folds/efficientnet-b5-7folds/efficientnet-b5-7folds/efficientnet-b5_fold_\",test_df), axis=1)* weights[i]\n        i += 1\n    elif  model_dir.split(\"/\")[-1].startswith(\"tu-tf_efficientnetv2_s\"):\n        preds += np.squeeze(get_preds_x('tu-tf_efficientnetv2_s','unetplusplus', \"/kaggle/input/gr-icrgw-model-7folds/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s/tu-tf_efficientnetv2_s_fold_\",test_df), axis=1)* weights[i]\n        i += 1\n    else:   \n        model_preds = get_predictions(test_df, model_dir, transform=None, batch_size=16) * weights[i]\n        if preds is None:\n            preds = model_preds\n        else:\n            preds += model_preds\n        i += 1  \n        if not model_dir.split(\"/\")[-1].startswith(\"r50\"):\n            model_preds = get_predictions(test_df, model_dir, transform=hflip, batch_size=16) * weights[i]\n            preds += model_preds\n            i += 1 ","metadata":{"execution":{"iopub.status.busy":"2023-08-09T21:58:49.06835Z","iopub.execute_input":"2023-08-09T21:58:49.069015Z","iopub.status.idle":"2023-08-09T22:05:48.985963Z","shell.execute_reply.started":"2023-08-09T21:58:49.068977Z","shell.execute_reply":"2023-08-09T22:05:48.983915Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"i","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:48.988217Z","iopub.execute_input":"2023-08-09T22:05:48.988601Z","iopub.status.idle":"2023-08-09T22:05:48.996359Z","shell.execute_reply.started":"2023-08-09T22:05:48.988561Z","shell.execute_reply":"2023-08-09T22:05:48.995409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"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\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\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","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:48.997833Z","iopub.execute_input":"2023-08-09T22:05:48.998387Z","iopub.status.idle":"2023-08-09T22:05:49.0168Z","shell.execute_reply.started":"2023-08-09T22:05:48.998354Z","shell.execute_reply":"2023-08-09T22:05:49.015815Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def triplet_binary(y_pred, top_thr, area_sum, bottom_thr):\n    # Calculate the area sum for the prediction after applying the top threshold\n    area_sum_pred = (y_pred >= top_thr).sum(dim=(1, 2))\n    y_pred_binary = y_pred.clone()\n\n    # Zero all the predictions where area_sum_pred < area_sum\n    mask_below_area_sum = (area_sum_pred < area_sum).unsqueeze(-1).unsqueeze(-1).expand_as(y_pred)\n    y_pred_binary[mask_below_area_sum] = 0\n\n    # Apply bottom_thr to predictions where area_sum_pred >= area_sum\n    mask_above_area_sum = (area_sum_pred >= area_sum).unsqueeze(-1).unsqueeze(-1).expand_as(y_pred)\n    y_pred_binary[mask_above_area_sum] = (y_pred_binary[mask_above_area_sum] >= bottom_thr).float()\n    return y_pred_binary","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:49.018296Z","iopub.execute_input":"2023-08-09T22:05:49.018625Z","iopub.status.idle":"2023-08-09T22:05:49.029183Z","shell.execute_reply.started":"2023-08-09T22:05:49.018596Z","shell.execute_reply":"2023-08-09T22:05:49.028183Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\"\"\"\npreds = torch.from_numpy(preds).to(Config.device).view(-1, 256, 256)\nmasks = triplet_binary(preds, 0.31, 5, 0.04).int().cpu().numpy() # 0.6563329100608826\n\"\"\"\nTH = 0.44 # 0.44908161888481496 #0.37720203022139254 # 0.41\nmasks = (preds > TH).astype(\"int\")","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:49.030518Z","iopub.execute_input":"2023-08-09T22:05:49.031308Z","iopub.status.idle":"2023-08-09T22:05:49.045082Z","shell.execute_reply.started":"2023-08-09T22:05:49.031275Z","shell.execute_reply":"2023-08-09T22:05:49.044177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv(Paths.data + '/sample_submission.csv', index_col='record_id')\n\nfor i, pred in enumerate(preds):\n    rec = test_df['record_id'][i]\n    # mask = (pred[0]>Config.thr).astype(np.float32)\n    mask = masks[i]\n    submission.loc[int(rec), 'encoded_pixels'] = list_to_string(rle_encode(mask))\n\nsubmission.head()","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:49.048133Z","iopub.execute_input":"2023-08-09T22:05:49.048685Z","iopub.status.idle":"2023-08-09T22:05:49.076898Z","shell.execute_reply.started":"2023-08-09T22:05:49.048637Z","shell.execute_reply":"2023-08-09T22:05:49.075834Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv')","metadata":{"execution":{"iopub.status.busy":"2023-08-09T22:05:49.078302Z","iopub.execute_input":"2023-08-09T22:05:49.078666Z","iopub.status.idle":"2023-08-09T22:05:49.088129Z","shell.execute_reply.started":"2023-08-09T22:05:49.078633Z","shell.execute_reply":"2023-08-09T22:05:49.087209Z"},"trusted":true},"execution_count":null,"outputs":[]}]}