{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"############# Packages ##################\n\n%load_ext cudf.pandas\nimport numpy as np, pandas as pd, cupy as cp\nimport xgboost as xgb, joblib, os, warnings\nimport kaggle_evaluation.cmi_inference_server\nwarnings.filterwarnings('ignore')\n\n############# Features ##################\n\nid_features = ['row_id','sequence_id', 'subject'] # categorical \ntrain_only_features = ['sequence_type', 'orientation', 'behavior', 'phase', 'gesture'] # categorical\nsequence_features = ['sequence_counter']\naccel_features = ['acc_x', 'acc_y', 'acc_z']\nrot_features = ['rot_w', 'rot_x', 'rot_y', 'rot_z']\nthm_features = ['thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5']\ntof_features = [f\"tof_{i}_v{j}\" for i in range(1, 6) for j in range(64)]\ndemo_features =  ['adult_child', 'age', 'sex', 'handedness', 'height_cm','shoulder_to_wrist_cm', 'elbow_to_wrist_cm']\n\nfeatures = sequence_features + accel_features + rot_features + thm_features + tof_features + demo_features\n\nfeatures","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-24T02:59:00.751872Z","iopub.execute_input":"2025-06-24T02:59:00.752236Z","iopub.status.idle":"2025-06-24T02:59:00.766356Z","shell.execute_reply.started":"2025-06-24T02:59:00.752214Z","shell.execute_reply":"2025-06-24T02:59:00.765347Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Gestures ##################\n\ngesture_mapping = {\"Cheek - pinch skin\": 1,\n                   \"Forehead - pull hairline\": 2,\n                   \"Neck - scratch\": 3, \n                   \"Neck - pinch skin\": 4, \n                   \"Eyelash - pull hair\": 5, \n                   \"Eyebrow - pull hair\": 6, \n                   \"Forehead - scratch\": 7, \n                   \"Above ear - pull hair\": 8, \n                   \"Non-Target\": 0 }\n\ndef encode_gesture(gesture):\n    return gesture_mapping.get(gesture, 0)\n\ngesture_mapping","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T02:59:00.768407Z","iopub.execute_input":"2025-06-24T02:59:00.768764Z","iopub.status.idle":"2025-06-24T02:59:00.786147Z","shell.execute_reply.started":"2025-06-24T02:59:00.768745Z","shell.execute_reply":"2025-06-24T02:59:00.785324Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Data ##################\n\ntrain = pd.read_csv(\"../input/cmi-detect-behavior-with-sensor-data/train.csv\")\ntrain = train[train.phase=='Gesture']\ntrain_demographics = pd.read_csv(\"../input/cmi-detect-behavior-with-sensor-data/train_demographics.csv\")\ntrain_merged = train.merge(train_demographics, on=\"subject\", how=\"left\")\n\ntest = pd.read_csv(\"../input/cmi-detect-behavior-with-sensor-data/test.csv\")\ntest_demographics = pd.read_csv(\"../input/cmi-detect-behavior-with-sensor-data/test_demographics.csv\")\ntest_merged = test.merge(test_demographics, on=\"subject\", how=\"left\")\n\ntest_merged.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T02:59:00.786857Z","iopub.execute_input":"2025-06-24T02:59:00.787172Z","iopub.status.idle":"2025-06-24T02:59:02.700880Z","shell.execute_reply.started":"2025-06-24T02:59:00.787154Z","shell.execute_reply":"2025-06-24T02:59:02.700033Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Modelling ##################\n\ndf = train_merged[features + ['gesture'] + ['sequence_id']]\ndf[\"encoded_gesture\"] = df[\"gesture\"].apply(encode_gesture)\n\nX = cp.array(df[features])\ny = cp.array(df[\"encoded_gesture\"])\n\nmodel_xgb = xgb.XGBClassifier(max_depth = 4, n_estimators = 1200, device = 'cuda')\nmodel_xgb.fit(X,y)\njoblib.dump(model_xgb,'model_xgb.joblib')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T02:59:02.701869Z","iopub.execute_input":"2025-06-24T02:59:02.702142Z","iopub.status.idle":"2025-06-24T03:03:24.721330Z","shell.execute_reply.started":"2025-06-24T02:59:02.702113Z","shell.execute_reply":"2025-06-24T03:03:24.720311Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# TODO: DO WHATVER YOU WANT WITH `model_xgb.joblib` HERE!","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T03:03:24.723276Z","iopub.execute_input":"2025-06-24T03:03:24.723544Z","iopub.status.idle":"2025-06-24T03:03:24.728277Z","shell.execute_reply.started":"2025-06-24T03:03:24.723525Z","shell.execute_reply":"2025-06-24T03:03:24.727415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Prediction ##################\n\ndef predict(sequence: pd.DataFrame, demographics: pd.DataFrame) -> str:\n    \n    # Convert from Polars to Pandas if needed\n    if not isinstance(sequence, pd.DataFrame):\n        sequence = sequence.to_pandas()\n    if not isinstance(demographics, pd.DataFrame):\n        demographics = demographics.to_pandas()\n\n    # Merge with demographics\n    sequence = sequence.merge(demographics, on=\"subject\", how=\"left\")\n\n    # Keep the latter part of the sequence\n    sequence = sequence.iloc[-21:]\n\n    # Select relevant features only from the second half\n    X_test = sequence[features]\n\n    # Select relevant features and make row-level predictions\n    sequence[\"row_preds\"] = model_xgb.predict(X_test)\n\n    # Compute the mode prediction for this sequence\n    mode_pred = sequence[\"row_preds\"].mode()\n    top_pred = mode_pred.iloc[0] if not mode_pred.empty else sequence[\"row_preds\"].value_counts().idxmax()\n\n    # Map prediction to gesture label\n    gesture_label = {int(v): k for k, v in gesture_mapping.items()}\n    return \"Text on phone\" if top_pred == 0 else gesture_label.get(top_pred, \"Text on phone\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T03:03:24.729144Z","iopub.execute_input":"2025-06-24T03:03:24.729346Z","iopub.status.idle":"2025-06-24T03:03:24.748441Z","shell.execute_reply.started":"2025-06-24T03:03:24.729330Z","shell.execute_reply":"2025-06-24T03:03:24.747809Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Test ##################\n\nresults = []\nfor sequence_id, group in test.groupby('sequence_id'):\n    sequence = group.drop(columns=['sequence_id'])  # Extract features\n    gesture = predict(sequence, test_demographics)\n    results.append([sequence_id, gesture])\n    \npredictions_df = pd.DataFrame(results, columns=['sequence_id', 'gesture'])\npredictions_df.to_parquet('submission.parquet', index=False)\nprint(predictions_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-24T03:03:24.749242Z","iopub.execute_input":"2025-06-24T03:03:24.749518Z","iopub.status.idle":"2025-06-24T03:03:27.417281Z","shell.execute_reply.started":"2025-06-24T03:03:24.749500Z","shell.execute_reply":"2025-06-24T03:03:27.416316Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"############# Inference ##################\n\ninference_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-06-24T03:03:27.418353Z","iopub.execute_input":"2025-06-24T03:03:27.418596Z","iopub.status.idle":"2025-06-24T03:03:30.478186Z","shell.execute_reply.started":"2025-06-24T03:03:27.418577Z","shell.execute_reply":"2025-06-24T03:03:30.477437Z"}},"outputs":[],"execution_count":null}]}