{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":178833205,"sourceType":"kernelVersion"}],"dockerImageVersionId":30559,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip show torchvision","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:12:39.781566Z","iopub.execute_input":"2024-05-21T23:12:39.781851Z","iopub.status.idle":"2024-05-21T23:12:51.622156Z","shell.execute_reply.started":"2024-05-21T23:12:39.781826Z","shell.execute_reply":"2024-05-21T23:12:51.620993Z"},"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":"2024-05-21T23:12:51.624200Z","iopub.execute_input":"2024-05-21T23:12:51.624503Z","iopub.status.idle":"2024-05-21T23:12:55.189736Z","shell.execute_reply.started":"2024-05-21T23:12:51.624477Z","shell.execute_reply":"2024-05-21T23:12:55.188763Z"},"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":"2024-05-21T23:12:55.191058Z","iopub.execute_input":"2024-05-21T23:12:55.191462Z","iopub.status.idle":"2024-05-21T23:12:55.196383Z","shell.execute_reply.started":"2024-05-21T23:12:55.191436Z","shell.execute_reply":"2024-05-21T23:12:55.195384Z"},"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":"2024-05-21T23:12:55.198781Z","iopub.execute_input":"2024-05-21T23:12:55.199089Z","iopub.status.idle":"2024-05-21T23:12:56.186860Z","shell.execute_reply.started":"2024-05-21T23:12:55.199061Z","shell.execute_reply":"2024-05-21T23:12:56.185698Z"},"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":"2024-05-21T23:12:56.190378Z","iopub.execute_input":"2024-05-21T23:12:56.190687Z","iopub.status.idle":"2024-05-21T23:12:56.423769Z","shell.execute_reply.started":"2024-05-21T23:12:56.190660Z","shell.execute_reply":"2024-05-21T23:12:56.422598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_series['large_enmo'] = test_series['enmo'] > 0.1506","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:12:56.425409Z","iopub.execute_input":"2024-05-21T23:12:56.425829Z","iopub.status.idle":"2024-05-21T23:12:56.432933Z","shell.execute_reply.started":"2024-05-21T23:12:56.425793Z","shell.execute_reply":"2024-05-21T23:12:56.431738Z"},"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":"2024-05-21T23:12:56.434164Z","iopub.execute_input":"2024-05-21T23:12:56.434889Z","iopub.status.idle":"2024-05-21T23:12:56.445175Z","shell.execute_reply.started":"2024-05-21T23:12:56.434861Z","shell.execute_reply":"2024-05-21T23:12:56.444014Z"},"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=20, minute=30, tzinfo=timezone.utc)\n    lower_bound = upper_bound + timedelta(hours=-24) # 8:30pm 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":"2024-05-21T23:12:56.446788Z","iopub.execute_input":"2024-05-21T23:12:56.447159Z","iopub.status.idle":"2024-05-21T23:12:57.165390Z","shell.execute_reply.started":"2024-05-21T23:12:56.447126Z","shell.execute_reply":"2024-05-21T23:12:57.164313Z"},"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":"2024-05-21T23:12:57.166807Z","iopub.execute_input":"2024-05-21T23:12:57.167190Z","iopub.status.idle":"2024-05-21T23:12:57.179710Z","shell.execute_reply.started":"2024-05-21T23:12:57.167161Z","shell.execute_reply":"2024-05-21T23:12:57.178697Z"},"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    transforms.append(T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225]))\n    return T.Compose(transforms)","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:12:57.184291Z","iopub.execute_input":"2024-05-21T23:12:57.184669Z","iopub.status.idle":"2024-05-21T23:12:57.190726Z","shell.execute_reply.started":"2024-05-21T23:12:57.184639Z","shell.execute_reply":"2024-05-21T23:12:57.189628Z"},"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":"2024-05-21T23:12:57.192276Z","iopub.execute_input":"2024-05-21T23:12:57.192614Z","iopub.status.idle":"2024-05-21T23:12:57.205886Z","shell.execute_reply.started":"2024-05-21T23:12:57.192583Z","shell.execute_reply":"2024-05-21T23:12:57.204934Z"},"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":"2024-05-21T23:12:57.207385Z","iopub.execute_input":"2024-05-21T23:12:57.207816Z","iopub.status.idle":"2024-05-21T23:12:57.251482Z","shell.execute_reply.started":"2024-05-21T23:12:57.207737Z","shell.execute_reply":"2024-05-21T23:12:57.250524Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = torchvision.models.detection.fasterrcnn_resnet50_fpn(weights=None, weights_backbone=None, max_size=1440)\nnum_classes = 3 # 'onset' + 'wakeup' + 'background' \nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:12:57.252904Z","iopub.execute_input":"2024-05-21T23:12:57.253538Z","iopub.status.idle":"2024-05-21T23:12:57.935092Z","shell.execute_reply.started":"2024-05-21T23:12:57.253502Z","shell.execute_reply":"2024-05-21T23:12:57.934115Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"weights = torch.load(\"/kaggle/input/k/iambestfeeder/d-s-s-faster-r-cnn-modeling/m12_4.pth\", map_location=device)\nmodel.load_state_dict(weights)","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:12:57.936203Z","iopub.execute_input":"2024-05-21T23:12:57.936487Z","iopub.status.idle":"2024-05-21T23:13:00.019096Z","shell.execute_reply.started":"2024-05-21T23:12:57.936462Z","shell.execute_reply":"2024-05-21T23:13:00.018207Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.to(device);","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:13:00.020063Z","iopub.execute_input":"2024-05-21T23:13:00.020308Z","iopub.status.idle":"2024-05-21T23:13:00.084318Z","shell.execute_reply.started":"2024-05-21T23:13:00.020285Z","shell.execute_reply":"2024-05-21T23:13:00.083411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference","metadata":{}},{"cell_type":"code","source":"model.eval()\nthresh = 0.3 # Tune this.\nreverse_label_mapping = {1: \"onset\", 2: \"wakeup\"}","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:13:00.085503Z","iopub.execute_input":"2024-05-21T23:13:00.085803Z","iopub.status.idle":"2024-05-21T23:13:00.091233Z","shell.execute_reply.started":"2024-05-21T23:13:00.085772Z","shell.execute_reply":"2024-05-21T23:13:00.090301Z"},"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 # All images have width 1,440px.\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":"2024-05-21T23:13:00.092611Z","iopub.execute_input":"2024-05-21T23:13:00.092960Z","iopub.status.idle":"2024-05-21T23:13:00.108429Z","shell.execute_reply.started":"2024-05-21T23:13:00.092929Z","shell.execute_reply":"2024-05-21T23:13:00.107602Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = get_submission_df()\nsubmission_df","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:13:00.109528Z","iopub.execute_input":"2024-05-21T23:13:00.109940Z","iopub.status.idle":"2024-05-21T23:13:01.252479Z","shell.execute_reply.started":"2024-05-21T23:13:00.109908Z","shell.execute_reply":"2024-05-21T23:13:01.251558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf /kaggle/working/images","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:13:01.253818Z","iopub.execute_input":"2024-05-21T23:13:01.254426Z","iopub.status.idle":"2024-05-21T23:13:02.222403Z","shell.execute_reply.started":"2024-05-21T23:13:01.254391Z","shell.execute_reply":"2024-05-21T23:13:02.221291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df.to_csv(\"submission.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-21T23:13:02.224151Z","iopub.execute_input":"2024-05-21T23:13:02.224556Z","iopub.status.idle":"2024-05-21T23:13:02.236734Z","shell.execute_reply.started":"2024-05-21T23:13:02.224520Z","shell.execute_reply":"2024-05-21T23:13:02.235806Z"},"trusted":true},"execution_count":null,"outputs":[]}]}