{"metadata":{"kaggle":{"accelerator":"tpu1vmV38","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":8108072,"sourceType":"datasetVersion","datasetId":4789213},{"sourceId":8363000,"sourceType":"datasetVersion","datasetId":4970504},{"sourceId":8708046,"sourceType":"datasetVersion","datasetId":4786201},{"sourceId":8730903,"sourceType":"datasetVersion","datasetId":4836532},{"sourceId":8754009,"sourceType":"datasetVersion","datasetId":4955173}],"dockerImageVersionId":30698,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false},"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.10.11"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!lscpu","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:03:34.083882Z","iopub.status.busy":"2024-06-05T21:03:34.082943Z","iopub.status.idle":"2024-06-05T21:03:35.107911Z","shell.execute_reply":"2024-06-05T21:03:35.106571Z","shell.execute_reply.started":"2024-06-05T21:03:34.083811Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!export OMP_NUM_THREADS=N\n\n!export OMP_SCHEDULE=STATIC\n!export OMP_PROC_BIND=CLOSE\n!export GOMP_CPU_AFFINITY=\"N-M\"","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:03:35.552576Z","iopub.status.busy":"2024-06-05T21:03:35.552163Z","iopub.status.idle":"2024-06-05T21:03:39.66983Z","shell.execute_reply":"2024-06-05T21:03:39.668198Z","shell.execute_reply.started":"2024-06-05T21:03:35.552544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install \"/kaggle/input/openvino-202410-py310/openvino-2024.1.0-15008-cp310-cp310-manylinux2014_x86_64.whl\" --no-index --find-links \"/kaggle/input/openvino-202410-py310\"","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:03:39.673298Z","iopub.status.busy":"2024-06-05T21:03:39.672755Z","iopub.status.idle":"2024-06-05T21:03:54.875603Z","shell.execute_reply":"2024-06-05T21:03:54.874235Z","shell.execute_reply.started":"2024-06-05T21:03:39.673251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from datetime import datetime\nfrom glob import glob\nfrom pathlib import Path\n\nimport librosa as lb\nimport numpy as np\nimport openvino as ov\nimport pandas as pd\nimport torch\nimport torchaudio\nfrom torch.utils.data import DataLoader","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:03:54.878026Z","iopub.status.busy":"2024-06-05T21:03:54.877518Z","iopub.status.idle":"2024-06-05T21:04:03.419536Z","shell.execute_reply":"2024-06-05T21:04:03.418095Z","shell.execute_reply.started":"2024-06-05T21:03:54.877975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    num_classes = 182\n    DEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n    data_root = \"/kaggle/input/birdclef-2024/\"\n    train_path = \"/kaggle/input/birdclef-2024/train_metadata.csv\"\n    test_path = \"/kaggle/input/birdclef-2024/test_soundscapes\"\n\n    SR = 32000\n    DURATION = 5\n    infer_duration = 5\n    train_duration = 10\n\n    # simple melspec model\n    simple_model_ckpt = [\n        \"/kaggle/input/birdcled2024-models/v045/simple_cnn_v1.xml\",\n    ]\n\n    # 2022-2nd melspec model\n    re_model_ckpt = [\n        \"/kaggle/input/birdcled2024-models/v028/cnn_v3_rexnet.xml\",\n        \"/kaggle/input/hb-b24/0508 187class/187class.xml\",\n    ]\n\n    # raw-signal model\n    reshp_model_ckpt = [\n        \"/kaggle/input/birdclef2024-openvino-model/EXP034_reshape_effnetb0_5sec_removedupl_gsk5folds_ds2_unlabelnoise_cleandata/best_fold-0.xml\",\n        \"/kaggle/input/birdclef2024-openvino-model/EXP034_reshape_effnetb0_5sec_removedupl_gsk5folds_ds2_unlabelnoise_cleandata/best_fold-1.xml\",\n    ]","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:03.422501Z","iopub.status.busy":"2024-06-05T21:04:03.422096Z","iopub.status.idle":"2024-06-05T21:04:03.429693Z","shell.execute_reply":"2024-06-05T21:04:03.428318Z","shell.execute_reply.started":"2024-06-05T21:04:03.422468Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Make dataframe","metadata":{}},{"cell_type":"code","source":"test_files = glob(Config.test_path + \"/*\")\nif len(test_files) == 1:\n    Config.test_path = \"/kaggle/input/birdclef-2024/unlabeled_soundscapes\"\n    IS_COMMIT = True\nelse:\n    IS_COMMIT = False\nprint(f\"{IS_COMMIT=}\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(Config.train_path)\nConfig.num_classes = len(df_train.primary_label.unique())","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:03.452553Z","iopub.status.busy":"2024-06-05T21:04:03.452233Z","iopub.status.idle":"2024-06-05T21:04:03.651891Z","shell.execute_reply":"2024-06-05T21:04:03.650651Z","shell.execute_reply.started":"2024-06-05T21:04:03.452526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.DataFrame(\n    [(path.stem, path) for path in Path(Config.test_path).glob(\"*.ogg\")], columns=[\"filename\", \"path\"]\n)\n\nif IS_COMMIT:\n    df_test = df_test.sort_values(by=\"filename\", ascending=True).reset_index(drop=True)\n    df_test = df_test.iloc[:15]\nprint(df_test.shape)\ndf_test.head()","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:03.653609Z","iopub.status.busy":"2024-06-05T21:04:03.65329Z","iopub.status.idle":"2024-06-05T21:04:03.824625Z","shell.execute_reply":"2024-06-05T21:04:03.823542Z","shell.execute_reply.started":"2024-06-05T21:04:03.653583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dataset","metadata":{}},{"cell_type":"code","source":"class Compose:\n    def __init__(self, transforms: list):\n        self.transforms = transforms\n\n    def __call__(self, y: np.ndarray, sr):\n        for trns in self.transforms:\n            y = trns(y, sr)\n        return y\n\n\nclass AudioTransform:\n    def __init__(self, always_apply=False, p=0.5):\n        self.always_apply = always_apply\n        self.p = p\n\n    def __call__(self, y: np.ndarray, sr):\n        if self.always_apply:\n            return self.apply(y, sr=sr)\n        else:\n            if np.random.rand() < self.p:\n                return self.apply(y, sr=sr)\n            else:\n                return y\n\n    def apply(self, y: np.ndarray, **params):\n        raise NotImplementedError\n\n\nclass OneOf(Compose):\n    # https://github.com/albumentations-team/albumentations/blob/master/albumentations/core/composition.py\n    def __init__(self, transforms, p=0.5):\n        super().__init__(transforms)\n        self.p = p\n        transforms_ps = [t.p for t in transforms]\n        s = sum(transforms_ps)\n        self.transforms_ps = [t / s for t in transforms_ps]\n\n    def __call__(self, y: np.ndarray, sr):\n        data = y\n        if self.transforms_ps and (random.random() < self.p):\n            random_state = np.random.RandomState(random.randint(0, 2**32 - 1))\n            t = random_state.choice(self.transforms, p=self.transforms_ps)\n            data = t(y, sr)\n        return data\n\n\nclass Normalize(AudioTransform):\n    def __init__(self, always_apply=False, p=1):\n        super().__init__(always_apply, p)\n\n    def apply(self, y: np.ndarray, **params):\n        max_vol = np.abs(y).max()\n        y_vol = y * 1 / max_vol\n        return np.asfortranarray(y_vol)","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:03.826637Z","iopub.status.busy":"2024-06-05T21:04:03.826218Z","iopub.status.idle":"2024-06-05T21:04:03.841674Z","shell.execute_reply":"2024-06-05T21:04:03.840551Z","shell.execute_reply.started":"2024-06-05T21:04:03.826598Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"END_PAD = int(Config.SR * (Config.train_duration - Config.DURATION) / 2)\nSTART_PAD = int(Config.SR * (Config.train_duration - Config.DURATION) / 2)\n\nWINDOW_DIFF = Config.train_duration - Config.DURATION\nHALF_WINDOW_DIFF = WINDOW_DIFF / 2","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:03.843839Z","iopub.status.busy":"2024-06-05T21:04:03.843386Z","iopub.status.idle":"2024-06-05T21:04:04.020236Z","shell.execute_reply":"2024-06-05T21:04:04.018709Z","shell.execute_reply.started":"2024-06-05T21:04:03.843781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 256x128 img\nhop_length256 = Config.infer_duration * Config.SR // (256 - 1)\nmelspec_transform256 = torchaudio.transforms.MelSpectrogram(\n    sample_rate=Config.SR,\n    hop_length=hop_length256,\n    n_mels=128,\n    f_min=0,\n    f_max=Config.SR // 2,\n    n_fft=2048,\n    center=True,\n    pad_mode=\"constant\",\n    norm=\"slaney\",\n    onesided=True,\n    mel_scale=\"slaney\",\n)\ndb_transform = torchaudio.transforms.AmplitudeToDB(stype=\"power\", top_db=80)\n\ndef transform_to_spec(audio, train=True):\n    spec256 = melspec_transform256(audio)\n    spec256 = db_transform(spec256)\n\n    spec256_80 = (spec256 + 80) / 80\n    spec256 = spec256 / 255\n\n    return spec256, spec256_80\n\n\ndef reshp(images):\n    bs, clip_len, channel_num, mel_num, time_len = images.size()\n    images = images.reshape((bs * clip_len, channel_num, mel_num, time_len))\n    return images\n\n\ndef reshp_wave(waves):\n    bs, clip_len, dims = waves.size()\n    waves = waves.reshape((bs * clip_len, dims))\n    return waves, dims","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BirdDatasetSED(torch.utils.data.Dataset):\n    def __init__(\n        self,\n        df,\n        sr=Config.SR,\n        n_mels=128,\n        fmin=0,\n        fmax=None,\n        step=None,\n        res_type=\"kaiser_fast\",\n        resample=True,\n        duration=Config.DURATION,\n        downsample=2,\n        train=True,\n    ):\n        self.df = df\n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax or self.sr // 2\n\n        self.train = train\n        self.duration = duration\n\n        self.audio_length = self.duration * self.sr\n        self.step = step or self.audio_length\n\n        self.res_type = res_type\n        self.resample = resample\n        self.downsample = downsample\n        self.wave_transform = Compose(\n            [\n                Normalize(p=1),\n            ]\n        )\n\n    def __len__(self):\n        return len(self.df)\n\n    def read_file(self, filepath):\n        audio, orig_sr = torchaudio.load(filepath)\n\n        # convert signal to mono\n        if audio.shape[0] == 1:\n            audio = audio[0].numpy()\n        else:\n            audio = audio.mean(0).numpy()\n\n        if self.resample and orig_sr != self.sr:\n            audio = lb.resample(audio, orig_sr, self.sr, res_type=self.res_type)\n\n        seconds = []\n        for i in range(self.audio_length, len(audio) + self.step, self.step):\n            start = max(0, i - self.audio_length)\n            end = start + self.audio_length\n            if end > len(audio):\n                pass\n            else:\n                seconds.append(int(end / self.sr))\n\n        # padding\n        audio = np.concatenate([audio, audio, audio])\n\n        audios = []\n        audios_clip = []\n        for i, second in enumerate(seconds):\n            end_seconds = int(second)\n            start_seconds = int(end_seconds - Config.DURATION)\n\n            # for raw-signal models, make -2.5 ~ 5.0sec clips\n            end_index_clip = int(self.sr * (end_seconds)) + len(audio) // 3\n            start_index_clip = int(self.sr * (start_seconds - HALF_WINDOW_DIFF)) + len(audio) // 3\n            start_pad_clip = int(self.sr * HALF_WINDOW_DIFF)\n\n            y_clip = audio[start_index_clip:end_index_clip].astype(np.float32)\n            if i == 0:\n                y_clip[:start_pad_clip] = 0\n\n            audio_clip = self.wave_transform(y_clip, self.sr)\n            audio_clip = audio_clip[0 : len(audio_clip) : self.downsample]\n            audios_clip.append(audio_clip)\n\n            # for melspec models, make -2.5 ~ 7.5sec clips\n            end_index = int(self.sr * (end_seconds + HALF_WINDOW_DIFF)) + len(audio) // 3\n            start_index = int(self.sr * (start_seconds - HALF_WINDOW_DIFF)) + len(audio) // 3\n\n            y = audio[start_index:end_index].astype(np.float32)\n            if i == 0:\n                y[:START_PAD] = 0\n            elif i == (len(seconds) - 1):\n                y[-END_PAD:] = 0\n            audios.append(y)\n\n        # make batch, B x L\n        audios = np.stack(audios)\n        audios = torch.from_numpy(audios).float().unsqueeze(1)\n        audios_clip = np.stack(audios_clip)\n        audios_clip = torch.from_numpy(audios_clip).float()\n\n        # trasform to melspecs\n        spec256, spec256_80 = transform_to_spec(audios, train=False)\n        return spec256, spec256_80, audios_clip\n\n    def __getitem__(self, idx):\n        return self.read_file(self.df.iloc[idx][\"path\"])","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:04.024666Z","iopub.status.busy":"2024-06-05T21:04:04.024283Z","iopub.status.idle":"2024-06-05T21:04:04.043882Z","shell.execute_reply":"2024-06-05T21:04:04.042499Z","shell.execute_reply.started":"2024-06-05T21:04:04.024633Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_test = BirdDatasetSED(df_test, sr=Config.SR, duration=Config.DURATION, train=False)\ndl_test = DataLoader(ds_test, batch_size=2, num_workers=4, pin_memory=True)","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:04.182844Z","iopub.status.busy":"2024-06-05T21:04:04.182361Z","iopub.status.idle":"2024-06-05T21:04:04.197288Z","shell.execute_reply":"2024-06-05T21:04:04.195932Z","shell.execute_reply.started":"2024-06-05T21:04:04.182784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load Models","metadata":{}},{"cell_type":"code","source":"core = ov.Core()\n\nrexnet_w256_vol80 = core.compile_model(Config.re_model_ckpt[0], \"CPU\")\nresnext_w256_vol255_c187 = core.compile_model(Config.re_model_ckpt[1], \"CPU\")\n\neffnetb0_reshape_fold0 = core.compile_model(Config.reshp_model_ckpt[0], \"CPU\")\neffnetb0_reshape_fold1 = core.compile_model(Config.reshp_model_ckpt[1], \"CPU\")\n\nrexnet_w256_vol80 = rexnet_w256_vol80.create_infer_request()\nresnext_w256_vol255_c187 = resnext_w256_vol255_c187.create_infer_request()\neffnetb0_reshape_fold0 = effnetb0_reshape_fold0.create_infer_request()\neffnetb0_reshape_fold1 = effnetb0_reshape_fold1.create_infer_request()\n\ninception_w256_vol255 = core.compile_model(Config.simple_model_ckpt[0], \"CPU\")\ninception_w256_vol255 = inception_w256_vol255.create_infer_request()","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:04.199554Z","iopub.status.busy":"2024-06-05T21:04:04.199063Z","iopub.status.idle":"2024-06-05T21:04:06.501757Z","shell.execute_reply":"2024-06-05T21:04:06.500453Z","shell.execute_reply.started":"2024-06-05T21:04:04.199509Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calculate_outputs(outputs1, outputs2):\n    \"\"\"Merge individual TTA predicts into one\"\"\"\n    num_rows = outputs1.shape[0]\n\n    outputs = np.zeros_like(outputs1)\n    for i in range(num_rows):\n        if (i + 1) % 48 != 0:\n            outputs[i] = 0.3 * outputs1[i] + 0.3 * outputs1[i + 1] + 0.4 * outputs2[i]\n        else:\n            outputs[i] = 0.45 * outputs1[i] + 0.55 * outputs2[i]\n    return outputs\n\ndef sigmoid(a):\n    return 1 / (1 + np.exp(-a))","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:04:22.224961Z","iopub.status.busy":"2024-06-05T21:04:22.224483Z","iopub.status.idle":"2024-06-05T21:06:29.125619Z","shell.execute_reply":"2024-06-05T21:06:29.124242Z","shell.execute_reply.started":"2024-06-05T21:04:22.224922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"start = datetime.now()\npredictions = []\nfor spec256, spec256_80, audio_clip in dl_test:\n    spec256 = reshp(spec256)\n    spec256_80 = reshp(spec256_80)\n\n    audio_clip, dims = reshp_wave(audio_clip)\n\n    # raw signals\n    audio_clip1 = audio_clip[:, : int(dims * (2 / 3))] # -2.5 -> 2.5 sec\n    audio_clip2 = audio_clip[:, int(dims * (1 / 3)) :] # 0.0 -> 5.0 sec\n\n    # melspecs\n    img_vol255_tta1 = spec256[:, :, :, 64:320].numpy() # -2.5 -> 2.5 sec\n    img_vol255_tta2 = spec256[:, :, :, 128:384].numpy() # 0.0 -> 5.0 sec\n    img_vol80_tta1 = spec256_80[:, :, :, 64:320].numpy()\n    img_vol80_tta2 = spec256_80[:, :, :, 128:384].numpy()\n\n    # 2022cnn, rexnet\n    outputs_0_1 = rexnet_w256_vol80.infer(img_vol80_tta1)\n    outputs_0_1 = outputs_0_1[list(outputs_0_1.keys())[0]]\n    outputs_0_1 = sigmoid(outputs_0_1)\n\n    outputs_0_2 = rexnet_w256_vol80.infer(img_vol80_tta2)\n    outputs_0_2 = outputs_0_2[list(outputs_0_2.keys())[0]]\n    outputs_0_2 = sigmoid(outputs_0_2)\n\n    # 2022cnn, seresnext\n    outputs_1_1 = resnext_w256_vol255_c187.infer(img_vol255_tta1)\n    outputs_1_1 = outputs_1_1[list(outputs_1_1.keys())[0]]\n    outputs_1_1 = sigmoid(outputs_1_1)\n    outputs_1_1 = outputs_1_1[:, :182]\n\n    outputs_1_2 = resnext_w256_vol255_c187.infer(img_vol255_tta2)\n    outputs_1_2 = outputs_1_2[list(outputs_1_2.keys())[0]]\n    outputs_1_2 = sigmoid(outputs_1_2)\n    outputs_1_2 = outputs_1_2[:, :182]\n\n    # simple cnn, inception-next\n    outputs_simple = inception_w256_vol255.infer(img_vol255_tta2)\n    outputs_simple = outputs_simple[list(outputs_simple.keys())[0]]\n    outputs_simple = sigmoid(outputs_simple)\n\n    # raw-signal, tf_efficientnet\n    outputs_3_1 = effnetb0_reshape_fold0.infer(audio_clip1.numpy())\n    outputs_3_1 = outputs_3_1[list(outputs_3_1.keys())[0]]\n    outputs_3_1 = sigmoid(outputs_3_1)\n\n    outputs_3_2 = effnetb0_reshape_fold0.infer(audio_clip2.numpy())\n    outputs_3_2 = outputs_3_2[list(outputs_3_2.keys())[0]]\n    outputs_3_2 = sigmoid(outputs_3_2)\n\n    # merge TTA predicts\n    outputs_0 = calculate_outputs(outputs_0_1, outputs_0_2)\n    outputs_1 = calculate_outputs(outputs_1_1, outputs_1_2)\n    outputs_3 = calculate_outputs(outputs_3_1, outputs_3_2)\n\n    # ensemble\n    outputs = (0.15 * outputs_simple + 0.25 * outputs_0 + 0.3 * outputs_1 + 0.3 * outputs_3) + 0.3 * (\n        outputs_0 * outputs_3\n    ) ** (0.5)\n    predictions.append(outputs)\n\npredictions = np.concatenate(predictions)\nprint(datetime.now() - start)","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:07:06.982986Z","iopub.status.busy":"2024-06-05T21:07:06.982536Z","iopub.status.idle":"2024-06-05T21:07:06.991844Z","shell.execute_reply":"2024-06-05T21:07:06.990566Z","shell.execute_reply.started":"2024-06-05T21:07:06.982948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# make a submission dataframe\n\ndef make_row_ids(file, num_rows=48):\n    row_ids = np.array([f\"{file}_{(i+1)*5}\" for i in range(num_rows)])\n    return row_ids\n\n\nrow_ids = np.concatenate([make_row_ids(f) for f in df_test[\"filename\"].values])\nbird_cols = list(pd.get_dummies(df_train[\"primary_label\"]).columns)\nsub_df = pd.DataFrame(columns=[\"row_id\"] + bird_cols)\nsub_df[\"row_id\"] = row_ids\nsub_df[bird_cols] = predictions\nrow_ids.shape","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:29.138141Z","iopub.status.busy":"2024-06-05T21:06:29.137847Z","iopub.status.idle":"2024-06-05T21:06:29.207726Z","shell.execute_reply":"2024-06-05T21:06:29.206391Z","shell.execute_reply.started":"2024-06-05T21:06:29.138117Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"debug = sub_df.shape[0]<=720\n\nif debug:\n    import matplotlib.pyplot as plt\n    sub_df_tmp = sub_df.copy()\n    #nocall_df = pd.DataFrame({'nocall': preds[0][1][:,0].tolist()})\n    sub_df_tmp = pd.concat([sub_df_tmp], axis=1)\n    fig, ax = plt.subplots(figsize=(20, 15))\n    heatmap = ax.pcolor(sub_df_tmp.iloc[:48,1:].values.T, edgecolors='k', linewidths=0.1, vmin=0, vmax=1, cmap='Blues')\n    # cbar = plt.colorbar(heatmap)\n    ax.set_xticks(np.arange(0, 48+0.5, 12))\n    ax.set_yticks(np.arange(sub_df_tmp.shape[1]-1))\n    ax.set_xticklabels(np.arange(0,245,60))\n    #ax.set_yticklabels(CFG.target_columns)\n    plt.xlabel('sec')\n    plt.ylabel('species')\n    fig.tight_layout()\n    fig, ax = plt.subplots(figsize=(15, 0.5))\n    #heatmap = ax.pcolor(sub_df_tmp.T, edgecolors='k', linewidths=0.1, vmin=0, vmax=1, cmap='Blues')\n    plt.show()","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:29.21086Z","iopub.status.busy":"2024-06-05T21:06:29.210477Z","iopub.status.idle":"2024-06-05T21:06:31.224103Z","shell.execute_reply":"2024-06-05T21:06:31.222918Z","shell.execute_reply.started":"2024-06-05T21:06:29.210803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.iloc[20,1:].sort_values()","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:31.226438Z","iopub.status.busy":"2024-06-05T21:06:31.225989Z","iopub.status.idle":"2024-06-05T21:06:31.238451Z","shell.execute_reply":"2024-06-05T21:06:31.237051Z","shell.execute_reply.started":"2024-06-05T21:06:31.226397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Post processing","metadata":{}},{"cell_type":"code","source":"# Smoothing\ndef make_mean_score(df):\n    z0 = df[bird_cols]\n    z1 = df.groupby(\"row_prefix\")[bird_cols].shift(1).bfill()\n    z2 = df.groupby(\"row_prefix\")[bird_cols].shift(-1).ffill()\n    z3 = df.groupby(\"row_prefix\")[bird_cols].shift(2).bfill()\n    z4 = df.groupby(\"row_prefix\")[bird_cols].shift(-2).ffill()\n    z5 = df.groupby(\"row_prefix\")[bird_cols].shift(3).bfill()\n    z6 = df.groupby(\"row_prefix\")[bird_cols].shift(-3).ffill()\n    z_ave = np.average([z0, z1, z2, z3, z4, z5, z6], axis=0, weights=[2.4, 1.2, 1.2, 0.3, 0.3, 0.1, 0.1])\n    df[bird_cols] = z_ave\n    return df\n\nsub_df[\"row_prefix\"] = sub_df[\"row_id\"].str.split(\"_\").str[0]\nsub_df[\"row_number\"] = sub_df[\"row_id\"].str.split(\"_\").str[1]\nsub_df = make_mean_score(sub_df).drop([\"row_prefix\", \"row_number\"], axis=1)","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:31.240524Z","iopub.status.busy":"2024-06-05T21:06:31.240068Z","iopub.status.idle":"2024-06-05T21:06:31.384147Z","shell.execute_reply":"2024-06-05T21:06:31.3829Z","shell.execute_reply.started":"2024-06-05T21:06:31.240482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Cut-off\npred_df = sub_df.copy()\ntarget_columns = pred_df.columns[1:]\nfor i in range(0, len(pred_df), 48):\n    chunk = pred_df.iloc[i : i + 48]\n    for col in target_columns:\n        max_value = chunk[col].max()\n        if max_value < 0.05:\n            pred_df.loc[i : i + 48, col] *= 0.25\n        elif max_value < 0.1:\n            pred_df.loc[i : i + 48, col] *= 0.4\n        elif max_value < 0.15:\n            pred_df.loc[i : i + 48, col] *= 0.7","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:31.385929Z","iopub.status.busy":"2024-06-05T21:06:31.385587Z","iopub.status.idle":"2024-06-05T21:06:32.963004Z","shell.execute_reply":"2024-06-05T21:06:32.961877Z","shell.execute_reply.started":"2024-06-05T21:06:31.385899Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.execute_input":"2024-06-05T21:06:33.308552Z","iopub.status.busy":"2024-06-05T21:06:33.308099Z","iopub.status.idle":"2024-06-05T21:06:33.361495Z","shell.execute_reply":"2024-06-05T21:06:33.360359Z","shell.execute_reply.started":"2024-06-05T21:06:33.308512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df.tail(10)","metadata":{},"execution_count":null,"outputs":[]}]}