{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-16T14:58:21.465226Z","iopub.execute_input":"2025-07-16T14:58:21.465537Z","iopub.status.idle":"2025-07-16T14:58:21.478157Z","shell.execute_reply.started":"2025-07-16T14:58:21.465512Z","shell.execute_reply":"2025-07-16T14:58:21.477082Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport numpy as np\nimport polars as pl\nfrom xgboost import XGBClassifier\nfrom sklearn.preprocessing import LabelEncoder\nimport kaggle_evaluation.cmi_inference_server\n\n# === 1. Load and prepare training data ===\ntrain = pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv')\ntrain_demo = pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv')\nmerged = pd.merge(train, train_demo, on='subject', how='left')\n\n# === 2. ToF Imputation ===\ntof_cols = [col for col in merged.columns if col.startswith('tof')]\nmerged[tof_cols] = merged[tof_cols].replace(-1, np.nan)\nmedians = np.nanmedian(merged[tof_cols].values, axis=0)\nmerged[tof_cols] = np.where(np.isnan(merged[tof_cols]), medians, merged[tof_cols])\n\n# === 3. Add ToF aggregates ===\ntof_agg_df = pd.DataFrame({\n    'tof_mean': merged[tof_cols].mean(axis=1),\n    'tof_std': merged[tof_cols].std(axis=1),\n    'tof_min': merged[tof_cols].min(axis=1),\n    'tof_max': merged[tof_cols].max(axis=1),\n    'tof_median': merged[tof_cols].median(axis=1),\n}, index=merged.index)\n\nmerged = pd.concat([merged.reset_index(drop=True), tof_agg_df.reset_index(drop=True)], axis=1)\n\n# === 4. Feature columns ===\nfeatures = [\n    'acc_x', 'acc_y', 'acc_z',\n    'rot_w', 'rot_x', 'rot_y', 'rot_z',\n    'thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5',\n    'adult_child', 'age', 'sex', 'handedness',\n    'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm',\n    'tof_mean', 'tof_std', 'tof_min', 'tof_max', 'tof_median'\n]\n\nX = merged[features]\ny = merged[\"gesture\"]\n\n# === 5. Encode target ===\ngesture_le = LabelEncoder()\ny_encoded = gesture_le.fit_transform(y)\n\n# === 6. Train model ===\nmodel = XGBClassifier(\n    eval_metric=\"mlogloss\",\n    use_label_encoder=False,\n    n_jobs=-1,\n    verbosity=0,\n    random_state=42\n)\nmodel.fit(X, y_encoded)\n\n# === 7. Inference function ===\ndef predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    seq_df = sequence.to_pandas()\n    demo_df = demographics.to_pandas()\n\n    # ToF Fix\n    for col in tof_cols:\n        if col in seq_df.columns:\n            seq_df[col] = seq_df[col].replace(-1, np.nan)\n    med_vals = pd.Series(medians, index=tof_cols)\n    seq_df[tof_cols] = seq_df[tof_cols].fillna(med_vals)\n\n    # Add ToF aggregates\n    tof_agg = pd.DataFrame({\n        'tof_mean': seq_df[tof_cols].mean(axis=1),\n        'tof_std': seq_df[tof_cols].std(axis=1),\n        'tof_min': seq_df[tof_cols].min(axis=1),\n        'tof_max': seq_df[tof_cols].max(axis=1),\n        'tof_median': seq_df[tof_cols].median(axis=1),\n    })\n    seq_df = pd.concat([seq_df.reset_index(drop=True), tof_agg.reset_index(drop=True)], axis=1)\n\n    # Final features\n    sensor_features = seq_df.iloc[-1][[\n        'acc_x', 'acc_y', 'acc_z',\n        'rot_w', 'rot_x', 'rot_y', 'rot_z',\n        'thm_1', 'thm_2', 'thm_3', 'thm_4', 'thm_5',\n        'tof_mean', 'tof_std', 'tof_min', 'tof_max', 'tof_median'\n    ]]\n    demo_features = demo_df.iloc[0][[\n        'adult_child', 'age', 'sex', 'handedness',\n        'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm'\n    ]]\n\n    full_input = pd.concat([sensor_features, demo_features]).values.reshape(1, -1)\n    pred = model.predict(full_input)[0]\n    return gesture_le.inverse_transform([pred])[0]\n\n# === 8. CMI Inference Server ===\ninference_server = kaggle_evaluation.cmi_inference_server.CMIInferenceServer(predict)\n\nif os.getenv('KAGGLE_IS_COMPETITION_RERUN'):\n    inference_server.serve()\nelse:\n    # === 9. Local Prediction & Submission File Generation ===\n    test = pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv')\n    test_demo = pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv')\n\n    results = []\n    for seq_id, seq_df in test.groupby(\"sequence_id\"):\n        demo = test_demo[test_demo[\"subject\"] == seq_df[\"subject\"].iloc[0]]\n\n        sequence_pl = pl.from_pandas(seq_df.reset_index(drop=True))\n        demo_pl = pl.from_pandas(demo.reset_index(drop=True))\n\n        pred = predict(sequence_pl, demo_pl)\n        results.append({\"row_id\": seq_id, \"gesture\": pred})\n\n    # Create and save submission\n    submission_df = pd.DataFrame(results)\n    submission_df.to_parquet(\"submission.parquet\", index=False)\n    print(\"submission.parquet saved successfully!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-16T16:32:23.191920Z","iopub.execute_input":"2025-07-16T16:32:23.192296Z","iopub.status.idle":"2025-07-16T16:34:43.166850Z","shell.execute_reply.started":"2025-07-16T16:32:23.192270Z","shell.execute_reply":"2025-07-16T16:34:43.166013Z"}},"outputs":[],"execution_count":null}]}