{"cells": [{"cell_type": "markdown", "metadata": {}, "source": "# CMI V12 Simple Inference - Real Data Model Only\n\n\u30b7\u30f3\u30d7\u30eb\u306aV12\u30e2\u30c7\u30eb\u5358\u72ec\u306e\u63a8\u8ad6"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "import os\nimport sys\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nimport pickle\nimport warnings\nwarnings.filterwarnings('ignore')\n\n# \u74b0\u5883\u5224\u5b9a\nIS_KAGGLE = os.path.exists('/kaggle/input')\nprint(f\"Running on Kaggle: {IS_KAGGLE}\")\n\nif IS_KAGGLE:\n    V12_MODEL_PATH = '/kaggle/input/cmi-v12-real-data-models'\nelse:\n    V12_MODEL_PATH = 'models_v12'"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# \u30e2\u30c7\u30eb\u3092\u30ed\u30fc\u30c9\nimport lightgbm as lgb\nimport xgboost as xgb\nfrom catboost import CatBoostClassifier\nfrom sklearn.preprocessing import StandardScaler\n\nprint(\"Loading V12 models...\")\nlgb_model = lgb.Booster(model_file=os.path.join(V12_MODEL_PATH, 'lgb_model_v12_final.txt'))\nxgb_model = xgb.Booster()\nxgb_model.load_model(os.path.join(V12_MODEL_PATH, 'xgb_model_v12_final.json'))\ncat_model = CatBoostClassifier()\ncat_model.load_model(os.path.join(V12_MODEL_PATH, 'cat_model_v12_final.cbm'))\n\n# \u30e1\u30bf\u30c7\u30fc\u30bf\nwith open(os.path.join(V12_MODEL_PATH, 'scaler_v12.pkl'), 'rb') as f:\n    scaler = pickle.load(f)\nwith open(os.path.join(V12_MODEL_PATH, 'feature_names_v12.pkl'), 'rb') as f:\n    feature_names = pickle.load(f)\nwith open(os.path.join(V12_MODEL_PATH, 'gesture_mapping_v12.pkl'), 'rb') as f:\n    gesture_mapping = pickle.load(f)\n\nprint(f\"Models loaded. Features: {len(feature_names)}\")"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "def extract_features(df):\n    \"\"\"\u7279\u5fb4\u91cf\u62bd\u51fa\"\"\"\n    features = {}\n    \n    # \u57fa\u672c\u7d71\u8a08\u91cf\n    for col in df.columns:\n        if col not in ['timestamp', 'sequence_id']:\n            features[f'{col}_mean'] = np.mean(df[col])\n            features[f'{col}_std'] = np.std(df[col])\n            features[f'{col}_min'] = np.min(df[col])\n            features[f'{col}_max'] = np.max(df[col])\n            features[f'{col}_median'] = np.median(df[col])\n            features[f'{col}_q25'] = np.percentile(df[col], 25)\n            features[f'{col}_q75'] = np.percentile(df[col], 75)\n            features[f'{col}_iqr'] = features[f'{col}_q75'] - features[f'{col}_q25']\n            features[f'{col}_skew'] = df[col].skew() if len(df[col]) > 2 else 0\n            features[f'{col}_kurtosis'] = df[col].kurtosis() if len(df[col]) > 3 else 0\n    \n    # \u91cd\u529b\u9664\u53bb\u7dda\u5f62\u52a0\u901f\u5ea6\n    if 'acc_x' in df.columns:\n        gravity_x = np.mean(df['acc_x'])\n        gravity_y = np.mean(df['acc_y'])\n        gravity_z = np.mean(df['acc_z'])\n        \n        linear_acc_x = df['acc_x'] - gravity_x\n        linear_acc_y = df['acc_y'] - gravity_y\n        linear_acc_z = df['acc_z'] - gravity_z\n        \n        features['linear_acc_x_mean'] = np.mean(linear_acc_x)\n        features['linear_acc_y_mean'] = np.mean(linear_acc_y)\n        features['linear_acc_z_mean'] = np.mean(linear_acc_z)\n        features['linear_acc_magnitude'] = np.mean(np.sqrt(linear_acc_x**2 + linear_acc_y**2 + linear_acc_z**2))\n    \n    # \u30af\u30a9\u30fc\u30bf\u30cb\u30aa\u30f3\u304b\u3089\u30aa\u30a4\u30e9\u30fc\u89d2\n    if all(col in df.columns for col in ['quat_w', 'quat_x', 'quat_y', 'quat_z']):\n        qw = df['quat_w'].values\n        qx = df['quat_x'].values\n        qy = df['quat_y'].values\n        qz = df['quat_z'].values\n        \n        roll = np.arctan2(2*(qw*qx + qy*qz), 1 - 2*(qx**2 + qy**2))\n        pitch = np.arcsin(np.clip(2*(qw*qy - qz*qx), -1, 1))\n        yaw = np.arctan2(2*(qw*qz + qx*qy), 1 - 2*(qy**2 + qz**2))\n        \n        features['euler_roll_mean'] = np.mean(roll)\n        features['euler_pitch_mean'] = np.mean(pitch)\n        features['euler_yaw_mean'] = np.mean(yaw)\n        features['euler_roll_std'] = np.std(roll)\n        features['euler_pitch_std'] = np.std(pitch)\n        features['euler_yaw_std'] = np.std(yaw)\n        \n        # \u89d2\u901f\u5ea6\n        if len(df) > 1 and 'timestamp' in df.columns:\n            dt = np.diff(df['timestamp'].values) / 1000.0\n            dt[dt == 0] = 1e-6  # \u30bc\u30ed\u9664\u7b97\u3092\u9632\u3050\n            dqw = np.diff(qw) / dt\n            dqx = np.diff(qx) / dt\n            dqy = np.diff(qy) / dt\n            dqz = np.diff(qz) / dt\n            \n            features['angular_velocity_mean'] = np.mean(np.sqrt(dqx**2 + dqy**2 + dqz**2))\n            features['angular_velocity_std'] = np.std(np.sqrt(dqx**2 + dqy**2 + dqz**2))\n        else:\n            features['angular_velocity_mean'] = 0\n            features['angular_velocity_std'] = 0\n    \n    # \u30b8\u30e3\u30fc\u30af\n    if 'acc_x' in df.columns and len(df) > 1 and 'timestamp' in df.columns:\n        dt = np.diff(df['timestamp'].values) / 1000.0\n        dt[dt == 0] = 1e-6\n        jerk_x = np.diff(df['acc_x']) / dt\n        jerk_y = np.diff(df['acc_y']) / dt\n        jerk_z = np.diff(df['acc_z']) / dt\n        \n        features['jerk_x_mean'] = np.mean(jerk_x)\n        features['jerk_y_mean'] = np.mean(jerk_y)\n        features['jerk_z_mean'] = np.mean(jerk_z)\n        features['jerk_magnitude'] = np.mean(np.sqrt(jerk_x**2 + jerk_y**2 + jerk_z**2))\n    else:\n        features['jerk_x_mean'] = 0\n        features['jerk_y_mean'] = 0\n        features['jerk_z_mean'] = 0\n        features['jerk_magnitude'] = 0\n    \n    # ToF\u30bb\u30f3\u30b5\u30fc\n    tof_cols = [col for col in df.columns if col.startswith('tof_')]\n    if tof_cols:\n        tof_values = df[tof_cols].values.flatten()\n        features['tof_global_mean'] = np.mean(tof_values)\n        features['tof_global_std'] = np.std(tof_values)\n        features['tof_global_min'] = np.min(tof_values)\n        features['tof_global_max'] = np.max(tof_values)\n    \n    # \u30b7\u30fc\u30b1\u30f3\u30b9\u9577\n    features['sequence_length'] = len(df)\n    if 'timestamp' in df.columns:\n        features['duration_ms'] = df['timestamp'].max() - df['timestamp'].min()\n    else:\n        features['duration_ms'] = 0\n    \n    return features"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": "# CMI\u63a8\u8ad6\u30b5\u30fc\u30d0\u30fc\nif IS_KAGGLE:\n    from kaggle_evaluation.cmi_inference_server import CMIInferenceServer\n    \n    def predict(test_data: pl.DataFrame, metadata: pl.DataFrame) -> pl.DataFrame:\n        \"\"\"V12\u30e2\u30c7\u30eb\u306b\u3088\u308b\u4e88\u6e2c\"\"\"\n        print(f\"Starting prediction for {len(metadata)} sequences\")\n        \n        # pandas\u5909\u63db\n        test_df = test_data.to_pandas()\n        metadata_df = metadata.to_pandas()\n        \n        predictions = []\n        \n        # \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u540d\u30ea\u30b9\u30c8\n        gesture_names = [\n            'Above ear - pull hair', 'Cheek - pinch skin', 'Drink from bottle/cup',\n            'Eyebrow - pull hair', 'Eyelash - pull hair', 'Feel around in tray and pull out an object',\n            'Forehead - pull hairline', 'Forehead - scratch', 'Glasses on/off',\n            'Neck - pinch skin', 'Neck - scratch', 'Pinch knee/leg skin',\n            'Pull air toward your face', 'Scratch knee/leg skin', 'Text on phone',\n            'Wave hello', 'Write name in air', 'Write name on leg'\n        ]\n        \n        for idx, row in metadata_df.iterrows():\n            seq_id = row['sequence_id']\n            seq_data = test_df[test_df['sequence_id'] == seq_id].copy()\n            \n            if len(seq_data) == 0:\n                predictions.append('Wave hello')\n                continue\n            \n            # \u7279\u5fb4\u91cf\u62bd\u51fa\n            features = extract_features(seq_data)\n            X = pd.DataFrame([features])\n            \n            # \u7279\u5fb4\u91cf\u3092\u6574\u5f62\n            X_aligned = X[feature_names]\n            X_scaled = scaler.transform(X_aligned)\n            \n            # \u4e88\u6e2c\uff08\u30a2\u30f3\u30b5\u30f3\u30d6\u30eb\uff09\n            pred_lgb = lgb_model.predict(X_scaled, num_iteration=lgb_model.best_iteration)[0]\n            \n            dmatrix = xgb.DMatrix(X_scaled, feature_names=feature_names)\n            pred_xgb = xgb_model.predict(dmatrix)[0]\n            \n            pred_cat = cat_model.predict_proba(X_scaled)[0]\n            \n            # \u30a2\u30f3\u30b5\u30f3\u30d6\u30eb\uff08LightGBM 40% + XGBoost 30% + CatBoost 30%\uff09\n            ensemble_probs = 0.4 * pred_lgb + 0.3 * pred_xgb + 0.3 * pred_cat\n            \n            # \u6700\u3082\u78ba\u7387\u306e\u9ad8\u3044\u30af\u30e9\u30b9\n            pred_class = np.argmax(ensemble_probs)\n            \n            # \u30b8\u30a7\u30b9\u30c1\u30e3\u30fc\u540d\n            gesture_name = gesture_names[pred_class] if pred_class < 18 else 'Wave hello'\n            predictions.append(gesture_name)\n        \n        # \u7d50\u679c\u3092\u8fd4\u3059\n        result = pl.DataFrame({\n            'sequence_id': metadata['sequence_id'],\n            'gesture': predictions\n        })\n        \n        print(f\"Predictions completed. Shape: {result.shape}\")\n        return result\n    \n    # \u30b5\u30fc\u30d0\u30fc\u8d77\u52d5\n    print(\"Starting CMI Inference Server...\")\n    inference_server = CMIInferenceServer(predict)\n    inference_server.serve()\n    print(\"Inference completed\")\n    \nelse:\n    print(\"Local test mode - creating dummy submission\")\n    \n    gesture_names = [\n        'Above ear - pull hair', 'Cheek - pinch skin', 'Drink from bottle/cup',\n        'Eyebrow - pull hair', 'Eyelash - pull hair', 'Feel around in tray and pull out an object',\n        'Forehead - pull hairline', 'Forehead - scratch', 'Glasses on/off',\n        'Neck - pinch skin', 'Neck - scratch', 'Pinch knee/leg skin',\n        'Pull air toward your face', 'Scratch knee/leg skin', 'Text on phone',\n        'Wave hello', 'Write name in air', 'Write name on leg'\n    ]\n    \n    submission = pl.DataFrame({\n        'sequence_id': list(range(1, 101)),\n        'gesture': [gesture_names[i % 18] for i in range(100)]\n    })\n    submission.write_parquet('submission.parquet')\n    print(f\"Dummy submission created: {submission.shape}\")"}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"codemirror_mode": {"name": "ipython", "version": 3}, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.12"}}, "nbformat": 4, "nbformat_minor": 4}