{"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":"gpu","dataSources":[{"sourceId":53666,"databundleVersionId":6589269,"sourceType":"competition"},{"sourceId":7100476,"sourceType":"datasetVersion","datasetId":4093016},{"sourceId":7101466,"sourceType":"datasetVersion","datasetId":4093703},{"sourceId":7127796,"sourceType":"datasetVersion","datasetId":4063559},{"sourceId":7124130,"sourceType":"datasetVersion","datasetId":4109527},{"sourceId":7124148,"sourceType":"datasetVersion","datasetId":4109540},{"sourceId":152581884,"sourceType":"kernelVersion"},{"sourceId":153323987,"sourceType":"kernelVersion"}],"dockerImageVersionId":30588,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install -q hydra-core segmentation_models_pytorch==0.3.3 --no-index --find-links=/kaggle/input/sleep-packages","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:07:27.433336Z","iopub.execute_input":"2023-12-05T16:07:27.433666Z","iopub.status.idle":"2023-12-05T16:07:49.696613Z","shell.execute_reply.started":"2023-12-05T16:07:27.433639Z","shell.execute_reply":"2023-12-05T16:07:49.695534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport sys\nimport gc\nimport re\nimport random\nimport shutil\nimport subprocess\nfrom pathlib import Path\n\nfrom tqdm.notebook import tqdm\n\nimport numpy as np\nimport polars as pl\n\nsys.path.append(\"/kaggle/input/sleep-metrics\")\nfrom sleep_metrics import event_detection_ap\n\nINPUT = Path(\"/kaggle/input\")\nWORKING = Path(\"/kaggle/working\")\n\nSEQUENCE_PREDICTION_SCHEMA = {\n    \"series_id\": str,\n    \"step\": pl.UInt32,\n    \"onset_prediction\": pl.Float32,\n    \"wakeup_prediction\": pl.Float32,\n    \"sleep_prediction\": pl.Float32,\n}\n\nEVENT_SCHEMA = {\n    \"series_id\": str,\n    \"step\": pl.UInt32,\n    \"score\": pl.Float32,\n    \"event\": str,\n}\n\n\nSEQUENCE_PREDICTION_DATAFRAME = (\n    pl.scan_parquet(\"/kaggle/input/child-mind-institute-detect-sleep-states/test_series.parquet\")\n    .select([\"series_id\", \"step\"])\n    .sort([\"series_id\", \"step\"])\n    .collect()\n)\nSERIES_IDS = (\n    SEQUENCE_PREDICTION_DATAFRAME\n    .get_column(\"series_id\")\n    .unique()\n    .to_list()\n)","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:07:49.698622Z","iopub.execute_input":"2023-12-05T16:07:49.698922Z","iopub.status.idle":"2023-12-05T16:07:50.493063Z","shell.execute_reply.started":"2023-12-05T16:07:49.698896Z","shell.execute_reply":"2023-12-05T16:07:50.492232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AGG_TYPE = \"gmean\" # {\"mean\", \"gmean\"}\nEXP_1XX = [\n#     \"exp116\",\n    \"exp120\",\n    \"exp121\",\n]\n\nEXP_2XX = [\n    (\"exp213\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34\"),\n    (\"exp214\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=efficientnet-b0\"),\n#     (\"exp215\", \"model=Spec2DCNN feature_extractor=LSTMFeatureExtractor decoder=UNet1DDecoder model.params.encoder_name=resnet34\"),\n#     (\"exp216\", \"model=Spec2DCNN feature_extractor=LSTMFeatureExtractor decoder=LSTMDecoder model.params.encoder_name=resnet34\"),\n    (\"exp217\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34 downsample_rate=4 duration=8640\"),\n    (\"exp218\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34 downsample_rate=2 duration=8640\"),\n#     (\"exp219\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=LSTMDecoder model.params.encoder_name=resnet34 downsample_rate=4 duration=8640\"),\n    (\"exp220\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=resnet34 downsample_rate=2 duration=8640\"),\n    (\"exp221\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=efficientnet-b0 downsample_rate=2 duration=8640\"),\n    (\"exp222\", \"model=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=efficientnet-b0 downsample_rate=4 duration=8640\"),\n]\n\nN = len(EXP_1XX) + len(EXP_2XX)","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:16:21.154330Z","iopub.execute_input":"2023-12-05T16:16:21.154698Z","iopub.status.idle":"2023-12-05T16:16:21.161175Z","shell.execute_reply.started":"2023-12-05T16:16:21.154671Z","shell.execute_reply":"2023-12-05T16:16:21.160177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# inference","metadata":{}},{"cell_type":"markdown","source":"# exp1xx","metadata":{}},{"cell_type":"code","source":"for EXPERIMENT in EXP_1XX:\n    for path in (INPUT / f\"sleep-{EXPERIMENT}\").glob(\"*\"):\n        p = path.as_posix()\n        if re.match(r\"^.+\\.(py|yaml|pt|pkl)$\", p):\n            shutil.copy(path, WORKING)\n            print(f\"### {p} -> {WORKING.as_posix()}/{os.path.basename(p)}\")\n\n    subprocess.run(\"python inference.py\", shell=True)\n\n    os.rename(\n        \"/kaggle/working/test_sequence_prediction_dataframe.parquet\",\n        f\"/kaggle/working/{EXPERIMENT}.parquet\"\n    )\n    \n    # remove unnecessary items\n    for path in Path(\"/kaggle/working/\").glob(\"*\"):\n        p = path.as_posix()\n        if re.match(r\"^.+\\.parquet$\", p):\n            continue\n\n        if path.is_dir():\n            shutil.rmtree(path)\n        else:\n            os.remove(path)","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:07:50.500648Z","iopub.execute_input":"2023-12-05T16:07:50.501221Z","iopub.status.idle":"2023-12-05T16:08:51.714718Z","shell.execute_reply.started":"2023-12-05T16:07:50.501189Z","shell.execute_reply":"2023-12-05T16:08:51.713768Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# exp2xx","metadata":{}},{"cell_type":"markdown","source":"## exp213\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34\n\n## exp214\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=efficientnet-b0\n\n## exp215\nmodel=Spec2DCNN feature_extractor=LSTMFeatureExtractor decoder=UNet1DDecoder model.params.encoder_name=resnet34\n\n## exp216\nmodel=Spec2DCNN feature_extractor=LSTMFeatureExtractor decoder=LSTMDecoder model.params.encoder_name=resnet34\n\n## exp217\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34 downsample_rate=4 duration=8640\n\n## exp218\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=UNet1DDecoder model.params.encoder_name=resnet34 downsample_rate=2 duration=8640\n\n## exp219\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=LSTMDecoder model.params.encoder_name=resnet34 downsample_rate=4 duration=8640\n\n## exp220\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=resnet34 downsample_rate=2 duration=8640\n\n## exp221\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=efficientnet-b0 downsample_rate=2 duration=8640\n\n## exp222\nmodel=Spec2DCNN feature_extractor=CNNSpectrogram decoder=TransformerDecoder model.params.encoder_name=efficientnet-b0 downsample_rate=4 duration=8640\n","metadata":{}},{"cell_type":"code","source":"%cd /kaggle/input/sleep-code/tubo-san","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:08:54.853764Z","iopub.execute_input":"2023-12-05T16:08:54.854646Z","iopub.status.idle":"2023-12-05T16:08:54.867716Z","shell.execute_reply.started":"2023-12-05T16:08:54.854611Z","shell.execute_reply":"2023-12-05T16:08:54.866704Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!python -m run.prepare_data dir=kaggle phase=test","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:08:54.994661Z","iopub.execute_input":"2023-12-05T16:08:54.995340Z","iopub.status.idle":"2023-12-05T16:08:57.803608Z","shell.execute_reply.started":"2023-12-05T16:08:54.995307Z","shell.execute_reply":"2023-12-05T16:08:57.802470Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for EXP_NAME, args in EXP_2XX:\n    test_sequence_prediction_dataframe = SEQUENCE_PREDICTION_DATAFRAME.select(\"series_id\", \"step\")\n    \n    for fold_name in [\n        \"fold0\",\n        \"fold1\",\n        \"fold2\",\n        \"fold3\",\n        \"fold4\",\n    ]:\n        exp_fold_name = f\"{EXP_NAME}_{fold_name}\"\n\n        print(\"###\", exp_fold_name, \"###\")\n\n        command = \\\n        f\"\"\"\n        python -m run.inference \\\n            dir=kaggle \\\n            num_workers=2 \\\n            exp_name={exp_fold_name} \\\n            weight.run_name=single \\\n            phase=test \\\n            {args}\n        \"\"\"\n\n        subprocess.run(command, shell=True)\n\n        test_sequence_prediction = pl.read_parquet(\"/kaggle/working/sequence_prediction_dataframe.parquet\").sort([\"series_id\", \"step\"])\n        test_sequence_prediction_dataframe = test_sequence_prediction_dataframe.join(\n            test_sequence_prediction.select(\n                [\n                    pl.col(\"series_id\"),\n                    pl.col(\"step\"),\n                    pl.col(\"onset_prediction\").name.suffix(f\"_{exp_fold_name}\"),\n                    pl.col(\"wakeup_prediction\").name.suffix(f\"_{exp_fold_name}\"),\n                ]\n            ),\n            on=[\"series_id\", \"step\"],\n        )\n\n    test_sequence_prediction_dataframe = test_sequence_prediction_dataframe.select(\n        pl.col(\"series_id\"),\n        pl.col(\"step\"),\n    ).with_columns(\n        test_sequence_prediction_dataframe.select(\"^onset_prediction_.+$\").mean(axis=1).cast(pl.Float32).alias(\"onset_prediction\"),\n        test_sequence_prediction_dataframe.select(\"^wakeup_prediction_.+$\").mean(axis=1).cast(pl.Float32).alias(\"wakeup_prediction\"),\n    )\n    \n    test_sequence_prediction_dataframe.write_parquet(f\"/kaggle/working/{EXP_NAME}.parquet\")\n    \n    del test_sequence_prediction_dataframe\n    gc.collect()","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:16:34.057282Z","iopub.execute_input":"2023-12-05T16:16:34.058192Z","iopub.status.idle":"2023-12-05T16:20:05.561668Z","shell.execute_reply.started":"2023-12-05T16:16:34.058150Z","shell.execute_reply":"2023-12-05T16:20:05.560804Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# make ensemble submission","metadata":{}},{"cell_type":"code","source":"from scipy.signal import find_peaks\n\ndef make_event_prediction(\n    series_id: str,\n    sequence_prediction: pl.DataFrame,\n    height: float,\n    distance: int,\n):\n    step = sequence_prediction.get_column(\"step\").to_numpy()\n    onset_prediction = sequence_prediction.get_column(\"onset_prediction\").rolling_mean(12, center=True).to_numpy().copy()\n    wakeup_prediction = sequence_prediction.get_column(\"wakeup_prediction\").rolling_mean(12, center=True).to_numpy().copy()\n    \n    # find peaks\n    onset_candidate = find_peaks(onset_prediction, height=height, distance=distance)[0]\n    wakeup_candidate = find_peaks(wakeup_prediction, height=height, distance=distance)[0]\n    \n    onset = pl.DataFrame(\n        {\n            \"series_id\": series_id,\n            \"step\": step[onset_candidate],\n            \"score\": onset_prediction[onset_candidate].reshape(-1),\n            \"event\": [\"onset\"] * len(onset_candidate),\n        },\n        schema=EVENT_SCHEMA,\n    )\n\n    wakeup = pl.DataFrame(\n        {\n            \"series_id\": series_id,\n            \"step\": step[wakeup_candidate],\n            \"score\": wakeup_prediction[wakeup_candidate].reshape(-1),\n            \"event\": [\"wakeup\"] * len(wakeup_candidate),\n        },\n        schema=EVENT_SCHEMA,\n    )\n\n    result = pl.concat([onset, wakeup], how=\"vertical\").sort([\"series_id\", \"step\"])\n\n    if len(result) == 0:\n        return pl.DataFrame(\n            {\n                \"series_id\": series_id,\n                \"step\": 0,\n                \"event\": \"onset\",\n                \"score\": 0,\n            },\n            schema=EVENT_SCHEMA,\n        )\n\n    return result","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:22:06.847975Z","iopub.execute_input":"2023-12-05T16:22:06.848712Z","iopub.status.idle":"2023-12-05T16:22:06.858763Z","shell.execute_reply.started":"2023-12-05T16:22:06.848678Z","shell.execute_reply":"2023-12-05T16:22:06.857568Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_event_prediction_dataframe = pl.DataFrame(schema=EVENT_SCHEMA)\n\nfor series_id in SERIES_IDS:\n    print(\"###\", f\"{series_id=}\", \"###\")\n    sequence_prediction_dataframe = SEQUENCE_PREDICTION_DATAFRAME.filter(pl.col(\"series_id\") == series_id)\n    for idx, sequence_prediction_path in enumerate(sorted(list(Path(\"/kaggle/working\").glob(\"exp*.parquet\")))):\n        sequence_prediction = pl.scan_parquet(\n            sequence_prediction_path,\n        ).filter(pl.col(\"series_id\") == series_id).sort([\"step\"]).collect()\n\n        sequence_prediction_dataframe = sequence_prediction_dataframe.join(\n            (\n                sequence_prediction\n                .with_columns(\n                    pl.col(\"onset_prediction\").alias(f\"onset_prediction_{idx}\"),\n                    pl.col(\"wakeup_prediction\").alias(f\"wakeup_prediction_{idx}\"),\n                )\n                .select(\n                    \"series_id\",\n                    \"step\",\n                    f\"onset_prediction_{idx}\",\n                    f\"wakeup_prediction_{idx}\",\n                )\n            ),\n            on=[\"series_id\", \"step\"]\n        )\n    \n    # aggregation\n    if AGG_TYPE == \"mean\":\n        sequence_prediction_dataframe = sequence_prediction_dataframe.select(\n            pl.col(\"series_id\"),\n            pl.col(\"step\"),\n        ).with_columns(\n            sequence_prediction_dataframe.select(\"^onset_prediction.*$\").mean(axis=1).cast(pl.Float32).alias(\"onset_prediction\"),\n            sequence_prediction_dataframe.select(\"^wakeup_prediction.*$\").mean(axis=1).cast(pl.Float32).alias(\"wakeup_prediction\"),\n        ).clone()\n    elif AGG_TYPE == \"gmean\":\n        sequence_prediction_dataframe = sequence_prediction_dataframe.select(\n            pl.col(\"series_id\"),\n            pl.col(\"step\"),\n        ).with_columns(\n            sequence_prediction_dataframe.select(pl.sum_horizontal(pl.col(\"^onset_prediction_.+$\").log() / N).exp()).to_series().alias(\"onset_prediction\"),\n            sequence_prediction_dataframe.select(pl.sum_horizontal(pl.col(\"^wakeup_prediction_.+$\").log() / N).exp()).to_series().alias(\"wakeup_prediction\"),\n        ).clone()\n    else:\n        raise ValueError()\n    \n    # make event prediction\n    test_event_prediction = make_event_prediction(\n        series_id=series_id,\n        sequence_prediction=sequence_prediction_dataframe.sort(\"step\"),\n        height=0.08,\n        distance=75,\n    )\n    test_event_prediction_dataframe = pl.concat([test_event_prediction_dataframe, test_event_prediction], how=\"vertical\")","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:22:07.009970Z","iopub.execute_input":"2023-12-05T16:22:07.010708Z","iopub.status.idle":"2023-12-05T16:22:07.080071Z","shell.execute_reply.started":"2023-12-05T16:22:07.010677Z","shell.execute_reply":"2023-12-05T16:22:07.078976Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"row_id = pl.Series(list(range(len(test_event_prediction_dataframe))), dtype=pl.Int64).alias(\"row_id\")\n(\n    test_event_prediction_dataframe\n    .with_columns(row_id)\n    .select([\"row_id\", \"series_id\", \"step\", \"event\", \"score\"])\n    .write_csv(\"/kaggle/working/submission.csv\")\n)\n\n!head /kaggle/working/submission.csv","metadata":{"execution":{"iopub.status.busy":"2023-12-05T16:22:09.885784Z","iopub.execute_input":"2023-12-05T16:22:09.886611Z","iopub.status.idle":"2023-12-05T16:22:10.839910Z","shell.execute_reply.started":"2023-12-05T16:22:09.886576Z","shell.execute_reply":"2023-12-05T16:22:10.838774Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# remove unnecessary files","metadata":{}},{"cell_type":"code","source":"%%bash\n\n# remove files except for submission.csv\n\nKEEP_FILE=\"/kaggle/working/submission.csv\"\nfor item in /kaggle/working/*; do\n    if [ \"$item\" != \"$KEEP_FILE\" ]; then\n        rm -rf \"$item\"\n    fi\ndone","metadata":{"execution":{"iopub.status.busy":"2023-12-04T23:08:05.483675Z","iopub.execute_input":"2023-12-04T23:08:05.483987Z","iopub.status.idle":"2023-12-04T23:08:05.523704Z","shell.execute_reply.started":"2023-12-04T23:08:05.483953Z","shell.execute_reply":"2023-12-04T23:08:05.522950Z"},"trusted":true},"execution_count":null,"outputs":[]}]}