{"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":"none","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":152623651,"sourceType":"kernelVersion"},{"sourceId":151018325,"sourceType":"kernelVersion"},{"sourceId":152301720,"sourceType":"kernelVersion"}],"dockerImageVersionId":30587,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Reference: https://github.com/pytorch/tutorials/blob/d686b662932a380a58b7683425faa00c06bcf502/intermediate_source/torchvision_tutorial.rst","metadata":{}},{"cell_type":"code","source":"!pip install pycocotools","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:56:53.762297Z","iopub.execute_input":"2023-11-30T21:56:53.762674Z","iopub.status.idle":"2023-11-30T21:57:10.386717Z","shell.execute_reply.started":"2023-11-30T21:56:53.762632Z","shell.execute_reply":"2023-11-30T21:57:10.385518Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nfrom pathlib import Path\nimport random\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport torch\nimport torchvision\n\nfrom tqdm import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-11-30T21:57:17.764671Z","iopub.execute_input":"2023-11-30T21:57:17.765183Z","iopub.status.idle":"2023-11-30T21:57:22.720566Z","shell.execute_reply.started":"2023-11-30T21:57:17.765124Z","shell.execute_reply":"2023-11-30T21:57:22.718944Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_folder = Path(\"/kaggle/input/child-mind-institute-detect-sleep-states\")\ntrain_events = pd.read_csv(data_folder/\"train_events.csv\")\ntrain_events","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:57:25.325530Z","iopub.execute_input":"2023-11-30T21:57:25.326141Z","iopub.status.idle":"2023-11-30T21:57:25.405611Z","shell.execute_reply.started":"2023-11-30T21:57:25.326103Z","shell.execute_reply":"2023-11-30T21:57:25.404607Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_ids = train_events['series_id'].unique()\nlen(series_ids)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:57:28.746643Z","iopub.execute_input":"2023-11-30T21:57:28.747047Z","iopub.status.idle":"2023-11-30T21:57:28.763812Z","shell.execute_reply.started":"2023-11-30T21:57:28.747000Z","shell.execute_reply":"2023-11-30T21:57:28.762509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_prep_folder = Path(\"/kaggle/input/d-s-s-faster-r-cnn-data-prep\")\nimages_folder = data_prep_folder/\"images\"","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:07.419097Z","iopub.execute_input":"2023-11-30T21:59:07.419505Z","iopub.status.idle":"2023-11-30T21:59:07.424967Z","shell.execute_reply.started":"2023-11-30T21:59:07.419475Z","shell.execute_reply":"2023-11-30T21:59:07.423697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_names = []\nfor file_path in images_folder.glob(\"*.jpg\"):\n    file_name = str(file_path).split(\"/\")[-1]\n    image_names.append(file_name)\nlen(image_names)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:08.235898Z","iopub.execute_input":"2023-11-30T21:59:08.236327Z","iopub.status.idle":"2023-11-30T21:59:08.847693Z","shell.execute_reply.started":"2023-11-30T21:59:08.236293Z","shell.execute_reply":"2023-11-30T21:59:08.846338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_names[:5]","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:10.463943Z","iopub.execute_input":"2023-11-30T21:59:10.464373Z","iopub.status.idle":"2023-11-30T21:59:10.471121Z","shell.execute_reply.started":"2023-11-30T21:59:10.464340Z","shell.execute_reply":"2023-11-30T21:59:10.469940Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"annotations_df = pd.read_csv(data_prep_folder/\"annotations_8_30pm_utc_cutoff.csv\")\nannotations_df","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:11.512168Z","iopub.execute_input":"2023-11-30T21:59:11.513002Z","iopub.status.idle":"2023-11-30T21:59:11.572990Z","shell.execute_reply.started":"2023-11-30T21:59:11.512956Z","shell.execute_reply":"2023-11-30T21:59:11.572107Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(annotations_df['series_id'].unique())","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:13.999143Z","iopub.execute_input":"2023-11-30T21:59:13.999904Z","iopub.status.idle":"2023-11-30T21:59:14.010391Z","shell.execute_reply.started":"2023-11-30T21:59:13.999851Z","shell.execute_reply":"2023-11-30T21:59:14.008989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(annotations_df['image_name'].unique())","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:14.817170Z","iopub.execute_input":"2023-11-30T21:59:14.817589Z","iopub.status.idle":"2023-11-30T21:59:14.827904Z","shell.execute_reply.started":"2023-11-30T21:59:14.817560Z","shell.execute_reply":"2023-11-30T21:59:14.826550Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"window_properties_df = pd.read_csv(data_prep_folder/\"window_properties_8_30pm_utc_cutoff.csv\")\nwindow_properties_df","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:15.776131Z","iopub.execute_input":"2023-11-30T21:59:15.776521Z","iopub.status.idle":"2023-11-30T21:59:15.823395Z","shell.execute_reply.started":"2023-11-30T21:59:15.776491Z","shell.execute_reply":"2023-11-30T21:59:15.822270Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"num_test_series_ids = round(0.1 * len(series_ids))\nnum_val_series_ids = round(0.2 * len(series_ids))\nnum_val_test_series_ids = num_test_series_ids + num_val_series_ids","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:19.571234Z","iopub.execute_input":"2023-11-30T21:59:19.571654Z","iopub.status.idle":"2023-11-30T21:59:19.577836Z","shell.execute_reply.started":"2023-11-30T21:59:19.571618Z","shell.execute_reply":"2023-11-30T21:59:19.576429Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(42)\nseries_ids_in_val_test = np.random.choice(series_ids, size=num_val_test_series_ids, replace=False)\nseries_ids_in_val = np.random.choice(series_ids_in_val_test, size = num_val_series_ids, replace=False)\nseries_ids_in_test = series_ids_in_val_test[~ np.isin(series_ids_in_val_test, series_ids_in_val)]\n# print(series_ids_in_val_test, len(series_ids_in_val_test))\nprint(series_ids_in_val, len(series_ids_in_val))\nprint(series_ids_in_test, len(series_ids_in_test))","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:20.023653Z","iopub.execute_input":"2023-11-30T21:59:20.024220Z","iopub.status.idle":"2023-11-30T21:59:20.036597Z","shell.execute_reply.started":"2023-11-30T21:59:20.024179Z","shell.execute_reply":"2023-11-30T21:59:20.035408Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_ids_in_train = series_ids[~ np.isin(series_ids, series_ids_in_val_test)]\nprint(series_ids_in_train,len(series_ids_in_train))","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:20.485764Z","iopub.execute_input":"2023-11-30T21:59:20.486556Z","iopub.status.idle":"2023-11-30T21:59:20.494687Z","shell.execute_reply.started":"2023-11-30T21:59:20.486519Z","shell.execute_reply":"2023-11-30T21:59:20.493745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = window_properties_df.loc[window_properties_df['series_id'].isin(series_ids_in_train)].reset_index(drop=True)\nval = window_properties_df.loc[window_properties_df['series_id'].isin(series_ids_in_val)].reset_index(drop=True)\ntest = window_properties_df.loc[window_properties_df['series_id'].isin(series_ids_in_test)].reset_index(drop=True)\nlen(train), len(val) , len(test)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:21.180960Z","iopub.execute_input":"2023-11-30T21:59:21.182001Z","iopub.status.idle":"2023-11-30T21:59:21.204817Z","shell.execute_reply.started":"2023-11-30T21:59:21.181954Z","shell.execute_reply":"2023-11-30T21:59:21.203446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"val_events = train_events.loc[train_events['series_id'].isin(series_ids_in_val)]\nval_events = val_events.loc[val_events['timestamp'].notna()].reset_index(drop=True)\nval_events","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:22.774227Z","iopub.execute_input":"2023-11-30T21:59:22.774635Z","iopub.status.idle":"2023-11-30T21:59:22.796986Z","shell.execute_reply.started":"2023-11-30T21:59:22.774603Z","shell.execute_reply":"2023-11-30T21:59:22.795993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_events = train_events.loc[train_events['series_id'].isin(series_ids_in_test)]\ntest_events = test_events.loc[test_events['timestamp'].notna()].reset_index(drop=True)\ntest_events","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:23.244035Z","iopub.execute_input":"2023-11-30T21:59:23.244454Z","iopub.status.idle":"2023-11-30T21:59:23.268973Z","shell.execute_reply.started":"2023-11-30T21:59:23.244412Z","shell.execute_reply":"2023-11-30T21:59:23.267664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_events = train_events.loc[train_events['series_id'].isin(series_ids_in_train)]\ntrain_events = train_events.loc[train_events['timestamp'].notna()].reset_index(drop=True)\ntrain_events","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:23.749278Z","iopub.execute_input":"2023-11-30T21:59:23.749671Z","iopub.status.idle":"2023-11-30T21:59:23.775631Z","shell.execute_reply.started":"2023-11-30T21:59:23.749640Z","shell.execute_reply":"2023-11-30T21:59:23.774327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Competition Metric Functions:**","metadata":{}},{"cell_type":"code","source":"class ParticipantVisibleError(Exception):\n    pass","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:26.081682Z","iopub.execute_input":"2023-11-30T21:59:26.082095Z","iopub.status.idle":"2023-11-30T21:59:26.088149Z","shell.execute_reply.started":"2023-11-30T21:59:26.082057Z","shell.execute_reply":"2023-11-30T21:59:26.087018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"series_id_column_name = None\ntime_column_name = None\nevent_column_name = None\nscore_column_name = None\nuse_scoring_intervals = None","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:26.549838Z","iopub.execute_input":"2023-11-30T21:59:26.550268Z","iopub.status.idle":"2023-11-30T21:59:26.556031Z","shell.execute_reply.started":"2023-11-30T21:59:26.550233Z","shell.execute_reply":"2023-11-30T21:59:26.554536Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def score(solution, submission, tolerances, series_id_column_name, time_column_name, event_column_name, score_column_name, use_scoring_intervals=False):\n    # Validate metric parameters.\n    assert len(tolerances) > 0, \"Events must have defined tolerances.\"\n    assert set(tolerances.keys()) == set(solution[event_column_name]).difference({'start', 'end'}),\\\n        (f\"Solution column {event_column_name} must contain the same events \"\n         \"as defined in tolerances.\")\n    assert pd.api.types.is_numeric_dtype(solution[time_column_name]),\\\n        f\"Solution column {time_column_name} must be of numeric type.\"\n\n    # Validate submission format.\n    for column_name in [\n        series_id_column_name,\n        time_column_name,\n        event_column_name,\n        score_column_name,\n    ]:\n        if column_name not in submission.columns:\n            raise ParticipantVisibleError(f\"Submission must have column '{column_name}'.\")\n\n    if not pd.api.types.is_numeric_dtype(submission[time_column_name]):\n        raise ParticipantVisibleError(\n            f\"Submission column '{time_column_name}' must be of numeric type.\"\n        )\n    if not pd.api.types.is_numeric_dtype(submission[score_column_name]):\n        raise ParticipantVisibleError(\n            f\"Submission column '{score_column_name}' must be of numeric type.\"\n        )\n\n    # Set these globally to avoid passing around a bunch of arguments.\n    globals()['series_id_column_name'] = series_id_column_name\n    globals()['time_column_name'] = time_column_name\n    globals()['event_column_name'] = event_column_name\n    globals()['score_column_name'] = score_column_name\n    globals()['use_scoring_intervals'] = use_scoring_intervals\n\n    return event_detection_ap(solution, submission, tolerances)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:28.546873Z","iopub.execute_input":"2023-11-30T21:59:28.547305Z","iopub.status.idle":"2023-11-30T21:59:28.558581Z","shell.execute_reply.started":"2023-11-30T21:59:28.547270Z","shell.execute_reply":"2023-11-30T21:59:28.557628Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def filter_detections(detections, intervals):\n    detection_time = detections.loc[:, time_column_name].sort_values().to_numpy()\n    intervals = intervals.to_numpy()\n    is_scored = np.full_like(detection_time, False, dtype=bool)\n\n    i, j = 0, 0\n    while i < len(detection_time) and j < len(intervals):\n        time = detection_time[i]\n        int_ = intervals[j]\n\n        # If the detection is prior in time to the interval, go to the next detection.\n        if time < int_.left:\n            i += 1\n        # If the detection is inside the interval, keep it and go to the next detection.\n        elif time in int_:\n            is_scored[i] = True\n            i += 1\n        # If the detection is later in time, go to the next interval.\n        else:\n            j += 1\n\n    return detections.loc[is_scored].reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:30.060719Z","iopub.execute_input":"2023-11-30T21:59:30.061414Z","iopub.status.idle":"2023-11-30T21:59:30.071466Z","shell.execute_reply.started":"2023-11-30T21:59:30.061365Z","shell.execute_reply":"2023-11-30T21:59:30.070139Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def match_detections(tolerance, ground_truths, detections):\n    detections_sorted = detections.sort_values(score_column_name, ascending=False).dropna()\n    is_matched = np.full_like(detections_sorted[event_column_name], False, dtype=bool)\n    gts_matched = set()\n    for i, det in enumerate(detections_sorted.itertuples(index=False)):\n        best_error = tolerance\n        best_gt = None\n\n        for gt in ground_truths.itertuples(index=False):\n            error = abs(getattr(det, time_column_name) - getattr(gt, time_column_name))\n            if error < best_error and gt not in gts_matched:\n                best_gt = gt\n                best_error = error\n\n        if best_gt is not None:\n            is_matched[i] = True\n            gts_matched.add(best_gt)\n\n    detections_sorted['matched'] = is_matched\n\n    return detections_sorted","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:30.502047Z","iopub.execute_input":"2023-11-30T21:59:30.502435Z","iopub.status.idle":"2023-11-30T21:59:30.511200Z","shell.execute_reply.started":"2023-11-30T21:59:30.502405Z","shell.execute_reply":"2023-11-30T21:59:30.510281Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def precision_recall_curve(matches, scores, p):\n    if len(matches) == 0:\n        return [1], [0], []\n\n    # Sort matches by decreasing confidence.\n    idxs = np.argsort(scores, kind='stable')[::-1]\n    scores = scores[idxs]\n    matches = matches[idxs]\n\n    distinct_value_indices = np.where(np.diff(scores))[0]\n    threshold_idxs = np.r_[distinct_value_indices, matches.size - 1]\n    thresholds = scores[threshold_idxs]\n\n    # Matches become TPs and non-matches FPs as confidence threshold decreases.\n    tps = np.cumsum(matches)[threshold_idxs]\n    fps = np.cumsum(~matches)[threshold_idxs]\n\n    precision = tps / (tps + fps)\n    precision[np.isnan(precision)] = 0\n    recall = tps / p  # Total number of ground truths might be different than total number of matches.\n\n    # Stop when full recall attained and reverse the outputs so recall is non-increasing.\n    last_ind = tps.searchsorted(tps[-1])\n    sl = slice(last_ind, None, -1)\n\n    # Final precision is 1 and final recall is 0.\n    return np.r_[precision[sl], 1], np.r_[recall[sl], 0], thresholds[sl]","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:30.923528Z","iopub.execute_input":"2023-11-30T21:59:30.924096Z","iopub.status.idle":"2023-11-30T21:59:30.935196Z","shell.execute_reply.started":"2023-11-30T21:59:30.924047Z","shell.execute_reply":"2023-11-30T21:59:30.933866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def average_precision_score(matches, scores, p):\n    precision, recall, _ = precision_recall_curve(matches, scores, p)\n    # Compute step integral.\n    return -np.sum(np.diff(recall) * np.array(precision)[:-1])","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:32.007162Z","iopub.execute_input":"2023-11-30T21:59:32.007551Z","iopub.status.idle":"2023-11-30T21:59:32.016118Z","shell.execute_reply.started":"2023-11-30T21:59:32.007520Z","shell.execute_reply":"2023-11-30T21:59:32.014566Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def event_detection_ap(solution, submission, tolerances):\n    # Ensure solution and submission are sorted properly.\n    solution = solution.sort_values([series_id_column_name, time_column_name])\n    submission = submission.sort_values([series_id_column_name, time_column_name])\n\n    # Extract scoring intervals.\n    if use_scoring_intervals:\n        intervals = (\n            solution\n            .query(\"event in ['start', 'end']\")\n            .assign(interval=lambda x: x.groupby([series_id_column_name, event_column_name]).cumcount())\n            .pivot(\n                index='interval',\n                columns=[series_id_column_name, event_column_name],\n                values=time_column_name,\n            )\n            .stack(series_id_column_name)\n            .swaplevel()\n            .sort_index()\n            .loc[:, ['start', 'end']]\n            .apply(lambda x: pd.Interval(*x, closed='both'), axis=1)\n        )\n\n    # Extract ground-truth events.\n    ground_truths = (\n        solution\n        .query(\"event not in ['start', 'end']\")\n        .reset_index(drop=True)\n    )\n\n    # Map each event class to its prevalence (needed for recall calculation).\n    class_counts = ground_truths.value_counts(event_column_name).to_dict()\n\n    # Create table for detections with a column indicating a match to a ground-truth event.\n    detections = submission.assign(matched = False)\n\n    # Remove detections outside of scoring intervals.\n    if use_scoring_intervals:\n        detections_filtered = []\n        for (det_group, dets), (int_group, ints) in zip(\n            detections.groupby(series_id_column_name), intervals.groupby(series_id_column_name)\n        ):\n            assert det_group == int_group\n            detections_filtered.append(filter_detections(dets, ints))\n        detections_filtered = pd.concat(detections_filtered, ignore_index=True)\n    else:\n        detections_filtered = detections\n\n    # Create table of event-class x tolerance x series_id values.\n    aggregation_keys = pd.DataFrame(\n        [(ev, tol, vid)\n         for ev in tolerances.keys()\n         for tol in tolerances[ev]\n         for vid in ground_truths[series_id_column_name].unique()],\n        columns=[event_column_name, 'tolerance', series_id_column_name],\n    )\n\n    # Create match evaluation groups: event-class x tolerance x series_id.\n    detections_grouped = (\n        aggregation_keys\n        .merge(detections_filtered, on=[event_column_name, series_id_column_name], how='left')\n        .groupby([event_column_name, 'tolerance', series_id_column_name])\n    )\n    ground_truths_grouped = (\n        aggregation_keys\n        .merge(ground_truths, on=[event_column_name, series_id_column_name], how='left')\n        .groupby([event_column_name, 'tolerance', series_id_column_name])\n    )\n    # Match detections to ground truth events by evaluation group.\n    detections_matched = []\n    for key in aggregation_keys.itertuples(index=False):\n        dets = detections_grouped.get_group(key)\n        gts = ground_truths_grouped.get_group(key)\n        detections_matched.append(\n            match_detections(dets['tolerance'].iloc[0], gts, dets)\n        )\n    detections_matched = pd.concat(detections_matched)\n\n    # Compute AP per event x tolerance group.\n    event_classes = ground_truths[event_column_name].unique()\n    ap_table = (\n        detections_matched\n        .query(\"event in @event_classes\")\n        .groupby([event_column_name, 'tolerance']).apply(\n            lambda group: average_precision_score(\n                group['matched'].to_numpy(),\n                group[score_column_name].to_numpy(),\n                class_counts[group[event_column_name].iat[0]],\n            )\n        )\n    )\n    # Average over tolerances, then over event classes.\n    mean_ap = ap_table.groupby(event_column_name).mean().sum() / len(event_classes)\n\n    return mean_ap","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:32.538464Z","iopub.execute_input":"2023-11-30T21:59:32.538988Z","iopub.status.idle":"2023-11-30T21:59:32.561154Z","shell.execute_reply.started":"2023-11-30T21:59:32.538949Z","shell.execute_reply":"2023-11-30T21:59:32.560125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tolerances = {\n    \"onset\" : [12, 36, 60, 90, 120, 150, 180, 240, 300, 360],\n    'wakeup': [12, 36, 60, 90, 120, 150, 180, 240, 300, 360]    \n}","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:33.343972Z","iopub.execute_input":"2023-11-30T21:59:33.345236Z","iopub.status.idle":"2023-11-30T21:59:33.351256Z","shell.execute_reply.started":"2023-11-30T21:59:33.345191Z","shell.execute_reply":"2023-11-30T21:59:33.350093Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"column_names = {\n    'series_id_column_name': 'series_id',\n    'time_column_name': 'step',\n    'event_column_name': 'event',\n    'score_column_name': 'score'\n}","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:33.857412Z","iopub.execute_input":"2023-11-30T21:59:33.857811Z","iopub.status.idle":"2023-11-30T21:59:33.863639Z","shell.execute_reply.started":"2023-11-30T21:59:33.857781Z","shell.execute_reply":"2023-11-30T21:59:33.862290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Utils","metadata":{}},{"cell_type":"code","source":"# from torchvision.transforms import v2 as T\n# from torchvision.transforms.v2 import functional as F\n# def get_transforms():\n#     transforms = []\n# #     transforms.append(T.ToImageDtype(torch.float))\n#     transforms.append(T.ToDtype(torch.float))\n# #     transforms.append(T.ToPureTensor())\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":"2023-11-30T20:55:39.626728Z","iopub.status.idle":"2023-11-30T20:55:39.627187Z","shell.execute_reply.started":"2023-11-30T20:55:39.626964Z","shell.execute_reply":"2023-11-30T20:55:39.626983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Download helper functions:\nos.system(\"wget https://raw.githubusercontent.com/pytorch/vision/v0.15.1/references/detection/transforms.py\")\nos.system(\"wget https://raw.githubusercontent.com/pytorch/vision/v0.15.1/references/detection/utils.py\")\n# A change is needed for the following file (evaluate function), so it is included manually\n# os.system(\"wget https://raw.githubusercontent.com/pytorch/vision/v0.16.0/references/detection/engine.py\")\nos.system(\"wget https://raw.githubusercontent.com/pytorch/vision/v0.16.0/references/detection/coco_utils.py\")\nos.system(\"wget https://raw.githubusercontent.com/pytorch/vision/v0.16.0/references/detection/coco_eval.py\")","metadata":{"execution":{"iopub.status.busy":"2023-11-30T21:59:58.200028Z","iopub.execute_input":"2023-11-30T21:59:58.200443Z","iopub.status.idle":"2023-11-30T21:59:59.196357Z","shell.execute_reply.started":"2023-11-30T21:59:58.200412Z","shell.execute_reply":"2023-11-30T21:59:59.195258Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\nimport sys\nimport time\n\nimport torch\nimport torchvision.models.detection.mask_rcnn\nimport utils\nfrom coco_eval import CocoEvaluator\nfrom coco_utils import get_coco_api_from_dataset\n\n\ndef train_one_epoch(model, optimizer, data_loader, device, epoch, print_freq, scaler=None):\n    model.train()\n    metric_logger = utils.MetricLogger(delimiter=\"  \")\n    metric_logger.add_meter(\"lr\", utils.SmoothedValue(window_size=1, fmt=\"{value:.6f}\"))\n    header = f\"Epoch: [{epoch}]\"\n\n    lr_scheduler = None\n    if epoch == 0:\n        warmup_factor = 1.0 / 1000\n        warmup_iters = min(1000, len(data_loader) - 1)\n\n        lr_scheduler = torch.optim.lr_scheduler.LinearLR(\n            optimizer, start_factor=warmup_factor, total_iters=warmup_iters\n        )\n\n    for images, targets in metric_logger.log_every(data_loader, print_freq, header):\n        images = list(image.to(device) for image in images)\n        targets = [{k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in t.items()} for t in targets]\n        with torch.cuda.amp.autocast(enabled=scaler is not None):\n            loss_dict = model(images, targets)\n            losses = sum(loss for loss in loss_dict.values())\n\n        # reduce losses over all GPUs for logging purposes\n        loss_dict_reduced = utils.reduce_dict(loss_dict)\n        losses_reduced = sum(loss for loss in loss_dict_reduced.values())\n\n        loss_value = losses_reduced.item()\n\n        if not math.isfinite(loss_value):\n            print(f\"Loss is {loss_value}, stopping training\")\n            print(loss_dict_reduced)\n            sys.exit(1)\n\n        optimizer.zero_grad()\n        if scaler is not None:\n            scaler.scale(losses).backward()\n            scaler.step(optimizer)\n            scaler.update()\n        else:\n            losses.backward()\n            optimizer.step()\n\n        if lr_scheduler is not None:\n            lr_scheduler.step()\n\n        metric_logger.update(loss=losses_reduced, **loss_dict_reduced)\n        metric_logger.update(lr=optimizer.param_groups[0][\"lr\"])\n\n    return metric_logger\n\n\ndef _get_iou_types(model):\n    model_without_ddp = model\n    if isinstance(model, torch.nn.parallel.DistributedDataParallel):\n        model_without_ddp = model.module\n    iou_types = [\"bbox\"]\n    if isinstance(model_without_ddp, torchvision.models.detection.MaskRCNN):\n        iou_types.append(\"segm\")\n    if isinstance(model_without_ddp, torchvision.models.detection.KeypointRCNN):\n        iou_types.append(\"keypoints\")\n    return iou_types\n\n\n@torch.inference_mode()\ndef evaluate(model, data_loader, device):\n    n_threads = torch.get_num_threads()\n    # FIXME remove this and make paste_masks_in_image run on the GPU\n    torch.set_num_threads(1)\n    cpu_device = torch.device(\"cpu\")\n    model.eval()\n    metric_logger = utils.MetricLogger(delimiter=\"  \")\n    header = \"Test:\"\n\n    coco = get_coco_api_from_dataset(data_loader.dataset)\n    iou_types = _get_iou_types(model)\n    coco_evaluator = CocoEvaluator(coco, iou_types)\n\n    for images, targets in metric_logger.log_every(data_loader, 100, header):\n        images = list(img.to(device) for img in images)\n\n        if torch.cuda.is_available():\n            torch.cuda.synchronize()\n        model_time = time.time()\n        outputs = model(images)\n\n        outputs = [{k: v.to(device) if isinstance(v, torch.Tensor) else v for k, v in t.items()} for t in outputs]\n        model_time = time.time() - model_time\n\n        res = {target[\"image_id\"]: output for target, output in zip(targets, outputs)}\n        evaluator_time = time.time()\n        coco_evaluator.update(res)\n        evaluator_time = time.time() - evaluator_time\n        metric_logger.update(model_time=model_time, evaluator_time=evaluator_time)\n\n    # gather the stats from all processes\n    metric_logger.synchronize_between_processes()\n    print(\"Averaged stats:\", metric_logger)\n    coco_evaluator.synchronize_between_processes()\n\n    # accumulate predictions from all images\n    coco_evaluator.accumulate()\n    coco_evaluator.summarize()\n    torch.set_num_threads(n_threads)\n    return coco_evaluator","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.631417Z","iopub.status.idle":"2023-11-30T20:55:39.632238Z","shell.execute_reply.started":"2023-11-30T20:55:39.631968Z","shell.execute_reply":"2023-11-30T20:55:39.631989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import transforms as T\n\ndef get_transforms():\n    transforms = []\n    transforms.append(T.PILToTensor())\n    transforms.append(T.ConvertImageDtype(torch.float))\n    return T.Compose(transforms)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:03.421645Z","iopub.execute_input":"2023-11-30T22:00:03.422133Z","iopub.status.idle":"2023-11-30T22:00:03.439416Z","shell.execute_reply.started":"2023-11-30T22:00:03.422097Z","shell.execute_reply":"2023-11-30T22:00:03.438293Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"eval_transforms = get_transforms()\nreverse_label_mapping = {1: \"onset\", 2: \"wakeup\"}","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:05.919499Z","iopub.execute_input":"2023-11-30T22:00:05.919918Z","iopub.status.idle":"2023-11-30T22:00:05.925679Z","shell.execute_reply.started":"2023-11-30T22:00:05.919884Z","shell.execute_reply":"2023-11-30T22:00:05.924196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from torchvision.io import read_image\n# def compute_metric():\n#     all_val_preds = []\n#     for i, series_id in tqdm(enumerate(series_ids_in_val)): # 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(data_prep_folder, \"images\", image_name)\n#             image = read_image(image_path)\n# #             image = Image.open(image_path).convert(\"RGB\")\n#             with torch.no_grad():\n#                 x = eval_transforms(image)\n#                 x = x.to(device)\n#                 predictions = model([x])\n#             pred = predictions[0]\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#             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_val_preds.append(event)\n#     all_val_preds_df = pd.DataFrame(all_val_preds)\n#     all_val_preds_df = all_val_preds_df.sort_values(by=['series_id', 'step']).reset_index(drop=True)\n#     all_val_preds_df['row_id'] = np.arange(len(all_val_preds_df))\n#     all_val_preds_df = all_val_preds_df[['row_id', 'series_id', 'step', 'event', 'score']]\n#     competition_metric = round(score(val_events, all_val_preds_df, tolerances, **column_names), 4)\n#     return competition_metric","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.637758Z","iopub.status.idle":"2023-11-30T20:55:39.638463Z","shell.execute_reply.started":"2023-11-30T20:55:39.638252Z","shell.execute_reply":"2023-11-30T20:55:39.638274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.io import read_image\ndef compute_metric():\n    all_val_preds = []\n    dummy_target = {'boxes': torch.tensor([[424.,  20., 464., 380.],\n          [927.,  20., 967., 380.]]),\n  'labels': torch.tensor([1, 2]),\n  'image_id': 'c908a0ad3e31_2018-02-03T20:30:00.jpg',\n  'area': torch.tensor([14400., 14400.]),\n  'iscrowd': torch.tensor([0, 0])}\n    for i, series_id in tqdm(enumerate(series_ids_in_val)): # i is the index of the series.\n#     for i, images,targets = tqdm(iter(data_loader)):\n\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(data_prep_folder, \"images\", image_name)\n#             image = read_image(image_path)\n            image = Image.open(image_path).convert(\"RGB\")\n            model.eval()\n            with torch.no_grad():\n                x,_ = eval_transforms(image,dummy_target)\n                x = x.to(device)\n                predictions = model([x])\n            pred = predictions[0]\n            model.train()\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            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_val_preds.append(event)\n    all_val_preds_df = pd.DataFrame(all_val_preds)\n    all_val_preds_df = all_val_preds_df.sort_values(by=['series_id', 'step']).reset_index(drop=True)\n    all_val_preds_df['row_id'] = np.arange(len(all_val_preds_df))\n    all_val_preds_df = all_val_preds_df[['row_id', 'series_id', 'step', 'event', 'score']]\n    competition_metric = round(score(val_events, all_val_preds_df, tolerances, **column_names), 4)\n    return competition_metric","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.639949Z","iopub.status.idle":"2023-11-30T20:55:39.640726Z","shell.execute_reply.started":"2023-11-30T20:55:39.640450Z","shell.execute_reply":"2023-11-30T20:55:39.640481Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# compute_metric()","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.642497Z","iopub.status.idle":"2023-11-30T20:55:39.642974Z","shell.execute_reply.started":"2023-11-30T20:55:39.642750Z","shell.execute_reply":"2023-11-30T20:55:39.642771Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Create Dataclass","metadata":{}},{"cell_type":"code","source":"# from torchvision.io import read_image\n# from torchvision import tv_tensors\n# class SleepStatesDataset(torch.utils.data.Dataset):\n#     def __init__(self, split_df, annotations_df, images_folder, transforms):\n#         self.label_mapping = {'onset': 1, 'wakeup': 2}\n#         self.split_df = split_df\n#         self.annotations_df = annotations_df\n#         self.images_folder = images_folder\n#         self.transforms = transforms\n    \n#     def __len__(self):\n#         return len(self.split_df)\n    \n#     def __getitem__(self, idx):\n#         image_name = self.split_df['image_name'][idx]\n#         image_path = os.path.join(self.images_folder, image_name)\n#         image = read_image(image_path)\n#         window_df = self.annotations_df.loc[self.annotations_df['image_name'] == image_name]\n#         if len(window_df) > 0:            \n#             boxes = torch.tensor(window_df.iloc[:, 5:].values, dtype=torch.float32)\n#             labels = window_df['label']\n#             labels = torch.tensor([self.label_mapping[l] for l in labels], dtype=torch.int64)\n#             area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n#             iscrowd = torch.zeros(size=(len(window_df),), dtype=torch.int64)\n#         else:\n#             boxes = torch.empty(size=(0, 4), dtype=torch.float32)\n#             labels = torch.empty(size=(0,), dtype=torch.int64)\n#             area = torch.empty(size=(0,), dtype=torch.float32)\n#             iscrowd = torch.empty(size=(0,), dtype=torch.int64)\n        \n#         image = tv_tensors.Image(image)\n#         target = {}\n#         target['image_id'] = image_name\n#         target['boxes'] = tv_tensors.BoundingBoxes(boxes, format=\"XYXY\", canvas_size=F.get_size(image))\n#         target['labels'] = labels\n#         target['area'] = area\n#         target['iscrowd'] = iscrowd\n        \n#         if self.transforms is not None:\n#             image, target = self.transforms(image, target)\n\n#         return image, target","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.644904Z","iopub.status.idle":"2023-11-30T20:55:39.645376Z","shell.execute_reply.started":"2023-11-30T20:55:39.645166Z","shell.execute_reply":"2023-11-30T20:55:39.645188Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport torch\nfrom PIL import Image\n\n\nclass SleepStatesDataset(torch.utils.data.Dataset):\n    def __init__(self, split_df, annotations_df, images_folder, transforms):\n        self.label_mapping = {'onset': 1, 'wakeup': 2}\n        self.split_df = split_df\n        self.annotations_df = annotations_df\n        self.images_folder = images_folder\n        self.transforms = transforms\n\n    def __getitem__(self, idx):\n        # load images and masks\n        image_name = self.split_df['image_name'][idx]\n        img_path = os.path.join(self.images_folder, image_name)\n#         img_path = os.path.join(self.root, \"PNGImages\", self.imgs[idx])\n#         mask_path = os.path.join(self.root, \"PedMasks\", self.masks[idx])\n        img = Image.open(img_path).convert(\"RGB\")\n    \n#         # note that we haven't converted the mask to RGB,\n#         # because each color corresponds to a different instance\n#         # with 0 being background\n#         mask = Image.open(mask_path)\n#         # convert the PIL Image into a numpy array\n#         mask = np.array(mask)\n#         # instances are encoded as different colors\n#         obj_ids = np.unique(mask)\n#         # first id is the background, so remove it\n#         obj_ids = obj_ids[1:]\n#         # split the color-encoded mask into a set\n#         # of binary masks\n#         masks = mask == obj_ids[:, None, None]\n\n        window_df = self.annotations_df.loc[self.annotations_df['image_name'] == image_name]\n        \n        if len(window_df) > 0:            \n            boxes = torch.tensor(window_df.iloc[:, 5:].values, dtype=torch.float32)\n            labels = window_df['label']\n            labels = torch.tensor([self.label_mapping[l] for l in labels], dtype=torch.int64)\n            area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n            iscrowd = torch.zeros(size=(len(window_df),), dtype=torch.int64)\n        else:\n            boxes = torch.empty(size=(0, 4), dtype=torch.float32)\n            labels = torch.empty(size=(0,), dtype=torch.int64)\n            area = torch.empty(size=(0,), dtype=torch.float32)\n            iscrowd = torch.empty(size=(0,), dtype=torch.int64)\n        \n#         # get bounding box coordinates for each mask\n#         num_objs = len(obj_ids)\n#         boxes = []\n#         for i in range(num_objs):\n#             pos = np.nonzero(masks[i])\n#             xmin = np.min(pos[1])\n#             xmax = np.max(pos[1])\n#             ymin = np.min(pos[0])\n#             ymax = np.max(pos[0])\n#             boxes.append([xmin, ymin, xmax, ymax])\n\n        # convert everything into a torch.Tensor\n        boxes = torch.as_tensor(boxes, dtype=torch.float32)\n        # there is only one class\n#         labels = torch.ones((num_objs,), dtype=torch.int64)\n#         masks = torch.as_tensor(masks, dtype=torch.uint8)\n\n#         image_id = torch.tensor([idx])\n#         area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n#         # suppose all instances are not crowd\n#         iscrowd = torch.zeros((num_objs,), dtype=torch.int64)\n\n        target = {}\n        target[\"boxes\"] = boxes\n        target[\"labels\"] = labels\n#         target[\"masks\"] = masks\n        target[\"image_id\"] = image_name\n        target[\"area\"] = area\n        target[\"iscrowd\"] = iscrowd\n\n        if self.transforms is not None:\n            img, target = self.transforms(img, target)\n\n        return img, target\n\n    def __len__(self):\n        return len(self.split_df)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:53.712203Z","iopub.execute_input":"2023-11-30T22:00:53.712703Z","iopub.status.idle":"2023-11-30T22:00:53.732055Z","shell.execute_reply.started":"2023-11-30T22:00:53.712667Z","shell.execute_reply":"2023-11-30T22:00:53.730840Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset = SleepStatesDataset(train, annotations_df, images_folder, get_transforms())\nval_dataset = SleepStatesDataset(val, annotations_df, images_folder, get_transforms())","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:55.572281Z","iopub.execute_input":"2023-11-30T22:00:55.575395Z","iopub.status.idle":"2023-11-30T22:00:55.581474Z","shell.execute_reply.started":"2023-11-30T22:00:55.575337Z","shell.execute_reply":"2023-11-30T22:00:55.579902Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_dataset), len(val_dataset)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:56.483245Z","iopub.execute_input":"2023-11-30T22:00:56.483757Z","iopub.status.idle":"2023-11-30T22:00:56.493324Z","shell.execute_reply.started":"2023-11-30T22:00:56.483717Z","shell.execute_reply":"2023-11-30T22:00:56.492038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset[0]","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:57.349243Z","iopub.execute_input":"2023-11-30T22:00:57.349887Z","iopub.status.idle":"2023-11-30T22:00:57.450461Z","shell.execute_reply.started":"2023-11-30T22:00:57.349832Z","shell.execute_reply":"2023-11-30T22:00:57.449243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# The model","metadata":{}},{"cell_type":"code","source":"def seed_everything(seed):\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.cuda.manual_seed_all(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n\nseed_everything(42)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:00:27.514379Z","iopub.execute_input":"2023-11-30T22:00:27.514817Z","iopub.status.idle":"2023-11-30T22:00:27.528405Z","shell.execute_reply.started":"2023-11-30T22:00:27.514782Z","shell.execute_reply":"2023-11-30T22:00:27.527057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torchvision.models.detection.faster_rcnn import FastRCNNPredictor\n# Load an object detection model pre-trained on COCO:\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(weights=\"DEFAULT\", 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-30T22:00:30.123984Z","iopub.execute_input":"2023-11-30T22:00:30.124400Z","iopub.status.idle":"2023-11-30T22:00:32.080336Z","shell.execute_reply.started":"2023-11-30T22:00:30.124369Z","shell.execute_reply":"2023-11-30T22:00:32.079195Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import utils # utils.py\ntrain_loader = torch.utils.data.DataLoader(train_dataset, batch_size=8, shuffle=True, num_workers=4, collate_fn=utils.collate_fn)\nval_loader = torch.utils.data.DataLoader(val_dataset, batch_size=8, shuffle=False, num_workers=4, collate_fn=utils.collate_fn)\nlen(train_loader), len(val_loader)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:01:03.916727Z","iopub.execute_input":"2023-11-30T22:01:03.917148Z","iopub.status.idle":"2023-11-30T22:01:03.927320Z","shell.execute_reply.started":"2023-11-30T22:01:03.917117Z","shell.execute_reply":"2023-11-30T22:01:03.926062Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images, targets = next(iter(val_loader))\ntype(images), type(targets)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.662621Z","iopub.status.idle":"2023-11-30T20:55:39.663058Z","shell.execute_reply.started":"2023-11-30T20:55:39.662851Z","shell.execute_reply":"2023-11-30T20:55:39.662872Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"targets","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.664351Z","iopub.status.idle":"2023-11-30T20:55:39.664761Z","shell.execute_reply.started":"2023-11-30T20:55:39.664561Z","shell.execute_reply":"2023-11-30T20:55:39.664580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images = [image for image in images]\ntargets = [target for target in targets]\noutput = model(images, targets)\noutput","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.666484Z","iopub.status.idle":"2023-11-30T20:55:39.666931Z","shell.execute_reply.started":"2023-11-30T20:55:39.666726Z","shell.execute_reply":"2023-11-30T20:55:39.666747Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"# # from engine import train_one_epoch, evaluate # engine.py\n# device = torch.device(\"cuda\") if torch.cuda.is_available() else torch.device(\"cpu\")\n# model.to(device)\n# params = [p for p in model.parameters() if p.requires_grad]\n# optimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)\n# lr_scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=3, gamma=0.1)","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.668271Z","iopub.status.idle":"2023-11-30T20:55:39.668692Z","shell.execute_reply.started":"2023-11-30T20:55:39.668483Z","shell.execute_reply":"2023-11-30T20:55:39.668503Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model_idx = \"m12\"\n# num_epochs = 5\n# for epoch in range(num_epochs):\n#     # Train for one epoch:\n#     train_one_epoch(model, optimizer, train_loader, device, epoch, print_freq=25)\n#     # Note: The above function modifies the model in-place.\n#     # Update the learning rate at the end of each epoch:\n#     lr_scheduler.step()\n#     # Evaluate on the validation set:\n#     evaluate(model, val_loader, device=device)\n#     # Compute the competition metric:\n#     competition_metric = compute_metric()\n#     print(f\"Competition metric: {competition_metric}\")\n#     print(\"Saving model weights...\")\n#     torch.save(model.state_dict(), f\"{model_idx}_{epoch}.pth\")\n#     print(\"Model weights saved.\")\n#     print(\"---\")\n# print(\"That's it!\")","metadata":{"execution":{"iopub.status.busy":"2023-11-30T20:55:39.670331Z","iopub.status.idle":"2023-11-30T20:55:39.670767Z","shell.execute_reply.started":"2023-11-30T20:55:39.670559Z","shell.execute_reply":"2023-11-30T20:55:39.670579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Testing","metadata":{}},{"cell_type":"code","source":"model.load_state_dict(torch.load(\"/kaggle/input/rcnn-model/m12_4.pth\",map_location=torch.device('cpu')))\nmodel.eval()","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:01:53.518034Z","iopub.execute_input":"2023-11-30T22:01:53.519496Z","iopub.status.idle":"2023-11-30T22:01:55.642300Z","shell.execute_reply.started":"2023-11-30T22:01:53.519449Z","shell.execute_reply":"2023-11-30T22:01:55.640994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_names_with_annotations = annotations_df['image_name'].unique()\ntest_with_annotations = test.loc[test['image_name'].isin(image_names_with_annotations)].reset_index(drop=True)\ntest_with_annotations","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:02:00.607625Z","iopub.execute_input":"2023-11-30T22:02:00.608086Z","iopub.status.idle":"2023-11-30T22:02:00.631092Z","shell.execute_reply.started":"2023-11-30T22:02:00.608048Z","shell.execute_reply":"2023-11-30T22:02:00.629749Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualization","metadata":{}},{"cell_type":"code","source":"from torchvision.utils import draw_bounding_boxes","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:02:04.160526Z","iopub.execute_input":"2023-11-30T22:02:04.160991Z","iopub.status.idle":"2023-11-30T22:02:04.166539Z","shell.execute_reply.started":"2023-11-30T22:02:04.160946Z","shell.execute_reply":"2023-11-30T22:02:04.165237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.random.seed(55)\nidx = np.random.randint(low = 0, high = len(test_with_annotations),size = 5)\ndummy_target = {'boxes': torch.tensor([[424.,  20., 464., 380.],\n                                      [927.,  20., 967., 380.]]),\n                  'labels': torch.tensor([1, 2]),\n                  'image_id': 'c908a0ad3e31_2018-02-03T20:30:00.jpg',\n                  'area': torch.tensor([14400., 14400.]),\n                  'iscrowd': torch.tensor([0, 0])\n               }\n\n\ndevice = torch.device('cpu') \n    ","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:17.543034Z","iopub.execute_input":"2023-11-30T22:07:17.543754Z","iopub.status.idle":"2023-11-30T22:07:17.551998Z","shell.execute_reply.started":"2023-11-30T22:07:17.543713Z","shell.execute_reply":"2023-11-30T22:07:17.551102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index = idx[0]\nplt.close()\nfrom torchvision.io import read_image\nimage_name = test_with_annotations['image_name'][index]\nprint(index, \"  :  \", image_name)\nimage_path = os.path.join(data_prep_folder, \"images\", image_name)\nimage1 = read_image(image_path)\nimage = Image.open(image_path).convert(\"RGB\")\nwindow = annotations_df.loc[annotations_df['image_name'] == image_name].reset_index(drop=True)\nwindow['x'] = (window['x0'] + window['x1']) / 2\n#     plt.figure(figsize=(14.4, 4))\n#     plt.imshow(image.permute(1, 2, 0));\n#     plt.figure(figsize=(14.4, 4))\n#     plt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\n#     plt.imshow(image.permute(1, 2, 0));\nwith torch.no_grad():\n    x, _ = eval_transforms(image,dummy_target)\n    x = x.to(device)\n    predictions = model([x])\npred = predictions[0]\nthresh = 0.7\npred['boxes'] = pred['boxes'][pred['scores'] > thresh]\npred['labels'] = pred['labels'][pred['scores'] > thresh]\npred['scores'] = pred['scores'][pred['scores'] > thresh]\npred_boxes = pred['boxes'].long()\npred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\noutput_image = draw_bounding_boxes(image1, pred_boxes, pred_labels, colors=\"cyan\", width=4)\nplt.figure(figsize=(14.4, 4))\nplt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\nplt.imshow(output_image.permute(1, 2, 0));","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:18.575679Z","iopub.execute_input":"2023-11-30T22:07:18.576720Z","iopub.status.idle":"2023-11-30T22:07:22.630486Z","shell.execute_reply.started":"2023-11-30T22:07:18.576677Z","shell.execute_reply":"2023-11-30T22:07:22.629184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index = idx[1]\nplt.close()\nimage_name = test_with_annotations['image_name'][index]\nprint(index, \"  :  \", image_name)\nimage_path = os.path.join(data_prep_folder, \"images\", image_name)\nimage1 = read_image(image_path)\nimage = Image.open(image_path).convert(\"RGB\")\nwindow = annotations_df.loc[annotations_df['image_name'] == image_name].reset_index(drop=True)\nwindow['x'] = (window['x0'] + window['x1']) / 2\n#     plt.figure(figsize=(14.4, 4))\n#     plt.imshow(image.permute(1, 2, 0));\n#     plt.figure(figsize=(14.4, 4))\n#     plt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\n#     plt.imshow(image.permute(1, 2, 0));\nwith torch.no_grad():\n    x, _ = eval_transforms(image,dummy_target)\n    x = x.to(device)\n    predictions = model([x])\npred = predictions[0]\nthresh = 0.7\npred['boxes'] = pred['boxes'][pred['scores'] > thresh]\npred['labels'] = pred['labels'][pred['scores'] > thresh]\npred['scores'] = pred['scores'][pred['scores'] > thresh]\npred_boxes = pred['boxes'].long()\npred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\noutput_image = draw_bounding_boxes(image1, pred_boxes, pred_labels, colors=\"cyan\", width=4)\nplt.figure(figsize=(14.4, 4))\nplt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\nplt.imshow(output_image.permute(1, 2, 0));","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:23.048269Z","iopub.execute_input":"2023-11-30T22:07:23.049044Z","iopub.status.idle":"2023-11-30T22:07:27.770671Z","shell.execute_reply.started":"2023-11-30T22:07:23.048961Z","shell.execute_reply":"2023-11-30T22:07:27.769348Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index = idx[2]\nplt.close()\nimage_name = test_with_annotations['image_name'][index]\nprint(index, \"  :  \", image_name)\nimage_path = os.path.join(data_prep_folder, \"images\", image_name)\nimage1 = read_image(image_path)\nimage = Image.open(image_path).convert(\"RGB\")\nwindow = annotations_df.loc[annotations_df['image_name'] == image_name].reset_index(drop=True)\nwindow['x'] = (window['x0'] + window['x1']) / 2\n#     plt.figure(figsize=(14.4, 4))\n#     plt.imshow(image.permute(1, 2, 0));\n#     plt.figure(figsize=(14.4, 4))\n#     plt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\n#     plt.imshow(image.permute(1, 2, 0));\nwith torch.no_grad():\n    x, _ = eval_transforms(image,dummy_target)\n    x = x.to(device)\n    predictions = model([x])\npred = predictions[0]\nthresh = 0.7\npred['boxes'] = pred['boxes'][pred['scores'] > thresh]\npred['labels'] = pred['labels'][pred['scores'] > thresh]\npred['scores'] = pred['scores'][pred['scores'] > thresh]\npred_boxes = pred['boxes'].long()\npred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\noutput_image = draw_bounding_boxes(image1, pred_boxes, pred_labels, colors=\"cyan\", width=4)\nplt.figure(figsize=(14.4, 4))\nplt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\nplt.imshow(output_image.permute(1, 2, 0));","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:27.773157Z","iopub.execute_input":"2023-11-30T22:07:27.773635Z","iopub.status.idle":"2023-11-30T22:07:32.050246Z","shell.execute_reply.started":"2023-11-30T22:07:27.773599Z","shell.execute_reply":"2023-11-30T22:07:32.048856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index = idx[3]\nplt.close()\nimage_name = test_with_annotations['image_name'][index]\nprint(index, \"  :  \", image_name)\nimage_path = os.path.join(data_prep_folder, \"images\", image_name)\nimage1 = read_image(image_path)\nimage = Image.open(image_path).convert(\"RGB\")\nwindow = annotations_df.loc[annotations_df['image_name'] == image_name].reset_index(drop=True)\nwindow['x'] = (window['x0'] + window['x1']) / 2\n#     plt.figure(figsize=(14.4, 4))\n#     plt.imshow(image.permute(1, 2, 0));\n#     plt.figure(figsize=(14.4, 4))\n#     plt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\n#     plt.imshow(image.permute(1, 2, 0));\nwith torch.no_grad():\n    x, _ = eval_transforms(image,dummy_target)\n    x = x.to(device)\n    predictions = model([x])\npred = predictions[0]\nthresh = 0.7\npred['boxes'] = pred['boxes'][pred['scores'] > thresh]\npred['labels'] = pred['labels'][pred['scores'] > thresh]\npred['scores'] = pred['scores'][pred['scores'] > thresh]\npred_boxes = pred['boxes'].long()\npred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\noutput_image = draw_bounding_boxes(image1, pred_boxes, pred_labels, colors=\"cyan\", width=4)\nplt.figure(figsize=(14.4, 4))\nplt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\nplt.imshow(output_image.permute(1, 2, 0));","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:32.051784Z","iopub.execute_input":"2023-11-30T22:07:32.052191Z","iopub.status.idle":"2023-11-30T22:07:36.073588Z","shell.execute_reply.started":"2023-11-30T22:07:32.052158Z","shell.execute_reply":"2023-11-30T22:07:36.072685Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"index = idx[4]\nplt.close()\nimage_name = test_with_annotations['image_name'][index]\nprint(index, \"  :  \", image_name)\nimage_path = os.path.join(data_prep_folder, \"images\", image_name)\nimage1 = read_image(image_path)\nimage = Image.open(image_path).convert(\"RGB\")\nwindow = annotations_df.loc[annotations_df['image_name'] == image_name].reset_index(drop=True)\nwindow['x'] = (window['x0'] + window['x1']) / 2\n#     plt.figure(figsize=(14.4, 4))\n#     plt.imshow(image.permute(1, 2, 0));\n#     plt.figure(figsize=(14.4, 4))\n#     plt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\n#     plt.imshow(image.permute(1, 2, 0));\nwith torch.no_grad():\n    x, _ = eval_transforms(image,dummy_target)\n    x = x.to(device)\n    predictions = model([x])\npred = predictions[0]\nthresh = 0.7\npred['boxes'] = pred['boxes'][pred['scores'] > thresh]\npred['labels'] = pred['labels'][pred['scores'] > thresh]\npred['scores'] = pred['scores'][pred['scores'] > thresh]\npred_boxes = pred['boxes'].long()\npred_labels = [reverse_label_mapping[l.item()] for l in pred['labels']]\noutput_image = draw_bounding_boxes(image1, pred_boxes, pred_labels, colors=\"cyan\", width=4)\nplt.figure(figsize=(14.4, 4))\nplt.vlines(x=window['x'], ymin=0, ymax=400, colors=\"yellow\", linewidth=4)\nplt.imshow(output_image.permute(1, 2, 0));","metadata":{"execution":{"iopub.status.busy":"2023-11-30T22:07:36.075881Z","iopub.execute_input":"2023-11-30T22:07:36.076281Z","iopub.status.idle":"2023-11-30T22:07:40.167826Z","shell.execute_reply.started":"2023-11-30T22:07:36.076248Z","shell.execute_reply":"2023-11-30T22:07:40.166476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}