{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.13.15","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[],"dockerImageVersionId":28755,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\n\nfor root, dirs, files in os.walk(\"/kaggle/input\"):\n    for file in files:\n        print(os.path.join(root, file))","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:27:06.610495Z","iopub.execute_input":"2026-10-10T16:27:06.610854Z","iopub.status.idle":"2026-10-10T16:27:06.638001Z","shell.execute_reply.started":"2026-10-10T16:27:06.610817Z","shell.execute_reply":"2026-10-10T16:27:06.636986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\nDATA_PATH = \"/kaggle/input/competitions/esa-adb-challenge\"\n\ntrain = pd.read_parquet(f\"{DATA_PATH}/train.parquet\")\ntest = pd.read_parquet(f\"{DATA_PATH}/test.parquet\")\ntarget_channels = pd.read_csv(f\"{DATA_PATH}/target_channels.csv\")\nsample_submission = pd.read_parquet(\n    f\"{DATA_PATH}/sample_submission.parquet\"\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:04.091364Z","iopub.execute_input":"2026-10-10T16:28:04.091823Z","iopub.status.idle":"2026-10-10T16:28:16.233549Z","shell.execute_reply.started":"2026-10-10T16:28:04.091785Z","shell.execute_reply":"2026-10-10T16:28:16.23262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train:\", train.shape)\nprint(\"Test:\", test.shape)\nprint(\"Target channels:\", target_channels.shape)\nprint(\"Sample submission:\", sample_submission.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:24.554409Z","iopub.execute_input":"2026-10-10T16:28:24.555519Z","iopub.status.idle":"2026-10-10T16:28:24.561634Z","shell.execute_reply.started":"2026-10-10T16:28:24.555472Z","shell.execute_reply":"2026-10-10T16:28:24.56066Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train.columns.tolist())\nprint(\"\\nMissing in test:\", set(train.columns) - set(test.columns))\nprint(\"\\nTarget channels:\")\nprint(target_channels)\nprint(\"\\nAnomaly distribution:\")\nprint(train[\"is_anomaly\"].value_counts(normalize=True))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:30.354793Z","iopub.execute_input":"2026-10-10T16:28:30.355815Z","iopub.status.idle":"2026-10-10T16:28:30.480953Z","shell.execute_reply.started":"2026-10-10T16:28:30.355772Z","shell.execute_reply":"2026-10-10T16:28:30.480019Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Missing values:\")\nprint(train.isna().sum().sum())\n\nprint(\"\\nDuplicate IDs:\")\nprint(train[\"id\"].duplicated().sum())\n\nprint(\"\\nID range:\")\nprint(train[\"id\"].min(), \"→\", train[\"id\"].max())\n\nprint(\"\\nAnomaly counts:\")\nprint(train[\"is_anomaly\"].value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:37.349197Z","iopub.execute_input":"2026-10-10T16:28:37.350135Z","iopub.status.idle":"2026-10-10T16:28:41.041271Z","shell.execute_reply.started":"2026-10-10T16:28:37.350093Z","shell.execute_reply":"2026-10-10T16:28:41.040108Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Columns:\")\nfor i, col in enumerate(train.columns):\n    print(i, col)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:43.411494Z","iopub.execute_input":"2026-10-10T16:28:43.412339Z","iopub.status.idle":"2026-10-10T16:28:43.418611Z","shell.execute_reply.started":"2026-10-10T16:28:43.412278Z","shell.execute_reply":"2026-10-10T16:28:43.417629Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nData types:\")\nprint(train.dtypes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:50.032594Z","iopub.execute_input":"2026-10-10T16:28:50.033811Z","iopub.status.idle":"2026-10-10T16:28:50.041702Z","shell.execute_reply.started":"2026-10-10T16:28:50.033765Z","shell.execute_reply":"2026-10-10T16:28:50.040373Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nFirst 5 rows:\")\ndisplay(train.head())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:53.185184Z","iopub.execute_input":"2026-10-10T16:28:53.186239Z","iopub.status.idle":"2026-10-10T16:28:53.231471Z","shell.execute_reply.started":"2026-10-10T16:28:53.186195Z","shell.execute_reply":"2026-10-10T16:28:53.230552Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"channel_cols = [col for col in train.columns if col.startswith(\"channel_\")]\ntelecommand_cols = [col for col in train.columns if col.startswith(\"telecommand_\")]\n\nprint(\"Number of channels:\", len(channel_cols))\nprint(\"Number of telecommands:\", len(telecommand_cols))\n\nprint(\"\\nChannels:\")\nprint(channel_cols)\n\nprint(\"\\nTelecommands:\")\nprint(telecommand_cols)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:28:57.74667Z","iopub.execute_input":"2026-10-10T16:28:57.747664Z","iopub.status.idle":"2026-10-10T16:28:57.754694Z","shell.execute_reply.started":"2026-10-10T16:28:57.747612Z","shell.execute_reply":"2026-10-10T16:28:57.753648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(train[channel_cols].describe().T)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:29:03.675658Z","iopub.execute_input":"2026-10-10T16:29:03.676236Z","iopub.status.idle":"2026-10-10T16:29:37.703804Z","shell.execute_reply.started":"2026-10-10T16:29:03.676198Z","shell.execute_reply":"2026-10-10T16:29:37.702537Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"channel_stats = pd.DataFrame({\n    \"mean\": train[channel_cols].mean(),\n    \"std\": train[channel_cols].std(),\n    \"n_unique\": train[channel_cols].nunique(),\n    \"zero_ratio\": (train[channel_cols] == 0).mean()\n})\n\ndisplay(channel_stats.sort_values(\"std\"))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-10T16:29:49.896706Z","iopub.execute_input":"2026-10-10T16:29:49.89748Z","iopub.status.idle":"2026-10-10T16:30:21.404603Z","shell.execute_reply.started":"2026-10-10T16:29:49.897443Z","shell.execute_reply":"2026-10-10T16:30:21.403746Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Channels with very low variation:\")\ndisplay(channel_stats[channel_stats[\"std\"] < 1e-5])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:16:42.558396Z","iopub.execute_input":"2026-10-08T20:16:42.558798Z","iopub.status.idle":"2026-10-08T20:16:42.572007Z","shell.execute_reply.started":"2026-10-08T20:16:42.558764Z","shell.execute_reply":"2026-10-08T20:16:42.571138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Channels with >95% zeros:\")\ndisplay(channel_stats[channel_stats[\"zero_ratio\"] > 0.95])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:16:45.755653Z","iopub.execute_input":"2026-10-08T20:16:45.756072Z","iopub.status.idle":"2026-10-08T20:16:45.77058Z","shell.execute_reply.started":"2026-10-08T20:16:45.756038Z","shell.execute_reply":"2026-10-08T20:16:45.769717Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"low_variation_channels = [\n    \"channel_4\",\n    \"channel_5\",\n    \"channel_6\",\n    \"channel_7\",\n    \"channel_8\",\n    \"channel_9\",\n    \"channel_10\",\n    \"channel_11\"\n]\n\nbaseline_channels = [\n    col for col in channel_cols\n    if col not in low_variation_channels\n]\n\nprint(\"Baseline features:\", len(baseline_channels))\nprint(baseline_channels)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:25:08.125941Z","iopub.execute_input":"2026-10-08T20:25:08.127289Z","iopub.status.idle":"2026-10-08T20:25:08.145742Z","shell.execute_reply.started":"2026-10-08T20:25:08.127223Z","shell.execute_reply":"2026-10-08T20:25:08.144257Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train[baseline_channels]\ny = train[\"is_anomaly\"]\n\nprint(\"X shape:\", X.shape)\nprint(\"y shape:\", y.shape)\n\nprint(\"\\nClass distribution:\")\nprint(y.value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:25:24.627655Z","iopub.execute_input":"2026-10-08T20:25:24.628138Z","iopub.status.idle":"2026-10-08T20:25:27.779905Z","shell.execute_reply.started":"2026-10-08T20:25:24.6281Z","shell.execute_reply":"2026-10-08T20:25:27.778908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"n = len(train)\n\ntrain_end = int(n * 0.70)\nval_end = int(n * 0.85)\n\nX_train = X.iloc[:train_end]\nX_val = X.iloc[train_end:val_end]\nX_test = X.iloc[val_end:]\n\ny_train = y.iloc[:train_end]\ny_val = y.iloc[train_end:val_end]\ny_test = y.iloc[val_end:]\n\nprint(\"Train:\", X_train.shape)\nprint(\"Validation:\", X_val.shape)\nprint(\"Test:\", X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:26:22.198784Z","iopub.execute_input":"2026-10-08T20:26:22.19971Z","iopub.status.idle":"2026-10-08T20:26:22.210228Z","shell.execute_reply.started":"2026-10-08T20:26:22.19966Z","shell.execute_reply":"2026-10-08T20:26:22.208933Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train anomaly rate:\", y_train.mean())\nprint(\"Validation anomaly rate:\", y_val.mean())\nprint(\"Test anomaly rate:\", y_test.mean())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:26:37.110765Z","iopub.execute_input":"2026-10-08T20:26:37.111154Z","iopub.status.idle":"2026-10-08T20:26:37.13134Z","shell.execute_reply.started":"2026-10-08T20:26:37.111124Z","shell.execute_reply":"2026-10-08T20:26:37.130374Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import IsolationForest\n\nnormal_train = X_train[y_train == 0]\n\nprint(\"Normal training rows:\", len(normal_train))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:29:53.687688Z","iopub.execute_input":"2026-10-08T20:29:53.688653Z","iopub.status.idle":"2026-10-08T20:29:58.189975Z","shell.execute_reply.started":"2026-10-08T20:29:53.688607Z","shell.execute_reply":"2026-10-08T20:29:58.188934Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample_size = 300_000\n\nX_train_sample = normal_train.sample(\n    n=sample_size,\n    random_state=42\n)\n\nprint(\"Sample shape:\", X_train_sample.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:30:11.49351Z","iopub.execute_input":"2026-10-08T20:30:11.494071Z","iopub.status.idle":"2026-10-08T20:30:12.231754Z","shell.execute_reply.started":"2026-10-08T20:30:11.494039Z","shell.execute_reply":"2026-10-08T20:30:12.2309Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = IsolationForest(\n    n_estimators=200,\n    max_samples=10_000,\n    contamination=\"auto\",\n    random_state=42,\n    n_jobs=-1\n)\n\nmodel.fit(X_train_sample)\n\nprint(\"Training finished.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:30:37.537782Z","iopub.execute_input":"2026-10-08T20:30:37.538181Z","iopub.status.idle":"2026-10-08T20:30:40.285014Z","shell.execute_reply.started":"2026-10-08T20:30:37.53815Z","shell.execute_reply":"2026-10-08T20:30:40.284031Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\nprint(\"Validation scores:\")\nprint(\"Min:\", val_scores.min())\nprint(\"Max:\", val_scores.max())\nprint(\"Mean:\", val_scores.mean())\nprint(\"Median:\", np.median(val_scores))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:33:48.778341Z","iopub.execute_input":"2026-10-08T20:33:48.778752Z","iopub.status.idle":"2026-10-08T20:33:48.820039Z","shell.execute_reply.started":"2026-10-08T20:33:48.778718Z","shell.execute_reply":"2026-10-08T20:33:48.81882Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import precision_recall_curve\n\nprecision, recall, thresholds = precision_recall_curve(\n    y_val,\n    -val_scores\n)\n\nf1_scores = 2 * (precision * recall) / (precision + recall + 1e-10)\n\nbest_idx = np.argmax(f1_scores[:-1])\nbest_threshold = thresholds[best_idx]\n\nprint(\"Best threshold:\", best_threshold)\nprint(\"Best Precision:\", precision[best_idx])\nprint(\"Best Recall:\", recall[best_idx])\nprint(\"Best F1:\", f1_scores[best_idx])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:34:52.818396Z","iopub.execute_input":"2026-10-08T20:34:52.818806Z","iopub.status.idle":"2026-10-08T20:34:53.547778Z","shell.execute_reply.started":"2026-10-08T20:34:52.818775Z","shell.execute_reply":"2026-10-08T20:34:53.546779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"all_features = baseline_channels + telecommand_cols\n\nX_all = train[all_features]\n\nX_all_train = X_all.iloc[:train_end]\nX_all_val = X_all.iloc[train_end:val_end]\n\nprint(\"Features:\", len(all_features))\nprint(\"Train shape:\", X_all_train.shape)\nprint(\"Validation shape:\", X_all_val.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:37:08.168749Z","iopub.execute_input":"2026-10-08T20:37:08.169208Z","iopub.status.idle":"2026-10-08T20:37:10.958459Z","shell.execute_reply.started":"2026-10-08T20:37:08.169179Z","shell.execute_reply":"2026-10-08T20:37:10.957297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"normal_all_train = X_all_train[y_train == 0]\n\nprint(\"Normal training rows:\", len(normal_all_train))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:40:53.668342Z","iopub.execute_input":"2026-10-08T20:40:53.668896Z","iopub.status.idle":"2026-10-08T20:40:55.848431Z","shell.execute_reply.started":"2026-10-08T20:40:53.668817Z","shell.execute_reply":"2026-10-08T20:40:55.847614Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_all_train_sample = normal_all_train.sample(\n    n=300_000,\n    random_state=42\n)\n\nprint(\"Sample shape:\", X_all_train_sample.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:42:11.995863Z","iopub.execute_input":"2026-10-08T20:42:11.996248Z","iopub.status.idle":"2026-10-08T20:42:12.747628Z","shell.execute_reply.started":"2026-10-08T20:42:11.996216Z","shell.execute_reply":"2026-10-08T20:42:12.746652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model_all = IsolationForest(\n    n_estimators=200,\n    max_samples=10_000,\n    contamination=\"auto\",\n    random_state=42,\n    n_jobs=-1\n)\n\nmodel_all.fit(X_all_train_sample)\n\nprint(\"Training finished.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:43:23.846269Z","iopub.execute_input":"2026-10-08T20:43:23.846621Z","iopub.status.idle":"2026-10-08T20:43:27.305474Z","shell.execute_reply.started":"2026-10-08T20:43:23.846595Z","shell.execute_reply":"2026-10-08T20:43:27.30454Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_scores_all = model_all.decision_function(X_all_val)\n\nprint(\"Validation scores:\")\nprint(\"Min:\", val_scores_all.min())\nprint(\"Max:\", val_scores_all.max())\nprint(\"Mean:\", val_scores_all.mean())\nprint(\"Median:\", np.median(val_scores_all))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:45:33.62777Z","iopub.execute_input":"2026-10-08T20:45:33.628311Z","iopub.status.idle":"2026-10-08T20:46:19.422067Z","shell.execute_reply.started":"2026-10-08T20:45:33.628276Z","shell.execute_reply":"2026-10-08T20:46:19.420881Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"precision_all, recall_all, thresholds_all = precision_recall_curve(\n    y_val,\n    -val_scores_all\n)\n\nf1_scores_all = (\n    2 * (precision_all * recall_all)\n    / (precision_all + recall_all + 1e-10)\n)\n\nbest_idx_all = np.argmax(f1_scores_all[:-1])\nbest_threshold_all = thresholds_all[best_idx_all]\n\nprint(\"Best threshold:\", best_threshold_all)\nprint(\"Best Precision:\", precision_all[best_idx_all])\nprint(\"Best Recall:\", recall_all[best_idx_all])\nprint(\"Best F1:\", f1_scores_all[best_idx_all])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:46:36.096499Z","iopub.execute_input":"2026-10-08T20:46:36.096891Z","iopub.status.idle":"2026-10-08T20:46:36.849916Z","shell.execute_reply.started":"2026-10-08T20:46:36.096797Z","shell.execute_reply":"2026-10-08T20:46:36.848819Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"anomaly_mask = train[\"is_anomaly\"].to_numpy()\n\n# Find lengths of consecutive anomaly segments\nchanges = np.diff(\n    np.concatenate(([0], anomaly_mask, [0]))\n)\n\nstarts = np.where(changes == 1)[0]\nends = np.where(changes == -1)[0]\n\nanomaly_lengths = ends - starts\n\nprint(\"Number of anomaly segments:\", len(anomaly_lengths))\nprint(\"Shortest anomaly:\", anomaly_lengths.min())\nprint(\"Longest anomaly:\", anomaly_lengths.max())\nprint(\"Mean anomaly length:\", anomaly_lengths.mean())\nprint(\"Median anomaly length:\", np.median(anomaly_lengths))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:55:26.396959Z","iopub.execute_input":"2026-10-08T20:55:26.397661Z","iopub.status.idle":"2026-10-08T20:55:26.591204Z","shell.execute_reply.started":"2026-10-08T20:55:26.397618Z","shell.execute_reply":"2026-10-08T20:55:26.589944Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"\\nAnomaly length percentiles:\")\n\nprint(\n    np.percentile(\n        anomaly_lengths,\n        [25, 50, 75, 90, 95, 99]\n    )\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:55:42.029345Z","iopub.execute_input":"2026-10-08T20:55:42.029876Z","iopub.status.idle":"2026-10-08T20:55:42.037626Z","shell.execute_reply.started":"2026-10-08T20:55:42.029846Z","shell.execute_reply":"2026-10-08T20:55:42.036153Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Window size:\", 128)\nprint(\"Number of features:\", len(baseline_channels))\n\nprint(\"\\nTrain:\")\nprint(X_train.shape)\n\nprint(\"\\nValidation:\")\nprint(X_val.shape)\n\nprint(\"\\nTest:\")\nprint(X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:56:47.786808Z","iopub.execute_input":"2026-10-08T20:56:47.787236Z","iopub.status.idle":"2026-10-08T20:56:47.793907Z","shell.execute_reply.started":"2026-10-08T20:56:47.787208Z","shell.execute_reply":"2026-10-08T20:56:47.792984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import StandardScaler\n\nscaler = StandardScaler()\n\nscaler.fit(\n    X_train[y_train == 0]\n)\n\nprint(\"Scaler fitted on normal training data.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-10-08T20:58:08.835126Z","iopub.execute_input":"2026-10-08T20:58:08.835564Z","iopub.status.idle":"2026-10-08T20:58:12.980312Z","shell.execute_reply.started":"2026-10-08T20:58:08.835527Z","shell.execute_reply":"2026-10-08T20:58:12.979081Z"}},"outputs":[],"execution_count":null}]}