{"cells": [{"cell_type": "markdown", "metadata": {}, "source": "# CMI V11 Inference - Pre-trained Model with Synthetic Data"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "import numpy as np\nimport pandas as pd\nimport pickle\nimport json\nimport warnings\nfrom pathlib import Path\nimport lightgbm as lgb\nimport xgboost as xgb\nfrom catboost import CatBoostClassifier\nfrom sklearn.preprocessing import StandardScaler\nfrom kaggle_evaluation.cmi_inference_server import CMIInferenceServer\n\nwarnings.filterwarnings('ignore')\nprint('Libraries loaded')"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# Load pre-trained models from Dataset\nMODEL_DIR = Path('/kaggle/input/cmi-v11-models')\n\n# Load models\nprint('Loading models...')\nlgb_model = lgb.Booster(model_file=str(MODEL_DIR / 'lgb_model_v11.txt'))\nxgb_model = xgb.Booster()\nxgb_model.load_model(str(MODEL_DIR / 'xgb_model_v11.json'))\ncat_model = CatBoostClassifier()\ncat_model.load_model(str(MODEL_DIR / 'cat_model_v11.cbm'))\n\n# Load scaler and feature names\nwith open(MODEL_DIR / 'scaler_v11.pkl', 'rb') as f:\n    scaler = pickle.load(f)\n\nwith open(MODEL_DIR / 'feature_names_v11.pkl', 'rb') as f:\n    feature_names = pickle.load(f)\n\n# Load model info\nwith open(MODEL_DIR / 'model_info_v11.json', 'r') as f:\n    model_info = json.load(f)\n\nprint(f'Models loaded successfully')\nprint(f'Model version: {model_info[\"version\"]}')\nprint(f'Validation accuracy: {model_info[\"validation_accuracy\"][\"ensemble\"]:.2%}')"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# Gesture labels mapping\ngesture_labels = [\n    'Above ear - pull hair',\n    'Cheek - pinch skin',\n    'Drink from bottle/cup',\n    'Eyelash - pull hair',\n    'Eyebrow - pull hair',\n    'Feel around in tray and pull out an object',\n    'Forehead - pull hairline',\n    'Forehead - scratch',\n    'Glasses on/off',\n    'Neck - pinch skin',\n    'Neck - scratch',\n    'Pinch knee/leg skin',\n    'Pull air toward your face',\n    'Scratch knee/leg skin',\n    'Text on phone',\n    'Wave hello',\n    'Write name in air',\n    'Write name on leg'\n]\n\nprint(f'Gesture labels: {len(gesture_labels)} classes')"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "def extract_features(sequence_df, demographics_df):\n    \"\"\"Extract features from a single sequence\"\"\"\n    features = {}\n    \n    # Metadata features\n    features['subject_id'] = hash(demographics_df['subject'].iloc[0]) % 1000\n    features['seq_length'] = len(sequence_df)\n    \n    # Accelerometer features\n    for axis in ['x', 'y', 'z']:\n        col = f'acc_{axis}'\n        if col in sequence_df.columns:\n            values = sequence_df[col].values\n            features[f'acc_{axis}_mean'] = np.mean(values)\n            features[f'acc_{axis}_std'] = np.std(values)\n            features[f'acc_{axis}_max'] = np.max(values)\n            features[f'acc_{axis}_min'] = np.min(values)\n            features[f'acc_{axis}_range'] = np.ptp(values)\n            features[f'acc_{axis}_skew'] = pd.Series(values).skew()\n            features[f'acc_{axis}_kurt'] = pd.Series(values).kurt()\n            \n            # FFT features\n            fft_vals = np.abs(np.fft.fft(values))[:len(values)//2]\n            features[f'acc_{axis}_fft_max'] = np.max(fft_vals) if len(fft_vals) > 0 else 0\n            features[f'acc_{axis}_fft_mean'] = np.mean(fft_vals) if len(fft_vals) > 0 else 0\n            \n            # Jerk\n            if len(values) > 1:\n                jerk = np.diff(values)\n                features[f'acc_{axis}_jerk_mean'] = np.mean(np.abs(jerk))\n                features[f'acc_{axis}_jerk_std'] = np.std(jerk)\n            else:\n                features[f'acc_{axis}_jerk_mean'] = 0\n                features[f'acc_{axis}_jerk_std'] = 0\n    \n    # Acceleration magnitude\n    if all(f'acc_{axis}' in sequence_df.columns for axis in ['x', 'y', 'z']):\n        acc_magnitude = np.sqrt(sequence_df['acc_x']**2 + sequence_df['acc_y']**2 + sequence_df['acc_z']**2)\n        features['acc_magnitude_mean'] = np.mean(acc_magnitude)\n        features['acc_magnitude_std'] = np.std(acc_magnitude)\n        features['acc_magnitude_max'] = np.max(acc_magnitude)\n    \n    # Gyroscope features\n    for axis in ['x', 'y', 'z']:\n        col = f'gyr_{axis}'\n        if col in sequence_df.columns:\n            values = sequence_df[col].values\n            features[f'gyr_{axis}_mean'] = np.mean(values)\n            features[f'gyr_{axis}_std'] = np.std(values)\n            features[f'gyr_{axis}_max'] = np.max(values)\n            features[f'gyr_{axis}_energy'] = np.sum(values**2)\n    \n    # Angular velocity magnitude\n    if all(f'gyr_{axis}' in sequence_df.columns for axis in ['x', 'y', 'z']):\n        gyr_magnitude = np.sqrt(sequence_df['gyr_x']**2 + sequence_df['gyr_y']**2 + sequence_df['gyr_z']**2)\n        features['gyr_magnitude_mean'] = np.mean(gyr_magnitude)\n        features['gyr_magnitude_std'] = np.std(gyr_magnitude)\n    \n    # Quaternion features\n    for comp in ['w', 'x', 'y', 'z']:\n        col = f'quat_{comp}'\n        if col in sequence_df.columns:\n            values = sequence_df[col].values\n            features[f'quat_{comp}_mean'] = np.mean(values)\n            features[f'quat_{comp}_std'] = np.std(values)\n            features[f'quat_{comp}_change'] = values[-1] - values[0] if len(values) > 0 else 0\n    \n    # ToF sensor features\n    tof_features = []\n    for i in range(8):\n        col = f'tof_{i}'\n        if col in sequence_df.columns:\n            values = sequence_df[col].values\n            tof_features.extend([\n                np.mean(values),\n                np.std(values),\n                np.median(values)\n            ])\n    \n    # ToF principal components (first 5)\n    if tof_features:\n        for i in range(min(5, len(tof_features))):\n            features[f'tof_pc_{i}'] = tof_features[i]\n    \n    # Ensure all features are present\n    for fname in feature_names:\n        if fname not in features:\n            features[fname] = 0\n    \n    return features"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "def predict(sequence, demographics):\n    \"\"\"CMI inference function\"\"\"\n    \n    # Extract features\n    features = extract_features(sequence, demographics)\n    \n    # Create feature vector in correct order\n    X = np.array([[features[fname] for fname in feature_names]])\n    \n    # Scale features\n    X_scaled = scaler.transform(X)\n    \n    # Get predictions from each model\n    lgb_proba = lgb_model.predict(X_scaled)\n    xgb_proba = xgb_model.predict(xgb.DMatrix(X_scaled))\n    cat_proba = cat_model.predict_proba(X_scaled)\n    \n    # Ensure shape is (1, n_classes)\n    if lgb_proba.ndim == 1:\n        lgb_proba = lgb_proba.reshape(1, -1)\n    if xgb_proba.ndim == 1:\n        xgb_proba = xgb_proba.reshape(1, -1)\n    if cat_proba.ndim == 1:\n        cat_proba = cat_proba.reshape(1, -1)\n    \n    # Ensemble predictions\n    lgb_weight = model_info['ensemble_weights']['lgb']\n    xgb_weight = model_info['ensemble_weights']['xgb']\n    cat_weight = model_info['ensemble_weights']['catboost']\n    \n    ensemble_proba = lgb_weight * lgb_proba + xgb_weight * xgb_proba + cat_weight * cat_proba\n    \n    # Get predicted class\n    predicted_class = np.argmax(ensemble_proba[0])\n    \n    return gesture_labels[predicted_class]"}, {"cell_type": "code", "execution_count": null, "metadata": {}, "source": "# Initialize and run CMI Inference Server\nprint('=' * 50)\nprint('Starting CMI Inference Server with V11 Model')\nprint('=' * 50)\nprint(f'\\nModel Configuration:')\nprint(f'  - Real data: 50%')\nprint(f'  - Synthetic data: 50%')\nprint(f'  - Validation accuracy: {model_info[\"validation_accuracy\"][\"ensemble\"]:.2%}')\nprint(f'\\nStarting server...')\n\nserver = CMIInferenceServer(predict)\nserver.serve()\n\nprint('\\nInference complete')"}], "metadata": {"kernelspec": {"display_name": "Python 3", "language": "python", "name": "python3"}, "language_info": {"name": "python", "version": "3.10.0"}}, "nbformat": 4, "nbformat_minor": 4}