{"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":"This is a pytorch inference notebook. You can expect 0.25+ pF1 CV and 0.34 pF1 LB.\n\nI've tried models like seresnext50-32x4d and efficientnets. Efficientnets tend to perform much better.\n\nNote that the training time for 1 epoch is >1hr, perhaps someone could look into this and make it faster enough though I'm using the 2 T4.","metadata":{}},{"cell_type":"markdown","source":"Check out my other notebooks:\n\nTrain: https://www.kaggle.com/chaitanyagiri/rsna-breast-cancer-training-with-2-t4\n\nInfer: https://www.kaggle.com/chaitanyagiri/rsna-breast-cancer-inference-with-2-t4","metadata":{}},{"cell_type":"markdown","source":"References:\n\nhttps://www.kaggle.com/code/vslaykovsky/train-pytorch-aux-targets-weighted-loss-thres\n\nhttps://www.kaggle.com/code/theoviel/rsna-breast-baseline-faster-inference-with-dali\n\nhttps://www.kaggle.com/code/vslaykovsky/infer-pytorch-aux-targets-weighted-loss-thres","metadata":{}},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"try:\n    import pylibjpeg\nexcept:\n    !pip install -q /kaggle/input/rsna-2022-whl/{pydicom-2.3.0-py3-none-any.whl,pylibjpeg-1.4.0-py3-none-any.whl,python_gdcm-3.0.15-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl}\n    !pip install -q /kaggle/input/rsna-bcd-whl-ds/python_gdcm-3.0.20-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl\n    # !pip install -q /kaggle/input/rsna-bcd-whl-ds/pylibjpeg-1.4.0-py3-none-any.whl\n    !pip install -q /kaggle/input/rsna-bcd-whl-ds/dicomsdl-0.109.1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl","metadata":{"papermill":{"duration":112.187954,"end_time":"2022-12-05T00:23:08.74552","exception":false,"start_time":"2022-12-05T00:21:16.557566","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:38:31.968826Z","iopub.execute_input":"2022-12-28T21:38:31.969906Z","iopub.status.idle":"2022-12-28T21:40:15.979117Z","shell.execute_reply.started":"2022-12-28T21:38:31.969796Z","shell.execute_reply":"2022-12-28T21:40:15.977884Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\nimport os\nimport sys\nimport cv2\nimport glob\nimport json\nimport shutil\nimport random\nimport pydicom\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\nfrom PIL import Image\nimport matplotlib.pyplot as plt\n\nfrom sklearn.metrics import f1_score\nfrom sklearn.preprocessing import LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\n\nsys.path.append('../input/timm-pytorch-image-models/pytorch-image-models-master')\nimport timm\nfrom timm.data import create_transform\nfrom timm import create_model, list_models\n\nimport torch\nfrom torch import nn\nimport torch.nn.functional as F\nfrom torch.cuda.amp import GradScaler, autocast\nfrom torch.utils.data import Dataset, DataLoader\nfrom torch.nn.functional import binary_cross_entropy_with_logits, cross_entropy\n\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nfrom tqdm.notebook import tqdm\nfrom joblib import Parallel, delayed","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:40:15.981804Z","iopub.execute_input":"2022-12-28T21:40:15.982223Z","iopub.status.idle":"2022-12-28T21:40:22.63769Z","shell.execute_reply.started":"2022-12-28T21:40:15.982172Z","shell.execute_reply":"2022-12-28T21:40:22.63653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# CFG","metadata":{}},{"cell_type":"code","source":"class CFG:\n    seed = 42\n    resize_dim = 1024\n    aspect_ratio = True\n    img_size = (1024, 512)\n    batch_size = 16\n    \n    # Model\n    model_name = \"efficientnet_b4\"\n    num_classes = 1\n    n_channels = 3\n    \n    test_img_path = \"./test_images\"\nos.environ['CUDA_VISIBLE_DEVICES'] = \"0,1\"\ndevice = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:32.012913Z","iopub.execute_input":"2022-12-28T21:45:32.013342Z","iopub.status.idle":"2022-12-28T21:45:32.020006Z","shell.execute_reply.started":"2022-12-28T21:45:32.013308Z","shell.execute_reply":"2022-12-28T21:45:32.018764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed = 42):\n    '''Sets the seed of the entire notebook so results are the same every time we run.\n    This is for REPRODUCIBILITY.'''\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    # When running on the CuDNN backend, two further options must be set\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n    # Set a fixed value for the hash seed\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    print('> SEEDING DONE')\n    \nset_seed(CFG.seed)","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:36.527658Z","iopub.execute_input":"2022-12-28T21:45:36.528142Z","iopub.status.idle":"2022-12-28T21:45:36.536068Z","shell.execute_reply.started":"2022-12-28T21:45:36.52809Z","shell.execute_reply":"2022-12-28T21:45:36.534845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Prep","metadata":{}},{"cell_type":"code","source":"comp_path = \"/kaggle/input/rsna-breast-cancer-detection\"\ndef load_df_test():\n    df_test = pd.read_csv(f'{comp_path}/test.csv')\n    return df_test\n\ntest = load_df_test()\ntest","metadata":{"papermill":{"duration":0.047641,"end_time":"2022-12-05T00:23:12.38885","exception":false,"start_time":"2022-12-05T00:23:12.341209","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:45:36.538312Z","iopub.execute_input":"2022-12-28T21:45:36.538746Z","iopub.status.idle":"2022-12-28T21:45:36.563616Z","shell.execute_reply.started":"2022-12-28T21:45:36.538711Z","shell.execute_reply":"2022-12-28T21:45:36.562551Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test[\"path\"] = CFG.test_img_path + \"/\" + test[\"patient_id\"].astype(str) + \"/\" + test[\"image_id\"].astype(str) + \".png\"","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:36.565082Z","iopub.execute_input":"2022-12-28T21:45:36.565742Z","iopub.status.idle":"2022-12-28T21:45:36.573159Z","shell.execute_reply.started":"2022-12-28T21:45:36.565695Z","shell.execute_reply":"2022-12-28T21:45:36.572115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Preprocess images ROI","metadata":{}},{"cell_type":"code","source":"from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor\nimport re\nimport pydicom\n\ndef fit_image(fname, size=1024):\n    # 1. Read, resize\n    patient = fname.split('/')[-2]\n    image = fname.split('/')[-1][:-4]\n    dicom = pydicom.dcmread(fname)\n    img = dicom.pixel_array\n    img = (img - img.min()) / (img.max() - img.min())\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        img = 1 - img\n    img = cv2.resize(img, (CFG.img_size[0], CFG.img_size[1]))\n    \n    # 2. Crop\n    X = img\n    # Some images have narrow exterior \"frames\" that complicate selection of the main data. Cutting off the frame\n    X = X[5:-5, 5:-5]\n    \n    \n    # regions of non-empty pixels\n    output= cv2.connectedComponentsWithStats((X > 0.05).astype(np.uint8)[:, :], 8, cv2.CV_32S)\n\n    # stats.shape == (N, 5), where N is the number of regions, 5 dimensions correspond to:\n    # left, top, width, height, area_size\n    stats = output[2]\n    \n    # finding max area which always corresponds to the breast data. \n    idx = stats[1:, 4].argmax() + 1\n    x1, y1, w, h = stats[idx][:4]\n    x2 = x1 + w\n    y2 = y1 + h\n    \n    # cutting out the breast data\n    X_fit = X[y1: y2, x1: x2]\n    \n    patient_id, im_id = os.path.basename(os.path.dirname(fname)), os.path.basename(fname)[:-4]\n    os.makedirs(f'{CFG.test_img_path}/{patient_id}', exist_ok=True)\n    cv2.imwrite(f'{CFG.test_img_path}/{patient_id}/{im_id}.png', (X_fit[:, :] * 255).astype(np.uint8))\n\ndef fit_all_images(all_images):\n    with ThreadPoolExecutor(2) as p:\n        for i in tqdm(p.map(fit_image, all_images), total=len(all_images)):\n            pass\n\nall_images = glob.glob('/kaggle/input/rsna-breast-cancer-detection/test_images/*/*') \n# all_images = glob.glob('/kaggle/input/rsna-breast-cancer-detection/train_images/10006/*')\nfit_all_images(all_images)","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:36.576697Z","iopub.execute_input":"2022-12-28T21:45:36.577147Z","iopub.status.idle":"2022-12-28T21:45:38.99502Z","shell.execute_reply.started":"2022-12-28T21:45:36.577037Z","shell.execute_reply":"2022-12-28T21:45:38.994046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!find test_images | head","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:38.996576Z","iopub.execute_input":"2022-12-28T21:45:38.997359Z","iopub.status.idle":"2022-12-28T21:45:40.015136Z","shell.execute_reply.started":"2022-12-28T21:45:38.997316Z","shell.execute_reply":"2022-12-28T21:45:40.013996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"code","source":"class BreastCancerDataset(Dataset):\n    def __init__(self, df, transforms=None):\n        self.df = df\n        self.paths = df['path'].values\n        self.transforms = transforms\n\n    def __len__(self):\n        return len(self.paths)\n\n    def __getitem__(self, idx):\n        try:\n            image = np.asarray(Image.open(self.paths[idx]).convert('RGB'))\n        except Exception as ex:\n            print(self.paths[idx], ex)\n            return None\n        \n        if self.transforms:\n            image = self.transforms(image=image)[\"image\"]\n\n        return image","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:40.017078Z","iopub.execute_input":"2022-12-28T21:45:40.01792Z","iopub.status.idle":"2022-12-28T21:45:40.026076Z","shell.execute_reply.started":"2022-12-28T21:45:40.017872Z","shell.execute_reply":"2022-12-28T21:45:40.025084Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Augmentation","metadata":{}},{"cell_type":"code","source":"def transformer(stage):\n    if stage == \"train\":\n        return A.Compose([\n            A.HorizontalFlip(p=0.5),\n            A.Rotate(limit=5),\n            A.augmentations.crops.RandomResizedCrop(height=CFG.img_size[0], width=CFG.img_size[1], scale=(0.8, 1), ratio=(0.45, 0.55)),\n            A.Normalize(),\n            A.pytorch.transforms.ToTensorV2()\n        ])\n    else:\n        return A.Compose([\n                A.Resize(CFG.img_size[0], CFG.img_size[1]),\n                A.Normalize(),\n                A.pytorch.transforms.ToTensorV2()\n            ])","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"execution":{"iopub.status.busy":"2022-12-28T21:45:40.027225Z","iopub.execute_input":"2022-12-28T21:45:40.028475Z","iopub.status.idle":"2022-12-28T21:45:40.041522Z","shell.execute_reply.started":"2022-12-28T21:45:40.028433Z","shell.execute_reply":"2022-12-28T21:45:40.040553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utils","metadata":{}},{"cell_type":"code","source":"def load_model_weights(model, filename, verbose=1, cp_folder=\"\", strict=True):\n    \"\"\"\n    Loads the weights of a PyTorch model. The exception handles cpu/gpu incompatibilities.\n\n    Args:\n        model (torch model): Model to load the weights to.\n        filename (str): Name of the checkpoint.\n        verbose (int, optional): Whether to display infos. Defaults to 1.\n        cp_folder (str, optional): Folder to load from. Defaults to \"\".\n\n    Returns:\n        torch model: Model with loaded weights.\n    \"\"\"\n    state_dict = torch.load(os.path.join(cp_folder, filename), map_location=\"cpu\")\n    try:\n        model.load_state_dict(state_dict[\"model\"], strict=strict)\n    except BaseException:\n        try:\n            del state_dict['logits.weight'], state_dict['logits.bias']\n            model.load_state_dict(state_dict, strict=strict)\n        except BaseException:\n            del state_dict['encoder.conv_stem.weight']\n            model.load_state_dict(state_dict, strict=strict)\n\n    if verbose:\n        print(f\"\\n -> Loading encoder weights from {os.path.join(cp_folder,filename)}\\n\")\n\n    return model, state_dict[\"threshold\"], state_dict[\"model_type\"]","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:40.043035Z","iopub.execute_input":"2022-12-28T21:45:40.044057Z","iopub.status.idle":"2022-12-28T21:45:40.05337Z","shell.execute_reply.started":"2022-12-28T21:45:40.044017Z","shell.execute_reply":"2022-12-28T21:45:40.052369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def define_model(\n    name,\n    num_classes=1,\n    num_classes_aux=0,\n    n_channels=3,\n    pretrained_weights=\"\",\n    pretrained=True,\n):\n    \"\"\"\n    Loads a pretrained model & builds the architecture.\n    Supports timm models.\n\n    Args:\n        name (str): Model name\n        num_classes (int, optional): Number of classes. Defaults to 1.\n        num_classes_aux (int, optional): Number of aux classes. Defaults to 0.\n        n_channels (int, optional): Number of image channels. Defaults to 3.\n        pretrained_weights (str, optional): Path to pretrained encoder weights. Defaults to ''.\n        pretrained (bool, optional): Whether to load timm pretrained weights.\n\n    Returns:\n        torch model -- Pretrained model.\n    \"\"\"\n    # Load pretrained model\n    encoder = create_model(CFG.model_name, pretrained=False, num_classes=num_classes, drop_rate=0.)\n    encoder.name = name\n\n    # Tile Model\n    model = BreastCancerModel(\n        encoder,\n        num_classes=num_classes,\n        num_classes_aux=num_classes_aux,\n        n_channels=n_channels,\n    )\n\n    if pretrained_weights:\n        model = load_model_weights(model, pretrained_weights, verbose=1, strict=False)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:40.057069Z","iopub.execute_input":"2022-12-28T21:45:40.058051Z","iopub.status.idle":"2022-12-28T21:45:40.066807Z","shell.execute_reply.started":"2022-12-28T21:45:40.057998Z","shell.execute_reply":"2022-12-28T21:45:40.065691Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class BreastCancerModel(nn.Module):\n    def __init__(\n        self,\n        model,\n        num_classes=1,\n        num_classes_aux=0,\n        n_channels=3,\n    ):\n        \"\"\"\n        Constructor.\n\n        Args:\n            encoder (timm model): Encoder.\n            num_classes (int, optional): Number of classes. Defaults to 1.\n            num_classes_aux (int, optional): Number of aux classes. Defaults to 0.\n            n_channels (int, optional): Number of image channels. Defaults to 3.\n        \"\"\"\n        super().__init__()\n\n        self.model = model\n        self.backbone_dim = self.model(torch.randn(1, 3, CFG.img_size[0], CFG.img_size[1])).shape[-1]\n\n        self.num_classes = num_classes\n        self.n_channels = n_channels\n\n        self.logits = nn.Linear(self.backbone_dim, num_classes)\n        \n        self._update_num_channels()\n\n    def _update_num_channels(self):\n        if self.n_channels != 3:\n            for n, m in self.model.named_modules():\n                if n:\n                    # print(\"Replacing\", n)\n                    old_conv = getattr(self.model, n)\n                    new_conv = nn.Conv2d(\n                        self.n_channels,\n                        old_conv.out_channels,\n                        kernel_size=old_conv.kernel_size,\n                        stride=old_conv.stride,\n                        padding=old_conv.padding,\n                        bias=old_conv.bias is not None,\n                    )\n                    setattr(self.model, n, new_conv)\n                    break\n\n    def forward(self, x, return_fts=False):\n        \"\"\"\n        Forward function.\n\n        Args:\n            x (torch tensor [batch_size x n_channels x h x w]): Input batch.\n\n        Returns:\n            torch tensor [batch_size x num_classes]: logits.\n            torch tensor [batch_size x num_classes_aux]: logits aux.\n        \"\"\"\n        x = self.model(x)\n        logits = self.logits(x).squeeze()\n\n        return logits","metadata":{"papermill":{"duration":2.459131,"end_time":"2022-12-05T00:23:21.660809","exception":false,"start_time":"2022-12-05T00:23:19.201678","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:45:40.068652Z","iopub.execute_input":"2022-12-28T21:45:40.069363Z","iopub.status.idle":"2022-12-28T21:45:40.08245Z","shell.execute_reply.started":"2022-12-28T21:45:40.069327Z","shell.execute_reply":"2022-12-28T21:45:40.08146Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models_path = glob.glob(\"/kaggle/input/rsna-efficientnet-b4/*_best_score.pth\")","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:40.083964Z","iopub.execute_input":"2022-12-28T21:45:40.084712Z","iopub.status.idle":"2022-12-28T21:45:40.095243Z","shell.execute_reply.started":"2022-12-28T21:45:40.084676Z","shell.execute_reply":"2022-12-28T21:45:40.094353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"models = []\nfor fname in tqdm(sorted(models_path)):\n    model, thres, model_name = load_model_weights(nn.DataParallel(define_model(CFG.model_name)), fname)\n    model = model.to(device)\n    models.append((model, thres))\n    print(f'fname:{fname}, model_name:{model_name}, thres:{thres}')","metadata":{"papermill":{"duration":12.829022,"end_time":"2022-12-05T00:23:34.516853","exception":false,"start_time":"2022-12-05T00:23:21.687831","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:45:40.096869Z","iopub.execute_input":"2022-12-28T21:45:40.097634Z","iopub.status.idle":"2022-12-28T21:45:46.838207Z","shell.execute_reply.started":"2022-12-28T21:45:40.097596Z","shell.execute_reply":"2022-12-28T21:45:46.83708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission","metadata":{"papermill":{"duration":0.005913,"end_time":"2022-12-05T00:23:34.529375","exception":false,"start_time":"2022-12-05T00:23:34.523462","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# THRES = 0.91 #max\nTHRES = 0.84 # max","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:46.840007Z","iopub.execute_input":"2022-12-28T21:45:46.840754Z","iopub.status.idle":"2022-12-28T21:45:46.846045Z","shell.execute_reply.started":"2022-12-28T21:45:46.840699Z","shell.execute_reply":"2022-12-28T21:45:46.844824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def models_predict(models, test_dataset):\n    test_dataloader = DataLoader(test_dataset, batch_size=CFG.batch_size,\n                                 shuffle=False, num_workers=os.cpu_count())\n    for model, thres in models:\n        model.eval()\n\n    with torch.no_grad():\n        predictions = []\n        for idx, img in enumerate(tqdm(test_dataloader, mininterval=30)):\n            img = img.to(device)\n            pred = torch.zeros(len(img), len(models))\n            for idx, (model, thres) in enumerate(models):\n                preds = model(img)\n                preds = torch.sigmoid(preds)\n                pred[:, idx] = preds.cpu()\n            predictions.append(pred.mean(dim=-1))\n        return torch.concat(predictions).numpy()","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"papermill":{"duration":2.339608,"end_time":"2022-12-05T00:23:36.875001","exception":false,"start_time":"2022-12-05T00:23:34.535393","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:45:46.847473Z","iopub.execute_input":"2022-12-28T21:45:46.848735Z","iopub.status.idle":"2022-12-28T21:45:46.858922Z","shell.execute_reply.started":"2022-12-28T21:45:46.848666Z","shell.execute_reply":"2022-12-28T21:45:46.857787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_dataset = BreastCancerDataset(test, transformer(\"test\"))\nmodels_pred = models_predict(models, test_dataset)","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:46.860331Z","iopub.execute_input":"2022-12-28T21:45:46.861065Z","iopub.status.idle":"2022-12-28T21:45:57.612557Z","shell.execute_reply.started":"2022-12-28T21:45:46.861026Z","shell.execute_reply":"2022-12-28T21:45:57.611212Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test['cancer'] = models_pred\n\nsub = test.groupby('prediction_id')[['cancer']].max()\nsub","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:57.614558Z","iopub.execute_input":"2022-12-28T21:45:57.615892Z","iopub.status.idle":"2022-12-28T21:45:57.643055Z","shell.execute_reply.started":"2022-12-28T21:45:57.615843Z","shell.execute_reply":"2022-12-28T21:45:57.642081Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub['cancer'] = (sub.cancer > THRES).astype(float)\nsub","metadata":{"execution":{"iopub.status.busy":"2022-12-28T21:45:57.644308Z","iopub.execute_input":"2022-12-28T21:45:57.64467Z","iopub.status.idle":"2022-12-28T21:45:57.657869Z","shell.execute_reply.started":"2022-12-28T21:45:57.644632Z","shell.execute_reply":"2022-12-28T21:45:57.656726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv', index=True)\n!head submission.csv","metadata":{"papermill":{"duration":0.018763,"end_time":"2022-12-05T00:23:37.564404","exception":false,"start_time":"2022-12-05T00:23:37.545641","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2022-12-28T21:45:57.659788Z","iopub.execute_input":"2022-12-28T21:45:57.660707Z","iopub.status.idle":"2022-12-28T21:45:58.73113Z","shell.execute_reply.started":"2022-12-28T21:45:57.660668Z","shell.execute_reply":"2022-12-28T21:45:58.729862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}