{"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":7163574,"sourceType":"datasetVersion","datasetId":4137913},{"sourceId":154233048,"sourceType":"kernelVersion"}],"dockerImageVersionId":30588,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os, json, shutil, traceback\n\nimport numpy as np\nimport pandas as pd\nimport cv2\nimport torch, torchvision\nfrom torchvision.models.detection.faster_rcnn import FastRCNNPredictor\nfrom torchvision.models.detection.faster_rcnn import FasterRCNN\nimport albumentations as A\nfrom albumentations.pytorch.transforms import ToTensorV2\n\n# Set the maximum number of rows to display\npd.set_option('display.max_rows', 100)\npd.set_option('display.max_columns', 100)\n\n# min and max obtained from EDA\nANGLEZ_MIN = -90.0\nANGLEZ_MAX = 90.0\nANGLEZ_DER2_MIN = -4.0\nANGLEZ_DER2_MAX = 4.0\nENMO_MIN = 0.0\nENMO_MAX = 1.5\nLOG_OFFSET = 1\n\nY_HEIGHT = 256\nTIME_WIDTH = 1024\nTHRESH = 0.1\nTHRESH_EVENT = 0.9\nTHRESH_SUM = 1.2\n\nWORK_DIR = os.path.abspath('/kaggle/working/')\nMODEL_PATH = '/kaggle/input/cmi-train/model.pth'\n#TEST_SERIES_PATH = '/kaggle/input/train-series-2/train_series_2.csv'\nTEST_SERIES_PATH = '/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet'","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-12-09T22:54:45.036931Z","iopub.execute_input":"2023-12-09T22:54:45.037223Z","iopub.status.idle":"2023-12-09T22:54:50.758642Z","shell.execute_reply.started":"2023-12-09T22:54:45.037196Z","shell.execute_reply":"2023-12-09T22:54:50.757449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_transforms():\n    return A.Compose([\n        #A.Resize(512, 512),\n        #A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),\n        ToTensorV2(p=1.0)\n    ])\n\ndef get_submission_df(model: FasterRCNN, df: pd.DataFrame, images_dir: str):\n    all_test_preds = []\n    series_ids = df['series_id'].unique().tolist()\n    for i,series_id in enumerate(series_ids):\n        df_series = df[df['series_id'] == series_id]\n        df_series = preproc_timestamp(df_series)\n        generate_images(series_id, df_series, images_dir)\n        img_fnames = [f for f in os.listdir(images_dir) if os.path.isfile(os.path.join(images_dir, f))]\n        days = []\n        for fname in img_fnames:\n            if not '_s.' in fname:\n                fname_0 = fname.split('.')[0]\n                day = int(fname_0.split('_')[-1])\n                if not day in days:\n                    days.append(day)\n\n        raw_earliest_timestamp = df_series['timestamp'].min()\n        start_timestamp = get_ref_timestamp(df_series)\n        for day in days:\n            try:\n                print(30*' ' + f'\\rseries_id={series_id} day={day}', end='')\n                max_score = -1\n                max_score_s = -1\n\n                # 12pm\n                img_path = os.path.join(images_dir, f'{series_id}_{day}.png')\n                if os.path.exists(img_path):\n                    image = preprocess_image(img_path)\n                    with torch.no_grad():\n                        #x = eval_transforms(image)\n                        x = get_transforms()(image=image)['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                    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                        max_score_box, max_score = find_max_score_for_label(pred, 3)\n\n                # 12pm + 6hrs\n                img_s_path = os.path.join(images_dir, f'{series_id}_{day}_s.png')\n                if os.path.exists(img_s_path):\n                    image_s = preprocess_image(img_s_path)\n                    with torch.no_grad():\n                        #x = eval_transforms(image_s)\n                        x = get_transforms()(image=image_s)['image']\n                        x = x.to(device)\n                        predictions = model([x])\n                    pred_s = predictions[0]\n\n                    # Postprocessing: remove 'narrow' boxes as these are false positives.\n                    pred_widths = pred_s['boxes'][:, 2] - pred_s['boxes'][:, 0]\n                    pred_s['boxes'] = pred_s['boxes'][pred_widths > 10]\n                    pred_s['labels'] = pred_s['labels'][pred_widths > 10]\n                    pred_s['scores'] = pred_s['scores'][pred_widths > 10]\n                    pred_s['boxes'] = pred_s['boxes'][pred_s['scores'] > THRESH]\n                    pred_s['labels'] = pred_s['labels'][pred_s['scores'] > THRESH]\n                    pred_s['scores'] = pred_s['scores'][pred_s['scores'] > THRESH]\n\n                    if len(pred_s['labels']) != 0:\n                        max_score_s_box, max_score_s = find_max_score_for_label(pred_s, 3)\n\n                if max_score==-1 and max_score_s==-1:\n                    continue\n                elif max_score > max_score_s:\n                    # use 12pm\n                    chosen_box = max_score_box\n                    chosen_pred = pred\n                    ref_timestamp = start_timestamp + pd.to_timedelta(day, 'D')\n                else:\n                    # use 12pm + 6\n                    chosen_box = max_score_s_box\n                    chosen_pred = pred_s\n                    ref_timestamp = start_timestamp + pd.to_timedelta(day, 'D') + pd.to_timedelta(6, 'hours')\n\n                # Find label '1' with the largest score within the chosen bounding box\n                label_1_score, label_1_box = find_max_score_in_box(chosen_pred, 1, chosen_box)\n\n                # Filter out predictions with label '2' and x-coordinate less than or equal to label_1_box[0]\n                if label_1_score is not None:\n                    mask_label_2 = chosen_pred['labels'] == 2\n                    mask_remove = (mask_label_2) & (chosen_pred['boxes'][:, 0] <= label_1_box[0])\n                    chosen_pred['boxes'] = chosen_pred['boxes'][~mask_remove]\n                    chosen_pred['labels'] = chosen_pred['labels'][~mask_remove]\n                    chosen_pred['scores'] = chosen_pred['scores'][~mask_remove]\n\n                # Find label '2' with the largest score within the chosen bounding box\n                label_2_score, label_2_box = find_max_score_in_box(chosen_pred, 2, chosen_box)\n\n                # Calculate the midpoint x coordinate for both labels\n                if label_1_score is not None:\n                    label_1_midpoint_x = (label_1_box[0] + label_1_box[2]) / 2\n                    #print(f'Midpoint X for label 1: {label_1_midpoint_x}')\n                    onset_timestamp = pixel_to_timestamp(label_1_midpoint_x, ref_timestamp)\n                    s_elapsed = onset_timestamp.timestamp() - raw_earliest_timestamp.timestamp()\n\n                    event_1 = {}\n                    event_1['series_id'] = series_id\n                    event_1['step'] = round(s_elapsed/5)\n                    event_1['event'] = 'onset'\n                    event_1['score'] = round(float(label_1_score), 4)\n\n                if label_2_score is not None:\n                    label_2_midpoint_x = (label_2_box[0] + label_2_box[2]) / 2\n                    #print(f'Midpoint X for label 2: {label_2_midpoint_x}')\n                    wakeup_timestamp = pixel_to_timestamp(label_2_midpoint_x, ref_timestamp)\n                    s_elapsed = wakeup_timestamp.timestamp() - raw_earliest_timestamp.timestamp()\n\n                    event_2 = {}\n                    event_2['series_id'] = series_id\n                    event_2['step'] = round(s_elapsed/5)\n                    event_2['event'] = 'wakeup'\n                    event_2['score'] = round(float(label_2_score), 4)\n\n                if label_1_score is not None:\n                    if event_1['score'] >= THRESH_EVENT:\n                        all_test_preds.append(event_1)\n                    elif label_2_score is not None:\n                        sum_score = event_1['score'] + event_2['score']\n                        if sum_score >= THRESH_SUM:\n                            all_test_preds.append(event_1)\n                if label_2_score is not None:\n                    if event_2['score'] >= THRESH_EVENT:\n                        all_test_preds.append(event_2)\n                    elif label_1_score is not None:\n                        sum_score = event_1['score'] + event_2['score']\n                        if sum_score >= THRESH_SUM:\n                            all_test_preds.append(event_2)\n            except Exception:\n                print(traceback.format_exc())\n        delete_all_files(images_dir)\n\n    print()\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\n\ndef get_ref_timestamp(series_df: pd.DataFrame):\n    earliest_timestamp = series_df['timestamp'].min()\n    start_date = earliest_timestamp.date()\n    start_timestamp = pd.Timestamp(f'{start_date} 12:00:00')\n    start_timestamp_1 = pd.Timestamp(f'{start_date} 11:55:00')\n    #start_timestamp_2 = pd.Timestamp(f'{start_date} 12:05:00')\n    if not (earliest_timestamp<start_timestamp and earliest_timestamp>start_timestamp_1):\n        if earliest_timestamp < start_timestamp_1:\n            start_date = start_date - pd.to_timedelta(1, unit='D')\n            start_timestamp = pd.Timestamp(f'{start_date} 12:00:00')\n    return start_timestamp\n\ndef preprocess_image(image_path):\n    # Read image using OpenCV\n    image = cv2.imread(image_path, cv2.IMREAD_COLOR)\n    \n    # Convert color format from BGR to RGB\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB).astype(np.float32)\n    \n    # Normalize pixel values\n    image /= 255.0\n    \n    return image\n\ndef find_max_score_for_label(predictions, label):\n    # Move tensors to CPU if they are on GPU\n    scores = predictions['scores'].cpu().numpy()\n    labels = predictions['labels'].cpu().numpy()\n\n    # Find the index of the maximum score for the given label\n    max_score_index = np.argmax(scores[labels == label])\n\n    if max_score_index >= 0:\n        # Move boxes back to CPU if needed\n        boxes = predictions['boxes'].cpu().numpy()\n        \n        # Get the box and score with the maximum score for the given label\n        max_score_box = boxes[labels == label][max_score_index]\n        max_score = scores[labels == label][max_score_index]\n        return max_score_box, max_score\n    return None, None\n    \ndef find_max_score_in_box(predictions, label, box):\n    # Move tensors to CPU if they are on GPU\n    mask = (\n        (predictions['boxes'][:, 0] >= box[0]) & (predictions['boxes'][:, 2] <= box[2])\n    ).cpu().numpy()\n\n    if np.any(mask):\n        label_mask = (predictions['labels'] == label).cpu().numpy()\n        scores = predictions['scores'][mask & label_mask].cpu().numpy()\n        if len(scores) > 0:\n            max_score_index = np.argmax(scores)\n            max_score = scores[max_score_index]\n            selected_box = predictions['boxes'][mask & label_mask][max_score_index]\n            return max_score, selected_box\n\n    return None, None\n\ndef pixel_to_timestamp(x, ref_timestamp):\n    scnds_day = 24*60*60\n    offset = float(scnds_day*(x/TIME_WIDTH))\n    timestamp = ref_timestamp + pd.to_timedelta(offset, 'S')\n    return timestamp\n\ndef delete_all_files(dir: str):\n    for filename in os.listdir(dir):\n        file_path = os.path.join(dir, filename)\n        try:\n            if os.path.isfile(file_path) or os.path.islink(file_path):\n                os.unlink(file_path)\n            elif os.path.isdir(file_path):\n                shutil.rmtree(file_path)\n        except Exception as e:\n            print('Failed to delete %s. Reason: %s' % (file_path, e))\n\ndef generate_images(series_id: str, df_series: pd.DataFrame, output_dir = 'images'):\n    ########### PADDING PRIOR ##############\n    earliest_timestamp = df_series['timestamp'].min()\n    start_date = earliest_timestamp.date()\n    start_timestamp = pd.Timestamp(f'{start_date} 12:00:00')\n    start_timestamp_1 = pd.Timestamp(f'{start_date} 11:55:00')\n    #start_timestamp_2 = pd.Timestamp(f'{start_date} 12:05:00')\n    if not (earliest_timestamp<start_timestamp and earliest_timestamp>start_timestamp_1):\n        # Assumption: No onset occur during 11:55am-12pm on day 0\n        if earliest_timestamp < start_timestamp_1:\n            start_date = start_date - pd.to_timedelta(1, unit='D')\n            start_timestamp = pd.Timestamp(f'{start_date} 12:00:00')\n        # Add timestamps to the top of df_series with an interval of 5 seconds until it reaches start_timestamp\n        before_earliest = earliest_timestamp - pd.to_timedelta(5, unit='s')\n        additional_timestamps = pd.date_range(start=start_timestamp, end=before_earliest, freq='5S')\n        additional_data = pd.DataFrame({'timestamp': additional_timestamps})\n        additional_data['series_id'] = series_id\n        additional_data['step'] = -1\n        additional_data['anglez'] = 0.0\n        additional_data['enmo'] = 1.0\n\n        # Concatenate additional_data with df_series\n        df_series = pd.concat([additional_data, df_series], ignore_index=True)\n\n    ########### PADDING AFTER ##############\n    latest_timestamp = df_series['timestamp'].max()\n    end_date = latest_timestamp.date()\n    end_timestamp = pd.Timestamp(f'{end_date} 12:00:00')\n    #end_timestamp_1 = pd.Timestamp(f'{end_date} 11:55:00')\n    end_timestamp_2 = pd.Timestamp(f'{end_date} 12:05:00')\n    if not (latest_timestamp>end_timestamp and latest_timestamp<end_timestamp_2):\n        if latest_timestamp > end_timestamp_2:\n            end_date = end_date + pd.to_timedelta(1, unit='D')\n            end_timestamp = pd.Timestamp(f'{end_date} 12:00:00')\n        after_latest = latest_timestamp + pd.to_timedelta(5, unit='s')\n        additional_timestamps = pd.date_range(start=after_latest, end=end_timestamp, freq='5S')\n        additional_data = pd.DataFrame({'timestamp': additional_timestamps})\n        additional_data['series_id'] = series_id\n        additional_data['step'] = -1\n        additional_data['anglez'] = 0.0\n        additional_data['enmo'] = 1.0\n\n        # Concatenate additional_data with df_series\n        df_series = pd.concat([df_series, additional_data], ignore_index=True)\n    \n    df_series.sort_values('timestamp')\n\n    ########### FEATURE ENGINEERING ##############\n    df_series['enmo_log'] = np.log(df_series['enmo'] + LOG_OFFSET)\n    window_size = 60\n    df_series['anglez_wma'] = df_series['anglez'].rolling(window=window_size, min_periods=1).apply(weighted_average, raw=True)\n    df_series['anglez_der2'] = df_series['anglez'].diff().rolling(window=window_size, min_periods=1).mean().diff()\n    df_series['anglez_der2'] = df_series['anglez_der2'].fillna(0)\n\n    ########### LIMIT VALUES ##############\n    df_series['anglez'] = df_series['anglez'].clip(lower=ANGLEZ_MIN, upper=ANGLEZ_MAX)\n    df_series['anglez_wma'] = df_series['anglez_wma'].clip(lower=ANGLEZ_MIN, upper=ANGLEZ_MAX)\n    df_series['anglez_der2'] = df_series['anglez_der2'].clip(lower=ANGLEZ_DER2_MIN, upper=ANGLEZ_DER2_MAX)\n    df_series['enmo_log'] = df_series['enmo_log'].clip(lower=ENMO_MIN, upper=ENMO_MAX)\n\n    days_between = (end_timestamp - start_timestamp).days\n    data = {}\n    for day in range(days_between):\n        day_start_ts = start_timestamp + pd.to_timedelta(day, unit='D')\n        day_end_ts = start_timestamp + pd.to_timedelta(day + 1, unit='D')\n\n        rows_df = df_series[\n            (df_series['timestamp'] >= day_start_ts) & (df_series['timestamp'] < day_end_ts)\n        ]\n\n        if len(rows_df) < TIME_WIDTH:\n            print(f'NOTICE: Skipping series_id {series_id} day {day} due to insufficient rows. len(rows_df)={len(rows_df)}')\n            continue\n\n        # Time Sampling\n        target_frequency = int((24 * 60 * 60 * 1000) / TIME_WIDTH)\n        target_frequency = str(target_frequency) + 'ms'\n        rows_df = rows_df.resample(target_frequency, on='timestamp').last()\n        rows_df = rows_df.iloc[:TIME_WIDTH]\n        rows_df['anglez'] = rows_df['anglez'].fillna(0.0)\n        rows_df['anglez_wma'] = rows_df['anglez_wma'].fillna(0.0)\n        rows_df['anglez_der2'] = rows_df['anglez_der2'].fillna(0.0)\n        rows_df['enmo_log'] = rows_df['enmo_log'].fillna(np.log(1.0 + LOG_OFFSET))\n\n        data[day] = {\n            'anglez': [],\n            'anglez_wma': [],\n            'anglez_der2': [],\n            'enmo_log': []\n        }\n\n        # Vectorized calculations\n        y_coor_anglez = np.round((rows_df['anglez'].values - ANGLEZ_MIN) / (ANGLEZ_MAX - ANGLEZ_MIN) * (Y_HEIGHT - 1))\n        y_coor_anglez = (Y_HEIGHT - 1) - y_coor_anglez\n\n        y_coor_anglez_wma = np.round((rows_df['anglez_wma'].values - ANGLEZ_MIN) / (ANGLEZ_MAX - ANGLEZ_MIN) * (Y_HEIGHT - 1))\n        y_coor_anglez_wma = (Y_HEIGHT - 1) - y_coor_anglez_wma + Y_HEIGHT\n\n        y_coor_anglez_der2 = np.round((rows_df['anglez_der2'].values - ANGLEZ_DER2_MIN) / (ANGLEZ_DER2_MAX - ANGLEZ_DER2_MIN) * (Y_HEIGHT - 1))\n        y_coor_anglez_der2 = (Y_HEIGHT - 1) - y_coor_anglez_der2 + 2 * Y_HEIGHT\n\n        y_coor_enmo_log = np.round((rows_df['enmo_log'].values - ENMO_MIN) / (ENMO_MAX - ENMO_MIN) * (Y_HEIGHT - 1))\n        y_coor_enmo_log = (Y_HEIGHT - 1) - y_coor_enmo_log + 3 * Y_HEIGHT\n\n        row_count = np.arange(len(rows_df))\n\n        # Append to data dictionary\n        data[day]['anglez'] = np.column_stack((y_coor_anglez, row_count)).tolist()\n        data[day]['anglez_wma'] = np.column_stack((y_coor_anglez_wma, row_count)).tolist()\n        data[day]['anglez_der2'] = np.column_stack((y_coor_anglez_der2, row_count)).tolist()\n        data[day]['enmo_log'] = np.column_stack((y_coor_enmo_log, row_count)).tolist()\n\n    generate_plot_imgs(data, series_id, output_dir)\n    generate_plot_imgs_shifted(data, series_id, output_dir)\n\ndef preproc_timestamp(df):\n    df['timestamp'] = pd.to_datetime(df['timestamp'], errors='coerce')\n    sids = df['series_id'].unique().tolist()\n    offsets = {}\n    for sid in sids:\n        group_df = df[df['series_id'] == sid]\n        group_df['timestamp'] = pd.to_datetime(group_df['timestamp'], errors='coerce')\n        earliest_offset_minutes = group_df['timestamp'].min().utcoffset().total_seconds() / 60.0\n        offsets[sid] = earliest_offset_minutes\n    df = df.apply(lambda row: standardize_timezone(row, offsets[row['series_id']]), axis=1)\n    df['timestamp'] = df['timestamp'].apply(lambda x: x.replace(tzinfo=None))\n    return df\n\ndef standardize_timezone(row, offset: float):\n    offset_minutes = row['timestamp'].utcoffset().total_seconds() / 60.0\n    offset_diff = offset - offset_minutes\n    row['timestamp'] += pd.to_timedelta(offset_diff, unit='minutes')\n    return row\n\ndef weighted_average(arr):\n    window_size = 60\n    weights = np.arange(1, window_size + 1)\n    return np.sum(arr * weights[:len(arr)]) / np.sum(weights[:len(arr)])\n\ndef generate_plot_imgs(data, series_id, output_dir):\n    for day in data:\n        canvas = np.ones((Y_HEIGHT*len(data[day]), TIME_WIDTH), dtype=np.uint8) * 255\n        # Iterate over each type of data (anglez, anglez_wma, anglez_der2, enmo_log)\n        for data_type in ['anglez', 'anglez_wma', 'anglez_der2', 'enmo_log']:\n            # Extract coordinates and convert to integers\n            coordinates = np.array(data[day][data_type], dtype=int)\n            # Draw lines on the canvas based on the coordinates\n            for i in range(len(coordinates) - 1):\n                start_point = (coordinates[i, 1], coordinates[i, 0])\n                end_point = (coordinates[i + 1, 1], coordinates[i + 1, 0])\n                cv2.line(canvas, start_point, end_point, 0, 1)  # Draw a line (pixel value 0)\n        save_path = os.path.join(output_dir, f'{series_id}_{day}.png')\n        cv2.imwrite(str(save_path), canvas)\n        #print(f'png generated: {save_path}')\n\ndef generate_plot_imgs_shifted(data, series_id, output_dir):\n    for day in data:\n        next_day = day + 1\n        if not next_day in data:\n            continue\n        current_path = os.path.join(output_dir,f'{series_id}_{day}.png')\n        img_current = cv2.imread(str(current_path))\n        next_path = os.path.join(output_dir,f'{series_id}_{next_day}.png')\n        img_next = cv2.imread(str(next_path))\n\n        # Trim the first quarter of the first image\n        width_trim = img_current.shape[1] // 4\n        image1_trimmed = img_current[:, width_trim:]\n\n        # Take the first quarter of the second image\n        image2_quarter = img_next[:, :width_trim]\n\n        # Concatenate the two images horizontally\n        result_image = np.concatenate((image1_trimmed, image2_quarter), axis=1)\n\n        assert result_image.shape[1]==img_current.shape[1]\n        save_path = os.path.join(output_dir, f'{series_id}_{day}_s.png')\n        cv2.imwrite(str(save_path), result_image)\n        #print(f'png generated: {save_path}')","metadata":{"execution":{"iopub.status.busy":"2023-12-09T23:03:09.014678Z","iopub.execute_input":"2023-12-09T23:03:09.015120Z","iopub.status.idle":"2023-12-09T23:03:09.092986Z","shell.execute_reply.started":"2023-12-09T23:03:09.015086Z","shell.execute_reply":"2023-12-09T23:03:09.092053Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_folder = os.path.join(WORK_DIR,'images')\nif not os.path.exists(images_folder):\n    os.makedirs(images_folder)\n\npd.options.mode.chained_assignment = None  # default='warn'\ntest_series = pd.read_parquet(TEST_SERIES_PATH)\n#test_series = pd.read_csv(TEST_SERIES_PATH)\nprint('shape:',test_series.shape)\nprint(test_series.head())\n\neval_transforms = get_transforms()\ndevice = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')\nmodel = torchvision.models.detection.fasterrcnn_resnet50_fpn(weights=None, weights_backbone=None)\nnum_classes = 4  # 0: background, 1: onset, 2: wakeup, 3: sleep\nin_features = model.roi_heads.box_predictor.cls_score.in_features\nmodel.roi_heads.box_predictor = FastRCNNPredictor(in_features, num_classes)\nweights = torch.load(MODEL_PATH, map_location=device)\nmodel.load_state_dict(weights)\nmodel.to(device)\nmodel.eval()\n\nsubmission_df = get_submission_df(model, test_series, images_folder)\nsubmission_df.to_csv('submission.csv', index=False)\n\nprint('END')","metadata":{"execution":{"iopub.status.busy":"2023-12-09T23:03:18.998367Z","iopub.execute_input":"2023-12-09T23:03:18.998780Z","iopub.status.idle":"2023-12-09T23:07:08.549469Z","shell.execute_reply.started":"2023-12-09T23:03:18.998750Z","shell.execute_reply":"2023-12-09T23:07:08.548436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df","metadata":{"execution":{"iopub.status.busy":"2023-12-09T23:07:14.249092Z","iopub.execute_input":"2023-12-09T23:07:14.249826Z","iopub.status.idle":"2023-12-09T23:07:14.277172Z","shell.execute_reply.started":"2023-12-09T23:07:14.249791Z","shell.execute_reply":"2023-12-09T23:07:14.276231Z"},"trusted":true},"execution_count":null,"outputs":[]}]}