{"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"},{"sourceId":12327385,"sourceType":"datasetVersion","datasetId":7770642}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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-02T16:40:30.19647Z","iopub.execute_input":"2025-07-02T16:40:30.19676Z","iopub.status.idle":"2025-07-02T16:40:30.750112Z","shell.execute_reply.started":"2025-07-02T16:40:30.196733Z","shell.execute_reply":"2025-07-02T16:40:30.749334Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import numpy as np\n# import pandas as pd\n# import joblib\n# from tensorflow.keras.models import load_model\n\n# # ===============================\n# # 2️⃣ Load Models + Scalers\n# # ===============================\n# # --- MULTI ---\n# model_multi = load_model('/kaggle/input/main-data/multi_model.h5')\n# scaler_multi = joblib.load('/kaggle/input/main-data/multi_scaler.pkl')\n\n# # --- BINARY ---\n# clf_binary = joblib.load('/kaggle/input/main-data/binary_model.pkl')\n# scaler_binary = joblib.load('/kaggle/input/main-data/binary_scaler.pkl')\n\n# print(\"✅ Models & scalers loaded!\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.751034Z","iopub.execute_input":"2025-07-02T16:40:30.751376Z","iopub.status.idle":"2025-07-02T16:40:30.755171Z","shell.execute_reply.started":"2025-07-02T16:40:30.751359Z","shell.execute_reply":"2025-07-02T16:40:30.754421Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 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# test_df = pd.merge(test, test_demo, on=\"subject\", how=\"inner\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.75733Z","iopub.execute_input":"2025-07-02T16:40:30.757609Z","iopub.status.idle":"2025-07-02T16:40:30.777275Z","shell.execute_reply.started":"2025-07-02T16:40:30.757587Z","shell.execute_reply":"2025-07-02T16:40:30.77654Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# acc_cols = [col for col in test_df.columns if col.startswith(\"acc_\")]\n# rot_cols = [col for col in test_df.columns if col.startswith(\"rot_\")]\n# tuf_cols = [col for col in test_df.columns if col.startswith(\"tof_\")]\n# thm_cols = [col for col in test_df.columns if col.startswith(\"thm_\")]\n# demo_cols = [\n#     'adult_child', 'age', 'sex', 'handedness',\n#     'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm'\n# ]\n\n# label_map = {\n#     0: 'Above ear - pull hair',\n#     1: 'Cheek - pinch skin',\n#     2: 'Eyebrow - pull hair',\n#     3: 'Eyelash - pull hair',\n#     4: 'Forehead - pull hairline',\n#     5: 'Forehead - scratch',\n#     6: 'Neck - pinch skin',\n#     7: 'Neck - scratch'\n# }\n\n\n# # ===============================\n# # 5️⃣ Precompute row means\n# # ===============================\n# test_df['tuf_mean_row'] = test_df[tuf_cols].replace(-1, np.nan).mean(axis=1)\n# test_df['thm_mean_row'] = test_df[thm_cols].mean(axis=1)\n\n# input_features = acc_cols + rot_cols + demo_cols + ['tuf_mean_row', 'thm_mean_row']\n# from tensorflow.keras.preprocessing.sequence import pad_sequences\n\n# # If you need to know max_len: you MUST store it during training!\n# max_len = 693  # <- example, use YOUR actual max_len!\n\n# multi_sequences = []\n# multi_ids = []\n\n# for seq_id, group in test_df.groupby(\"sequence_id\"):\n#     group = group.sort_values(\"sequence_counter\")\n#     data = group[input_features].values\n#     multi_sequences.append(data)\n#     multi_ids.append(seq_id)\n\n# X_test_padded = pad_sequences(multi_sequences, maxlen=max_len, padding='post', dtype='float32')\n# X_test_scaled_multi = np.array([scaler_multi.transform(seq) for seq in X_test_padded])\n# X_test_scaled_multi = X_test_scaled_multi[..., np.newaxis]\n\n# # ===============================\n# # 7️⃣ Predict MULTI\n# # ===============================\n# y_pred_probs = model_multi.predict(X_test_scaled_multi)\n# y_pred_multi = np.argmax(y_pred_probs, axis=1)\n\n# gesture_pred_multi = [label_map[idx] for idx in y_pred_multi]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.778285Z","iopub.execute_input":"2025-07-02T16:40:30.778598Z","iopub.status.idle":"2025-07-02T16:40:30.793045Z","shell.execute_reply.started":"2025-07-02T16:40:30.778572Z","shell.execute_reply":"2025-07-02T16:40:30.792187Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# test_df_2 = pd.merge(test,test_demo, on=\"subject\", how=\"inner\")\n# FEATURE_COLUMNS = ['acc_x', 'acc_y', 'acc_z', 'rot_x', 'rot_y', 'rot_z', 'rot_w']\n# DEMO_COLUMNS = demo_cols\n\n# # Aggregate per sequence\n# rows = []\n# for seq_id, group in test_df_2.groupby('sequence_id'):\n#     feature_means = group[FEATURE_COLUMNS].mean().to_dict()\n#     demo_values = group[DEMO_COLUMNS].iloc[0].to_dict()\n#     combined_row = {**feature_means, **demo_values, 'sequence_id': seq_id}\n#     rows.append(combined_row)\n\n# test_seq_df = pd.DataFrame(rows)\n# X_test_bi = test_seq_df[FEATURE_COLUMNS + DEMO_COLUMNS]\n# X_test_scaled_bi = scaler_binary.transform(X_test_bi)\n\n# # Predict\n# gesture_pred_bi = clf_binary.predict(X_test_scaled_bi)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.793909Z","iopub.execute_input":"2025-07-02T16:40:30.794277Z","iopub.status.idle":"2025-07-02T16:40:30.811167Z","shell.execute_reply.started":"2025-07-02T16:40:30.794241Z","shell.execute_reply":"2025-07-02T16:40:30.810415Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# gesture_pred_bi_label = ['Target' if p == 1 else 'Non-Target' for p in gesture_pred_bi]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.811894Z","iopub.execute_input":"2025-07-02T16:40:30.812139Z","iopub.status.idle":"2025-07-02T16:40:30.831127Z","shell.execute_reply.started":"2025-07-02T16:40:30.81212Z","shell.execute_reply":"2025-07-02T16:40:30.830322Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# # Make DataFrame with BOTH predictions\n# final_df = pd.DataFrame({\n#     'sequence_id': multi_ids,\n#     'gesture_predicted': gesture_pred_multi,     # multi-class gesture names\n#     'gesture_type_predicted': gesture_pred_bi_label  # Target or Non-Target\n# })\n\n# # If binary = Non-Target → override gesture_predicted to \"Non-Target\"\n# final_df.loc[final_df['gesture_type_predicted'] == 'Non-Target', 'gesture_predicted'] = 'Non-Target'\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.832141Z","iopub.execute_input":"2025-07-02T16:40:30.832366Z","iopub.status.idle":"2025-07-02T16:40:30.844953Z","shell.execute_reply.started":"2025-07-02T16:40:30.832351Z","shell.execute_reply":"2025-07-02T16:40:30.844241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# final_df[['sequence_id', 'gesture_predicted']].to_csv('submission.csv', index=False)\n# print(\"✅ Submission file saved: submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.845869Z","iopub.execute_input":"2025-07-02T16:40:30.846096Z","iopub.status.idle":"2025-07-02T16:40:30.859926Z","shell.execute_reply.started":"2025-07-02T16:40:30.846076Z","shell.execute_reply":"2025-07-02T16:40:30.859019Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# final_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.862303Z","iopub.execute_input":"2025-07-02T16:40:30.862721Z","iopub.status.idle":"2025-07-02T16:40:30.875034Z","shell.execute_reply.started":"2025-07-02T16:40:30.862701Z","shell.execute_reply":"2025-07-02T16:40:30.874253Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import os\n\n# print(\"Does submission.csv exist?\", os.path.exists(\"submission.csv\"))\n# print(\"Current working dir:\", os.getcwd())\n# print(\"Files here:\", os.listdir(\".\"))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.875925Z","iopub.execute_input":"2025-07-02T16:40:30.876256Z","iopub.status.idle":"2025-07-02T16:40:30.88893Z","shell.execute_reply.started":"2025-07-02T16:40:30.876235Z","shell.execute_reply":"2025-07-02T16:40:30.88817Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\nimport polars as pl\nimport numpy as np\nfrom tensorflow.keras.models import load_model\nimport joblib\nimport pickle  # or joblib for scikit-learn model\n\nfrom sklearn.preprocessing import StandardScaler\n\nimport kaggle_evaluation.cmi_inference_server\n\n# 1️⃣ Load both models & scalers once\nmodel_multi = load_model('/kaggle/input/main-data/multi_model.h5')\nscaler_multi = joblib.load('/kaggle/input/main-data/multi_scaler.pkl')\n\nimport joblib\nclf_binary = joblib.load('/kaggle/input/main-data/binary_model.pkl')\nscaler_binary = joblib.load('/kaggle/input/main-data/binary_scaler.pkl')\n\n# 2️⃣ Label mapping for multi-class\nlabel_map = {\n    0: \"Above ear - pull hair\",\n    1: \"Cheek - pinch skin\",\n    2: \"Eyebrow - pull hair\",\n    3: \"Eyelash - pull hair\",\n    4: \"Forehead - pull hairline\",\n    5: \"Forehead - scratch\",\n    6: \"Neck - pinch skin\",\n    7: \"Neck - scratch\"\n}\n\n\n\n# 4️⃣ Your inference function\ndef predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    # Convert to pandas for numpy ops\n    seq_df = sequence.to_pandas()\n    demo_df = demographics.to_pandas()\n    # 3️⃣ Columns\n    acc_cols = [col for col in sequence.columns if col.startswith(\"acc_\")]\n    rot_cols = [col for col in sequence.columns if col.startswith(\"rot_\")]\n    tuf_cols = [col for col in sequence.columns if col.startswith(\"tof_\")]\n    thm_cols = [col for col in sequence.columns if col.startswith(\"thm_\")]\n    demo_cols = ['adult_child', 'age', 'sex', 'handedness',\n                 'height_cm', 'shoulder_to_wrist_cm', 'elbow_to_wrist_cm']\n\n    FEATURE_COLUMNS = acc_cols + rot_cols\n\n    # --- Binary prediction ---\n    # Get means\n    feature_means = seq_df[FEATURE_COLUMNS].mean()\n    demo_values = demo_df.iloc[0][demo_cols]\n\n    X_bi = pd.concat([feature_means, demo_values]).values.reshape(1, -1)\n    X_bi_scaled = scaler_binary.transform(X_bi)\n    pred_bi = clf_binary.predict(X_bi_scaled)[0]  # 0 or 1\n\n    if pred_bi == 0:\n        return \"Non-Target\"\n\n    # --- Multi gesture prediction ---\n    # For multi: sequence-level IMU + demo + mean(TUF) + mean(THM)\n\n    seq_df['tuf_mean_row'] = seq_df[tuf_cols].replace(-1, np.nan).mean(axis=1)\n    seq_df['thm_mean_row'] = seq_df[thm_cols].mean(axis=1)\n\n    input_features = acc_cols + rot_cols + demo_cols + ['tuf_mean_row', 'thm_mean_row']\n\n    group = seq_df.copy()\n    group[demo_cols] = demo_df.iloc[0][demo_cols].values\n\n    data = group[input_features].values\n\n    # Pad to max_len you used in training\n    from tensorflow.keras.preprocessing.sequence import pad_sequences\n    max_len = 693  # or your actual max_len from training\n    padded = pad_sequences([data], maxlen=max_len, padding='post', dtype='float32')[0]\n\n    scaled = scaler_multi.transform(padded)\n    scaled = np.expand_dims(scaled, axis=0)  # batch\n    scaled = scaled[..., np.newaxis]  # add channel\n\n    y_probs = model_multi.predict(scaled)\n    y_class = np.argmax(y_probs, axis=1)[0]\n\n    gesture_label = label_map[y_class]\n    return gesture_label\n\n# 5️⃣ Run server\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    )\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:30.889602Z","iopub.execute_input":"2025-07-02T16:40:30.889804Z","iopub.status.idle":"2025-07-02T16:40:47.136399Z","shell.execute_reply.started":"2025-07-02T16:40:30.889789Z","shell.execute_reply":"2025-07-02T16:40:47.135343Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# predictions = []\n# for seq_id, group in test_df.groupby('sequence_id'):\n#     pred = predict(pl.DataFrame(group), pl.DataFrame(test_demo[test_demo['subject'] == group['subject'].iloc[0]]))\n#     predictions.append((seq_id, pred))\n\n# pred_df_tr = pd.DataFrame(predictions, columns=['sequence_id', 'gesture_predicted'])\n# # pred_df_tr.to_csv('submission.csv', index=False)\n# # print(\"Saved local test predictions as submission.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:47.13697Z","iopub.status.idle":"2025-07-02T16:40:47.137237Z","shell.execute_reply.started":"2025-07-02T16:40:47.137115Z","shell.execute_reply":"2025-07-02T16:40:47.137128Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# pred_df_tr","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-02T16:40:47.1382Z","iopub.status.idle":"2025-07-02T16:40:47.138532Z","shell.execute_reply.started":"2025-07-02T16:40:47.13835Z","shell.execute_reply":"2025-07-02T16:40:47.13837Z"}},"outputs":[],"execution_count":null}]}