{"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":"# Welcome! Let's Start😊\n## Introduction:\nSimple Unet Baseline (Infer) : Simple UNet Baseline (Infer) refers to a basic structure of the UNet, a deep learning model commonly used in the field of computer vision. UNet is primarily applied to tasks such as medical image analysis or image segmentation, where it excels at accurately segmenting specific parts of an image.¶\nSimple UNet Baseline (Infer) specifically pertains to the inference stage of the UNet model. The inference stage involves using the trained UNet model to make predictions on new input images. In the context of image segmentation tasks, these predictions entail predicting the labels for each pixel in a given image.\nSimple UNet Baseline (Infer) is a simplified version based on the basic structure of the UNet model, typically used for initial experiments or simpler problems. This model has lower complexity compared to other variations of UNet, offering faster training and inference speeds\n\n**Note** : Please consider upvoting if you find this useful.","metadata":{}},{"cell_type":"markdown","source":"# Training part","metadata":{"papermill":{"duration":0.005433,"end_time":"2023-06-16T21:11:16.918829","exception":false,"start_time":"2023-06-16T21:11:16.913396","status":"completed"},"tags":[]}},{"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","metadata":{"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-06-16T21:11:16.93259Z","iopub.status.busy":"2023-06-16T21:11:16.931843Z","iopub.status.idle":"2023-06-16T21:11:24.19497Z","shell.execute_reply":"2023-06-16T21:11:24.194014Z"},"papermill":{"duration":7.272747,"end_time":"2023-06-16T21:11:24.197504","exception":false,"start_time":"2023-06-16T21:11:16.924757","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir -p /root/.cache/torch/hub/checkpoints/\n!cp /kaggle/input/timm-pretrained-resnest/resnest/gluon_resnest26-50eb607c.pth /root/.cache/torch/hub/checkpoints/gluon_resnest26-50eb607c.pth","metadata":{"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-06-16T21:11:24.212371Z","iopub.status.busy":"2023-06-16T21:11:24.210624Z","iopub.status.idle":"2023-06-16T21:11:27.694558Z","shell.execute_reply":"2023-06-16T21:11:27.693229Z"},"papermill":{"duration":3.493768,"end_time":"2023-06-16T21:11:27.697401","exception":false,"start_time":"2023-06-16T21:11:24.203633","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%writefile config.yaml\n\ndata_path: \"/kaggle/input/contrails-images-ash-color\"\noutput_dir: \"models\"\n\nseed: 42\n\ntrain_bs: 48\nvalid_bs: 128\nworkers: 2\n\nprogress_bar_refresh_rate: 1\n\nearly_stop:\n    monitor: \"val_loss\"\n    mode: \"min\"\n    patience: 999\n    verbose: 1\n\ntrainer:\n    max_epochs: 26\n    min_epochs: 26\n    enable_progress_bar: True\n    precision: \"16-mixed\"\n    devices: 2\n\nmodel:\n    seg_model: \"Unet\"\n    encoder_name: \"timm-resnest26d\"\n    loss_smooth: 1.0\n    image_size: 384\n    optimizer_params:\n        lr: 0.0005\n        weight_decay: 0.0\n    scheduler:\n        name: \"CosineAnnealingLR\"\n        params:\n            CosineAnnealingLR:\n                T_max: 2\n                eta_min: 1.0e-6\n                last_epoch: -1\n            ReduceLROnPlateau:\n                mode: \"min\"\n                factor: 0.31622776601\n                patience: 4\n                verbose: True","metadata":{"execution":{"iopub.execute_input":"2023-06-16T21:11:27.71207Z","iopub.status.busy":"2023-06-16T21:11:27.711372Z","iopub.status.idle":"2023-06-16T21:11:27.719302Z","shell.execute_reply":"2023-06-16T21:11:27.718029Z"},"papermill":{"duration":0.017521,"end_time":"2023-06-16T21:11:27.721287","exception":false,"start_time":"2023-06-16T21:11:27.703766","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport numpy as np\nimport torchvision.transforms as T\n\nclass ContrailsDataset(torch.utils.data.Dataset):\n    def __init__(self, df, image_size=256, train=True):\n\n        self.df = df\n        self.trn = train\n        self.normalize_image = T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))\n        self.image_size = image_size\n        if image_size != 256:\n            self.resize_image = T.transforms.Resize(image_size)\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        label = torch.tensor(label)\n\n        img = torch.tensor(np.reshape(img, (256, 256, 3))).to(torch.float32).permute(2, 0, 1)\n\n        if self.image_size != 256:\n            img = self.resize_image(img)\n\n        img = self.normalize_image(img)\n\n        return img.float(), label.float()\n\n    def __len__(self):\n        return len(self.df)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T21:11:27.734754Z","iopub.status.busy":"2023-06-16T21:11:27.733949Z","iopub.status.idle":"2023-06-16T21:11:27.743818Z","shell.execute_reply":"2023-06-16T21:11:27.742981Z"},"papermill":{"duration":0.018503,"end_time":"2023-06-16T21:11:27.745693","exception":false,"start_time":"2023-06-16T21:11:27.72719","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport pytorch_lightning as pl\nimport segmentation_models_pytorch as smp\nfrom torch.optim.lr_scheduler import CosineAnnealingLR, ReduceLROnPlateau\nfrom torch.optim import AdamW\nimport torch.nn as nn\nfrom torchmetrics.functional import dice\n\nseg_models = {\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}","metadata":{"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-06-16T21:11:27.759795Z","iopub.status.busy":"2023-06-16T21:11:27.758412Z","iopub.status.idle":"2023-06-16T21:11:39.299269Z","shell.execute_reply":"2023-06-16T21:11:39.298295Z"},"papermill":{"duration":11.550621,"end_time":"2023-06-16T21:11:39.30199","exception":false,"start_time":"2023-06-16T21:11:27.751369","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LightningModule(pl.LightningModule):\n    def __init__(self, config):\n        super().__init__()\n        self.config = config\n        self.model = model = seg_models[config[\"seg_model\"]](\n            encoder_name=config[\"encoder_name\"],\n            encoder_weights=\"imagenet\",\n            in_channels=3,\n            classes=1,\n            activation=None,\n        )\n        self.loss_module = smp.losses.DiceLoss(mode=\"binary\", smooth=config[\"loss_smooth\"])\n        self.val_step_outputs = []\n        self.val_step_labels = []\n\n    def forward(self, batch):\n        imgs = batch\n        preds = self.model(imgs)\n        return preds\n\n    def configure_optimizers(self):\n        optimizer = AdamW(self.parameters(), **self.config[\"optimizer_params\"])\n\n        if self.config[\"scheduler\"][\"name\"] == \"CosineAnnealingLR\":\n            scheduler = CosineAnnealingLR(\n                optimizer,\n                **self.config[\"scheduler\"][\"params\"][\"CosineAnnealingLR\"],\n            )\n            lr_scheduler_dict = {\"scheduler\": scheduler, \"interval\": \"step\"}\n            return {\"optimizer\": optimizer, \"lr_scheduler\": lr_scheduler_dict}\n        elif self.config[\"scheduler\"][\"name\"] == \"ReduceLROnPlateau\":\n            scheduler = ReduceLROnPlateau(\n                optimizer,\n                **self.config[\"scheduler\"][\"params\"][\"ReduceLROnPlateau\"],\n            )\n            lr_scheduler = {\"scheduler\": scheduler, \"monitor\": \"val_loss\"}\n            return {\"optimizer\": optimizer, \"lr_scheduler\": lr_scheduler}\n\n    def training_step(self, batch, batch_idx):\n        imgs, labels = batch\n        preds = self.model(imgs)\n        if self.config[\"image_size\"] != 256:\n            preds = torch.nn.functional.interpolate(preds, size=256, mode='bilinear')\n        loss = self.loss_module(preds, labels)\n        self.log(\"train_loss\", loss, on_step=True, on_epoch=True, prog_bar=True, batch_size=16)\n\n        for param_group in self.trainer.optimizers[0].param_groups:\n            lr = param_group[\"lr\"]\n        self.log(\"lr\", lr, on_step=True, on_epoch=False, prog_bar=True)\n\n        return loss\n\n    def validation_step(self, batch, batch_idx):\n        imgs, labels = batch\n        preds = self.model(imgs)\n        if self.config[\"image_size\"] != 256:\n            preds = torch.nn.functional.interpolate(preds, size=256, mode='bilinear')\n        loss = self.loss_module(preds, labels)\n        self.log(\"val_loss\", loss, on_step=False, on_epoch=True, prog_bar=True)\n        self.val_step_outputs.append(preds)\n        self.val_step_labels.append(labels)\n\n    def on_validation_epoch_end(self):\n        all_preds = torch.cat(self.val_step_outputs)\n        all_labels = torch.cat(self.val_step_labels)\n        all_preds = torch.sigmoid(all_preds)\n        self.val_step_outputs.clear()\n        self.val_step_labels.clear()\n        val_dice = dice(all_preds, all_labels.long())\n        self.log(\"val_dice\", val_dice, on_step=False, on_epoch=True, prog_bar=True)\n        if self.trainer.global_rank == 0:\n            print(f\"\\nEpoch: {self.current_epoch}\", flush=True)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\n\nwarnings.filterwarnings(\"ignore\")\n\nimport os\nimport torch\nimport yaml\nimport pandas as pd\nimport pytorch_lightning as pl\nfrom pprint import pprint\nfrom pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping, TQDMProgressBar\nfrom torch.utils.data import DataLoader\n\nwith open(\"config.yaml\", \"r\") as file_obj:\n    config = yaml.safe_load(file_obj)\n\ncontrails = os.path.join(config[\"data_path\"], \"contrails/\")\ntrain_path = os.path.join(config[\"data_path\"], \"train_df.csv\")\nvalid_path = os.path.join(config[\"data_path\"], \"valid_df.csv\")\n\ntrain_df = pd.read_csv(train_path)\nvalid_df = pd.read_csv(valid_path)\n\ntrain_df[\"path\"] = contrails + train_df[\"record_id\"].astype(str) + \".npy\"\nvalid_df[\"path\"] = contrails + valid_df[\"record_id\"].astype(str) + \".npy\"\n\ndataset_train = ContrailsDataset(train_df, config[\"model\"][\"image_size\"], train=True)\ndataset_validation = ContrailsDataset(valid_df, config[\"model\"][\"image_size\"], train=False)\n\ndata_loader_train = DataLoader(\n    dataset_train,\n    batch_size=config[\"train_bs\"],\n    shuffle=True,\n    num_workers=config[\"workers\"],\n)\ndata_loader_validation = DataLoader(\n    dataset_validation,\n    batch_size=config[\"valid_bs\"],\n    shuffle=False,\n    num_workers=config[\"workers\"],\n)\n\ncheckpoint_callback = ModelCheckpoint(\n    save_weights_only=True,\n    monitor=\"val_dice\",\n    dirpath=config[\"output_dir\"],\n    mode=\"max\",\n    filename=\"model\",\n    save_top_k=1,\n    verbose=1,\n)\n\nprogress_bar_callback = TQDMProgressBar(\n    refresh_rate=config[\"progress_bar_refresh_rate\"]\n)\n\nearly_stop_callback = EarlyStopping(**config[\"early_stop\"])\n\ntrainer = pl.Trainer(\n    callbacks=[checkpoint_callback, early_stop_callback, progress_bar_callback],\n    **config[\"trainer\"],\n)\n\nconfig[\"model\"][\"scheduler\"][\"params\"][\"CosineAnnealingLR\"][\"T_max\"] *= len(data_loader_train)/config[\"trainer\"][\"devices\"]\nmodel = LightningModule(config[\"model\"])\n\ntrainer.fit(model, data_loader_train, data_loader_validation)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T21:11:39.316178Z","iopub.status.busy":"2023-06-16T21:11:39.315621Z","iopub.status.idle":"2023-06-16T23:35:32.345028Z","shell.execute_reply":"2023-06-16T23:35:32.343547Z"},"papermill":{"duration":8633.039148,"end_time":"2023-06-16T23:35:32.347666","exception":false,"start_time":"2023-06-16T21:11:39.308518","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission part","metadata":{"papermill":{"duration":0.013882,"end_time":"2023-06-16T23:35:32.376031","exception":false,"start_time":"2023-06-16T23:35:32.362149","status":"completed"},"tags":[]}},{"cell_type":"code","source":"batch_size = 128\ndevice = torch.device('cuda' if torch.cuda.is_available() else 'cpu')\ndata = '/kaggle/input/google-research-identify-contrails-reduce-global-warming'\ndata_root = '/kaggle/input/google-research-identify-contrails-reduce-global-warming/test/'","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:32.407541Z","iopub.status.busy":"2023-06-16T23:35:32.407178Z","iopub.status.idle":"2023-06-16T23:35:32.413036Z","shell.execute_reply":"2023-06-16T23:35:32.412197Z"},"papermill":{"duration":0.024526,"end_time":"2023-06-16T23:35:32.414974","exception":false,"start_time":"2023-06-16T23:35:32.390448","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filenames = os.listdir(data_root)\ntest_df = pd.DataFrame(filenames, columns=['record_id'])\ntest_df['path'] = data_root + test_df['record_id'].astype(str)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:32.444397Z","iopub.status.busy":"2023-06-16T23:35:32.444061Z","iopub.status.idle":"2023-06-16T23:35:32.480277Z","shell.execute_reply":"2023-06-16T23:35:32.479472Z"},"papermill":{"duration":0.05339,"end_time":"2023-06-16T23:35:32.482308","exception":false,"start_time":"2023-06-16T23:35:32.428918","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ContrailsDataset(torch.utils.data.Dataset):\n    def __init__(self, df, image_size=256, train=True):\n        \n        self.df = df\n        self.trn = train\n        self.df_idx: pd.DataFrame = pd.DataFrame({'idx': os.listdir(f'/kaggle/input/google-research-identify-contrails-reduce-global-warming/test')})\n        self.normalize_image = T.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))\n        self.image_size = image_size\n        if image_size != 256:\n            self.resize_image = T.transforms.Resize(image_size)\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        img = torch.tensor(np.reshape(img, (256, 256, 3))).to(torch.float32).permute(2, 0, 1)\n        \n        if self.image_size != 256:\n            img = self.resize_image(img)\n        \n        img = self.normalize_image(img)\n        \n        image_id = int(self.df_idx.iloc[index]['idx'])\n            \n        return img.float(), torch.tensor(image_id)\n    \n    def __len__(self):\n        return len(self.df)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:32.514104Z","iopub.status.busy":"2023-06-16T23:35:32.51252Z","iopub.status.idle":"2023-06-16T23:35:32.529558Z","shell.execute_reply":"2023-06-16T23:35:32.528762Z"},"papermill":{"duration":0.034197,"end_time":"2023-06-16T23:35:32.531556","exception":false,"start_time":"2023-06-16T23:35:32.497359","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_ds = ContrailsDataset(\n        test_df,\n        config[\"model\"][\"image_size\"],\n        train = False\n    )\n \ntest_dl = DataLoader(test_ds, batch_size=batch_size, num_workers = 1)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:32.561679Z","iopub.status.busy":"2023-06-16T23:35:32.560939Z","iopub.status.idle":"2023-06-16T23:35:32.569992Z","shell.execute_reply":"2023-06-16T23:35:32.569069Z"},"papermill":{"duration":0.026614,"end_time":"2023-06-16T23:35:32.572185","exception":false,"start_time":"2023-06-16T23:35:32.545571","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class LightningModule(pl.LightningModule):\n\n    def __init__(self):\n        super().__init__()\n        self.model = smp.Unet(encoder_name=\"timm-resnest26d\",\n                              encoder_weights=None,\n                              in_channels=3,\n                              classes=1,\n                              activation=None,\n                              )\n\n    def forward(self, batch):\n        return self.model(batch)","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:32.601948Z","iopub.status.busy":"2023-06-16T23:35:32.601695Z","iopub.status.idle":"2023-06-16T23:35:32.607099Z","shell.execute_reply":"2023-06-16T23:35:32.606224Z"},"papermill":{"duration":0.022048,"end_time":"2023-06-16T23:35:32.60905","exception":false,"start_time":"2023-06-16T23:35:32.587002","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = LightningModule().load_from_checkpoint(\"/kaggle/working/models/model.ckpt\")\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nmodel.to(device)\nmodel.eval()\nmodel.zero_grad()","metadata":{"_kg_hide-output":true,"execution":{"iopub.execute_input":"2023-06-16T23:35:32.638526Z","iopub.status.busy":"2023-06-16T23:35:32.638268Z","iopub.status.idle":"2023-06-16T23:35:40.126175Z","shell.execute_reply":"2023-06-16T23:35:40.125219Z"},"papermill":{"duration":7.505261,"end_time":"2023-06-16T23:35:40.128571","exception":false,"start_time":"2023-06-16T23:35:32.62331","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def rle_encode(x, fg_val=1):\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    if x: # non-empty list\n        s = str(x).replace(\"[\", \"\").replace(\"]\", \"\").replace(\",\", \"\")\n    else:\n        s = '-'\n    return s","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:40.158972Z","iopub.status.busy":"2023-06-16T23:35:40.158673Z","iopub.status.idle":"2023-06-16T23:35:40.166174Z","shell.execute_reply":"2023-06-16T23:35:40.16527Z"},"papermill":{"duration":0.024715,"end_time":"2023-06-16T23:35:40.168211","exception":false,"start_time":"2023-06-16T23:35:40.143496","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = pd.read_csv('/kaggle/input/google-research-identify-contrails-reduce-global-warming/sample_submission.csv', index_col='record_id')","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:40.197438Z","iopub.status.busy":"2023-06-16T23:35:40.197127Z","iopub.status.idle":"2023-06-16T23:35:40.236664Z","shell.execute_reply":"2023-06-16T23:35:40.235797Z"},"papermill":{"duration":0.056687,"end_time":"2023-06-16T23:35:40.238733","exception":false,"start_time":"2023-06-16T23:35:40.182046","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, data in enumerate(test_dl):\n    images, image_id = data\n    \n    images = images.to(device)\n    with torch.no_grad():\n        predicted_mask = model.forward(images[:, :, :, :])\n    if config[\"model\"][\"image_size\"] != 256:\n        predicted_mask = torch.nn.functional.interpolate(predicted_mask, size=256, mode='bilinear')\n    predicted_mask = torch.sigmoid(predicted_mask).cpu().detach().numpy()\n    \n    predicted_mask_with_threshold = np.zeros((images.shape[0], 256, 256))\n    predicted_mask_with_threshold[predicted_mask[:, 0, :, :] < 0.5] = 0\n    predicted_mask_with_threshold[predicted_mask[:, 0, :, :] > 0.5] = 1\n    \n    for img_num in range(0, images.shape[0]):\n        current_mask = predicted_mask_with_threshold[img_num, :, :]\n        current_image_id = image_id[img_num].item()\n        \n        submission.loc[int(current_image_id), 'encoded_pixels'] = list_to_string(rle_encode(current_mask))","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:40.268774Z","iopub.status.busy":"2023-06-16T23:35:40.268515Z","iopub.status.idle":"2023-06-16T23:35:47.224228Z","shell.execute_reply":"2023-06-16T23:35:47.222948Z"},"papermill":{"duration":6.97396,"end_time":"2023-06-16T23:35:47.226814","exception":false,"start_time":"2023-06-16T23:35:40.252854","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission.to_csv('submission.csv')","metadata":{"execution":{"iopub.execute_input":"2023-06-16T23:35:47.320423Z","iopub.status.busy":"2023-06-16T23:35:47.319634Z","iopub.status.idle":"2023-06-16T23:35:47.331743Z","shell.execute_reply":"2023-06-16T23:35:47.330748Z"},"papermill":{"duration":0.029365,"end_time":"2023-06-16T23:35:47.333768","exception":false,"start_time":"2023-06-16T23:35:47.304403","status":"completed"},"tags":[]},"execution_count":null,"outputs":[]}]}