{"metadata":{"kernelspec":{"name":"python3","display_name":"Python 3","language":"python"},"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":"gpu","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":"import numpy as np\nimport pandas as pd\nimport pickle\nfrom tsfresh import extract_features\nfrom tsfresh.feature_extraction import MinimalFCParameters\nfrom sklearn.preprocessing import StandardScaler, LabelEncoder\nfrom sklearn.model_selection import train_test_split\nimport polars as pl\nimport os\n\nimport kaggle_evaluation.cmi_inference_server\nimport warnings\nwarnings.filterwarnings(\"ignore\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:18:50.315712Z","iopub.execute_input":"2025-06-13T02:18:50.316269Z","iopub.status.idle":"2025-06-13T02:18:53.84851Z","shell.execute_reply.started":"2025-06-13T02:18:50.316242Z","shell.execute_reply":"2025-06-13T02:18:53.84798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"categorical_cols = ['sequence_type', 'orientation', 'phase', 'behavior']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:18:53.849746Z","iopub.execute_input":"2025-06-13T02:18:53.85022Z","iopub.status.idle":"2025-06-13T02:18:53.85379Z","shell.execute_reply.started":"2025-06-13T02:18:53.850193Z","shell.execute_reply":"2025-06-13T02:18:53.853079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_data =  pd.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\")\nnumerical_cols = [col for col in train_data.columns if col.startswith(('acc_', 'rot_', 'thm_', 'tof_'))]\ntrain_data.drop(columns = categorical_cols, inplace=True)\ntrain_data = train_data.groupby(\"sequence_id\").apply(lambda x: x.fillna(method=\"ffill\")).reset_index(drop=True)\ntrain_data.fillna(method='bfill', inplace=True)\n\ntrain_data[\"acc_magnitude\"] = (train_data['acc_x']**2 + train_data['acc_y']**2 + train_data['acc_z']** 2)**0.5\ntrain_data[\"rot_magnitude\"] = (train_data['rot_x']**2 + train_data['rot_y']**2 + train_data['rot_z']** 2)**0.5\ntrain_data['acc_x_diff'] = train_data.groupby('sequence_id')['acc_x'].diff().fillna(0)\ntrain_data['acc_x_mean'] = train_data.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).mean().reset_index(0, drop= True)\ntrain_data['acc_x_std'] = train_data.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).std().reset_index(0, drop= True)\n\nfor i in range(1, 6):\n    tof_cols = [col for col in train_data.columns if col.startswith(f'tof_{i}_')]\n    train_data[f'tof_{i}_mean'] = train_data[tof_cols].mean(axis = 1)\n    train_data[f'tof_{i}_std'] = train_data[tof_cols].std(axis= 1)\n    \nfor col in numerical_cols:\n    train_data[col].fillna(train_data[col].mean(), inplace=True)\n\nscaler = StandardScaler()\ntrain_data[numerical_cols] = scaler.fit_transform(train_data[numerical_cols])\n\n# subset = train_data[['sequence_id', 'sequence_counter', 'acc_x', 'acc_y', 'acc_z']]\n# features = extract_features(\n#     subset,\n#     column_id='sequence_id',\n#     column_sort='sequence_counter',\n#     default_fc_parameters=MinimalFCParameters()\n# )\n# features = features.reset_index().rename(columns={'index': 'sequence_id'})\n# train_data = train_data.merge(features, on='sequence_id', how='left')\ntrain_data[\"acc_x_std\"].fillna(train_data[\"acc_x_std\"].mean(), inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:54:17.344197Z","iopub.execute_input":"2025-06-13T02:54:17.344728Z","iopub.status.idle":"2025-06-13T02:54:54.48434Z","shell.execute_reply.started":"2025-06-13T02:54:17.344704Z","shell.execute_reply":"2025-06-13T02:54:54.483808Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# train_data.to_parquet(\"train_processed.parquet\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:41.59037Z","iopub.execute_input":"2025-06-13T02:19:41.590979Z","iopub.status.idle":"2025-06-13T02:19:41.594274Z","shell.execute_reply.started":"2025-06-13T02:19:41.590957Z","shell.execute_reply":"2025-06-13T02:19:41.593514Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## preprocess test data","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:41.595025Z","iopub.execute_input":"2025-06-13T02:19:41.59522Z","iopub.status.idle":"2025-06-13T02:19:41.613731Z","shell.execute_reply.started":"2025-06-13T02:19:41.595205Z","shell.execute_reply":"2025-06-13T02:19:41.612978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data = pd.read_csv('/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv')\nnumerical_cols = [col for col in test_data.columns if col.startswith(('acc_', 'rot_', 'thm_', 'tof_'))]\ntest_data = test_data.groupby('sequence_id').apply(lambda x: x.fillna(method='ffill')).reset_index(drop=True)\ntest_data.fillna(method='bfill', inplace=True)\nfor col in numerical_cols:\n    test_data[col].fillna(test_data[col].mean(), inplace=True)\n\ntest_data[\"acc_magnitude\"] = (test_data['acc_x']**2 + test_data['acc_y']**2 + test_data['acc_z']** 2)**0.5\ntest_data[\"rot_magnitude\"] = (test_data['rot_x']**2 + test_data['rot_y']**2 + test_data['rot_z']** 2)**0.5\ntest_data['acc_x_diff'] = test_data.groupby('sequence_id')['acc_x'].diff().fillna(0)\ntest_data['acc_x_mean'] = test_data.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).mean().reset_index(0, drop= True)\ntest_data['acc_x_std'] = test_data.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).std().reset_index(0, drop= True)\n\nfor i in range(1, 6):\n    tof_cols = [col for col in test_data.columns if col.startswith(f'tof_{i}_')]\n    test_data[f'tof_{i}_mean'] = test_data[tof_cols].mean(axis = 1)\n    test_data[f'tof_{i}_std'] = test_data[tof_cols].std(axis= 1)\n\ntest_data[numerical_cols] = scaler.transform(test_data[numerical_cols])\n\nsubset_test = test_data[['sequence_id', 'sequence_counter', 'acc_x', 'acc_y', 'acc_z']]\nfeatures_test = extract_features(\n    subset_test,\n    column_id='sequence_id',\n    column_sort='sequence_counter',\n    default_fc_parameters=MinimalFCParameters()\n)\nfeatures_test = features_test.reset_index().rename(columns={'index': 'sequence_id'})\ntest_data = test_data.merge(features_test, on='sequence_id', how='left')\ntest_data[\"acc_x_std\"].fillna(test_data[\"acc_x_std\"].mean(), inplace=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:41.614536Z","iopub.execute_input":"2025-06-13T02:19:41.61486Z","iopub.status.idle":"2025-06-13T02:19:41.89846Z","shell.execute_reply.started":"2025-06-13T02:19:41.614839Z","shell.execute_reply":"2025-06-13T02:19:41.897516Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"null_columns = test_data.columns[test_data.isnull().any()]\nprint(\"Columns with missing values:\")\nprint(null_columns)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:54:54.485577Z","iopub.execute_input":"2025-06-13T02:54:54.485808Z","iopub.status.idle":"2025-06-13T02:54:54.491495Z","shell.execute_reply.started":"2025-06-13T02:54:54.485791Z","shell.execute_reply":"2025-06-13T02:54:54.490961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# test_data.to_parquet('test_processed.parquet')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:41.906992Z","iopub.execute_input":"2025-06-13T02:19:41.907529Z","iopub.status.idle":"2025-06-13T02:19:41.919687Z","shell.execute_reply.started":"2025-06-13T02:19:41.907503Z","shell.execute_reply":"2025-06-13T02:19:41.918973Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Step 7: Encode categorical variables\nle = LabelEncoder()\ntrain_data['gesture'] = le.fit_transform(train_data['gesture'].astype(str))\nwith open('label_encoder.pkl', 'wb') as f:\n    pickle.dump(le, f)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:54:54.492164Z","iopub.execute_input":"2025-06-13T02:54:54.492334Z","iopub.status.idle":"2025-06-13T02:54:54.603732Z","shell.execute_reply.started":"2025-06-13T02:54:54.49232Z","shell.execute_reply":"2025-06-13T02:54:54.603145Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## Build and submit baseline model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:42.055237Z","iopub.execute_input":"2025-06-13T02:19:42.055489Z","iopub.status.idle":"2025-06-13T02:19:42.058668Z","shell.execute_reply.started":"2025-06-13T02:19:42.055474Z","shell.execute_reply":"2025-06-13T02:19:42.057965Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train_data.drop(['gesture', 'row_id', 'sequence_id', 'subject', 'sequence_counter'], axis=1, errors='ignore')\ny = train_data['gesture']\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:54:54.605243Z","iopub.execute_input":"2025-06-13T02:54:54.605545Z","iopub.status.idle":"2025-06-13T02:54:57.414808Z","shell.execute_reply.started":"2025-06-13T02:54:54.605527Z","shell.execute_reply":"2025-06-13T02:54:57.414209Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from xgboost import XGBClassifier\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:19:44.232301Z","iopub.execute_input":"2025-06-13T02:19:44.232508Z","iopub.status.idle":"2025-06-13T02:19:44.261981Z","shell.execute_reply.started":"2025-06-13T02:19:44.232492Z","shell.execute_reply":"2025-06-13T02:19:44.261425Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = XGBClassifier(use_label_encoder=False, eval_metric='logloss')\nmodel.fit(X_train, y_train)\nprint(f'Validation Score: {model.score(X_val, y_val)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T02:54:57.415529Z","iopub.execute_input":"2025-06-13T02:54:57.41574Z","iopub.status.idle":"2025-06-13T03:04:34.860502Z","shell.execute_reply.started":"2025-06-13T02:54:57.415724Z","shell.execute_reply":"2025-06-13T03:04:34.859585Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import kaggle_evaluation.cmi_inference_server\n\ndef predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    sequence_pd = sequence.to_pandas()\n\n    sequence_pd = sequence_pd.groupby('sequence_id').apply(lambda x: x.fillna(method='ffill')).reset_index(drop=True)\n    sequence_pd.fillna(method='bfill', inplace=True)\n\n    numerical_cols = [col for col in sequence_pd.columns if col.startswith(('acc_', 'rot_', 'thm_', 'tof_'))]\n    \n    \n    for col in numerical_cols:\n        sequence_pd[col].fillna(sequence_pd[col].mean(), inplace=True)\n\n    \n    \n    sequence_pd[\"acc_magnitude\"] = (sequence_pd['acc_x']**2 + sequence_pd['acc_y']**2 + sequence_pd['acc_z']**2)**0.5\n    sequence_pd[\"rot_magnitude\"] = (sequence_pd['rot_x']**2 + sequence_pd['rot_y']**2 + sequence_pd['rot_z']** 2)**0.5\n    sequence_pd['acc_x_diff'] = sequence_pd.groupby('sequence_id')['acc_x'].diff().fillna(0)\n    sequence_pd['acc_x_mean'] = sequence_pd.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).mean().reset_index(0, drop= True)\n    sequence_pd['acc_x_std'] = sequence_pd.groupby('sequence_id')['acc_x'].rolling(window = 10, min_periods = 1).std().reset_index(0, drop= True)\n\n    \n    \n    for i in range(1, 6):\n        tof_cols = [col for col in sequence_pd.columns if col.startswith(f'tof_{i}_')]\n        sequence_pd[f'tof_{i}_mean'] = sequence_pd[tof_cols].mean(axis = 1)\n        sequence_pd[f'tof_{i}_std'] = sequence_pd[tof_cols].std(axis= 1)\n\n    sequence_pd[numerical_cols] = scaler.transform(sequence_pd[numerical_cols])\n    \n    # subset_test = sequence_pd[['sequence_id', 'sequence_counter', 'acc_x', 'acc_y', 'acc_z']]\n    # features_test = extract_features(\n    #     subset_test,\n    #     column_id='sequence_id',\n    #     column_sort='sequence_counter',\n    #     default_fc_parameters=MinimalFCParameters()\n    # )\n    # features_test = features_test.reset_index().rename(columns={'index': 'sequence_id'})\n    # sequence_pd = sequence_pd.merge(features_test, on='sequence_id', how='left')\n    X_seq = sequence_pd.drop(['row_id', 'sequence_id', 'subject', 'sequence_counter'], axis=1, errors='ignore')\n    print(X_seq.isnull().any(axis=1).sum())\n    \n    \n    X_seq[\"acc_x_std\"].fillna(X_seq[\"acc_x_std\"].mean(), inplace=True)\n    \n    predictions = model.predict(X_seq)\n    gesture = le.inverse_transform([max(set(predictions), key=predictions.tolist().count)])[0]\n    return gesture\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    )\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-13T03:04:34.86184Z","iopub.execute_input":"2025-06-13T03:04:34.862104Z","iopub.status.idle":"2025-06-13T03:04:36.078362Z","shell.execute_reply.started":"2025-06-13T03:04:34.862082Z","shell.execute_reply":"2025-06-13T03:04:36.077591Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}