{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","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":"gpu","dataSources":[{"sourceId":102335,"databundleVersionId":12518947,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":12420527,"sourceType":"datasetVersion","datasetId":7833852}],"dockerImageVersionId":31041,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# CMI Detect Behavior with Sensor Data\n\nThis notebook covers the full workflow for the Kaggle competition: [CMI Detect Behavior with Sensor Data](https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/overview).","metadata":{}},{"cell_type":"markdown","source":"## 1. Load and Inspect Data \n\nLoad train, test, and demographic CSV files. Display basic statistics, shapes, and sample rows to understand the data structure.","metadata":{}},{"cell_type":"code","source":"RANDOM_SEED = 42 \nRANDOM_SEED_TEST = 42\n# why I choose random seed 42?\n# Because it's a common convention in programming to use 42 as a placeholder for a random seed\n# There are not any mathematical significance to this number, but it has become a popular cultural reference in programming communities.","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:00:42.144185Z","iopub.execute_input":"2025-07-09T14:00:42.144480Z","iopub.status.idle":"2025-07-09T14:00:42.148520Z","shell.execute_reply.started":"2025-07-09T14:00:42.144460Z","shell.execute_reply":"2025-07-09T14:00:42.147682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\ntrain = pd.read_csv(r'/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv')\ntest = pd.read_csv(r'/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv')\ntrain_demo = pd.read_csv(r'/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv')\ntest_demo = pd.read_csv(r'/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv')\n\ntrain_features, other_train_information,test_features, other_test_information = None, None, None, None\ntry:\n    train_features = pd.read_csv(r'/kaggle/input/cmi-competition-2/train_features.csv')\n    other_train_information = pd.read_csv(r'/kaggle/input/cmi-competition-2/other_train_information.csv')\n    test_features = pd.read_csv(r'/kaggle/input/cmi-competition-2/test_features.csv')\n    other_test_information = pd.read_csv(r'/kaggle/input/cmi-competition-2/other_test_information.csv')\n    print(\" read successfully\")\nexcept Exception as e:\n    print(f\"Error reading feature files: {e}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:00:42.149923Z","iopub.execute_input":"2025-07-09T14:00:42.150172Z","iopub.status.idle":"2025-07-09T14:01:06.599863Z","shell.execute_reply.started":"2025-07-09T14:00:42.150156Z","shell.execute_reply":"2025-07-09T14:01:06.599064Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Train shape:', train.shape)\nprint('Test shape:', test.shape)\nprint('Train demographics shape:', train_demo.shape)\nprint('Test demographics shape:', test_demo.shape)\nprint('Train features shape:', train_features.shape)    \nprint('Other train information shape:', other_train_information.shape)\nprint('Test features shape:', test_features.shape)  \nprint('Other test information shape:', other_test_information.shape)","metadata":{"_kg_hide-output":false,"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:06.600617Z","iopub.execute_input":"2025-07-09T14:01:06.600901Z","iopub.status.idle":"2025-07-09T14:01:06.606040Z","shell.execute_reply.started":"2025-07-09T14:01:06.600878Z","shell.execute_reply":"2025-07-09T14:01:06.605234Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 2. Preprocess Data\n\n","metadata":{}},{"cell_type":"code","source":"# Find columns in train but not in test\ntrain_cols = set(train.columns)\ntest_cols = set(test.columns)\ncolumns_in_train_only = list(train_cols - test_cols)\nprint(\"\\nColumns present in train but not in test:\")\nprint(columns_in_train_only)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:06.606870Z","iopub.execute_input":"2025-07-09T14:01:06.607454Z","iopub.status.idle":"2025-07-09T14:01:06.625474Z","shell.execute_reply.started":"2025-07-09T14:01:06.607428Z","shell.execute_reply":"2025-07-09T14:01:06.624877Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def number_missing_values(df:pd.DataFrame , name):\n    if df is None:\n        print(f\"{name}: DataFrame is None, skipping missing value check.\")\n        return\n    total_missing = df.isnull().sum().sum()\n\n    if total_missing == 0:\n        print(f\"{name}: No missing values found!\")\n    else:\n        print(f\"{name}: Found {total_missing} missing values!\")\n    \n    return total_missing\n\nnumber_missing_values(train, \"train.csv\")\nnumber_missing_values(test, \"test.csv\")\nnumber_missing_values(train_demo, \"train_demographics.csv\")\nnumber_missing_values(test_demo, \"test_demographics.csv\")\nnumber_missing_values(train_features, \"train_features.csv\")\nnumber_missing_values(other_train_information, \"other_train_information.csv\")    \nnumber_missing_values(test_features, \"test_features.csv\")\nnumber_missing_values(other_test_information, \"other_test_information.csv\")\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:06.627388Z","iopub.execute_input":"2025-07-09T14:01:06.627619Z","iopub.status.idle":"2025-07-09T14:01:07.466742Z","shell.execute_reply.started":"2025-07-09T14:01:06.627606Z","shell.execute_reply":"2025-07-09T14:01:07.466033Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def check_group_less_than_2_elements(df, logger_name):\n    print(logger_name)\n    grouped = df.groupby('sequence_id')\n    print(\"num groups:\", len(grouped))\n\n    flag = True\n    for name, group in grouped:\n        if len(group) < 2:\n            print(f\"Group {name} has less than 2 elements.\")\n            flag = False\n\n    if flag:\n        print(\"All groups have at least 2 elements.\")\n\ncheck_group_less_than_2_elements(train,'train')\ncheck_group_less_than_2_elements(test,'test')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:07.467368Z","iopub.execute_input":"2025-07-09T14:01:07.467585Z","iopub.status.idle":"2025-07-09T14:01:08.340392Z","shell.execute_reply.started":"2025-07-09T14:01:07.467569Z","shell.execute_reply":"2025-07-09T14:01:08.339686Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 4. Feature Engineering\n\nExtract relevant features from raw sensor data (e.g., statistical summaries, FFT, windowed features) to improve model performance.","metadata":{}},{"cell_type":"code","source":"#skip this cell because I have uploaded the results of this cell\nfrom math import inf\nimport numpy as np\nimport pandas as pd\nfrom scipy import stats\n\ndef extract_features(df, df_demo, drop_sequence_id=False, skip_info_list = False):\n    continue_columns = {\n        'sequence_id', 'row_id', 'sequence_type', 'sequence_counter',\n        'subject', 'orientation', 'behavior', 'phase', 'gesture'\n    }\n\n    # Group by sequence_id\n    grouped = df.groupby('sequence_id')\n    feature_list = []\n    info_list = []\n\n    for seq_id, group in grouped:\n        # Initialize feature and info dictionaries\n        features = {'sequence_id': seq_id}\n        info = {}\n\n        # Count total missing values in this sequence\n        missing_count = group.isna().sum().sum()\n        features['number_missing_values'] = missing_count\n        features['subject'] = group['subject'].values[0]\n        # Collect constant info fields\n        if skip_info_list == False:\n            for col in continue_columns:\n                if col in group.columns:\n                    vals = group[col].values\n                    if vals[0] == vals[-1] and (vals == vals[0]).all():\n                        info[col] = vals[0]\n\n        # Numeric feature extraction\n        numeric_cols = [col for col in group.columns if col not in continue_columns]\n        data = group[numeric_cols].values  # (n_rows, n_features)\n\n        means = data.mean(axis=0)\n        stds = data.std(axis=0)\n        mins = data.min(axis=0)\n        maxs = data.max(axis=0)\n        medians = np.median(data, axis=0)\n        no_responses = (data == -1).sum(axis=0)\n        modes = stats.mode(data, axis=0, keepdims=False)[0]\n\n        for i, col in enumerate(numeric_cols):\n            features[f'{col}_mean'] = means[i]\n            features[f'{col}_std'] = stds[i]\n            features[f'{col}_min'] = mins[i]\n            features[f'{col}_max'] = maxs[i]\n            features[f'{col}_median'] = medians[i]\n            features[f'{col}_no_response'] = no_responses[i]\n            features[f'{col}_mode'] = modes[i]\n            if stds[i] != 0:\n                features[f'{col}_skew'] = stats.skew(data[:, i])\n                features[f'{col}_kurtosis'] = stats.kurtosis(data[:, i])\n            else:\n                features[f'{col}_skew'] = -1\n                features[f'{col}_kurtosis'] = -1\n\n        feature_list.append(features)\n        info_list.append(info)\n\n    # Create DataFrames\n    feature_df = pd.DataFrame(feature_list)\n    info_df = pd.DataFrame(info_list)\n\n    # Merge demographic info\n    feature_df = feature_df.merge(df_demo, on='subject', how='inner')\n\n    # Drop columns\n    feature_df.drop(columns=['subject'], inplace=True, errors='ignore')\n    if drop_sequence_id:\n        feature_df.drop(columns=['sequence_id'], inplace=True, errors='ignore')\n\n    # Return feature_df, info_df\n    if skip_info_list:\n        return feature_df,None \n    else:\n        return feature_df, info_df\n    \n\n\n# train_features, other_train_information = extract_features(train,train_demo)\n# test_features, other_test_information = extract_features(test,test_demo)\n\n# display(train_features.head(1))\n# display(test_features.head(1))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:08.341140Z","iopub.execute_input":"2025-07-09T14:01:08.341451Z","iopub.status.idle":"2025-07-09T14:01:08.352034Z","shell.execute_reply.started":"2025-07-09T14:01:08.341431Z","shell.execute_reply":"2025-07-09T14:01:08.351141Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 5. Prepare Data for Modeling\n\nSplit data into training and validation sets. Convert data into appropriate formats for model input.","metadata":{}},{"cell_type":"code","source":"TARGET_GESTURES =  set(train[ train['sequence_type']=='Target' ]['gesture'])\nNON_TARGET_GESTURES = set(train[ train['sequence_type']=='Non-Target' ]['gesture'])\nALL_GESTURES = TARGET_GESTURES.union(NON_TARGET_GESTURES)\nNUM_GESTURES = len(ALL_GESTURES)\nprint(\"Target gestures:\", TARGET_GESTURES)\nprint(\"Non-target gestures:\", NON_TARGET_GESTURES)\nprint(\"Intersection: \", TARGET_GESTURES.intersection(NON_TARGET_GESTURES) )\nprint(\"all_gestures\", ALL_GESTURES)\n\nTARGET_GESTURES = list(TARGET_GESTURES)\nNON_TARGET_GESTURES = list(NON_TARGET_GESTURES)\nALL_GESTURES = list(ALL_GESTURES)\n\nGESTURE_TO_IDX = {gesture: i for i, gesture in enumerate(ALL_GESTURES)}\nIDX_TO_GESTURE = {i: gesture for i, gesture in enumerate(ALL_GESTURES)} \nprint(\"GESTURE_TO_IDX:\", GESTURE_TO_IDX)\nprint(\"IDX_TO_GESTURE:\", IDX_TO_GESTURE)\n\nMAX_INPUT_FEATURES = train_features.drop(columns=['sequence_id']).shape[1]\nprint(\"MAX_INPUT_FEATURES:\", MAX_INPUT_FEATURES)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:08.352692Z","iopub.execute_input":"2025-07-09T14:01:08.352891Z","iopub.status.idle":"2025-07-09T14:01:09.185409Z","shell.execute_reply.started":"2025-07-09T14:01:08.352875Z","shell.execute_reply":"2025-07-09T14:01:09.184690Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n\nX = train_features.drop(columns=['sequence_id'])\ny = other_train_information['gesture']\ny = y.map(GESTURE_TO_IDX) \n\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y, test_size=0.1, random_state=RANDOM_SEED_TEST, stratify=y\n)\nprint(\"Shape X_train:\", X_train.shape)\nprint(\"Shape X_val:\", X_val.shape)\nprint(\"Shape y_train:\", y_train.shape)\nprint(\"Shape y_val:\", y_val.shape)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:09.186171Z","iopub.execute_input":"2025-07-09T14:01:09.186342Z","iopub.status.idle":"2025-07-09T14:01:09.342491Z","shell.execute_reply.started":"2025-07-09T14:01:09.186328Z","shell.execute_reply":"2025-07-09T14:01:09.341778Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 6. Define F1 score\n\nDefine and train a simple neural network model (e.g., 1D CNN) or a traditional ML model (e.g., LightGBM). Implement cross-validation.","metadata":{}},{"cell_type":"code","source":"from sklearn.metrics import f1_score\n\ndef calculate_hierarchical_f1(y_true, y_pred):\n    \"\"\"\n    Calculate hierarchical F1 score từ class indices.\n    \n    Args:\n        y_true: numpy array of true class indices\n        y_pred: numpy array of predicted class indices\n        \n    Returns:\n        float: Hierarchical F1 score (0.5 * binary_f1 + 0.5 * macro_f1)\n    \"\"\"\n    # Convert indices back to gesture names\n    y_true_gestures = [IDX_TO_GESTURE[int(idx)] for idx in y_true]\n    y_pred_gestures = [IDX_TO_GESTURE[int(idx)] for idx in y_pred]\n    \n    # Binary F1 (Target vs Non-Target)\n    y_true_bin = [gesture in TARGET_GESTURES for gesture in y_true_gestures]\n    y_pred_bin = [gesture in TARGET_GESTURES for gesture in y_pred_gestures]\n    \n    f1_binary = f1_score(y_true_bin, y_pred_bin, pos_label=True, zero_division=0, average='binary')\n    \n    # Macro F1 (collapse non-targets to single class)\n    y_true_mc = [gesture if gesture in TARGET_GESTURES else 'non_target' for gesture in y_true_gestures]\n    y_pred_mc = [gesture if gesture in TARGET_GESTURES else 'non_target' for gesture in y_pred_gestures]\n    \n    f1_macro = f1_score(y_true_mc, y_pred_mc, average='macro', zero_division=0)\n    \n    return 0.5 * f1_binary + 0.5 * f1_macro\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:09.343351Z","iopub.execute_input":"2025-07-09T14:01:09.343654Z","iopub.status.idle":"2025-07-09T14:01:09.349454Z","shell.execute_reply.started":"2025-07-09T14:01:09.343606Z","shell.execute_reply":"2025-07-09T14:01:09.348759Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 7. Build and Train Model\n\nDefine and train a simple neural network model (e.g., 1D CNN) or a traditional ML model (e.g., LightGBM). Implement cross-validation.","metadata":{}},{"cell_type":"code","source":"import xgboost as xgb\n\nXGBOOST_MAX_NUM_TREES = 2000\nXGBOOST_EARLY_STOPPING_ROUNDS = 100 \nXGBOOST_VERBOSE_EVAL = 50\n\ndef xgb_hierarchical_f1_eval(preds, dtrain):\n    labels = dtrain.get_label()\n    preds_class = np.argmax(preds.reshape(-1, len(ALL_GESTURES)), axis=1)\n    score = calculate_hierarchical_f1(labels, preds_class)\n    return 'hierarchical_f1', score\n\ndef xgboost_show_importance(bst, importance_type='gain', num_features_show=50):\n\n    assert(num_features_show > 0 and num_features_show <= MAX_INPUT_FEATURES)\n    import matplotlib.pyplot as plt\n\n    xgb.plot_importance(bst, importance_type=importance_type, max_num_features=num_features_show)\n    plt.show()\n    importance_dict = bst.get_score( importance_type=importance_type )  \n    importance_list = [ (key,importance_dict[key]) for key in importance_dict]\n    importance_list_sorted = sorted(importance_list, key=lambda x: x[1], reverse=True)\n    for feature, importance in importance_list_sorted[:num_features_show]:\n        print(f\"{feature}: {importance:.4f}\")\n\n    print( \" num features:\", len(importance_list_sorted) ) \n    return importance_list_sorted\n\ndef xgboost_get_top_k_important_features(bst, k=1000, importance_type='gain'):\n    assert(k > 0 and k <= MAX_INPUT_FEATURES)\n    important_dict = bst.get_score(importance_type=importance_type)\n    topk = [feat for feat, _ in sorted(important_dict.items(), key=lambda x: x[1], reverse=True)[:k]]\n    return topk\n\ndef xgboost_train( X_train, y_train, X_val, y_val , print_best = True, print_warning = True):\n    import warnings\n    if not print_warning:\n        warnings.filterwarnings(\"ignore\", category=UserWarning)\n\n    params = {\n    'objective': 'multi:softprob',\n    'num_class': NUM_GESTURES,\n    'eval_metric': 'mlogloss',\n    'tree_method': 'gpu_hist',\n    'predictor': 'gpu_predictor',\n    'seed': RANDOM_SEED,\n}\n\n    dtrain = xgb.DMatrix(X_train, label=y_train)\n    dval = xgb.DMatrix(X_val, label=y_val)\n    watchlist = [(dtrain, 'train'), (dval, 'eval')]\n\n    bst = xgb.train(\n        params,\n        dtrain,\n        num_boost_round=XGBOOST_MAX_NUM_TREES,\n        evals=watchlist,\n        feval=xgb_hierarchical_f1_eval,\n        maximize=True,\n        early_stopping_rounds=XGBOOST_EARLY_STOPPING_ROUNDS,\n        verbose_eval=XGBOOST_VERBOSE_EVAL,\n    )\n    if print_best:\n        print(\"Best iteration:\", bst.best_iteration, \" Best score:\", bst.best_score)\n    return bst  \n\n\ndef xgboost_retrain_with_top_k_features(bst, X_train, y_train, X_val, y_val, k=1000, importance_type='gain', print_best=False): \n    assert(k > 0 and k <= MAX_INPUT_FEATURES)\n\n    topk = xgboost_get_top_k_important_features(bst, k=k, importance_type=importance_type)\n    X_train_topk = X_train[topk]\n    X_val_topk   = X_val[topk]\n    return xgboost_train(X_train_topk,y_train,X_val_topk,y_val,print_best,False)\n\n\ndef xgboost_predict(bst, sequence, demographics, type_return) -> str|int|list:\n    \"\"\"\n    type_return = 0 -> return str.  \n    type_return = 1 -> return int.  \n    type_return = 2 -> return list of probality.\n    \"\"\"\n    try:\n        sequence = sequence.to_pandas()\n        demographics = demographics.to_pandas()\n    except Exception as e:\n        print(\"Lỗi khi chuyển đổi sang pandas:\", e)\n\n    input_features, other_input_information = extract_features(sequence,demographics)\n    expected_cols = bst.feature_names\n    input_features = input_features[expected_cols]\n    input_features = xgb.DMatrix(input_features)\n    best_iter = bst.best_iteration\n    val = bst.predict(input_features,iteration_range=(0, best_iter))\n    \n    if type_return == 0 :\n        pred_indices = np.argmax(val, axis=1)\n        pred_gestures = [IDX_TO_GESTURE[idx] for idx in pred_indices]\n        return str(pred_gestures[0]) \n    elif type_return == 1: \n        pred_indices = np.argmax(val, axis=1)\n        return int(pred_indices[0]) \n    else :\n        return list(val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:09.350280Z","iopub.execute_input":"2025-07-09T14:01:09.350493Z","iopub.status.idle":"2025-07-09T14:01:09.376501Z","shell.execute_reply.started":"2025-07-09T14:01:09.350471Z","shell.execute_reply":"2025-07-09T14:01:09.375833Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# retrain with all data \nprint(\" start training\")\nxgboost_model =  xgboost_train(X_train, y_train, X_val, y_val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:01:09.377153Z","iopub.execute_input":"2025-07-09T14:01:09.377380Z","iopub.status.idle":"2025-07-09T14:02:47.937528Z","shell.execute_reply.started":"2025-07-09T14:01:09.377366Z","shell.execute_reply":"2025-07-09T14:02:47.936821Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"best_xgboost_model = xgboost_model\nbest_iteration = xgboost_model.best_iteration \nbest_score = xgboost_model.best_score \nbest_topK_features = MAX_INPUT_FEATURES\n\n# for num_features in range(100,2000+100,100):\nfor num_features in [500,1400,1500]:\n    print(f\"Retraining with top {num_features} features...\", end=\"\")\n    xgboost_mode_topK_features=  xgboost_retrain_with_top_k_features(xgboost_model, X_train, y_train, X_val, y_val, k=num_features, importance_type='gain')\n    iteration = xgboost_mode_topK_features.best_iteration\n    score = xgboost_mode_topK_features.best_score \n    print(\" iteration = \", iteration,\" score = \",score)\n    if score > best_score:\n        best_xgboost_model = xgboost_mode_topK_features\n        best_iteration = iteration\n        best_score = score\n        best_topK_features = num_features\n        print(f\"New best model found with {num_features} features: Best iteration: {iteration}, Best score: {score:.4f}\") \n\nprint(f\"Best model with {best_topK_features} features: Best iteration: {best_iteration}, Best score: {best_score:.4f}\")\n\nbest_xgboost_model.save_model(\"best_xgboost_model.json\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:02:47.939132Z","iopub.execute_input":"2025-07-09T14:02:47.939315Z","iopub.status.idle":"2025-07-09T14:05:01.553143Z","shell.execute_reply.started":"2025-07-09T14:02:47.939301Z","shell.execute_reply":"2025-07-09T14:05:01.552353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"final_model=  xgboost_retrain_with_top_k_features(xgboost_model, X, y, X_val, y_val, k=best_topK_features, importance_type='gain')\nprint(\" FINAL MODEL = score\", final_model.best_score)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:05:01.555968Z","iopub.execute_input":"2025-07-09T14:05:01.556178Z","iopub.status.idle":"2025-07-09T14:05:30.596568Z","shell.execute_reply.started":"2025-07-09T14:05:01.556163Z","shell.execute_reply":"2025-07-09T14:05:30.595856Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## 8. Submit\n","metadata":{}},{"cell_type":"code","source":"import polars as pl\nimport os\n\ndef predict(sequence: pl.DataFrame, demographics: pl.DataFrame) -> str:\n    return xgboost_predict(final_model,sequence,demographics,0) \n#predict( test, test_demo)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-09T14:12:58.340814Z","iopub.execute_input":"2025-07-09T14:12:58.341522Z","iopub.status.idle":"2025-07-09T14:12:58.345409Z","shell.execute_reply.started":"2025-07-09T14:12:58.341497Z","shell.execute_reply":"2025-07-09T14:12:58.344610Z"}},"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-07-09T14:12:59.718669Z","iopub.execute_input":"2025-07-09T14:12:59.719406Z","iopub.status.idle":"2025-07-09T14:13:01.474584Z","shell.execute_reply.started":"2025-07-09T14:12:59.719378Z","shell.execute_reply":"2025-07-09T14:13:01.473824Z"}},"outputs":[],"execution_count":null}]}