{"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":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:28.916311Z","iopub.execute_input":"2025-06-18T21:24:28.916539Z","iopub.status.idle":"2025-06-18T21:24:31.231037Z","shell.execute_reply.started":"2025-06-18T21:24:28.916518Z","shell.execute_reply":"2025-06-18T21:24:31.230241Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.metrics import f1_score, make_scorer\nfrom sklearn.preprocessing import StandardScaler\nfrom scipy.signal import butter, lfilter\nfrom scipy.stats import skew, kurtosis\nimport json # To handle potential JSON-like sensor data if it's embedded","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:31.232115Z","iopub.execute_input":"2025-06-18T21:24:31.232697Z","iopub.status.idle":"2025-06-18T21:24:33.512337Z","shell.execute_reply.started":"2025-06-18T21:24:31.232666Z","shell.execute_reply":"2025-06-18T21:24:33.511336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 1. Data Loading (Conceptual Placeholder) ---\n# This section provides a conceptual outline for loading data.\n# In a real competition, you would have specific file paths and formats\n# (e.g., CSV, parquet, HDF5, JSON).\n\ndef load_sensor_data(data_path, sensor_type='all'):\n    \"\"\"\n    Conceptual function to load sensor data.\n    In a real scenario, this would parse actual files (e.g., CSVs per sequence_id).\n    \n    Args:\n        data_path (str): Path to the directory containing sensor data files.\n        sensor_type (str): 'all' to load all sensors, 'imu' to load only IMU data.\n                           This simulates the competition's evaluation setup.\n    \n    Returns:\n        dict: A dictionary where keys are sequence_ids and values are pandas DataFrames\n              containing sensor readings over time for that sequence.\n        \n        Example structure (for a single sequence_id):\n        {\n            'sequence_id_1': pd.DataFrame({\n                'time': [...],\n                'acc_x': [...], 'acc_y': [...], 'acc_z': [...], # Accelerometer\n                'gyro_x': [...], 'gyro_y': [...], 'gyro_z': [...], # Gyroscope\n                'mag_x': [...], 'mag_y': [...], 'mag_z': [...], # Magnetometer (if available)\n                'therm_0': [...], 'therm_1': [...], ..., 'therm_4': [...], # Thermopiles\n                'tof_0': [...], 'tof_1': [...], ..., 'tof_4': [...] # Time-of-flight\n            }),\n            'sequence_id_2': ...\n        }\n    \"\"\"\n    print(f\"Conceptual: Loading sensor data from {data_path} with sensor type '{sensor_type}'...\")\n    \n    # --- Mock Data Generation ---\n    # Since we don't have actual files, we generate some mock data to make\n    # the subsequent feature engineering and model training conceptually viable.\n    mock_data = {}\n    num_sequences = 100\n    sequence_length = 200 # Number of sensor readings per sequence\n\n    imu_cols = ['acc_x', 'acc_y', 'acc_z', 'gyro_x', 'gyro_y', 'gyro_z']\n    therm_cols = [f'therm_{i}' for i in range(5)]\n    tof_cols = [f'tof_{i}' for i in range(5)]\n    \n    for i in range(num_sequences):\n        sequence_id = f'seq_{i:03d}'\n        df_cols = ['time'] + imu_cols\n        if sensor_type == 'all':\n            df_cols.extend(therm_cols)\n            df_cols.extend(tof_cols)\n\n        data = {col: np.random.rand(sequence_length) * (100 if 'therm' in col or 'tof' in col else 10) - 5\n                for col in df_cols}\n        data['time'] = np.arange(sequence_length) * 0.01 # Assuming 10ms sampling\n\n        mock_data[sequence_id] = pd.DataFrame(data)\n    \n    print(f\"Conceptual: Generated {num_sequences} mock sequences.\")\n    return mock_data\n\ndef load_labels(labels_path):\n    \"\"\"\n    Conceptual function to load gesture labels.\n    In a real scenario, this would load a CSV mapping sequence_id to gesture label.\n    \n    Args:\n        labels_path (str): Path to the labels file (e.g., CSV).\n    \n    Returns:\n        pd.DataFrame: A DataFrame with 'sequence_id' and 'gesture' columns.\n        \n        Example structure:\n        pd.DataFrame({\n            'sequence_id': ['seq_000', 'seq_001', ...],\n            'gesture': ['Above ear - Pull hair', 'Drink from bottle/cup', ...]\n        })\n    \"\"\"\n    print(f\"Conceptual: Loading labels from {labels_path}...\")\n    \n    # --- Mock Label Generation ---\n    bfrb_gestures = [\n        'Above ear - Pull hair', 'Forehead - Pull hairline', 'Forehead - Scratch',\n        'Eyebrow - Pull hair', 'Eyelash - Pull hair', 'Neck - Pinch skin',\n        'Neck - Scratch', 'Cheek - Pinch skin'\n    ]\n    non_bfrb_gestures = [\n        'Drink from bottle/cup', 'Glasses on/off', 'Pull air toward your face',\n        'Pinch knee/leg skin', 'Scratch knee/leg skin', 'Write name on leg',\n        'Text on phone', 'Feel around in tray and pull out an object',\n        'Write name in air', 'Wave hello'\n    ]\n    all_gestures = bfrb_gestures + non_bfrb_gestures\n    \n    num_sequences = 100 # Match num_sequences in load_sensor_data\n    mock_labels = {\n        'sequence_id': [f'seq_{i:03d}' for i in range(num_sequences)],\n        'gesture': np.random.choice(all_gestures, size=num_sequences)\n    }\n    \n    print(f\"Conceptual: Generated {num_sequences} mock labels.\")\n    return pd.DataFrame(mock_labels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.514746Z","iopub.execute_input":"2025-06-18T21:24:33.515222Z","iopub.status.idle":"2025-06-18T21:24:33.527992Z","shell.execute_reply.started":"2025-06-18T21:24:33.515195Z","shell.execute_reply":"2025-06-18T21:24:33.526962Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 2. Feature Engineering ---\n# This section defines how to extract meaningful features from raw sensor data.\n# This is crucial for time-series data and often involves statistical measures,\n# frequency domain analysis, and domain-specific insights.\n\nclass FeatureExtractor:\n    def __init__(self, sample_rate=100.0):\n        \"\"\"\n        Initializes the FeatureExtractor.\n        Args:\n            sample_rate (float): Sampling rate of the sensor data in Hz.\n        \"\"\"\n        self.sample_rate = sample_rate\n        self.imu_features = ['mean', 'std', 'max', 'min', 'range', 'median', 'rms', 'skew', 'kurtosis']\n        self.freq_features = ['energy_bands', 'peak_freq'] # Conceptual: FFT-based features\n        self.therm_tof_features = ['mean', 'std', 'diff_mean', 'diff_std'] # Statistical for therm/tof\n\n    def _butter_lowpass(self, cutoff, order=5):\n        nyq = 0.5 * self.sample_rate\n        normal_cutoff = cutoff / nyq\n        b, a = butter(order, normal_cutoff, btype='low', analog=False)\n        return b, a\n\n    def _apply_filter(self, data, cutoff=5.0):\n        b, a = self._butter_lowpass(cutoff)\n        y = lfilter(b, a, data)\n        return y\n\n    def _extract_statistical_features(self, series, prefix):\n        \"\"\"Extracts basic statistical features from a time series.\"\"\"\n        features = {}\n        features[f'{prefix}_mean'] = np.mean(series)\n        features[f'{prefix}_std'] = np.std(series)\n        features[f'{prefix}_max'] = np.max(series)\n        features[f'{prefix}_min'] = np.min(series)\n        features[f'{prefix}_range'] = np.max(series) - np.min(series)\n        features[f'{prefix}_median'] = np.median(series)\n        features[f'{prefix}_rms'] = np.sqrt(np.mean(series**2))\n        \n        # Avoid errors if series is too short or constant\n        try:\n            features[f'{prefix}_skew'] = skew(series)\n        except:\n            features[f'{prefix}_skew'] = 0.0 # Default if calculation fails\n        try:\n            features[f'{prefix}_kurtosis'] = kurtosis(series)\n        except:\n            features[f'{prefix}_kurtosis'] = 0.0 # Default if calculation fails\n\n        return features\n\n    def _extract_imu_features(self, df):\n        \"\"\"Extracts features from IMU data (accelerometer and gyroscope).\"\"\"\n        imu_features = {}\n        acc_cols = ['acc_x', 'acc_y', 'acc_z']\n        gyro_cols = ['gyro_x', 'gyro_y', 'gyro_z']\n        \n        # Apply low-pass filter (optional, but common for noise reduction)\n        for col in acc_cols + gyro_cols:\n            if col in df.columns:\n                df[f'{col}_filtered'] = self._apply_filter(df[col].values)\n        \n        # Magnitude features\n        if all(col in df.columns for col in acc_cols):\n            df['acc_mag'] = np.sqrt(df['acc_x']**2 + df['acc_y']**2 + df['acc_z']**2)\n            imu_features.update(self._extract_statistical_features(df['acc_mag'], 'acc_mag'))\n        \n        if all(col in df.columns for col in gyro_cols):\n            df['gyro_mag'] = np.sqrt(df['gyro_x']**2 + df['gyro_y']**2 + df['gyro_z']**2)\n            imu_features.update(self._extract_statistical_features(df['gyro_mag'], 'gyro_mag'))\n\n        # Features per axis\n        for col in acc_cols + gyro_cols:\n            if f'{col}_filtered' in df.columns: # Use filtered data for features\n                imu_features.update(self._extract_statistical_features(df[f'{col}_filtered'], col))\n            elif col in df.columns: # Fallback to unfiltered if no filtered version\n                 imu_features.update(self._extract_statistical_features(df[col], col))\n\n        # Conceptual: Add more advanced IMU features like orientation estimates,\n        # integral of angular velocity, etc., if needed.\n        return imu_features\n\n    def _extract_therm_tof_features(self, df):\n        \"\"\"Extracts features from thermopile and time-of-flight data.\"\"\"\n        other_features = {}\n        therm_cols = [f'therm_{i}' for i in range(5)]\n        tof_cols = [f'tof_{i}' for i in range(5)]\n\n        # Individual sensor statistics\n        for col in therm_cols + tof_cols:\n            if col in df.columns:\n                other_features.update(self._extract_statistical_features(df[col], col))\n        \n        # Differences between sensors (e.g., for proximity/temperature gradients)\n        if all(col in df.columns for col in therm_cols):\n            diff_therm = np.diff(df[therm_cols].values, axis=1) # Differences between adjacent thermopiles\n            other_features['therm_diff_mean'] = np.mean(diff_therm)\n            other_features['therm_diff_std'] = np.std(diff_therm)\n            \n        if all(col in df.columns for col in tof_cols):\n            diff_tof = np.diff(df[tof_cols].values, axis=1) # Differences between adjacent ToF sensors\n            other_features['tof_diff_mean'] = np.mean(diff_tof)\n            other_features['tof_diff_std'] = np.std(diff_tof)\n\n        # Conceptual: More complex features like dynamic changes,\n        # patterns over time for thermopiles (e.g., approaching hand),\n        # or specific ToF patterns indicating a target object.\n        return other_features\n\n    def extract_features_for_sequence(self, sequence_df, sensor_type='all'):\n        \"\"\"\n        Extracts all relevant features from a single sequence's sensor data.\n        \n        Args:\n            sequence_df (pd.DataFrame): DataFrame for a single sequence.\n            sensor_type (str): 'all' or 'imu' to determine which features to extract.\n            \n        Returns:\n            dict: A dictionary of extracted features.\n        \"\"\"\n        features = {}\n        \n        # IMU features are always extracted if data is present\n        features.update(self._extract_imu_features(sequence_df.copy())) # Use copy to avoid modifying original DF\n        \n        # Add thermopile and ToF features if sensor_type is 'all'\n        if sensor_type == 'all':\n            features.update(self._extract_therm_tof_features(sequence_df.copy()))\n        \n        return features\n\n    def extract_features_from_dataset(self, data_dict, sensor_type='all'):\n        \"\"\"\n        Extracts features from an entire dataset (dictionary of DataFrames).\n        \n        Args:\n            data_dict (dict): Dictionary of sequence_ids to DataFrames.\n            sensor_type (str): 'all' or 'imu'.\n            \n        Returns:\n            pd.DataFrame: A DataFrame where each row is a sequence_id\n                          and columns are the extracted features.\n        \"\"\"\n        all_features = []\n        for seq_id, df in data_dict.items():\n            features = self.extract_features_for_sequence(df, sensor_type=sensor_type)\n            features['sequence_id'] = seq_id # Add sequence_id for merging later\n            all_features.append(features)\n        \n        # Fill NaN values that might arise if some features couldn't be computed for short sequences.\n        # A common strategy is to fill with 0 or the mean/median of the column.\n        features_df = pd.DataFrame(all_features).fillna(0) # Or fillna(features_df.mean()) after computing\n        return features_df\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.529133Z","iopub.execute_input":"2025-06-18T21:24:33.529454Z","iopub.status.idle":"2025-06-18T21:24:33.566668Z","shell.execute_reply.started":"2025-06-18T21:24:33.529422Z","shell.execute_reply":"2025-06-18T21:24:33.565628Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 3. Model Definition (Conceptual Placeholder) ---\n# This section defines a simple machine learning model.\n# In a real scenario, you might use more complex models like LSTMs, Transformers,\n# or sophisticated ensemble methods.\n\nclass BehaviorClassifier:\n    def __init__(self, random_state=42):\n        \"\"\"\n        Initializes the classifier.\n        Using RandomForestClassifier as an example.\n        \"\"\"\n        self.model = RandomForestClassifier(n_estimators=100, random_state=random_state, class_weight='balanced')\n        self.scaler = StandardScaler()\n        self.label_encoder = {} # To map string labels to integers\n\n    def preprocess_features(self, X_df, fit_scaler=True):\n        \"\"\"\n        Scales features.\n        Args:\n            X_df (pd.DataFrame): DataFrame of features.\n            fit_scaler (bool): Whether to fit the scaler (True for training data).\n        Returns:\n            np.ndarray: Scaled features.\n        \"\"\"\n        # Drop sequence_id if present, as it's not a feature\n        X_numeric = X_df.drop(columns=['sequence_id'], errors='ignore')\n\n        if fit_scaler:\n            X_scaled = self.scaler.fit_transform(X_numeric)\n            # Store feature names seen during fit for consistent processing during transform\n            self.fitted_feature_names = list(X_numeric.columns)\n        else:\n            # Align test features with the features seen during training\n            missing_cols = set(self.fitted_feature_names) - set(X_numeric.columns)\n            for col in missing_cols:\n                X_numeric[col] = 0.0 # Fill missing columns (e.g., thermopile/ToF for IMU-only data) with zeros\n\n            # Ensure the order of columns matches the training data\n            X_aligned = X_numeric[self.fitted_feature_names]\n            X_scaled = self.scaler.transform(X_aligned)\n        return X_scaled\n\n    def encode_labels(self, y_series, fit_encoder=True):\n        \"\"\"\n        Encodes string labels to integers.\n        Args:\n            y_series (pd.Series): Series of string labels.\n            fit_encoder (bool): Whether to fit the encoder (True for training data).\n        Returns:\n            np.ndarray: Integer-encoded labels.\n        \"\"\"\n        if fit_encoder:\n            unique_labels = sorted(y_series.unique())\n            self.label_encoder = {label: i for i, label in enumerate(unique_labels)}\n            self.inverse_label_encoder = {i: label for label, i in self.label_encoder.items()}\n        \n        return y_series.map(self.label_encoder).values\n\n    def decode_predictions(self, y_pred_encoded):\n        \"\"\"\n        Decodes integer predictions back to string labels.\n        Args:\n            y_pred_encoded (np.ndarray): Integer-encoded predictions.\n        Returns:\n            pd.Series: String labels.\n        \"\"\"\n        return pd.Series(y_pred_encoded).map(self.inverse_label_encoder)\n\n    def train(self, X_train_df, y_train_series):\n        \"\"\"\n        Trains the classifier.\n        Args:\n            X_train_df (pd.DataFrame): Training features.\n            y_train_series (pd.Series): Training labels.\n        \"\"\"\n        X_train_scaled = self.preprocess_features(X_train_df, fit_scaler=True)\n        y_train_encoded = self.encode_labels(y_train_series, fit_encoder=True)\n        \n        print(\"Conceptual: Training model...\")\n        self.model.fit(X_train_scaled, y_train_encoded)\n        print(\"Conceptual: Model training complete.\")\n\n    def predict(self, X_test_df):\n        \"\"\"\n        Makes predictions on new data.\n        Args:\n            X_test_df (pd.DataFrame): Test features.\n        Returns:\n            pd.Series: Predicted string labels.\n        \"\"\"\n        X_test_scaled = self.preprocess_features(X_test_df, fit_scaler=False)\n        y_pred_encoded = self.model.predict(X_test_scaled)\n        return self.decode_predictions(y_pred_encoded)\n\n    def predict_proba(self, X_test_df):\n        \"\"\"\n        Makes probabilistic predictions.\n        Args:\n            X_test_df (pd.DataFrame): Test features.\n        Returns:\n            np.ndarray: Predicted probabilities for each class.\n        \"\"\"\n        X_test_scaled = self.preprocess_features(X_test_df, fit_scaler=False)\n        return self.model.predict_proba(X_test_scaled)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.567660Z","iopub.execute_input":"2025-06-18T21:24:33.568036Z","iopub.status.idle":"2025-06-18T21:24:33.585757Z","shell.execute_reply.started":"2025-06-18T21:24:33.568012Z","shell.execute_reply":"2025-06-18T21:24:33.584901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- 4. Evaluation Metric ---\n# Implementation of the custom macro F1 score described in the competition.\n\ndef custom_f1_score(y_true, y_pred, bfrb_gestures):\n    \"\"\"\n    Calculates the custom evaluation metric for the competition.\n    \n    The final score is the average of two components:\n    1. Binary F1 on whether the gesture is one of the target (BFRB) or non-target (non-BFRB) types.\n    2. Macro F1 on gesture, where all non-target sequences are collapsed into a single 'non_target' class.\n    \n    Args:\n        y_true (pd.Series): True gesture labels.\n        y_pred (pd.Series): Predicted gesture labels.\n        bfrb_gestures (list): List of gesture names considered BFRB-like.\n        \n    Returns:\n        float: The final custom F1 score.\n    \"\"\"\n    \n    # 1. Binary F1 for BFRB vs Non-BFRB\n    # Create binary labels: 1 for BFRB, 0 for Non-BFRB\n    y_true_binary = y_true.apply(lambda x: 1 if x in bfrb_gestures else 0)\n    y_pred_binary = y_pred.apply(lambda x: 1 if x in bfrb_gestures else 0)\n    \n    binary_f1 = f1_score(y_true_binary, y_pred_binary, average='binary', pos_label=1)\n    print(f\"  Binary F1 (BFRB vs Non-BFRB): {binary_f1:.4f}\")\n\n    # 2. Macro F1 for specific gestures, collapsing non-targets\n    y_true_collapsed = y_true.apply(lambda x: x if x in bfrb_gestures else 'non_target')\n    y_pred_collapsed = y_pred.apply(lambda x: x if x in bfrb_gestures else 'non_target')\n    \n    # Ensure all labels in y_true_collapsed are present in y_pred_collapsed's unique values\n    # to avoid errors if a predicted class is missing.\n    # We pass `labels` explicitly to f1_score to handle cases where a class might not appear in y_pred.\n    all_possible_collapsed_classes = sorted(list(set(y_true_collapsed.unique()).union(set(y_pred_collapsed.unique()))))\n\n    macro_f1_collapsed = f1_score(y_true_collapsed, y_pred_collapsed, \n                                  average='macro', labels=all_possible_collapsed_classes, zero_division=0)\n    print(f\"  Macro F1 (Collapsed Gestures): {macro_f1_collapsed:.4f}\")\n\n    final_score = (binary_f1 + macro_f1_collapsed) / 2\n    print(f\"  Final Custom F1 Score: {final_score:.4f}\")\n    \n    return final_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.586695Z","iopub.execute_input":"2025-06-18T21:24:33.587067Z","iopub.status.idle":"2025-06-18T21:24:33.616635Z","shell.execute_reply.started":"2025-06-18T21:24:33.587030Z","shell.execute_reply":"2025-06-18T21:24:33.615594Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# --- Main Execution Flow (Conceptual) ---\n\nif __name__ == \"__main__\":\n    print(\"Conceptual CMI Behavior Detection Model\")\n    print(\"---------------------------------------\")\n    print(\"NOTE: This code is conceptual and uses mock data.\")\n    print(\"It requires actual sensor data and labels to run meaningfully.\")\n    \n    # Define BFRB gestures for evaluation\n    bfrb_like_gestures = [\n        'Above ear - Pull hair', 'Forehead - Pull hairline', 'Forehead - Scratch',\n        'Eyebrow - Pull hair', 'Eyelash - Pull hair', 'Neck - Pinch skin',\n        'Neck - Scratch', 'Cheek - Pinch skin'\n    ]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.617628Z","iopub.execute_input":"2025-06-18T21:24:33.618149Z","iopub.status.idle":"2025-06-18T21:24:33.653989Z","shell.execute_reply.started":"2025-06-18T21:24:33.618126Z","shell.execute_reply":"2025-06-18T21:24:33.653091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Step 1: Load Data ---\n    # Replace with actual data loading paths and logic in a real scenario\n    mock_sensor_data = load_sensor_data(data_path=\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train.csv\", sensor_type='all')\n    mock_labels = load_labels(labels_path=\"/kaggle/input/cmi-detect-behavior-with-sensor-data/train_demographics.csv\")\n\n    # Align data and labels based on sequence_id\n    # In a real scenario, you'd ensure consistent sequence_ids.\n    available_sequences = list(mock_sensor_data.keys())\n    mock_labels = mock_labels[mock_labels['sequence_id'].isin(available_sequences)].set_index('sequence_id')\n    \n    # Split data into training and validation sets\n    train_seq_ids, val_seq_ids = train_test_split(\n        list(mock_sensor_data.keys()), test_size=0.2, random_state=42\n    )\n\n    X_train_raw = {seq_id: mock_sensor_data[seq_id] for seq_id in train_seq_ids}\n    X_val_raw = {seq_id: mock_sensor_data[seq_id] for seq_id in val_seq_ids}\n\n    y_train = mock_labels.loc[train_seq_ids]['gesture']\n    y_val = mock_labels.loc[val_seq_ids]['gesture']\n\n    print(f\"\\nTraining sequences: {len(X_train_raw)}\")\n    print(f\"Validation sequences: {len(X_val_raw)}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.655120Z","iopub.execute_input":"2025-06-18T21:24:33.656078Z","iopub.status.idle":"2025-06-18T21:24:33.752330Z","shell.execute_reply.started":"2025-06-18T21:24:33.656041Z","shell.execute_reply":"2025-06-18T21:24:33.751381Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Step 2: Feature Engineering ---\n    print(\"\\nExtracting features...\")\n    feature_extractor = FeatureExtractor(sample_rate=100.0) # Assuming 100 Hz sampling rate\n    \n    X_train_features = feature_extractor.extract_features_from_dataset(X_train_raw, sensor_type='all')\n    X_val_features = feature_extractor.extract_features_from_dataset(X_val_raw, sensor_type='all')\n\n    # Ensure feature DataFrames are aligned with labels based on sequence_id\n    X_train_features = X_train_features.set_index('sequence_id').loc[y_train.index].reset_index()\n    X_val_features = X_val_features.set_index('sequence_id').loc[y_val.index].reset_index()\n    \n    print(f\"Training features shape: {X_train_features.shape}\")\n    print(f\"Validation features shape: {X_val_features.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:33.755138Z","iopub.execute_input":"2025-06-18T21:24:33.755405Z","iopub.status.idle":"2025-06-18T21:24:37.818190Z","shell.execute_reply.started":"2025-06-18T21:24:33.755384Z","shell.execute_reply":"2025-06-18T21:24:37.817242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Step 3: Model Training ---\n    print(\"\\nInitializing and training the classifier...\")\n    classifier = BehaviorClassifier()\n    classifier.train(X_train_features, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:37.819283Z","iopub.execute_input":"2025-06-18T21:24:37.819610Z","iopub.status.idle":"2025-06-18T21:24:38.039952Z","shell.execute_reply.started":"2025-06-18T21:24:37.819583Z","shell.execute_reply":"2025-06-18T21:24:38.039163Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Step 4: Make Predictions on Validation Set ---\n    print(\"\\nMaking predictions on the validation set...\")\n    y_val_pred = classifier.predict(X_val_features)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:38.041017Z","iopub.execute_input":"2025-06-18T21:24:38.041339Z","iopub.status.idle":"2025-06-18T21:24:38.059463Z","shell.execute_reply.started":"2025-06-18T21:24:38.041312Z","shell.execute_reply":"2025-06-18T21:24:38.058568Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Step 5: Evaluate Model ---\n    print(\"\\nEvaluating model performance on validation set:\")\n    validation_score = custom_f1_score(y_val, y_val_pred, bfrb_like_gestures)\n    print(f\"\\nFinal Validation Score: {validation_score:.4f}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:38.060378Z","iopub.execute_input":"2025-06-18T21:24:38.060601Z","iopub.status.idle":"2025-06-18T21:24:38.075119Z","shell.execute_reply.started":"2025-06-18T21:24:38.060584Z","shell.execute_reply":"2025-06-18T21:24:38.074284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # --- Conceptual Test Set Prediction (simulating submission) ---\n    print(\"\\n--- Conceptual Test Set Prediction ---\")\n    print(\"In a real competition, you would receive test data in two phases:\")\n    print(\"1. Half with IMU data only.\")\n    print(\"2. Half with all sensor data (IMU, thermopile, ToF).\")\n    print(\"Your model needs to handle both scenarios.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:38.076253Z","iopub.execute_input":"2025-06-18T21:24:38.076545Z","iopub.status.idle":"2025-06-18T21:24:38.082096Z","shell.execute_reply.started":"2025-06-18T21:24:38.076520Z","shell.execute_reply":"2025-06-18T21:24:38.081189Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # Mock test data (IMU only)\n    mock_test_imu_data = load_sensor_data(data_path=\"/kaggle/input/cmi-detect-behavior-with-sensor-data/test.csv\", sensor_type='imu')\n    test_imu_features = feature_extractor.extract_features_from_dataset(mock_test_imu_data, sensor_type='imu')\n    test_imu_predictions = classifier.predict(test_imu_features)\n    print(f\"Conceptual: Predicted for {len(test_imu_predictions)} IMU-only test sequences.\")\n    print(test_imu_predictions.head()) # Uncomment to see sample predictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:38.082916Z","iopub.execute_input":"2025-06-18T21:24:38.083265Z","iopub.status.idle":"2025-06-18T21:24:40.087519Z","shell.execute_reply.started":"2025-06-18T21:24:38.083244Z","shell.execute_reply":"2025-06-18T21:24:40.086483Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # Mock test data (All sensors)\n    mock_test_all_data = load_sensor_data(data_path=\"/kaggle/input/cmi-detect-behavior-with-sensor-data/test_demographics.csv\", sensor_type='all')\n    test_all_features = feature_extractor.extract_features_from_dataset(mock_test_all_data, sensor_type='all')\n    test_all_predictions = classifier.predict(test_all_features)\n    print(f\"Conceptual: Predicted for {len(test_all_predictions)} all-sensor test sequences.\")\n    print(test_all_predictions.head()) # Uncomment to see sample predictions\n\n    print(\"\\n--- Submission File Format (Conceptual) ---\")\n    print(\"You would typically combine these predictions into a single DataFrame\")\n    print(\"and save it to a CSV file in the required format (sequence_id, gesture).\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:40.088419Z","iopub.execute_input":"2025-06-18T21:24:40.088641Z","iopub.status.idle":"2025-06-18T21:24:44.019254Z","shell.execute_reply.started":"2025-06-18T21:24:40.088623Z","shell.execute_reply":"2025-06-18T21:24:44.018007Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"    # Example of conceptual submission file structure\n    all_test_predictions = pd.concat([\n         pd.DataFrame({'sequence_id': test_imu_features['sequence_id'], 'gesture': test_imu_predictions}),\n         pd.DataFrame({'sequence_id': test_all_features['sequence_id'], 'gesture': test_all_predictions})\n     ])\n    all_test_predictions.to_csv(\"submission.parquet\", index=False)\n    print(\"\\nConceptual: 'submission.parquet' would be created.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-18T21:24:44.020230Z","iopub.execute_input":"2025-06-18T21:24:44.020566Z","iopub.status.idle":"2025-06-18T21:24:44.036525Z","shell.execute_reply.started":"2025-06-18T21:24:44.020539Z","shell.execute_reply":"2025-06-18T21:24:44.035419Z"}},"outputs":[],"execution_count":null}]}