{"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":"<div class='alert alert-info' style='text-align: center'><h1>Brain Tumor Classification</h1</div>\n\n#### This notebook is a train & predict script for classifiying brain tumors.\n#### It trains Classification (pos/neg for MGMT status).\n#### The datasets are split into train/test sets.\n#### I exported the JPGs from the RSNA-MICCAI brain MR dataset","metadata":{}},{"cell_type":"code","source":"import sys\nimport os\nimport platform\nprint(sys.version)\nprint(os.name)\nprint(platform.system())\nprint(platform.release())","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:22.361824Z","iopub.execute_input":"2021-10-24T08:26:22.362391Z","iopub.status.idle":"2021-10-24T08:26:22.404350Z","shell.execute_reply.started":"2021-10-24T08:26:22.362351Z","shell.execute_reply":"2021-10-24T08:26:22.403570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nis_cuda_enabled = torch.cuda.is_available()\nprint('Cuda enabled', is_cuda_enabled)\nif torch.cuda.is_available():\n    print(torch.cuda.current_device())\n    print(torch.cuda.device(0))\n    print(torch.cuda.device_count())\n    print(torch.cuda.get_device_name(0))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:22.406181Z","iopub.execute_input":"2021-10-24T08:26:22.406450Z","iopub.status.idle":"2021-10-24T08:26:22.449094Z","shell.execute_reply.started":"2021-10-24T08:26:22.406410Z","shell.execute_reply":"2021-10-24T08:26:22.448267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvcc --version","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:22.450406Z","iopub.execute_input":"2021-10-24T08:26:22.450708Z","iopub.status.idle":"2021-10-24T08:26:23.179118Z","shell.execute_reply.started":"2021-10-24T08:26:22.450673Z","shell.execute_reply":"2021-10-24T08:26:23.178323Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:23.180892Z","iopub.execute_input":"2021-10-24T08:26:23.181463Z","iopub.status.idle":"2021-10-24T08:26:23.912615Z","shell.execute_reply.started":"2021-10-24T08:26:23.181421Z","shell.execute_reply":"2021-10-24T08:26:23.911794Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%reload_ext autoreload\n%autoreload 2\n%matplotlib inline\n\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport pydicom\nimport pandas as pd\nfrom pydicom.pixel_data_handlers.util import apply_voi_lut\nfrom tqdm import tqdm\nimport binascii\nfrom PIL import Image\n\nfrom fastai.vision.all import *\nimport numpy as np\nimport pandas as pd\nimport random\nnp.set_printoptions(threshold=sys.maxsize)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T18:28:28.273511Z","iopub.execute_input":"2021-10-24T18:28:28.273779Z","iopub.status.idle":"2021-10-24T18:28:28.415363Z","shell.execute_reply.started":"2021-10-24T18:28:28.273749Z","shell.execute_reply":"2021-10-24T18:28:28.414620Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T18:28:28.744909Z","iopub.execute_input":"2021-10-24T18:28:28.745222Z","iopub.status.idle":"2021-10-24T18:28:28.825565Z","shell.execute_reply.started":"2021-10-24T18:28:28.745189Z","shell.execute_reply":"2021-10-24T18:28:28.824509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load labels","metadata":{}},{"cell_type":"code","source":"EPOCHS = 10\nINPUT_PATH = '../input/rsna-miccai-brain-tumor-radiogenomic-classification'\nLABELS_PATH = os.path.join(INPUT_PATH, 'train_labels.csv')\nMODEL_EXPORT = '/kaggle/working/trained_model'\n\ndf = pd.read_csv(LABELS_PATH, header=0, names=['id','value'], dtype=object)\nexclude_cases = [\"00109\", \"00123\", \"00709\"] #according to description\ndf = df[~df.id.isin(exclude_cases)]","metadata":{"execution":{"iopub.status.busy":"2021-10-24T18:28:30.275233Z","iopub.execute_input":"2021-10-24T18:28:30.275549Z","iopub.status.idle":"2021-10-24T18:28:30.361647Z","shell.execute_reply.started":"2021-10-24T18:28:30.275516Z","shell.execute_reply":"2021-10-24T18:28:30.360760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T18:28:30.735014Z","iopub.execute_input":"2021-10-24T18:28:30.735567Z","iopub.status.idle":"2021-10-24T18:28:30.813719Z","shell.execute_reply.started":"2021-10-24T18:28:30.735527Z","shell.execute_reply":"2021-10-24T18:28:30.813021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# values distribution\nplt.figure(figsize=(5, 4))\nsns.countplot(data=df, x=\"value\")","metadata":{"execution":{"iopub.status.busy":"2021-10-24T18:29:45.887348Z","iopub.execute_input":"2021-10-24T18:29:45.888228Z","iopub.status.idle":"2021-10-24T18:29:46.131356Z","shell.execute_reply.started":"2021-10-24T18:29:45.888177Z","shell.execute_reply":"2021-10-24T18:29:46.130569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#create output dataset folders\nos.makedirs('./train', exist_ok = True)\nprint('Train folder created')\n\nos.makedirs('./test', exist_ok = True)\nprint('Test folder created')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:24.226976Z","iopub.execute_input":"2021-10-24T08:26:24.227197Z","iopub.status.idle":"2021-10-24T08:26:24.291580Z","shell.execute_reply.started":"2021-10-24T08:26:24.227165Z","shell.execute_reply":"2021-10-24T08:26:24.290825Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=2021):\n    import random\n    import os\n    import tensorflow as tf\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    print('Seed done!')\n    \ndef natural_sort(l): \n    #https://stackoverflow.com/a/4836734/8245487\n    convert = lambda text: int(text) if text.isdigit() else text.lower()\n    alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]\n    return sorted(l, key=alphanum_key)    \n    \ndef process_dicom(path):\n    # Original from: https://www.kaggle.com/raddar/convert-dicom-to-np-array-the-correct-way\n    dicom = pydicom.read_file(path)\n    data = apply_voi_lut(dicom.pixel_array, dicom)\n    if dicom.PhotometricInterpretation == \"MONOCHROME1\":\n        data = np.amax(data) - data\n    \n    max_val = np.max(data)\n    if max_val == 0:  # RuntimeWarning: invalid value encountered in true_divide\n        return None\n    \n    data = data - np.min(data)\n    data = data / max_val\n    data = (data * 255).astype(np.uint8)\n    return data\n    \ndef save_image(data, outpath):\n    height = len(data)\n    width = len(data[0])\n    \n    pixels_out = []\n    for row in data:\n        pixels_out.extend(row)\n    assert(len(pixels_out) == height * width)\n    \n    image_out = Image.new('L', (width, height))\n    image_out.putdata(pixels_out)\n    image_out.save(outpath)\n    \ndef resolve_dicom_files(input_dir, dataset='train'):\n    for subdir, dirs, files in os.walk(f\"{input_dir}/{dataset}\"):\n        if len(files) == 0:\n            continue\n        filename = natural_sort(files)[len(files)//2] #take middle most image -- FLAIR DCM file per training item.\n        filepath = os.path.join(subdir, filename)\n        \n        if filepath.endswith(\".dcm\") and \"FLAIR\" in filepath:\n            cur_id = subdir.split('/')[-2]\n            outpath = os.path.join(f'./{dataset}',f'{cur_id}.png')\n            \n            data = process_dicom(filepath)\n            save_image(data, outpath)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:24.292937Z","iopub.execute_input":"2021-10-24T08:26:24.293446Z","iopub.status.idle":"2021-10-24T08:26:24.364625Z","shell.execute_reply.started":"2021-10-24T08:26:24.293348Z","shell.execute_reply":"2021-10-24T08:26:24.363889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"seed_everything()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:24.365794Z","iopub.execute_input":"2021-10-24T08:26:24.366109Z","iopub.status.idle":"2021-10-24T08:26:28.338244Z","shell.execute_reply.started":"2021-10-24T08:26:24.366074Z","shell.execute_reply":"2021-10-24T08:26:28.337462Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nresolve_dicom_files(INPUT_PATH, 'train')\nresolve_dicom_files(INPUT_PATH, 'test')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:26:28.339692Z","iopub.execute_input":"2021-10-24T08:26:28.340230Z","iopub.status.idle":"2021-10-24T08:28:26.401707Z","shell.execute_reply.started":"2021-10-24T08:26:28.340191Z","shell.execute_reply":"2021-10-24T08:28:26.400993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for id_num in df.id:\n    full_path = f'./train/{id_num}.png'\n    df.loc[df.id == id_num, 'file'] = full_path","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:26.402908Z","iopub.execute_input":"2021-10-24T08:28:26.403687Z","iopub.status.idle":"2021-10-24T08:28:26.883129Z","shell.execute_reply.started":"2021-10-24T08:28:26.403646Z","shell.execute_reply":"2021-10-24T08:28:26.882333Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:26.887641Z","iopub.execute_input":"2021-10-24T08:28:26.887948Z","iopub.status.idle":"2021-10-24T08:28:27.005528Z","shell.execute_reply.started":"2021-10-24T08:28:26.887909Z","shell.execute_reply":"2021-10-24T08:28:27.004656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# a DataLoaders object is a combination of training and validation data\nimage_data = ImageDataLoaders.from_df(df, item_tfms=Resize(224), bs=64, label_col=1, fn_col=2, path='')","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:27.006797Z","iopub.execute_input":"2021-10-24T08:28:27.007179Z","iopub.status.idle":"2021-10-24T08:28:31.604718Z","shell.execute_reply.started":"2021-10-24T08:28:27.007140Z","shell.execute_reply":"2021-10-24T08:28:31.603990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# look at the data\nimage_data.show_batch()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:31.605887Z","iopub.execute_input":"2021-10-24T08:28:31.606151Z","iopub.status.idle":"2021-10-24T08:28:32.659498Z","shell.execute_reply.started":"2021-10-24T08:28:31.606118Z","shell.execute_reply":"2021-10-24T08:28:32.655663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training stage","metadata":{}},{"cell_type":"code","source":"import torch \nimport torch.nn as nn\nimport torch.nn.functional as F\n\nclass Net(nn.Module):\n    def __init__(self, pretrained=False):\n        super().__init__()\n        # 3 input image channel, 6 output channels, 5x5 square convolution\n        # kernel\n        self.conv1 = nn.Conv2d(3, 6, 5)\n        self.pool = nn.MaxPool2d(2, 2)\n        self.conv2 = nn.Conv2d(6, 16, 5)\n        self.fc1 = nn.Linear(16 * 5 * 5, 120)\n        self.fc2 = nn.Linear(120, 84)\n        self.fc3 = nn.Linear(84, 10)\n\n    def forward(self, x):\n        x = self.pool(F.relu(self.conv1(x)))\n        x = self.pool(F.relu(self.conv2(x)))\n        x = torch.flatten(x, 1) # flatten all dimensions except batch\n        x = F.relu(self.fc1(x))\n        x = F.relu(self.fc2(x))\n        x = F.relu(self.fc3(x))\n        return x","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:32.660936Z","iopub.execute_input":"2021-10-24T08:28:32.661231Z","iopub.status.idle":"2021-10-24T08:28:32.768808Z","shell.execute_reply.started":"2021-10-24T08:28:32.661196Z","shell.execute_reply":"2021-10-24T08:28:32.768045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Net()\nprint(model)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:32.770207Z","iopub.execute_input":"2021-10-24T08:28:32.770472Z","iopub.status.idle":"2021-10-24T08:28:32.876170Z","shell.execute_reply.started":"2021-10-24T08:28:32.770437Z","shell.execute_reply":"2021-10-24T08:28:32.875409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"params = list(model.parameters())\nprint(len(params))\nprint(params[0].size())  # conv1's .weight","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:32.877336Z","iopub.execute_input":"2021-10-24T08:28:32.877624Z","iopub.status.idle":"2021-10-24T08:28:32.975072Z","shell.execute_reply.started":"2021-10-24T08:28:32.877588Z","shell.execute_reply":"2021-10-24T08:28:32.974174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# chooses an appropriate loss function\nlearn = cnn_learner(image_data, Net, metrics=[error_rate, accuracy], model_dir=\"/tmp/model/\").to_fp16()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:32.976861Z","iopub.execute_input":"2021-10-24T08:28:32.977280Z","iopub.status.idle":"2021-10-24T08:28:33.139518Z","shell.execute_reply.started":"2021-10-24T08:28:32.977242Z","shell.execute_reply":"2021-10-24T08:28:33.138822Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"learn.lr_find()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:28:33.140812Z","iopub.execute_input":"2021-10-24T08:28:33.141096Z","iopub.status.idle":"2021-10-24T08:29:09.953698Z","shell.execute_reply.started":"2021-10-24T08:28:33.141062Z","shell.execute_reply":"2021-10-24T08:29:09.952910Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Print model's state_dict\nprint(\"Model's state_dict:\")\nfor param_tensor in model.state_dict():\n    print(param_tensor, \"\\t\", model.state_dict()[param_tensor].size())","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:09.955462Z","iopub.execute_input":"2021-10-24T08:29:09.955890Z","iopub.status.idle":"2021-10-24T08:29:10.077118Z","shell.execute_reply.started":"2021-10-24T08:29:09.955848Z","shell.execute_reply":"2021-10-24T08:29:10.076370Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nlearn.fit_one_cycle(EPOCHS, lr_max=1e-2)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:10.078366Z","iopub.execute_input":"2021-10-24T08:29:10.078618Z","iopub.status.idle":"2021-10-24T08:29:39.941174Z","shell.execute_reply.started":"2021-10-24T08:29:10.078582Z","shell.execute_reply":"2021-10-24T08:29:39.940013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# show results of prediction\nlearn.show_results()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:39.942658Z","iopub.execute_input":"2021-10-24T08:29:39.944000Z","iopub.status.idle":"2021-10-24T08:29:41.301307Z","shell.execute_reply.started":"2021-10-24T08:29:39.943957Z","shell.execute_reply":"2021-10-24T08:29:41.299906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#save model to disk\nlearn.save(MODEL_EXPORT)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:41.302762Z","iopub.execute_input":"2021-10-24T08:29:41.303282Z","iopub.status.idle":"2021-10-24T08:29:41.413737Z","shell.execute_reply.started":"2021-10-24T08:29:41.303242Z","shell.execute_reply":"2021-10-24T08:29:41.412901Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"interp = ClassificationInterpretation.from_learner(learn)\ninterp.plot_top_losses(9, figsize=(15,11))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:41.415327Z","iopub.execute_input":"2021-10-24T08:29:41.415605Z","iopub.status.idle":"2021-10-24T08:29:42.981244Z","shell.execute_reply.started":"2021-10-24T08:29:41.415569Z","shell.execute_reply":"2021-10-24T08:29:42.979917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.DataFrame(columns=['id', 'value'])\ndf_test.id = os.listdir(os.path.join(INPUT_PATH, \"test/\"))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:42.982763Z","iopub.execute_input":"2021-10-24T08:29:42.983316Z","iopub.status.idle":"2021-10-24T08:29:43.110081Z","shell.execute_reply.started":"2021-10-24T08:29:42.983277Z","shell.execute_reply":"2021-10-24T08:29:43.109228Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Predict stage","metadata":{}},{"cell_type":"code","source":"# load weights\n#learn = cnn_learner(image_data, Net, metrics=[error_rate, accuracy], model_dir=\"/tmp/model/\").to_fp16()\n#learn_new = learn.load(MODEL_EXPORT)","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:33:39.622641Z","iopub.execute_input":"2021-10-24T08:33:39.624229Z","iopub.status.idle":"2021-10-24T08:33:39.809578Z","shell.execute_reply.started":"2021-10-24T08:33:39.624171Z","shell.execute_reply":"2021-10-24T08:33:39.808900Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nfor id_num in df_test.id:\n    full_path = f'./test/{id_num}.png'\n    prediction = learn.predict(full_path)\n    probability = prediction[2][1].item()\n    print(probability)\n    df_test.loc[df_test.id==id_num, 'value'] = probability","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:34:41.699651Z","iopub.execute_input":"2021-10-24T08:34:41.700267Z","iopub.status.idle":"2021-10-24T08:34:44.455246Z","shell.execute_reply.started":"2021-10-24T08:34:41.700222Z","shell.execute_reply":"2021-10-24T08:34:44.454542Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:45.505917Z","iopub.execute_input":"2021-10-24T08:29:45.506322Z","iopub.status.idle":"2021-10-24T08:29:45.618386Z","shell.execute_reply.started":"2021-10-24T08:29:45.506282Z","shell.execute_reply":"2021-10-24T08:29:45.617364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test.value.min(), df_test.value.max()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:45.619560Z","iopub.execute_input":"2021-10-24T08:29:45.619849Z","iopub.status.idle":"2021-10-24T08:29:45.728572Z","shell.execute_reply.started":"2021-10-24T08:29:45.619808Z","shell.execute_reply":"2021-10-24T08:29:45.727823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_output = df_test.rename(columns={'id':'BraTS21ID','value':'MGMT_value'})\ndf_output.to_csv('submission.csv', index=False)\ndf_output.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:45.729923Z","iopub.execute_input":"2021-10-24T08:29:45.730352Z","iopub.status.idle":"2021-10-24T08:29:45.835761Z","shell.execute_reply.started":"2021-10-24T08:29:45.730311Z","shell.execute_reply":"2021-10-24T08:29:45.834820Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Print requirements","metadata":{}},{"cell_type":"code","source":"# taken from here https://stackoverflow.com/a/49199019\nimport pkg_resources\nimport types\ndef get_imports():\n    for name, val in globals().items():\n        if isinstance(val, types.ModuleType):\n            # Split ensures you get root package, \n            # not just imported function\n            name = val.__name__.split(\".\")[0]\n\n        elif isinstance(val, type):\n            name = val.__module__.split(\".\")[0]\n\n        # Some packages are weird and have different\n        # imported names vs. system/pip names. Unfortunately,\n        # there is no systematic way to get pip names from\n        # a package's imported name. You'll have to add\n        # exceptions to this list manually!\n        poorly_named_packages = {\n            \"PIL\": \"Pillow\",\n            \"sklearn\": \"scikit-learn\"\n        }\n        if name in poorly_named_packages.keys():\n            name = poorly_named_packages[name]\n\n        yield name\nimports = list(set(get_imports()))\n\n# The only way I found to get the version of the root package\n# from only the name of the package is to cross-check the names \n# of installed packages vs. imported packages\nrequirements = []\nfor m in pkg_resources.working_set:\n    if m.project_name in imports and m.project_name!=\"pip\":\n        requirements.append((m.project_name, m.version))\n\nfor r in requirements:\n    print(\"{}=={}\".format(*r))","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:29:45.837399Z","iopub.execute_input":"2021-10-24T08:29:45.837720Z","iopub.status.idle":"2021-10-24T08:29:45.952387Z","shell.execute_reply.started":"2021-10-24T08:29:45.837684Z","shell.execute_reply":"2021-10-24T08:29:45.951559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test.head()","metadata":{"execution":{"iopub.status.busy":"2021-10-24T08:36:23.941405Z","iopub.execute_input":"2021-10-24T08:36:23.941698Z","iopub.status.idle":"2021-10-24T08:36:24.056056Z","shell.execute_reply.started":"2021-10-24T08:36:23.941666Z","shell.execute_reply":"2021-10-24T08:36:24.055302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}