{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport polars as pl\n\nimport numpy as np\n\nimport matplotlib.pyplot as plt\nimport seaborn as sns; sns.set()\n\nimport os\nfrom pathlib import Path\n\nfrom tqdm.auto import tqdm","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:08.691400Z","iopub.execute_input":"2025-07-19T21:26:08.691622Z","iopub.status.idle":"2025-07-19T21:26:13.287503Z","shell.execute_reply.started":"2025-07-19T21:26:08.691602Z","shell.execute_reply":"2025-07-19T21:26:13.286443Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dir = Path(\"/kaggle/input/cmi-detect-behavior-with-sensor-data\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:13.290060Z","iopub.execute_input":"2025-07-19T21:26:13.290594Z","iopub.status.idle":"2025-07-19T21:26:13.295450Z","shell.execute_reply.started":"2025-07-19T21:26:13.290566Z","shell.execute_reply":"2025-07-19T21:26:13.294525Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pl.read_csv(data_dir / \"train.csv\")\ntest_df = pl.read_csv(data_dir / \"test.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:13.296350Z","iopub.execute_input":"2025-07-19T21:26:13.296759Z","iopub.status.idle":"2025-07-19T21:26:26.131244Z","shell.execute_reply.started":"2025-07-19T21:26:13.296719Z","shell.execute_reply":"2025-07-19T21:26:26.130420Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_demo = pl.read_csv(data_dir / \"train_demographics.csv\")\ntest_demo = pl.read_csv(data_dir / \"test_demographics.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:26.132291Z","iopub.execute_input":"2025-07-19T21:26:26.132617Z","iopub.status.idle":"2025-07-19T21:26:26.144317Z","shell.execute_reply.started":"2025-07-19T21:26:26.132585Z","shell.execute_reply":"2025-07-19T21:26:26.143525Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Generate Sequence ID + Gesture (Label) Mapping","metadata":{}},{"cell_type":"code","source":"labels_df = train_df.unique(\n    subset=[\"sequence_id\", \"gesture\"]\n).select(\n    [\"sequence_id\", \"gesture\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:26.145463Z","iopub.execute_input":"2025-07-19T21:26:26.145784Z","iopub.status.idle":"2025-07-19T21:26:27.242859Z","shell.execute_reply.started":"2025-07-19T21:26:26.145757Z","shell.execute_reply":"2025-07-19T21:26:27.241799Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"seq2sub = train_df.unique(\n    subset=[\"sequence_id\", \"subject\"]\n).select(\n    [\"sequence_id\", \"subject\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:27.244133Z","iopub.execute_input":"2025-07-19T21:26:27.244421Z","iopub.status.idle":"2025-07-19T21:26:27.615363Z","shell.execute_reply.started":"2025-07-19T21:26:27.244396Z","shell.execute_reply":"2025-07-19T21:26:27.614301Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# we\"ll only do acc since those are the not null features\ntrain_df_subset = train_df.select([\n    \"sequence_id\",\n    \"acc_x\",\n    \"acc_y\",\n    \"acc_z\"\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:27.620028Z","iopub.execute_input":"2025-07-19T21:26:27.620357Z","iopub.status.idle":"2025-07-19T21:26:27.625948Z","shell.execute_reply.started":"2025-07-19T21:26:27.620326Z","shell.execute_reply":"2025-07-19T21:26:27.625030Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ts_features = train_df_subset.group_by(\"sequence_id\").agg(\n    pl.all().mean().name.suffix(\"_mean\"),\n    pl.all().min().name.suffix(\"_min\"),\n    pl.all().max().name.suffix(\"_max\"),\n    pl.all().var().name.suffix(\"_var\"),\n    pl.all().std().name.suffix(\"_std\"),\n    pl.all().skew().name.suffix(\"_skew\"),\n    pl.all().kurtosis().name.suffix(\"_kurtosis\"),\n    \n    pl.all().diff(1).mean().name.suffix(\"_mean_diff1\"),\n    pl.all().diff(1).min().name.suffix(\"_min_diff1\"),\n    pl.all().diff(1).max().name.suffix(\"_max_diff1\"),\n    pl.all().diff(1).var().name.suffix(\"_var_diff1\"),\n    pl.all().diff(1).std().name.suffix(\"_std_diff1\"),\n    pl.all().diff(1).skew().name.suffix(\"_skew_diff1\"),\n    pl.all().diff(1).kurtosis().name.suffix(\"_kurtosis_diff1\"),\n    \n    pl.all().cum_sum().mul(0.1).mean().name.suffix(\"_vel_mean\"),\n    pl.all().cum_sum().mul(0.1).min().name.suffix(\"_vel_min\"),\n    pl.all().cum_sum().mul(0.1).max().name.suffix(\"_vel_max\"),\n    pl.all().cum_sum().mul(0.1).var().name.suffix(\"_vel_var\"),\n    pl.all().cum_sum().mul(0.1).std().name.suffix(\"_vel_std\"),\n    pl.all().cum_sum().mul(0.1).skew().name.suffix(\"_vel_skew\"),\n    pl.all().cum_sum().mul(0.1).kurtosis().name.suffix(\"_vel_kurtosis\"),\n\n    pl.all().cum_sum().cum_sum().mul(0.1).mean().name.suffix(\"_pos_mean\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).min().name.suffix(\"_pos_min\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).max().name.suffix(\"_pos_max\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).var().name.suffix(\"_pos_var\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).std().name.suffix(\"_pos_std\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).skew().name.suffix(\"_pos_skew\"),\n    pl.all().cum_sum().cum_sum().mul(0.1).kurtosis().name.suffix(\"_pos_kurtosis\"),\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:27.626968Z","iopub.execute_input":"2025-07-19T21:26:27.627394Z","iopub.status.idle":"2025-07-19T21:26:29.416692Z","shell.execute_reply.started":"2025-07-19T21:26:27.627351Z","shell.execute_reply":"2025-07-19T21:26:29.415793Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_total = ts_features.join(\n    seq2sub, on=\"sequence_id\"\n).join(\n    train_demo, on=\"subject\"\n).join(\n    labels_df, on=\"sequence_id\" \n).drop([\"sequence_id\", \"subject\"])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:29.417616Z","iopub.execute_input":"2025-07-19T21:26:29.417999Z","iopub.status.idle":"2025-07-19T21:26:29.455732Z","shell.execute_reply.started":"2025-07-19T21:26:29.417940Z","shell.execute_reply":"2025-07-19T21:26:29.454926Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_total.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:26:30.037474Z","iopub.execute_input":"2025-07-19T21:26:30.037786Z","iopub.status.idle":"2025-07-19T21:26:30.046539Z","shell.execute_reply.started":"2025-07-19T21:26:30.037762Z","shell.execute_reply":"2025-07-19T21:26:30.045431Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gestures = sorted(labels_df[\"gesture\"].unique().to_list())\ngestures2id = {gesture:idx for idx,gesture in enumerate(gestures)}\nid2gestures = {idx:gesture for gesture,idx in gestures2id.items()}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:28:47.789612Z","iopub.execute_input":"2025-07-19T21:28:47.789932Z","iopub.status.idle":"2025-07-19T21:28:47.800062Z","shell.execute_reply.started":"2025-07-19T21:28:47.789908Z","shell.execute_reply":"2025-07-19T21:28:47.798907Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target_gestures = set([\n    \"Above ear - pull hair\",\n    \"Cheek - pinch skin\",\n    \"Eyebrow - pull hair\",\n    \"Eyelash - pull hair\",\n    \"Forehead - pull hairline\",\n    \"Forehead - scratch\",\n    \"Neck - pinch skin\",\n    \"Neck - scratch\",\n])\n\nnon_target_gestures = set([\n    \"Write name on leg\",\n    \"Wave hello\",\n    \"Glasses on/off\",\n    \"Text on phone\",\n    \"Write name in air\",\n    \"Feel around in tray and pull out an object\",\n    \"Scratch knee/leg skin\",\n    \"Pull air toward your face\",\n    \"Drink from bottle/cup\",\n    \"Pinch knee/leg skin\",\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:28:48.157304Z","iopub.execute_input":"2025-07-19T21:28:48.157622Z","iopub.status.idle":"2025-07-19T21:28:48.163170Z","shell.execute_reply.started":"2025-07-19T21:28:48.157598Z","shell.execute_reply":"2025-07-19T21:28:48.162076Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"gestures2id, id2gestures, target_gestures, non_target_gestures","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:29:06.590833Z","iopub.execute_input":"2025-07-19T21:29:06.591547Z","iopub.status.idle":"2025-07-19T21:29:06.599156Z","shell.execute_reply.started":"2025-07-19T21:29:06.591518Z","shell.execute_reply":"2025-07-19T21:29:06.598012Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_total = df_total.with_columns(\n    gesture_label=pl.col(\"gesture\").map_elements(lambda x: gestures2id[x])\n)\n\ndf_total = df_total.with_columns(\n    target_gesture=pl.col(\"gesture\").map_elements(lambda x: x in target_gestures)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:31:29.112023Z","iopub.execute_input":"2025-07-19T21:31:29.112428Z","iopub.status.idle":"2025-07-19T21:31:29.152933Z","shell.execute_reply.started":"2025-07-19T21:31:29.112403Z","shell.execute_reply":"2025-07-19T21:31:29.151950Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Simple Baseline Modeling","metadata":{}},{"cell_type":"code","source":"from sklearn.linear_model import LogisticRegressionCV\nfrom xgboost import XGBClassifier\nfrom catboost import CatBoostClassifier\n\nfrom sklearn.preprocessing import MinMaxScaler, OneHotEncoder, StandardScaler\n\nfrom sklearn.compose import ColumnTransformer\nfrom sklearn.pipeline import Pipeline\n\n\nfrom sklearn.model_selection import KFold, train_test_split\n\nfrom sklearn.metrics import f1_score, accuracy_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:31:52.297039Z","iopub.execute_input":"2025-07-19T21:31:52.297378Z","iopub.status.idle":"2025-07-19T21:31:53.309441Z","shell.execute_reply.started":"2025-07-19T21:31:52.297331Z","shell.execute_reply":"2025-07-19T21:31:53.308327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"numeric_cols = [\n\"acc_x_mean\",\n\"acc_y_mean\",\n\"acc_z_mean\",\n\"acc_x_min\",\n\"acc_y_min\",\n\"acc_z_min\",\n\"acc_x_max\",\n\"acc_y_max\",\n\"acc_z_max\",\n\"acc_x_var\",\n\"acc_y_var\",\n\"acc_z_var\",\n\"acc_x_std\",\n\"acc_y_std\",\n\"acc_z_std\",\n\"acc_x_skew\",\n\"acc_y_skew\",\n\"acc_z_skew\",\n\"acc_x_kurtosis\",\n\"acc_y_kurtosis\",\n\"acc_z_kurtosis\",\n\"acc_x_mean_diff1\",\n\"acc_y_mean_diff1\",\n\"acc_z_mean_diff1\",\n\"acc_x_min_diff1\",\n\"acc_y_min_diff1\",\n\"acc_z_min_diff1\",\n\"acc_x_max_diff1\",\n\"acc_y_max_diff1\",\n\"acc_z_max_diff1\",\n\"acc_x_var_diff1\",\n\"acc_y_var_diff1\",\n\"acc_z_var_diff1\",\n\"acc_x_std_diff1\",\n\"acc_y_std_diff1\",\n\"acc_z_std_diff1\",\n\"acc_x_skew_diff1\",\n\"acc_y_skew_diff1\",\n\"acc_z_skew_diff1\",\n\"acc_x_kurtosis_diff1\",\n\"acc_y_kurtosis_diff1\",\n\"acc_z_kurtosis_diff1\",\n\"acc_x_vel_mean\",\n\"acc_y_vel_mean\",\n\"acc_z_vel_mean\",\n\"acc_x_vel_min\",\n\"acc_y_vel_min\",\n\"acc_z_vel_min\",\n\"acc_x_vel_max\",\n\"acc_y_vel_max\",\n\"acc_z_vel_max\",\n\"acc_x_vel_var\",\n\"acc_y_vel_var\",\n\"acc_z_vel_var\",\n\"acc_x_vel_std\",\n\"acc_y_vel_std\",\n\"acc_z_vel_std\",\n\"acc_x_vel_skew\",\n\"acc_y_vel_skew\",\n\"acc_z_vel_skew\",\n\"acc_x_vel_kurtosis\",\n\"acc_y_vel_kurtosis\",\n\"acc_z_vel_kurtosis\",\n\"acc_x_pos_mean\",\n\"acc_y_pos_mean\",\n\"acc_z_pos_mean\",\n\"acc_x_pos_min\",\n\"acc_y_pos_min\",\n\"acc_z_pos_min\",\n\"acc_x_pos_max\",\n\"acc_y_pos_max\",\n\"acc_z_pos_max\",\n\"acc_x_pos_var\",\n\"acc_y_pos_var\",\n\"acc_z_pos_var\",\n\"acc_x_pos_std\",\n\"acc_y_pos_std\",\n\"acc_z_pos_std\",\n\"acc_x_pos_skew\",\n\"acc_y_pos_skew\",\n\"acc_z_pos_skew\",\n\"acc_x_pos_kurtosis\",\n\"acc_y_pos_kurtosis\",\n\"acc_z_pos_kurtosis\",\n\"age\",\n\"handedness\",\n\"height_cm\",\n\"shoulder_to_wrist_cm\",\n\"elbow_to_wrist_cm\",]\n\ncat_cols = [\"adult_child\", \"sex\"]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:32:06.733707Z","iopub.execute_input":"2025-07-19T21:32:06.734346Z","iopub.status.idle":"2025-07-19T21:32:06.742056Z","shell.execute_reply.started":"2025-07-19T21:32:06.734315Z","shell.execute_reply":"2025-07-19T21:32:06.740652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(\n    df_total.drop([\"gesture\", \"gesture_label\", \"target_gesture\"]), \n    df_total[\"gesture_label\", \"target_gesture\"], \n    test_size=0.2, \n    random_state=420, \n    stratify=df_total[\"gesture_label\", \"target_gesture\"]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:34:17.400697Z","iopub.execute_input":"2025-07-19T21:34:17.401064Z","iopub.status.idle":"2025-07-19T21:34:17.460393Z","shell.execute_reply.started":"2025-07-19T21:34:17.401035Z","shell.execute_reply":"2025-07-19T21:34:17.459176Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"ct = ColumnTransformer([\n    (\"ss\", StandardScaler(), numeric_cols),\n    (\"ohe\", OneHotEncoder(handle_unknown=\"infrequent_if_exist\", min_frequency=0.01), cat_cols)\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:34:18.237765Z","iopub.execute_input":"2025-07-19T21:34:18.238117Z","iopub.status.idle":"2025-07-19T21:34:18.243161Z","shell.execute_reply.started":"2025-07-19T21:34:18.238094Z","shell.execute_reply":"2025-07-19T21:34:18.242270Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pipeline = Pipeline([\n    (\"ct\", ct),\n    (\"clf\", XGBClassifier())\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:34:19.620225Z","iopub.execute_input":"2025-07-19T21:34:19.620533Z","iopub.status.idle":"2025-07-19T21:34:19.626145Z","shell.execute_reply.started":"2025-07-19T21:34:19.620511Z","shell.execute_reply":"2025-07-19T21:34:19.625170Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pipeline.fit(X_train.to_pandas(), y_train[\"gesture_label\"].to_pandas())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:34:37.065433Z","iopub.execute_input":"2025-07-19T21:34:37.065745Z","iopub.status.idle":"2025-07-19T21:34:53.702511Z","shell.execute_reply.started":"2025-07-19T21:34:37.065722Z","shell.execute_reply":"2025-07-19T21:34:53.701611Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"preds = pipeline.predict(X_test.to_pandas())\npreds_target_gesture = [id2gestures[x] in target_gestures for x in preds] # shitty but works for now","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:39:42.775474Z","iopub.execute_input":"2025-07-19T21:39:42.775841Z","iopub.status.idle":"2025-07-19T21:39:42.866845Z","shell.execute_reply.started":"2025-07-19T21:39:42.775814Z","shell.execute_reply":"2025-07-19T21:39:42.865922Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"f1_macro = f1_score(preds, y_test[\"gesture_label\"], average=\"macro\")\n\nf1_binary = f1_score(\n    y_test[\"target_gesture\"],\n    preds_target_gesture,\n    pos_label=True,\n    zero_division=0,\n    average=\"binary\"\n) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:42:55.845384Z","iopub.execute_input":"2025-07-19T21:42:55.845733Z","iopub.status.idle":"2025-07-19T21:42:55.859530Z","shell.execute_reply.started":"2025-07-19T21:42:55.845704Z","shell.execute_reply":"2025-07-19T21:42:55.858567Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"0.5 * f1_binary + 0.5 * f1_macro","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:43:18.155583Z","iopub.execute_input":"2025-07-19T21:43:18.155915Z","iopub.status.idle":"2025-07-19T21:43:18.162565Z","shell.execute_reply.started":"2025-07-19T21:43:18.155890Z","shell.execute_reply":"2025-07-19T21:43:18.161417Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### 5-Fold Validation","metadata":{}},{"cell_type":"code","source":"kf = KFold(n_splits=5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:43:26.075931Z","iopub.execute_input":"2025-07-19T21:43:26.076544Z","iopub.status.idle":"2025-07-19T21:43:26.080918Z","shell.execute_reply.started":"2025-07-19T21:43:26.076513Z","shell.execute_reply":"2025-07-19T21:43:26.079668Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"folds = {}\n\nfor i, (train_index, test_index) in tqdm(enumerate(kf.split(df_total)), total=5):\n    ct = ColumnTransformer([\n        (\"ss\", StandardScaler(), numeric_cols),\n        (\"ohe\", OneHotEncoder(handle_unknown=\"infrequent_if_exist\", min_frequency=0.01), cat_cols)\n    ])\n\n    pipeline = Pipeline([\n        (\"ct\", ct),\n        (\"clf\", XGBClassifier())\n    ])\n\n    pipeline.fit(\n        df_total.to_pandas().drop([\"gesture\", \"gesture_label\", \"target_gesture\"], axis=1).loc[train_index, :], \n        df_total.to_pandas()[\"gesture_label\"][train_index]\n    )\n\n    # make predictions\n    preds = pipeline.predict(df_total.to_pandas().drop(\n        [\"gesture\", \"gesture_label\", \"target_gesture\"], axis=1).loc[test_index, :])\n    preds_target_gesture = [id2gestures[x] in target_gestures for x in preds]\n\n    f1_binary = f1_score(\n        df_total[\"target_gesture\"][test_index],\n        preds_target_gesture,\n        pos_label=True,\n        zero_division=0,\n        average=\"binary\"\n    )\n\n    f1_macro = f1_score(\n        df_total[\"gesture_label\"][test_index],\n        preds,\n        average=\"macro\",\n    )\n\n    print(f\"FOLD {i+1}: \", 0.5 * f1_binary + 0.5 * f1_macro)\n\n    folds[i+1] = {\"ct\": ct, \"pipeline\": pipeline}\n    folds[i+1][\"f1_binary\"] = f1_binary\n    folds[i+1][\"f1_macro\"] = f1_macro\n    folds[i+1][\"weighed_f1\"] = 0.5 * f1_binary + 0.5 * f1_macro","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:54:10.808694Z","iopub.execute_input":"2025-07-19T21:54:10.809175Z","iopub.status.idle":"2025-07-19T21:55:42.007586Z","shell.execute_reply.started":"2025-07-19T21:54:10.809143Z","shell.execute_reply":"2025-07-19T21:55:42.003772Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"avg_f1_binary = sum([folds[i+1][\"f1_binary\"] for i in range(len(folds))]) / len(folds)\navg_f1_macro = sum([folds[i+1][\"f1_macro\"] for i in range(len(folds))]) / len(folds)\navg_weighed_f1 = sum([folds[i+1][\"weighed_f1\"] for i in range(len(folds))]) / len(folds)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:56:01.217597Z","iopub.execute_input":"2025-07-19T21:56:01.217901Z","iopub.status.idle":"2025-07-19T21:56:01.224155Z","shell.execute_reply.started":"2025-07-19T21:56:01.217878Z","shell.execute_reply":"2025-07-19T21:56:01.223009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"AVG F1 Binary: {avg_f1_binary}\\n\", f\"AVG F1 MACRO: {avg_f1_macro}\\n\", f\"WEIGHED F1: {avg_weighed_f1}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-19T21:57:05.267580Z","iopub.execute_input":"2025-07-19T21:57:05.267890Z","iopub.status.idle":"2025-07-19T21:57:05.275242Z","shell.execute_reply.started":"2025-07-19T21:57:05.267867Z","shell.execute_reply":"2025-07-19T21:57:05.273523Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Inference","metadata":{}},{"cell_type":"code","source":"import kaggle_evaluation.cmi_inference_server","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T20:40:16.322666Z","iopub.execute_input":"2025-07-12T20:40:16.322946Z","iopub.status.idle":"2025-07-12T20:40:16.518779Z","shell.execute_reply.started":"2025-07-12T20:40:16.322927Z","shell.execute_reply":"2025-07-12T20:40:16.517965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    \n    test_infer_features = sequence.select(\n    [\"sequence_id\", \"acc_x\", \"acc_y\", \"acc_z\"]\n    ).group_by(\"sequence_id\").agg(\n        pl.all().mean().name.suffix(\"_mean\"),\n        pl.all().min().name.suffix(\"_min\"),\n        pl.all().max().name.suffix(\"_max\"),\n        pl.all().var().name.suffix(\"_var\"),\n        pl.all().std().name.suffix(\"_std\"),\n        pl.all().skew().name.suffix(\"_skew\"),\n        pl.all().kurtosis().name.suffix(\"_kurtosis\"),\n        \n        pl.all().diff(1).mean().name.suffix(\"_mean_diff1\"),\n        pl.all().diff(1).min().name.suffix(\"_min_diff1\"),\n        pl.all().diff(1).max().name.suffix(\"_max_diff1\"),\n        pl.all().diff(1).var().name.suffix(\"_var_diff1\"),\n        pl.all().diff(1).std().name.suffix(\"_std_diff1\"),\n        pl.all().diff(1).skew().name.suffix(\"_skew_diff1\"),\n        pl.all().diff(1).kurtosis().name.suffix(\"_kurtosis_diff1\"),\n        \n        pl.all().cum_sum().mul(0.1).mean().name.suffix(\"_vel_mean\"),\n        pl.all().cum_sum().mul(0.1).min().name.suffix(\"_vel_min\"),\n        pl.all().cum_sum().mul(0.1).max().name.suffix(\"_vel_max\"),\n        pl.all().cum_sum().mul(0.1).var().name.suffix(\"_vel_var\"),\n        pl.all().cum_sum().mul(0.1).std().name.suffix(\"_vel_std\"),\n        pl.all().cum_sum().mul(0.1).skew().name.suffix(\"_vel_skew\"),\n        pl.all().cum_sum().mul(0.1).kurtosis().name.suffix(\"_vel_kurtosis\"),\n    \n        pl.all().cum_sum().cum_sum().mul(0.1).mean().name.suffix(\"_pos_mean\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).min().name.suffix(\"_pos_min\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).max().name.suffix(\"_pos_max\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).var().name.suffix(\"_pos_var\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).std().name.suffix(\"_pos_std\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).skew().name.suffix(\"_pos_skew\"),\n        pl.all().cum_sum().cum_sum().mul(0.1).kurtosis().name.suffix(\"_pos_kurtosis\"),\n    )\n\n    seq2sub_test = sequence.unique([\"sequence_id\", \"subject\"])[\"sequence_id\", \"subject\"]\n\n    df_infer = test_infer_features.join(\n    seq2sub_test, on=\"sequence_id\"\n    ).join(\n        demographics, on=\"subject\"\n    ).drop([\"sequence_id\", \"subject\"])\n\n    preds = None\n    for fold in folds:\n        pred = folds[fold][\"pipeline\"].predict_proba(df_infer.to_pandas())\n        \n        if preds is None:\n            preds = pred\n        else:\n            preds += pred\n            \n    preds /= len(folds)\n\n    pred_cat = np.argmax(preds, axis=1)[0]\n    \n    return id2gestures[pred_cat]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T20:53:35.519859Z","iopub.execute_input":"2025-07-12T20:53:35.520923Z","iopub.status.idle":"2025-07-12T20:53:35.536320Z","shell.execute_reply.started":"2025-07-12T20:53:35.520873Z","shell.execute_reply":"2025-07-12T20:53:35.534962Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"inference_server = kaggle_evaluation.cmi_inference_server.CMIInferenceServer(predict)\n\nif os.getenv(\"KAGGLE_IS_COMPETITION_RERUN\"):\n    inference_server.serve()\nelse:\n    inference_server.run_local_gateway(\n        data_paths=(\n            \"/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv\",\n            \"/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv\",\n        )\n    )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-12T20:53:35.901232Z","iopub.execute_input":"2025-07-12T20:53:35.901659Z","iopub.status.idle":"2025-07-12T20:53:37.331331Z","shell.execute_reply.started":"2025-07-12T20:53:35.901633Z","shell.execute_reply":"2025-07-12T20:53:37.330333Z"}},"outputs":[],"execution_count":null}]}