{"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 Notebook is taken from [Sadhaklal's](https://www.kaggle.com/sambitmukherjee) shared notebook.","metadata":{}},{"cell_type":"code","source":"!pip show torchvision","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:25.031911Z","iopub.execute_input":"2023-11-06T12:05:25.032263Z","iopub.status.idle":"2023-11-06T12:05:36.818545Z","shell.execute_reply.started":"2023-11-06T12:05:25.032232Z","shell.execute_reply":"2023-11-06T12:05:36.817611Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom pathlib import Path\nimport numpy as np\nimport pandas as pd\nfrom datetime import datetime, timezone, timedelta\nimport matplotlib.pyplot as plt\nimport matplotlib\nmatplotlib.use(\"Agg\")\nimport torch\nimport torchvision\nfrom torchvision.io import read_image\nfrom torchvision.transforms import v2 as T\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:36.820430Z","iopub.execute_input":"2023-11-06T12:05:36.820724Z","iopub.status.idle":"2023-11-06T12:05:40.596077Z","shell.execute_reply.started":"2023-11-06T12:05:36.820695Z","shell.execute_reply":"2023-11-06T12:05:40.594989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Object detection data prep","metadata":{}},{"cell_type":"code","source":"working_folder = Path(\"/kaggle/working/\")\nimages_folder = working_folder/\"images\"\nimages_folder.mkdir()","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:40.597345Z","iopub.execute_input":"2023-11-06T12:05:40.597948Z","iopub.status.idle":"2023-11-06T12:05:40.602905Z","shell.execute_reply.started":"2023-11-06T12:05:40.597912Z","shell.execute_reply":"2023-11-06T12:05:40.601917Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_folder = Path(\"/kaggle/input/child-mind-institute-detect-sleep-states\")\n!ls {data_folder}","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:40.604197Z","iopub.execute_input":"2023-11-06T12:05:40.604615Z","iopub.status.idle":"2023-11-06T12:05:41.578235Z","shell.execute_reply.started":"2023-11-06T12:05:40.604584Z","shell.execute_reply":"2023-11-06T12:05:41.577164Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_series = pd.read_parquet(data_folder/\"test_series.parquet\")\ntest_series","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:41.582008Z","iopub.execute_input":"2023-11-06T12:05:41.582742Z","iopub.status.idle":"2023-11-06T12:05:41.825156Z","shell.execute_reply.started":"2023-11-06T12:05:41.582710Z","shell.execute_reply":"2023-11-06T12:05:41.824292Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_series['large_enmo'] = test_series['enmo'] > 0.1506","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:41.826503Z","iopub.execute_input":"2023-11-06T12:05:41.827100Z","iopub.status.idle":"2023-11-06T12:05:41.832508Z","shell.execute_reply.started":"2023-11-06T12:05:41.827064Z","shell.execute_reply":"2023-11-06T12:05:41.831618Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_ids = test_series['series_id'].unique()\nlen(series_ids)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:41.833576Z","iopub.execute_input":"2023-11-06T12:05:41.833826Z","iopub.status.idle":"2023-11-06T12:05:41.847161Z","shell.execute_reply.started":"2023-11-06T12:05:41.833804Z","shell.execute_reply":"2023-11-06T12:05:41.846374Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"window_properties = []\nfor i in range(len(series_ids)):\n    print(\"i:\", i)\n    print(\"series_id:\", series_ids[i])\n    series = test_series.loc[test_series['series_id'] == series_ids[i]].reset_index(drop=True)\n    series['color'] = [\"blue\" if large_enmo else \"green\" for large_enmo in series['large_enmo']]\n    series['timestamp'] = pd.to_datetime(series['timestamp'])\n    series['timestamp_utc'] = series['timestamp'].map(lambda timestamp: timestamp.astimezone(timezone.utc))\n    series['anglez_radians'] = (np.pi / 180) * series['anglez']\n    series['cos_anglez'] = np.cos(series['anglez_radians'])\n    series['enmo'] = np.clip(series['enmo'], 0, 1)\n    min_date_utc = series['timestamp_utc'].dt.date.min()\n    max_date_utc = series['timestamp_utc'].dt.date.max()\n    series_24_hour_windows = {}    \n    upper_bound = datetime(year=min_date_utc.year, month=min_date_utc.month, day=min_date_utc.day, hour=17, tzinfo=timezone.utc)\n    lower_bound = upper_bound + timedelta(hours=-24) # 5pm UTC on the previous day.\n    while lower_bound < series['timestamp_utc'].max():\n        window_df = series.loc[(series['timestamp_utc'] >= lower_bound) & (series['timestamp_utc'] < upper_bound)].reset_index(drop=True)\n        if len(window_df) > 0:\n            series_24_hour_windows[upper_bound.isoformat()[:-6]] = window_df\n        upper_bound += timedelta(hours=24)\n        lower_bound += timedelta(hours=24)\n    \n    windows = list(series_24_hour_windows.keys())\n    num_steps_cumulative = 0\n    for window_idx, window in enumerate(windows):        \n        fig = plt.figure(figsize=(14.4, 4))  # (width, height) in inches\n        plt.plot(series_24_hour_windows[window]['timestamp_utc'], series_24_hour_windows[window]['cos_anglez'], color=\"red\")\n        plt.scatter(series_24_hour_windows[window]['timestamp_utc'], series_24_hour_windows[window]['enmo'], color=series_24_hour_windows[window]['color'], s=1)\n        ax = plt.gca()\n        ax.spines['top'].set_visible(False)\n        ax.spines['right'].set_visible(False)\n        ax.spines['bottom'].set_visible(False)\n        ax.spines['left'].set_visible(False)\n        ax.set_xticks([])\n        ax.set_yticks([])\n        plt.margins(0, 0)\n        plt.subplots_adjust(left=0, right=1, top=1, bottom=0)\n        plt.savefig(images_folder/f\"{series_ids[i]}_{window}.jpg\", bbox_inches=\"tight\", pad_inches=0)\n        plt.clf()\n        plt.cla()\n        plt.close()\n\n        min_ts_window = series_24_hour_windows[window]['timestamp_utc'].min()\n        max_ts_window = series_24_hour_windows[window]['timestamp_utc'].max()\n        num_steps_window = (max_ts_window - min_ts_window).total_seconds() / 5 + 1\n        num_steps_cumulative += num_steps_window\n        window_properties.append({\n            'series_id': series_ids[i], \n            'image_name': f\"{series_ids[i]}_{window}.jpg\", \n            'idx_in_series': window_idx, \n            'num_steps_window': num_steps_window, \n            'num_steps_cumulative': num_steps_cumulative\n        })","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:41.848484Z","iopub.execute_input":"2023-11-06T12:05:41.848974Z","iopub.status.idle":"2023-11-06T12:05:42.525085Z","shell.execute_reply.started":"2023-11-06T12:05:41.848942Z","shell.execute_reply":"2023-11-06T12:05:42.524174Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"window_properties_df = pd.DataFrame(window_properties)\nwindow_properties_df","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:42.526309Z","iopub.execute_input":"2023-11-06T12:05:42.526618Z","iopub.status.idle":"2023-11-06T12:05:42.538229Z","shell.execute_reply.started":"2023-11-06T12:05:42.526594Z","shell.execute_reply":"2023-11-06T12:05:42.537361Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Transforms","metadata":{}},{"cell_type":"code","source":"def get_transforms():\n    transforms = []\n    transforms.append(T.ConvertDtype(torch.float))\n    return T.Compose(transforms)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:42.539353Z","iopub.execute_input":"2023-11-06T12:05:42.539648Z","iopub.status.idle":"2023-11-06T12:05:42.549522Z","shell.execute_reply.started":"2023-11-06T12:05:42.539623Z","shell.execute_reply":"2023-11-06T12:05:42.548732Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"From the <a href=\"https://pytorch.org/vision/0.15/generated/torchvision.transforms.v2.ConvertDtype.html\" target=\"_blank\">documentation</a>:\n\n> Convert input image or video to the given `dtype` and scale the values accordingly.","metadata":{}},{"cell_type":"code","source":"eval_transforms = get_transforms()","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:42.550547Z","iopub.execute_input":"2023-11-06T12:05:42.550792Z","iopub.status.idle":"2023-11-06T12:05:42.561477Z","shell.execute_reply.started":"2023-11-06T12:05:42.550769Z","shell.execute_reply":"2023-11-06T12:05:42.560682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Instantiating the model","metadata":{}},{"cell_type":"code","source":"device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\ndevice","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:42.562618Z","iopub.execute_input":"2023-11-06T12:05:42.562899Z","iopub.status.idle":"2023-11-06T12:05:42.609113Z","shell.execute_reply.started":"2023-11-06T12:05:42.562875Z","shell.execute_reply":"2023-11-06T12:05:42.608276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Load an object detection model pre-trained on COCO:\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(weights=None, weights_backbone=None, max_size=1440)\n# Replace the classifier with a new one, that has num_classes which is user-defined:\nnum_classes = 3 # 2 classes ('onset' & 'wakeup') + the 'background' class\n# Get the number of input features for the box classifier:\nin_features = model.roi_heads.box_predictor.cls_score.in_features\n# Replace the pre-trained box predictor head with a new one:\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:42.610081Z","iopub.execute_input":"2023-11-06T12:05:42.610337Z","iopub.status.idle":"2023-11-06T12:05:43.304643Z","shell.execute_reply.started":"2023-11-06T12:05:42.610300Z","shell.execute_reply":"2023-11-06T12:05:43.303842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weights = torch.load(\"/kaggle/input/c-m-i-d-s-s-extra-data/m1_4.pth\", map_location=device)\nmodel.load_state_dict(weights)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:43.307734Z","iopub.execute_input":"2023-11-06T12:05:43.308024Z","iopub.status.idle":"2023-11-06T12:05:48.084101Z","shell.execute_reply.started":"2023-11-06T12:05:43.308000Z","shell.execute_reply":"2023-11-06T12:05:48.083196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.to(device);","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:48.085342Z","iopub.execute_input":"2023-11-06T12:05:48.085692Z","iopub.status.idle":"2023-11-06T12:05:48.151873Z","shell.execute_reply.started":"2023-11-06T12:05:48.085657Z","shell.execute_reply":"2023-11-06T12:05:48.151160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"model.eval()\nthresh = 0.0 # Tune this.\nreverse_label_mapping = {1: \"onset\", 2: \"wakeup\"}","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:48.153353Z","iopub.execute_input":"2023-11-06T12:05:48.153689Z","iopub.status.idle":"2023-11-06T12:05:48.159249Z","shell.execute_reply.started":"2023-11-06T12:05:48.153658Z","shell.execute_reply":"2023-11-06T12:05:48.158383Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_submission_df():\n    all_test_preds = []\n    for i, series_id in enumerate(series_ids): # i is the index of the series.\n        series_rows = window_properties_df.loc[window_properties_df['series_id'] == series_id].reset_index(drop=True)\n        for j in range(len(series_rows)): # j is the index of the image (within the series).\n            image_name = series_rows['image_name'][j]\n            image_path = os.path.join(images_folder, image_name)\n            image = read_image(image_path)\n            with torch.no_grad():\n                x = eval_transforms(image)\n                x = x.to(device)\n                predictions = model([x])\n            pred = predictions[0]\n            \n            # Postprocessing: remove 'narrow' boxes as these are false positives.\n            pred_widths = pred['boxes'][:, 2] - pred['boxes'][:, 0]\n            pred['boxes'] = pred['boxes'][pred_widths > 10]\n            pred['labels'] = pred['labels'][pred_widths > 10]\n            pred['scores'] = pred['scores'][pred_widths > 10]\n            \n            pred['boxes'] = pred['boxes'][pred['scores'] > thresh]\n            pred['labels'] = pred['labels'][pred['scores'] > thresh]\n            pred['scores'] = pred['scores'][pred['scores'] > thresh]\n            \n            if len(pred['labels']) == 0:\n                continue\n            else:\n                pred_x = (pred['boxes'][:, 0] + pred['boxes'][:, 2]) / 2\n                pred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\n                num_steps_window = series_rows['num_steps_window'][j]\n                if j == 0:\n                    prev_num_steps_cumulative = 0\n                else:\n                    prev_num_steps_cumulative = series_rows['num_steps_cumulative'][j - 1]            \n                for k in range(len(pred_labels)): # k is the index of the bounding box (within the image).\n                    event = {}\n                    step_in_window = (pred_x[k] / 1440) * num_steps_window\n                    step_in_series = int(prev_num_steps_cumulative + step_in_window)\n                    event['series_id'] = series_id\n                    event['step'] = step_in_series\n                    event['event'] = pred_labels[k]\n                    event['score'] = pred['scores'][k].item()\n                    all_test_preds.append(event)          \n    if len(all_test_preds) > 0:\n        submission_df = pd.DataFrame(all_test_preds)\n        submission_df = submission_df.sort_values(by=['series_id', 'step']).reset_index(drop=True)\n        submission_df['row_id'] = np.arange(len(submission_df))\n        submission_df = submission_df[['row_id', 'series_id', 'step', 'event', 'score']]\n    else:\n        submission_df = pd.DataFrame({'row_id': [], 'series_id': [], 'step': [], 'event': [], 'score': []})\n    return submission_df","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:48.160659Z","iopub.execute_input":"2023-11-06T12:05:48.160943Z","iopub.status.idle":"2023-11-06T12:05:48.176397Z","shell.execute_reply.started":"2023-11-06T12:05:48.160920Z","shell.execute_reply":"2023-11-06T12:05:48.175477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = get_submission_df()\nsubmission_df","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:48.178846Z","iopub.execute_input":"2023-11-06T12:05:48.179101Z","iopub.status.idle":"2023-11-06T12:05:53.101193Z","shell.execute_reply.started":"2023-11-06T12:05:48.179078Z","shell.execute_reply":"2023-11-06T12:05:53.100363Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf /kaggle/working/images","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:53.102414Z","iopub.execute_input":"2023-11-06T12:05:53.102710Z","iopub.status.idle":"2023-11-06T12:05:54.086289Z","shell.execute_reply.started":"2023-11-06T12:05:53.102684Z","shell.execute_reply":"2023-11-06T12:05:54.085026Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2023-11-06T12:05:54.088045Z","iopub.execute_input":"2023-11-06T12:05:54.088384Z","iopub.status.idle":"2023-11-06T12:05:54.099989Z","shell.execute_reply.started":"2023-11-06T12:05:54.088353Z","shell.execute_reply":"2023-11-06T12:05:54.098882Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}