{"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":"none","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"sourceType":"competition"}],"dockerImageVersionId":31040,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport polars as pl\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.ensemble import RandomForestClassifier\n\n\ndef flatten_list(l):\n    flat_list = []\n    for xs in l:\n        for x in xs:\n            flat_list.append(x)\n    return flat_list\n\ndef prep_data(train_path):\n    df = pl.read_csv(train_path) \n\n    classes = df.select(\"gesture\").unique() \\\n        .with_columns(\n            pl.arange(0, pl.len())\n            .alias(\"label\")\n        )\n    \n    selected_cols = [\n        \"acc_x\", \"acc_y\", \"acc_z\",\n        \"rot_x\", \"rot_y\", \"rot_z\", \"rot_w\"\n    ]\n    \n    data = df \\\n        .fill_null(0) \\\n        .group_by(\n            \"sequence_id\", \"gesture\", \"sequence_type\",\n        ) \\\n        .agg(flatten_list([\n            [\n                pl.col(col).mean().alias(f\"avg_{col}\"),\n                pl.col(col).std().alias(f\"std_{col}\"),\n                pl.col(col).min().alias(f\"min_{col}\"),\n                pl.col(col).max().alias(f\"max_{col}\"),\n            ] for col in selected_cols\n        ])) \\\n        .join(\n            classes,\n            on=\"gesture\"\n        ) \\\n        .drop(\"sequence_id\", \"gesture\", \"sequence_type\")\n    return data, classes\n\ndef split_data(data):\n    X = data.drop(\"label\").to_numpy()\n    y = data.select(\"label\").to_numpy().ravel()\n\n    X_train, X_val, y_train, y_val = train_test_split(\n        X, y, test_size=0.25, \n        random_state=42, \n        shuffle=True, stratify=y)\n    \n    return X_train, X_val, y_train, y_val\n\ndef train(X_train, y_train):\n    clf = RandomForestClassifier(max_depth=8, random_state=0)\n    clf.fit(X_train, y_train)\n    return clf\n\ndef eval(clf, X_val, y_val):\n    pred = clf.predict(X_val)\n    acc = sum(y_val == pred) / len(pred)\n    return acc","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:21:06.736038Z","iopub.execute_input":"2025-06-12T15:21:06.736794Z","iopub.status.idle":"2025-06-12T15:21:06.748484Z","shell.execute_reply.started":"2025-06-12T15:21:06.736762Z","shell.execute_reply":"2025-06-12T15:21:06.747425Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_path = \"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\"\ndata, classes = prep_data(train_path)\nX_train, X_val, y_train, y_val = split_data(data)\nclf = train(X_train, y_train)\nacc = eval(clf, X_val, y_val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:13.126361Z","iopub.execute_input":"2025-06-12T15:20:13.126725Z","iopub.status.idle":"2025-06-12T15:20:24.217730Z","shell.execute_reply.started":"2025-06-12T15:20:13.126692Z","shell.execute_reply":"2025-06-12T15:20:24.216659Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df = pl.read_csv(\"/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:24.218725Z","iopub.execute_input":"2025-06-12T15:20:24.219075Z","iopub.status.idle":"2025-06-12T15:20:24.244728Z","shell.execute_reply.started":"2025-06-12T15:20:24.219043Z","shell.execute_reply":"2025-06-12T15:20:24.243656Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"selected_cols = [\n    \"acc_x\", \"acc_y\", \"acc_z\",\n    \"rot_x\", \"rot_y\", \"rot_z\", \"rot_w\"\n]\n\ntest_data = test_df \\\n    .filter(pl.col(\"sequence_id\") == \"SEQ_000001\") \\\n    .fill_null(0) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:24.247265Z","iopub.execute_input":"2025-06-12T15:20:24.247567Z","iopub.status.idle":"2025-06-12T15:20:24.290827Z","shell.execute_reply.started":"2025-06-12T15:20:24.247543Z","shell.execute_reply":"2025-06-12T15:20:24.289547Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df.filter(pl.col(\"sequence_id\") == \"SEQ_000001\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:24.291983Z","iopub.execute_input":"2025-06-12T15:20:24.292330Z","iopub.status.idle":"2025-06-12T15:20:24.327386Z","shell.execute_reply.started":"2025-06-12T15:20:24.292306Z","shell.execute_reply":"2025-06-12T15:20:24.326230Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    # Replace this function with your inference code.\n    # You can return either a Pandas or Polars dataframe, though Polars is recommended.\n    # Each prediction (except the very first) must be returned within 30 minutes of the batch features being provided.\n\n    test_data = sequence \\\n        .fill_null(0) \\\n        .group_by(\n            \"sequence_id\",\n        ) \\\n        .agg(flatten_list([\n            [\n                pl.col(col).mean().alias(f\"avg_{col}\"),\n                pl.col(col).std().alias(f\"std_{col}\"),\n                pl.col(col).min().alias(f\"min_{col}\"),\n                pl.col(col).max().alias(f\"max_{col}\"),\n            ] for col in selected_cols\n        ])) \\\n        .drop(\"sequence_id\") \\\n        .to_numpy()\n    pred_cls = clf.predict(test_data)[0]\n    gesture = classes.filter(pl.col(\"label\") == pred_cls).select(\"gesture\").item()\n    return gesture","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:24.328345Z","iopub.execute_input":"2025-06-12T15:20:24.328644Z","iopub.status.idle":"2025-06-12T15:20:24.336202Z","shell.execute_reply.started":"2025-06-12T15:20:24.328619Z","shell.execute_reply":"2025-06-12T15:20:24.334880Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"predict(test_data, pl.DataFrame({\"a\": [1]}))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-12T15:20:24.337723Z","iopub.execute_input":"2025-06-12T15:20:24.338066Z","iopub.status.idle":"2025-06-12T15:20:24.389512Z","shell.execute_reply.started":"2025-06-12T15:20:24.338040Z","shell.execute_reply":"2025-06-12T15:20:24.388715Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import kaggle_evaluation.cmi_inference_server\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-12T15:21:10.184746Z","iopub.execute_input":"2025-06-12T15:21:10.185110Z","iopub.status.idle":"2025-06-12T15:21:31.308697Z","shell.execute_reply.started":"2025-06-12T15:21:10.185082Z","shell.execute_reply":"2025-06-12T15:21:31.307670Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}