{"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":"# Install Dependencies","metadata":{}},{"cell_type":"code","source":"!conda install '/kaggle/input/pydicom-conda-helper/libjpeg-turbo-2.1.0-h7f98852_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/libgcc-ng-9.3.0-h2828fa1_19.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/gdcm-2.8.9-py37h500ead1_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/conda-4.10.1-py37h89c1867_0.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/certifi-2020.12.5-py37h89c1867_1.tar.bz2' -c conda-forge -y\n!conda install '/kaggle/input/pydicom-conda-helper/openssl-1.1.1k-h7f98852_0.tar.bz2' -c conda-forge -y","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:54:42.708230Z","iopub.execute_input":"2021-07-10T02:54:42.708774Z","iopub.status.idle":"2021-07-10T02:56:09.563854Z","shell.execute_reply.started":"2021-07-10T02:54:42.708685Z","shell.execute_reply":"2021-07-10T02:56:09.562163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Imports","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nprint(tf.__version__)\nimport torch\nprint(f\"Setup complete. Using torch {torch.__version__} ({torch.cuda.get_device_properties(0).name if torch.cuda.is_available() else 'CPU'})\")\n\nimport os\nimport gc\nimport cv2\nimport glob\nimport numpy as np\nimport pandas as pd\nfrom PIL import Image\nfrom tqdm import tqdm\nfrom shutil import copyfile\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\n\nimport pydicom\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-07-10T02:56:09.571872Z","iopub.execute_input":"2021-07-10T02:56:09.576444Z","iopub.status.idle":"2021-07-10T02:56:17.668974Z","shell.execute_reply.started":"2021-07-10T02:56:09.576324Z","shell.execute_reply":"2021-07-10T02:56:17.667871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"gpus = tf.config.list_physical_devices('GPU')\nif gpus:\n  try:\n    # Currently, memory growth needs to be the same across GPUs\n    for gpu in gpus:\n      tf.config.experimental.set_memory_growth(gpu, True)\n    logical_gpus = tf.config.experimental.list_logical_devices('GPU')\n    print(len(gpus), \"Physical GPUs,\", len(logical_gpus), \"Logical GPUs\")\n  except RuntimeError as e:\n    # Memory growth must be set before GPUs have been initialized\n    print(e)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:17.671349Z","iopub.execute_input":"2021-07-10T02:56:17.671853Z","iopub.status.idle":"2021-07-10T02:56:24.890440Z","shell.execute_reply.started":"2021-07-10T02:56:17.671805Z","shell.execute_reply":"2021-07-10T02:56:24.889227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Submission ","metadata":{}},{"cell_type":"code","source":"# Read the submisison file\nsub_df = pd.read_csv('/kaggle/input/siim-covid19-detection/sample_submission.csv')\nprint(len(sub_df))\nsub_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.894252Z","iopub.execute_input":"2021-07-10T02:56:24.894572Z","iopub.status.idle":"2021-07-10T02:56:24.935050Z","shell.execute_reply.started":"2021-07-10T02:56:24.894540Z","shell.execute_reply":"2021-07-10T02:56:24.933676Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_df = sub_df.loc[sub_df.id.str.contains('_study')]\nlen(study_df)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.936975Z","iopub.execute_input":"2021-07-10T02:56:24.937447Z","iopub.status.idle":"2021-07-10T02:56:24.949314Z","shell.execute_reply.started":"2021-07-10T02:56:24.937402Z","shell.execute_reply":"2021-07-10T02:56:24.948098Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_df = sub_df.loc[sub_df.id.str.contains('_image')]\nlen(image_df)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.951215Z","iopub.execute_input":"2021-07-10T02:56:24.952076Z","iopub.status.idle":"2021-07-10T02:56:24.964747Z","shell.execute_reply.started":"2021-07-10T02:56:24.952027Z","shell.execute_reply":"2021-07-10T02:56:24.963114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utils to extract images and resize them","metadata":{}},{"cell_type":"code","source":"# Ref: https://www.kaggle.com/xhlulu/siim-covid-19-convert-to-jpg-256px\ndef read_xray(path, voi_lut = True, fix_monochrome = True):\n    # Original from: https://www.kaggle.com/raddar/convert-dicom-to-np-array-the-correct-way\n    dicom = pydicom.read_file(path)\n    \n    # VOI LUT (if available by DICOM device) is used to transform raw DICOM data to \n    # \"human-friendly\" view\n    if voi_lut:\n        data = apply_voi_lut(dicom.pixel_array, dicom)\n    else:\n        data = dicom.pixel_array\n               \n    # depending on this value, X-ray may look inverted - fix that:\n    if fix_monochrome and dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n        \n    data = data - np.min(data)\n    data = data / np.max(data)\n    data = (data * 255).astype(np.uint8)\n        \n    return data\n\ndef resize_xray(array, size, keep_ratio=False, resample=Image.LANCZOS):\n    # Original from: https://www.kaggle.com/xhlulu/vinbigdata-process-and-resize-to-image\n    im = Image.fromarray(array)\n    \n    if keep_ratio:\n        im.thumbnail((size, size), resample)\n    else:\n        im = im.resize((size, size), resample)\n    \n    return im","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.966881Z","iopub.execute_input":"2021-07-10T02:56:24.967342Z","iopub.status.idle":"2021-07-10T02:56:24.978309Z","shell.execute_reply.started":"2021-07-10T02:56:24.967298Z","shell.execute_reply":"2021-07-10T02:56:24.976726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TEST_PATH = f'/kaggle/tmp/test/'\nIMG_SIZE = 512\n\ndef prepare_test_images():\n    image_id = []\n    dim0 = []\n    dim1 = []\n\n    os.makedirs(TEST_PATH, exist_ok=True)\n\n    for dirname, _, filenames in tqdm(os.walk(f'../input/siim-covid19-detection/test')):\n        for file in filenames:\n            # set keep_ratio=True to have original aspect ratio\n            xray = read_xray(os.path.join(dirname, file))\n            im = resize_xray(xray, size=IMG_SIZE)  \n            im.save(os.path.join(TEST_PATH, file.replace('dcm', 'png')))\n\n            image_id.append(file.replace('.dcm', ''))\n            dim0.append(xray.shape[0])\n            dim1.append(xray.shape[1])\n            \n    return image_id, dim0, dim1","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.981588Z","iopub.execute_input":"2021-07-10T02:56:24.982037Z","iopub.status.idle":"2021-07-10T02:56:24.994683Z","shell.execute_reply.started":"2021-07-10T02:56:24.981992Z","shell.execute_reply":"2021-07-10T02:56:24.993462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prepare Image Level Test Images","metadata":{}},{"cell_type":"code","source":"image_ids, dim0, dim1 = prepare_test_images()\nprint(f'Number of test images: {len(os.listdir(TEST_PATH))}')","metadata":{"execution":{"iopub.status.busy":"2021-07-10T02:56:24.998324Z","iopub.execute_input":"2021-07-10T02:56:24.998666Z","iopub.status.idle":"2021-07-10T03:06:44.913354Z","shell.execute_reply.started":"2021-07-10T02:56:24.998632Z","shell.execute_reply":"2021-07-10T03:06:44.908960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_df = pd.DataFrame.from_dict({'image_id': image_ids, 'dim0': dim0, 'dim1': dim1})\n\n# Associate image-level id with study-level ids.\n# Note that a study-level might have more than one image-level ids.\nfor study_dir in os.listdir('../input/siim-covid19-detection/test'):\n    for series in os.listdir(f'../input/siim-covid19-detection/test/{study_dir}'):\n        for image in os.listdir(f'../input/siim-covid19-detection/test/{study_dir}/{series}/'):\n            image_id = image[:-4]\n            meta_df.loc[meta_df['image_id'] == image_id, 'study_id'] = study_dir\n        \nmeta_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:06:44.915209Z","iopub.execute_input":"2021-07-10T03:06:44.915701Z","iopub.status.idle":"2021-07-10T03:06:48.001608Z","shell.execute_reply.started":"2021-07-10T03:06:44.915656Z","shell.execute_reply":"2021-07-10T03:06:48.000541Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# YOLOv5 Inferencecontains","metadata":{}},{"cell_type":"code","source":"# YOLO_MODEL_PATH = '../input/yolo-models/yolov5s-e-100-img-512.pt'\nYOLO_MODEL_PATHS = [\n    '../input/yolo-models/yolov5s-e-100-img-512-fold-0.pt',\n    '../input/yolo-models/yolov5s-e-100-img-512-fold-1.pt',\n    '../input/yolo-models/yolov5s-e-100-img-512-fold-2.pt',\n    '../input/yolo-models/yolov5s-e-100-img-512-fold-3.pt',\n    '../input/yolo-models/yolov5s-e-100-img-512-fold-4.pt',\n]\n\n!python ../input/kaggle-yolov5/detect.py --weights {YOLO_MODEL_PATHS[0]} {YOLO_MODEL_PATHS[1]} {YOLO_MODEL_PATHS[2]} {YOLO_MODEL_PATHS[3]} {YOLO_MODEL_PATHS[4]} \\\n                                      --source {TEST_PATH} \\\n                                      --img {IMG_SIZE} \\\n                                      --conf 0.2 \\\n                                      --iou-thres 0.5 \\\n                                      --max-det 10 \\\n                                      --save-txt \\\n                                      --save-conf\\\n                                      --nosave","metadata":{"scrolled":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2021-07-10T03:11:36.640427Z","iopub.execute_input":"2021-07-10T03:11:36.640809Z","iopub.status.idle":"2021-07-10T03:14:56.826929Z","shell.execute_reply.started":"2021-07-10T03:11:36.640777Z","shell.execute_reply":"2021-07-10T03:14:56.825556Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"PRED_PATH = 'runs/detect/exp/labels'\nprediction_files = os.listdir(PRED_PATH)\nprint(f'Number of opacity predicted by YOLOv5: {len(prediction_files)}')","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:16:45.037347Z","iopub.execute_input":"2021-07-10T03:16:45.037791Z","iopub.status.idle":"2021-07-10T03:16:45.045883Z","shell.execute_reply.started":"2021-07-10T03:16:45.037753Z","shell.execute_reply":"2021-07-10T03:16:45.044493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Study Level Inference","metadata":{}},{"cell_type":"markdown","source":"## Hyperparameters","metadata":{}},{"cell_type":"code","source":"AUTOTUNE = tf.data.AUTOTUNE\n\nCONFIG = dict (\n    seed = 42,\n    num_labels = 4,\n    num_folds = 5,\n    img_width = 512,\n    img_height = 512,\n    batch_size = 32,\n    _wandb_kernel = 'ayut',\n    architecture = \"CNN\",\n    infra = \"GCP\",\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:16:56.211707Z","iopub.execute_input":"2021-07-10T03:16:56.212088Z","iopub.status.idle":"2021-07-10T03:16:56.219551Z","shell.execute_reply.started":"2021-07-10T03:16:56.212057Z","shell.execute_reply":"2021-07-10T03:16:56.217935Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Prepare testloader","metadata":{}},{"cell_type":"code","source":"image_df['path'] = image_df.apply(lambda row: TEST_PATH+row.id.split('_')[0]+'.png', axis=1)\nimage_df = image_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:16:59.435041Z","iopub.execute_input":"2021-07-10T03:16:59.435447Z","iopub.status.idle":"2021-07-10T03:16:59.475825Z","shell.execute_reply.started":"2021-07-10T03:16:59.435414Z","shell.execute_reply":"2021-07-10T03:16:59.474641Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@tf.function\ndef decode_image(image):\n    # convert the compressed string to a 3D uint8 tensor\n    image = tf.image.decode_png(image, channels=3)\n    # Normalize image\n    image = tf.image.convert_image_dtype(image, dtype=tf.float32)\n    return image\n\n@tf.function\ndef load_image(df_dict):\n    # Load image\n    image = tf.io.read_file(df_dict['path'])\n    image = decode_image(image)\n    \n    # Resize image\n    image = tf.image.resize(image, (CONFIG['img_height'], CONFIG['img_width']))\n    \n    return image\n\ntestloader = tf.data.Dataset.from_tensor_slices(dict(image_df))\n\ntestloader = (\n    testloader\n    .shuffle(1024)\n    .map(load_image, num_parallel_calls=AUTOTUNE)\n    .batch(CONFIG['batch_size'])\n    .prefetch(AUTOTUNE)\n)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:17:03.830292Z","iopub.execute_input":"2021-07-10T03:17:03.830760Z","iopub.status.idle":"2021-07-10T03:17:04.079785Z","shell.execute_reply.started":"2021-07-10T03:17:03.830713Z","shell.execute_reply":"2021-07-10T03:17:04.078721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Get models","metadata":{}},{"cell_type":"code","source":"# Load Model\nSTUDY_MODEL_PATHS = '../input/siim-study-level-models/effnet-mixup/effnetb0_mixup/'\nstudy_models = os.listdir(STUDY_MODEL_PATHS)\nstudy_models","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:17:07.585362Z","iopub.execute_input":"2021-07-10T03:17:07.585771Z","iopub.status.idle":"2021-07-10T03:17:07.611739Z","shell.execute_reply.started":"2021-07-10T03:17:07.585738Z","shell.execute_reply":"2021-07-10T03:17:07.610726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Inference","metadata":{}},{"cell_type":"code","source":"predictions = []\nfor model in study_models:\n    # Load model\n    tf.keras.backend.clear_session()\n    model = tf.keras.models.load_model(STUDY_MODEL_PATHS+model)\n    # Prediction\n    tmp = []\n    for img_batch in tqdm(testloader):\n        preds = model.predict(img_batch)\n        tmp.extend(preds)\n        \n    predictions.append(tmp)\n    \n    del model\n    _ = gc.collect()\n    \npredictions = np.mean(predictions, axis=0)","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:17:10.556281Z","iopub.execute_input":"2021-07-10T03:17:10.556727Z","iopub.status.idle":"2021-07-10T03:19:55.618633Z","shell.execute_reply.started":"2021-07-10T03:17:10.556695Z","shell.execute_reply":"2021-07-10T03:19:55.617479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_labels = ['0', '1', '2', '3']\nimage_df.loc[:, class_labels] = predictions\nimage_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:27.427129Z","iopub.execute_input":"2021-07-10T03:29:27.427782Z","iopub.status.idle":"2021-07-10T03:29:27.458786Z","shell.execute_reply.started":"2021-07-10T03:29:27.427729Z","shell.execute_reply":"2021-07-10T03:29:27.457672Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_to_id = { \n    'negative': 0,\n    'typical': 1,\n    'indeterminate': 2,\n    'atypical': 3}\nid_to_class  = {v:k for k, v in class_to_id.items()}\n\ndef get_study_prediction_string(preds, threshold=0):\n    string = ''\n    for idx in range(4):\n        conf =  preds[idx]\n        if conf>threshold:\n            string+=f'{id_to_class[idx]} {conf:0.2f} 0 0 1 1 '\n    string = string.strip()\n    return string","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:33.892167Z","iopub.execute_input":"2021-07-10T03:29:33.892572Z","iopub.status.idle":"2021-07-10T03:29:33.901001Z","shell.execute_reply.started":"2021-07-10T03:29:33.892538Z","shell.execute_reply":"2021-07-10T03:29:33.898493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"study_ids = []\npred_strings = []\n\nfor study_id, df in meta_df.groupby('study_id'):\n    # accumulate preds for diff images belonging to same study_id\n    tmp_pred = []\n    \n    df = df.reset_index(drop=True)\n    for image_id in df.image_id.values:\n        preds = image_df.loc[image_df.id == image_id+'_image'].values[0]\n        tmp_pred.append(preds[3:])\n    \n    preds = np.mean(tmp_pred, axis=0)\n    pred_string = get_study_prediction_string(preds)\n    pred_strings.append(pred_string)\n    \n    study_ids.append(f'{study_id}_study')\n    \nstudy_df = pd.DataFrame.from_dict({'id': study_ids, 'PredictionString': pred_strings})\nstudy_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:36.149539Z","iopub.execute_input":"2021-07-10T03:29:36.149932Z","iopub.status.idle":"2021-07-10T03:29:37.543688Z","shell.execute_reply.started":"2021-07-10T03:29:36.149898Z","shell.execute_reply":"2021-07-10T03:29:37.542429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Merge Results","metadata":{}},{"cell_type":"code","source":"# The submisison requires xmin, ymin, xmax, ymax format. \n# YOLOv5 returns x_center, y_center, width, height\ndef correct_bbox_format(bboxes):\n    correct_bboxes = []\n    for b in bboxes:\n        xc, yc = int(np.round(b[0]*IMG_SIZE)), int(np.round(b[1]*IMG_SIZE))\n        w, h = int(np.round(b[2]*IMG_SIZE)), int(np.round(b[3]*IMG_SIZE))\n\n        xmin = xc - int(np.round(w/2))\n        ymin = yc - int(np.round(h/2))\n        xmax = xc + int(np.round(w/2))\n        ymax = yc + int(np.round(h/2))\n        \n        correct_bboxes.append([xmin, ymin, xmax, ymax])\n        \n    return correct_bboxes\n\ndef scale_bboxes_to_original(row, bboxes):\n    # Get scaling factor\n    scale_x = IMG_SIZE/row.dim1\n    scale_y = IMG_SIZE/row.dim0\n    \n    scaled_bboxes = []\n    for bbox in bboxes:\n        xmin, ymin, xmax, ymax = bbox\n        \n        xmin = int(np.round(xmin/scale_x))\n        ymin = int(np.round(ymin/scale_y))\n        xmax = int(np.round(xmax/scale_x))\n        ymax = int(np.round(ymax/scale_y))\n        \n        scaled_bboxes.append([xmin, ymin, xmax, ymax])\n        \n    return scaled_bboxes\n\n# Read the txt file generated by YOLOv5 during inference and extract \n# confidence and bounding box coordinates.\ndef get_conf_bboxes(file_path):\n    confidence = []\n    bboxes = []\n    with open(file_path, 'r') as file:\n        for line in file:\n            preds = line.strip('\\n').split(' ')\n            preds = list(map(float, preds))\n            confidence.append(preds[-1])\n            bboxes.append(preds[1:-1])\n    return confidence, bboxes","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:39.945040Z","iopub.execute_input":"2021-07-10T03:29:39.945446Z","iopub.status.idle":"2021-07-10T03:29:39.959800Z","shell.execute_reply.started":"2021-07-10T03:29:39.945397Z","shell.execute_reply":"2021-07-10T03:29:39.958312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_pred_strings = []\nfor i in tqdm(range(len(image_df))):\n    row = meta_df.loc[i]\n    id_name = row.image_id\n    \n    if f'{id_name}.txt' in prediction_files:\n        # opacity label\n        confidence, bboxes = get_conf_bboxes(f'{PRED_PATH}/{id_name}.txt')\n        bboxes = correct_bbox_format(bboxes)\n        ori_bboxes = scale_bboxes_to_original(row, bboxes)\n        \n        pred_string = ''\n        for j, conf in enumerate(confidence):\n            pred_string += f'opacity {conf} ' + ' '.join(map(str, ori_bboxes[j])) + ' '\n        image_pred_strings.append(pred_string[:-1]) \n    else:\n        image_pred_strings.append(\"none 1 0 0 1 1\")","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:41.694350Z","iopub.execute_input":"2021-07-10T03:29:41.694804Z","iopub.status.idle":"2021-07-10T03:29:42.571071Z","shell.execute_reply.started":"2021-07-10T03:29:41.694771Z","shell.execute_reply":"2021-07-10T03:29:42.569742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_df['PredictionString'] = image_pred_strings\nimage_df = meta_df[['image_id', 'PredictionString']]\nimage_df.insert(0, 'id', image_df.apply(lambda row: row.image_id+'_image', axis=1))\nimage_df = image_df.drop('image_id', axis=1)\nimage_df.head()","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:44.108200Z","iopub.execute_input":"2021-07-10T03:29:44.108649Z","iopub.status.idle":"2021-07-10T03:29:44.155314Z","shell.execute_reply.started":"2021-07-10T03:29:44.108607Z","shell.execute_reply":"2021-07-10T03:29:44.153895Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf runs","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:46.009412Z","iopub.execute_input":"2021-07-10T03:29:46.009793Z","iopub.status.idle":"2021-07-10T03:29:46.889596Z","shell.execute_reply.started":"2021-07-10T03:29:46.009760Z","shell.execute_reply":"2021-07-10T03:29:46.888154Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df = pd.concat([study_df, image_df])\nsub_df.to_csv('submission.csv', index=False)\nsub_df","metadata":{"execution":{"iopub.status.busy":"2021-07-10T03:29:48.142297Z","iopub.execute_input":"2021-07-10T03:29:48.142801Z","iopub.status.idle":"2021-07-10T03:29:48.517295Z","shell.execute_reply.started":"2021-07-10T03:29:48.142762Z","shell.execute_reply":"2021-07-10T03:29:48.516144Z"},"trusted":true},"execution_count":null,"outputs":[]}]}