{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":11050647,"sourceType":"datasetVersion","datasetId":6884413},{"sourceId":11050696,"sourceType":"datasetVersion","datasetId":6884447},{"sourceId":11078689,"sourceType":"datasetVersion","datasetId":6905032},{"sourceId":11107250,"sourceType":"datasetVersion","datasetId":6924630},{"sourceId":11115020,"sourceType":"datasetVersion","datasetId":6930268},{"sourceId":11115282,"sourceType":"datasetVersion","datasetId":6930465},{"sourceId":11134283,"sourceType":"datasetVersion","datasetId":6944431},{"sourceId":11134578,"sourceType":"datasetVersion","datasetId":6944632},{"sourceId":11153308,"sourceType":"datasetVersion","datasetId":6958736},{"sourceId":11312097,"sourceType":"datasetVersion","datasetId":7075193},{"sourceId":11312157,"sourceType":"datasetVersion","datasetId":7075234}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"from xgboost import XGBClassifier\nfrom tensorflow import keras\nimport joblib\nfrom tensorflow.keras.models import load_model\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.layers import Layer\nfrom tensorflow.keras.saving import register_keras_serializable\nimport tensorflow as tf\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Conv1D, BatchNormalization, Dropout, Activation\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras import backend as K\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.layers import Dense\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv1D, MaxPooling1D, Dropout, Flatten, Dense, Reshape\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.optimizers import Adam\nfrom sklearn.model_selection import train_test_split\n\n\ndef custom_loss_2(y_true, y_pred):\n    alpha = 6.0\n    weight = 1 + alpha * K.abs(y_true)\n    mse_loss = K.mean(weight * K.square(y_true - y_pred))\n\n    # Ranking loss: Encourage event time steps (|y_true| > 0.5) to have higher |y_pred|\n    pos_mask = K.cast(K.greater(K.abs(y_true), 0.6), 'float32')\n    neg_mask = 1.0 - pos_mask\n\n    pos_count = K.sum(pos_mask) + K.epsilon()\n    neg_count = K.sum(neg_mask) + K.epsilon()\n    pos_mean = K.sum(K.abs(y_pred) * pos_mask) / pos_count\n    neg_mean = K.sum(K.abs(y_pred) * neg_mask) / neg_count\n\n    margin = 0.6\n    ranking_loss = K.relu(margin - (pos_mean - neg_mean))\n\n    return mse_loss + 0.1 * ranking_loss","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-07T14:51:45.343352Z","iopub.execute_input":"2025-04-07T14:51:45.343802Z","iopub.status.idle":"2025-04-07T14:51:45.353662Z","shell.execute_reply.started":"2025-04-07T14:51:45.343744Z","shell.execute_reply":"2025-04-07T14:51:45.352181Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from xgboost import XGBClassifier\nfrom tensorflow import keras\nimport joblib\nfrom tensorflow.keras.models import load_model\n\n\n# Load the model from the file\nxgboost_worn_unworn_model = XGBClassifier()\nxgboost_worn_unworn_model.load_model('/kaggle/input/worn-unworn-latest/worn_unworn_xgboost_model_2.json')\nprint(\"🚀 xgboost model loaded successfully!\")\nrf_worn_unworn_model = joblib.load('/kaggle/input/worn-unworn-latest/worn_unworn_rf_model_kaggle.pkl')\nprint(\"🚀 rf model loaded successfully!\")\ncnn_worn_unworn_model = load_model(\"/kaggle/input/worn-unworn-latest/worn_unworn_cnn_model.keras\")\nprint(\"🚀 cnn model loaded successfully!\")\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.layers import Layer\nfrom tensorflow.keras.saving import register_keras_serializable\nimport tensorflow as tf\nimport tensorflow as tf\nfrom tensorflow.keras.layers import Conv1D, BatchNormalization, Dropout, Activation\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras import backend as K\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.models import load_model\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras.layers import Dense\n\nclass ResidualBlock(tf.keras.layers.Layer):\n    def __init__(self, filters, kernel_size, dilation_rate, dropout_rate=0.2, **kwargs):\n        super().__init__(**kwargs)\n        self.filters = filters\n        self.kernel_size = kernel_size\n        self.dilation_rate = dilation_rate\n        self.dropout_rate = dropout_rate\n\n        self.conv1 = Conv1D(filters, kernel_size, padding='causal', dilation_rate=dilation_rate)\n        self.bn1 = BatchNormalization()\n        self.act1 = Activation('gelu')\n        self.drop1 = Dropout(dropout_rate)\n\n        self.conv2 = Conv1D(filters, kernel_size, padding='causal', dilation_rate=dilation_rate)\n        self.bn2 = BatchNormalization()\n        self.act2 = Activation('gelu')\n        self.drop2 = Dropout(dropout_rate)\n\n        self.residual = Conv1D(filters, 1, padding='same')\n\n    def call(self, x):\n        res = self.residual(x)\n        x = self.conv1(x)\n        x = self.bn1(x)\n        x = self.act1(x)\n        x = self.drop1(x)\n\n        x = self.conv2(x)\n        x = self.bn2(x)\n        x = self.act2(x)\n        x = self.drop2(x)\n\n        return tf.keras.activations.gelu(x + res)\n\n    def get_config(self):\n        config = super().get_config()\n        config.update({\n            'filters': self.filters,\n            'kernel_size': self.kernel_size,\n            'dilation_rate': self.dilation_rate,\n            'dropout_rate': self.dropout_rate,\n        })\n        return config\n    \n    def build(self, input_shape):\n        self.conv1.build(input_shape)\n        x_shape = self.conv1.compute_output_shape(input_shape)\n        self.bn1.build(x_shape)\n        self.drop1.build(x_shape)\n    \n        self.conv2.build(x_shape)\n        x_shape = self.conv2.compute_output_shape(x_shape)\n        self.bn2.build(x_shape)\n        self.drop2.build(x_shape)\n    \n        self.residual.build(input_shape)\n    \n        super().build(input_shape)\n        \nclass PositionalEncoding_UNET(Layer):\n    def __init__(self, **kwargs):  # <-- Accept all standard Keras args\n        super(PositionalEncoding, self).__init__(**kwargs)\n\n    def call(self, x):\n        seq_len = tf.shape(x)[1]\n        d_model = tf.shape(x)[2]\n        position = tf.cast(tf.range(seq_len), tf.float32)[:, tf.newaxis]         # (seq_len, 1)\n        i = tf.cast(tf.range(d_model), tf.float32)[tf.newaxis, :]               # (1, d_model)\n\n        angle_rates = 1 / tf.pow(10000.0, (2 * (i // 2)) / tf.cast(d_model, tf.float32))\n        angle_rads = position * angle_rates                                     # (seq_len, d_model)\n\n        # Apply sin to even indices and cos to odd indices\n        sines = tf.sin(angle_rads[:, 0::2])\n        cosines = tf.cos(angle_rads[:, 1::2])\n\n        # Interleave sine and cosine\n        pos_encoding = tf.concat([sines, cosines], axis=-1)\n        pos_encoding = tf.reshape(pos_encoding, (1, seq_len, d_model))          # (1, seq_len, d_model)\n\n        return x + pos_encoding\n\n    def get_config(self):\n            config = super(PositionalEncoding, self).get_config()\n            return config\n\nclass PositionalEncoding_Transformer(tf.keras.layers.Layer):\n    def __init__(self, sequence_len, d_model, **kwargs):\n        super().__init__(**kwargs)\n        self.sequence_len = sequence_len\n        self.d_model = d_model\n\n        position = np.arange(sequence_len)[:, np.newaxis]\n        div_term = np.exp(np.arange(0, d_model, 2) * -(np.log(10000.0) / d_model))\n        pe = np.zeros((sequence_len, d_model))\n        pe[:, 0::2] = np.sin(position * div_term)\n        pe[:, 1::2] = np.cos(position * div_term)\n        self.pe = tf.constant(pe[np.newaxis, ...], dtype=tf.float32)\n\n    def call(self, x):\n        return x + self.pe[:, :tf.shape(x)[1], :]\n\n    def get_config(self):\n        config = super().get_config()\n        config.update({\n            'sequence_len': self.sequence_len,\n            'd_model': self.d_model,\n        })\n        return config\n\n\n\ndef custom_loss(y_true, y_pred):\n    alpha = 5.0\n    weight = 1 + alpha * K.abs(y_true)\n    mse_loss = K.mean(weight * K.square(y_true - y_pred))\n\n    # Ranking loss: Encourage event time steps (|y_true| > 0.5) to have higher |y_pred|\n    pos_mask = K.cast(K.greater(K.abs(y_true), 0.5), 'float32')\n    neg_mask = 1.0 - pos_mask\n\n    pos_count = K.sum(pos_mask) + K.epsilon()\n    neg_count = K.sum(neg_mask) + K.epsilon()\n    pos_mean = K.sum(K.abs(y_pred) * pos_mask) / pos_count\n    neg_mean = K.sum(K.abs(y_pred) * neg_mask) / neg_count\n\n    margin = 0.5\n    ranking_loss = K.relu(margin - (pos_mean - neg_mean))\n\n    return mse_loss + 0.1 * ranking_loss\n    \ndef attention_block(x, num_heads=4):\n    attn_output = MultiHeadAttention(num_heads=num_heads, key_dim=x.shape[-1])(x, x)\n    x = Add()([x, attn_output])  # Residual connection\n    x = LayerNormalization()(x)\n    return x\n    \nfrom tensorflow import keras\n\n\n#### load score prediction models (unet, tcn,transformer)\n\nmodel_path = \"/kaggle/input/bestmodels/unet1d_with_attention_2_27.3_score.keras\"\n\nscore_predict_model = keras.models.load_model(\n    model_path,\n    custom_objects={\n        \"custom_loss\": custom_loss_2,\n        \"PositionalEncoding\": PositionalEncoding_UNET\n    }\n)\n\nprint(\"🚀 Score predict model loaded successfully!\")\n\nsecond_score_model = keras.models.load_model(\n    \"/kaggle/input/bestmodels/transformer_5.4.keras\",\n    custom_objects={\n        \"custom_loss_2\": custom_loss_2,\n        \"PositionalEncoding\": PositionalEncoding_Transformer\n            }\n)\nprint(\"🚀 2nd Score predict model loaded successfully!\")\n\nthird_score_model = keras.models.load_model(\n    \"/kaggle/input/bestmodels/tcn_5.4_2.keras\",\n    custom_objects={\n        \"custom_loss_2\": custom_loss_2,\n        'ResidualBlock': ResidualBlock,\n            }\n)\nprint(\"🚀 3rd Score predict model loaded successfully!\")\n\n# test_model = keras.models.load_model(\n#     \"/kaggle/input/bestmodels/unet1d_with_attention_5.4_earlystop.keras\",\n#     custom_objects={\n#         \"custom_loss\": custom_loss_2,\n#         \"PositionalEncoding\": PositionalEncoding_UNET\n#             }\n# )\n# print(\"🚀 4th Score predict model loaded successfully!\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-07T14:51:46.140405Z","iopub.execute_input":"2025-04-07T14:51:46.140794Z","iopub.status.idle":"2025-04-07T14:51:48.692162Z","shell.execute_reply.started":"2025-04-07T14:51:46.140764Z","shell.execute_reply":"2025-04-07T14:51:48.691016Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport os\nfrom concurrent.futures import ProcessPoolExecutor\ntest_series = pd.read_parquet('/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet')\n\n# Define a custom bucket: 18:00 to 18:00 the following day\ndef assign_bucket(timestamp):\n    if timestamp.hour >= 18:\n        return timestamp.date()\n    else:\n        return (timestamp - pd.Timedelta(days=1)).date()\n\ndef process_series_df(series_id):\n    # Step 1: Check if required columns exist\n    required_cols = ['series_id', 'timestamp', 'anglez', 'enmo', 'step']\n    missing_cols = [col for col in required_cols if col not in test_series.columns]\n    if missing_cols:\n        print(f\"Missing columns: {missing_cols}\")\n        return []\n\n    # Step 2: Filter the series\n    series_df = test_series[test_series['series_id'] == series_id].copy()\n    if series_df.empty:\n        return []\n\n    # Step 3: Handle missing anglez column\n    if series_df['anglez'].isna().all():\n        return []\n\n    # Step 4: Fill missing values in relevant columns (forward fill)\n    series_df[['timestamp', 'anglez', 'enmo', 'step']] = (\n        series_df[['timestamp', 'anglez', 'enmo', 'step']].ffill()\n    )\n\n    # Step 5: Convert timestamp safely\n    series_df['timestamp'] = pd.to_datetime(series_df['timestamp'], errors='coerce', utc=True)\n    if series_df['timestamp'].isna().all():\n        return []\n\n    # Step 6: Extract time-based features\n    series_df['date_hour_minute'] = series_df['timestamp'].dt.strftime('%Y-%m-%d %H:%M')\n    series_df['hour'] = series_df['timestamp'].dt.hour\n\n    # Step 7: Compute anglez value counts\n    series_df['anglez_value_counts'] = series_df['anglez'].map(series_df['anglez'].value_counts())\n\n    # Step 8: Group by minute\n    series_minute_grouped = series_df.groupby('date_hour_minute').agg({\n        'anglez': ['mean', 'std', 'median'],\n        'enmo': ['mean', 'std', 'median'],\n        'step': 'min',\n        'hour': 'first',\n        'anglez_value_counts': 'max',\n    }).reset_index()\n\n    if series_minute_grouped.empty:\n        return []\n\n    # Step 9: Rename columns\n    series_minute_grouped.columns = [\n        'date_hour_minute', 'anglez_mean', 'anglez_std', 'anglez_med',\n        'enmo_mean', 'enmo_std', 'enmo_med', 'step_min',\n        'hour', 'anglez_value_counts'\n    ]\n\n    # Step 10: Parse date_hour_minute and assign bucket\n    series_minute_grouped['date_hour_minute'] = pd.to_datetime(\n        series_minute_grouped['date_hour_minute'], errors='coerce'\n    )\n\n\n\n    series_minute_grouped['bucket'] = series_minute_grouped['date_hour_minute'].apply(assign_bucket)\n\n    return series_minute_grouped\n      \ndef process(series_id):\n  print(f\"start processing {series_id}\")\n  series_minute_grouped = process_series_df(series_id)\n  if series_minute_grouped.empty:\n        print(f\"No valid data for series_id {series_id}\")\n        return []\n  series_minute_grouped['bucket'] = series_minute_grouped['bucket'].astype(str)\n\n  # Group data into buckets (dates)\n  buckets = series_minute_grouped.groupby('bucket')\n\n  # Store data for each bucket as arrays\n  bucket_arrays = []\n\n  for bucket, group in buckets:\n      step = group['step_min'].to_numpy()\n      hour = group['hour'].to_numpy()\n      enmo_values = group['enmo_mean'].to_numpy()\n      enmo_std_values = group['enmo_std'].to_numpy()\n      anglez_values = group['anglez_mean'].to_numpy()\n      anglez_values = np.clip(anglez_values, -90, 90)\n      anglez_log_values = np.log1p(anglez_values + 91)  # Apply shift by 91 so the range is 1-181 and log1p transformation\n      anglez_std_values = group['anglez_std'].to_numpy()\n      anglez_value_counts = group['anglez_value_counts'].to_numpy()\n      bucket_arrays.append({\n          'series_id': series_id,\n          'bucket': bucket,\n          'step': step,\n          'hour': hour,\n          'enmo': enmo_values,\n          'enmo_std' : enmo_std_values,\n          'anglez_log': anglez_log_values,\n          'anglez_std' : anglez_std_values,\n          'anglez_value_counts' : anglez_value_counts,\n      })\n  print(f\"finished processing {series_id}\")\n  return bucket_arrays","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.767104Z","iopub.execute_input":"2025-03-16T15:10:07.767588Z","iopub.status.idle":"2025-03-16T15:10:07.798743Z","shell.execute_reply.started":"2025-03-16T15:10:07.767538Z","shell.execute_reply":"2025-03-16T15:10:07.797079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TARGET_LENGTH = 1440\n\ndef pad_to_length_edge(array, target_length=1440):\n    pad_length = target_length - len(array)\n    if pad_length > 0:\n        return np.pad(array, (0, pad_length), mode='edge')\n    return array\n\nseries_ids = test_series['series_id'].unique()\nresults = [process(series_id) for series_id in series_ids]\n\nflat_data = []\nfor result in results:\n    for bucket in result:\n        flat_data.append({\n            \"series_id\": bucket['series_id'],\n            \"bucket\": bucket['bucket'],\n            \"step\": bucket['step'],\n            \"hour\": bucket['hour'],\n            \"enmo\": list(bucket['enmo']),\n            \"enmo_std\": list(bucket['enmo_std']),\n            \"anglez_log\": list(bucket['anglez_log']),\n            \"anglez_std\": list(bucket['anglez_std']),\n            \"anglez_value_counts\": list(bucket['anglez_value_counts']),\n        })\n\nbuckets = pd.DataFrame(flat_data)\n\n# Apply padding to each feature column\nfor col in ['step', 'enmo', 'hour', 'enmo_std', 'anglez_log', 'anglez_std', 'anglez_value_counts']:\n    buckets[col] = buckets[col].apply(lambda x: pad_to_length_edge(x, 1440))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.800880Z","iopub.execute_input":"2025-03-16T15:10:07.801303Z","iopub.status.idle":"2025-03-16T15:10:07.886984Z","shell.execute_reply.started":"2025-03-16T15:10:07.801264Z","shell.execute_reply":"2025-03-16T15:10:07.885584Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nfrom numpy.lib.stride_tricks import sliding_window_view\n\nbuckets['anglez_log_ewma'] = buckets['anglez_log'].apply(lambda x: pd.Series(x).ewm(span=30).mean().to_numpy())\nbuckets['enmo_ewma'] = buckets['enmo'].apply(lambda x: pd.Series(x).ewm(span=30).mean().to_numpy())\nfor col_name in ['enmo', 'enmo_std', 'anglez_log', 'anglez_std', 'anglez_log_ewma', 'enmo_ewma']:\n  buckets[col_name] = buckets[col_name].apply(lambda arr: (arr - np.mean(arr)) / np.std(arr) if np.std(arr) != 0 else arr)\n\n\n# Efficient sliding window std\ndef sliding_window_std(array, window_size=10):\n    if len(array) < window_size:\n        return np.array([0] * len(array))  # Handle edge cases\n    windows = sliding_window_view(array, window_shape=window_size)  # Create overlapping windows\n    return np.std(windows, axis=1)\n\n# Efficient sliding window mad\ndef sliding_window_mad(array, window_size=10):\n    if len(array) < window_size:\n        return np.array([0] * len(array))  # Handle edge cases\n    windows = sliding_window_view(array, window_shape=window_size)  # Create overlapping windows\n    return np.mean(np.abs(np.diff(windows, axis=1)), axis=1)\ndef pad_to_length_constant(array, target_length=1440):\n    pad_length = target_length - len(array)\n    if pad_length > 0:\n        return np.pad(array, (0, pad_length), mode='constant')\n    return array\nbuckets['anglez_log_std'] = buckets['anglez_log'].apply(lambda x: sliding_window_std(np.array(x), window_size=30))\nbuckets['anglez_log_mad'] = buckets['anglez_log'].apply(lambda x: sliding_window_mad(np.array(x), window_size=30))\n\n\n# Pad the sliding window results\nbuckets['anglez_log_std'] = buckets['anglez_log_std'].apply(lambda x: pad_to_length_edge(x, 1440))\nbuckets['anglez_log_mad'] = buckets['anglez_log_mad'].apply(lambda x: pad_to_length_edge(x, 1440))\nbuckets['hour_sin'] = buckets['hour'].apply(lambda x: np.sin(2 * np.pi * x / 24))\nbuckets['hour_cos'] = buckets['hour'].apply(lambda x: np.cos(2 * np.pi * x / 24))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.888343Z","iopub.execute_input":"2025-03-16T15:10:07.888690Z","iopub.status.idle":"2025-03-16T15:10:07.908021Z","shell.execute_reply.started":"2025-03-16T15:10:07.888662Z","shell.execute_reply":"2025-03-16T15:10:07.906262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Feature engineering: Prepare features and targets\nfeatures = []\nfor _, row in buckets.iterrows():\n    # Stack all features into a single array for the row\n    feature_matrix = np.column_stack([\n        row['anglez_log_ewma'],\n        row['anglez_log_std'],\n        row['anglez_log_mad'],\n        row['enmo_ewma'],\n        row['enmo_std'],\n        row['anglez_std'],\n        row['anglez_value_counts'],\n        row['hour_sin'],\n        row['hour_cos']\n    ])\n    features.append(feature_matrix)\n# Convert features and targets to numpy arrays\nX_test = np.array(features)  # Shape: (n_samples, 1440, n_features)\n\n# Flatten the input arrays into 1D vectors\nif X_test.size != 0:\n    X_test_flattened = X_test.reshape(X_test.shape[0], -1)  # Shape: (num_samples, features)\n    print(f\"Shape of flattened X: {X_test_flattened.shape}\")\n    worn_predictions_1 = xgboost_worn_unworn_model.predict(X_test_flattened)\n    worn_predictions_2 = rf_worn_unworn_model.predict(X_test_flattened)\n    cnn_probs = cnn_worn_unworn_model.predict(X_test).ravel()\n    worn_predictions_3 = (cnn_probs > 0.4).astype(int)\n    # Majority vote (element-wise)\n    final_preds = (worn_predictions_1 + worn_predictions_2 + worn_predictions_3) >= 2\n    worn_predictions = final_preds.astype(int)\n    \n    # cnn_probs = cnn_worn_unworn_model.predict(X_test).ravel()\n    # rf_probs = rf_worn_unworn_model.predict_proba(X_test_flattened)[:, 1]\n    # xgb_probs = xgboost_worn_unworn_model.predict_proba(X_test_flattened)[:, 1]\n    # # Average probabilities\n    # avg_probs = 0.2*cnn_probs + 0.2*rf_probs + 0.6*xgb_probs\n\n    # # Final prediction\n    # worn_predictions = (avg_probs > 0.5).astype(int)\n    # worn_predictions = worn_predictions_3\n    buckets['worn'] = worn_predictions\n    filtered_buckets = buckets[buckets['worn'] == 1]\nelse:\n    filtered_buckets = buckets","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.909706Z","iopub.execute_input":"2025-03-16T15:10:07.910148Z","iopub.status.idle":"2025-03-16T15:10:07.933707Z","shell.execute_reply.started":"2025-03-16T15:10:07.910108Z","shell.execute_reply":"2025-03-16T15:10:07.932356Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# Extract features\nfeatures = []\nfor _, row in filtered_buckets.iterrows():\n# Stack features: each is a 1440-length array for one day\n    feature_matrix = np.column_stack([\n    row['anglez_log_ewma'],\n    row['anglez_log_std'],\n    row['anglez_log_mad'],\n    row['enmo_ewma'],\n    row['enmo_std'],\n    row['anglez_std'],\n    row['anglez_value_counts'],\n    row['hour_sin'],\n    row['hour_cos']\n    ])\n    features.append(feature_matrix)\n\nX = np.array(features)  # Ensure shape: (n_samples, 1440, n_features)\n\n# Predict using the trained model\nsleep_awake_predictions_1 = score_predict_model.predict(X)\nsleep_awake_predictions_2 = second_score_model.predict(X)\nsleep_awake_predictions_3 = third_score_model.predict(X)\n# sleep_awake_predictions_4 = test_model.predict(X)\n\n\n\n# Convert scores to weights (higher score → higher weight)\nweights = np.array([0.648, 0.6, 0.603])\nweights /= weights.sum()\n# Assign predictions to the DataFrame  \nfiltered_buckets[\"predicted_target\"] = [(0.5*sleep_awake_predictions_1[i].flatten()+0.2*sleep_awake_predictions_2[i].flatten()+0.3*sleep_awake_predictions_3[i].flatten()) for i in range(len(filtered_buckets))]\n# filtered_buckets[\"predicted_target\"] = [sleep_awake_predictions_2[i].flatten() for i in range(len(filtered_buckets))]\n\n# Save results\nfiltered_buckets.to_parquet(\"buckets_for_post_processing.parquet\", index=False)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.963540Z","iopub.execute_input":"2025-03-16T15:10:07.964048Z","iopub.status.idle":"2025-03-16T15:10:07.989302Z","shell.execute_reply.started":"2025-03-16T15:10:07.964003Z","shell.execute_reply":"2025-03-16T15:10:07.987899Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import dask.dataframe as dd\nimport pandas as pd\nimport numpy as np\n# Load the data using Dask\ndf = dd.read_parquet('buckets_for_post_processing.parquet')\nthreshold = 0.1\n\ndef process_sleep_data(input_df):\n    \"\"\"\n    Process the dataframe to extract one onset and one wakeup event per bucket.\n    The onset event is determined by the maximum value in the predicted_target array,\n    and the wakeup event by the minimum value.\n\n    Parameters:\n    -----------\n    input_df : dask.dataframe.DataFrame\n        Input dataframe with columns `series_id`, `predicted_target`, and `step`.\n        - `predicted_target`: an array of 1440 score values.\n        - `step`: an array of 1440 time steps corresponding to each score.\n\n    Returns:\n    --------\n    dask.dataframe.DataFrame:\n        Submission dataframe with columns `row_id`, `series_id`, `step`, `event`, and `score`.\n    \"\"\"\n\n    def adjust_step(step, event_type):\n      \"\"\"\n      Apply post-processing tweaks:\n      1. Avoid predicting on exact minute/half-minute by shifting by -1 if step % 12 == 0 or 6.\n      2. Adjust based on empirical 15-minute step patterns.\n      \"\"\"\n      # 1. Avoid predicting exact minute or half-minute\n      if step % 12 == 0:\n          step -= 1\n      elif step % 12 == 6:\n          step -= 1\n\n      # 2. Empirical 15-min pattern correction\n      # step//12 converts to minutes, %15 gives position in 15-min window\n      e15 = event_type[0] + str((step // 12) % 15)\n      if e15 in ['o1', 'o8', 'o9', 'w0', 'w4', 'w8', 'w12']:\n          step -= 12\n      elif e15 in ['o4', 'o12', 'w1', 'w5', 'w9', 'w13']:\n          step += 12\n\n      return step\n\n    \n    def extract_events(row):\n      predicted_target = np.array(row['predicted_target'])\n      steps = row['step']\n      events = []\n\n      onset_idx = int(np.argmax(predicted_target))\n      wakeup_idx = int(np.argmin(predicted_target))\n\n      onset_score = float(predicted_target[onset_idx])\n      wakeup_score = float(predicted_target[wakeup_idx])\n\n      onset_step = adjust_step(steps[onset_idx], 'onset')\n      wakeup_step = adjust_step(steps[wakeup_idx], 'wakeup')\n      if abs(onset_score) > threshold:\n          events.append({\n              'series_id': row['series_id'],\n              'step': onset_step,\n              'event': 'onset',\n              'score': abs(onset_score)\n          })\n      if abs(wakeup_score) > threshold:\n          events.append({\n              'series_id': row['series_id'],\n              'step': wakeup_step,\n              'event': 'wakeup',\n              'score': abs(wakeup_score)\n          })\n      \n      return events\n\n    def process_partition(partition_df):\n        processed_rows = []\n        for _, row in partition_df.iterrows():\n            processed_rows.extend(extract_events(row))\n        if processed_rows:\n            return pd.DataFrame(processed_rows)\n        else:\n            return pd.DataFrame(columns=['series_id', 'step', 'event', 'score'])\n\n    # Apply extraction function to each partition\n    results = input_df.map_partitions(process_partition, meta={\n        'series_id': str,\n        'step': int,\n        'event': str,\n        'score': int\n    })\n\n    # Reset index and add a row_id column.\n    results = results.reset_index(drop=True)\n    results['row_id'] = results.index\n    results = results[['row_id', 'series_id', 'step', 'event', 'score']]\n    return results\n\n# Process the data\nsubmission_df = process_sleep_data(df)\n\n# Compute and save the result\nsubmission_df = submission_df.compute()\nsubmission_df.to_csv('submission.csv', index=False)\n\n# submission = pd.read_csv('/kaggle/input/child-mind-institute-detect-sleep-states/sample_submission.csv')\n# submission.to_csv('submission.csv', index=False)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-16T15:10:07.992034Z","iopub.execute_input":"2025-03-16T15:10:07.992521Z","iopub.status.idle":"2025-03-16T15:10:08.040723Z","shell.execute_reply.started":"2025-03-16T15:10:07.992486Z","shell.execute_reply":"2025-03-16T15:10:08.039489Z"}},"outputs":[],"execution_count":null}]}