{"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":91844,"databundleVersionId":11361821,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":10992522,"sourceType":"datasetVersion","datasetId":6842191},{"sourceId":11006697,"sourceType":"datasetVersion","datasetId":6852193},{"sourceId":11007574,"sourceType":"datasetVersion","datasetId":6852834},{"sourceId":11048751,"sourceType":"datasetVersion","datasetId":6869450},{"sourceId":11049372,"sourceType":"datasetVersion","datasetId":6883149},{"sourceId":11053663,"sourceType":"datasetVersion","datasetId":6886569},{"sourceId":11060723,"sourceType":"datasetVersion","datasetId":6891568},{"sourceId":11075449,"sourceType":"datasetVersion","datasetId":6902504},{"sourceId":11151956,"sourceType":"datasetVersion","datasetId":6957736},{"sourceId":11166743,"sourceType":"datasetVersion","datasetId":6873009},{"sourceId":29256486,"sourceType":"kernelVersion"},{"sourceId":94042851,"sourceType":"kernelVersion"},{"sourceId":110828502,"sourceType":"kernelVersion"},{"sourceId":121384152,"sourceType":"kernelVersion"},{"sourceId":227215399,"sourceType":"kernelVersion"},{"sourceId":227215575,"sourceType":"kernelVersion"},{"sourceId":227579048,"sourceType":"kernelVersion"},{"sourceId":229718410,"sourceType":"kernelVersion"}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"OPTION = {'N':'59',\n  'SOLUTIONs': [\n       {f'SOLUTION':'SOLUTION_16',f'FILE_SUBM':'subm_16.csv',f'WEIGHT':0.50,f'LB':'n.d.'},\n       {f'SOLUTION':'SOLUTION_15',f'FILE_SUBM':'subm_15.csv',f'WEIGHT':0.50,f'LB': 0.801},\n    ]\n}\n\n# OPTION = {'N':'70', skipy.stats.rankdata..\n\nexSOLUTIONS         = True;\nexEDA               = not exSOLUTIONS","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:35.756997Z","iopub.execute_input":"2025-03-28T06:59:35.757385Z","iopub.status.idle":"2025-03-28T06:59:35.763334Z","shell.execute_reply.started":"2025-03-28T06:59:35.757357Z","shell.execute_reply":"2025-03-28T06:59:35.761967Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if exEDA:\n    OPTION = 'EDA'\n    WEIGHTS            = []\n    FILES_SUBM         = []\n    ENSEMBLE_SOLUTIONS = ['SOLUTION_3']\n\n\nimport time\n\n\ncell_Start_time = time.time()\n\n\ndef begin(solution_name):\n    global cell_Start_time; cell_Start_time = time.time()\n    print(solution_name)\n\n\ndef end():\n    global cell_Start_time;\n    print(\"cell time:\", round(time.time() - cell_Start_time, 1))\n\n\nif type(OPTION) == dict:\n\n    def from_dict(OPTION):\n        OP = OPTION['N']\n        LB  = [e['LB']        for e in OPTION['SOLUTIONs']]\n        ES  = [e['SOLUTION']  for e in OPTION['SOLUTIONs']]\n        FS  = [e['FILE_SUBM'] for e in OPTION['SOLUTIONs']]\n        WTS = [e['WEIGHT']    for e in OPTION['SOLUTIONs']]\n        return OP, LB, ES, FS, WTS \n\n    OPTION, LB, ENSEMBLE_SOLUTIONS, FILES_SUBM, WEIGHTS = from_dict(OPTION)\n\nprint(ENSEMBLE_SOLUTIONS)","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:35.764982Z","iopub.execute_input":"2025-03-28T06:59:35.765385Z","iopub.status.idle":"2025-03-28T06:59:35.790697Z","shell.execute_reply.started":"2025-03-28T06:59:35.765354Z","shell.execute_reply":"2025-03-28T06:59:35.789545Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_15'\n\nif  solution in ENSEMBLE_SOLUTIONS:\n     #### 后处理优化\n#- 对预测结果进行了时间平滑处理。\n#- 使用滑动窗口对相邻时间段的预测结果进行加权平均（如 0.2 * 前一段 + 0.6 * 当前段 + 0.2 * 后一段 ）。\n#- 这种后处理可以减少预测结果的波动，提高稳定性。\n#### 5. 音频参数优化\n#- 对 Mel 频谱图的生成参数进行了调整：\n#  - HOP_LENGTH = 64\n#  - N_MELS = 148\n#  - FMIN = 20\n#  - FMAX = 16000\n#- 这些参数优化可以更好地捕捉音频特征，提升模型的表现。                                   \n    begin(solution)\n\n    # what changed ?\n    # \n    #  HOP_LENGTH = 16\n    #  N_MELS     = 148\n    #  FMIN       = 20\n    #  FMAX       = 16000\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This notebook is exact copy of the notebook mentioned below but with TTA on Predictions\n    # \n    # - [Copied from Notebook](https://www.kaggle.com/code/kumarandatascientist/lb-0-784-efficientnet-b0-pytorch-inference)  \n    \n\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/birdclef-2025-efficientnet-b0'  \n        \n        # Audio parameters\n        FS = 32000  \n        WINDOW_SIZE = 5  \n        \n        # Mel spectrogram parameters\n        N_FFT = 1024\n\n        \n        # HOP_LENGTH =    128\n        # N_MELS     =    154\n        # FMIN       =     30\n        # FMAX       = 15_000\n\n        HOP_LENGTH =     64\n        N_MELS     =    148\n        FMIN       =     20\n        FMAX       = 16_000\n\n        \n        TARGET_SHAPE = (256, 256)\n        \n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  \n        \n        # Inference parameters\n        batch_size = 32\n        use_tta = False  \n        tta_count = 5   \n        threshold = 0.45\n        \n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    #add by xiazhijian\n    def audio2melspec(audio_data, cfg):\n    #\"\"\"Convert audio data to mel spectrogram\"\"\"\n    # 添加数据增强\n        if np.random.rand() > 0.5:\n            audio_data = librosa.effects.time_stretch(audio_data, rate=np.random.uniform(0.9, 1.1))\n    \n        if np.random.rand() > 0.5:\n            audio_data = librosa.effects.pitch_shift(audio_data, sr=cfg.FS, n_steps=np.random.uniform(-2, 2))\n    \n    # 添加噪声增强\n        if np.random.rand() > 0.5:\n            noise = np.random.normal(0, 0.005, audio_data.shape)\n            audio_data = audio_data + noise\n\n        # 原有处理逻辑\n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n        \n    \n    #add by xiazhijian\n    def process_audio_segment(audio_data, cfg):\n        #\"\"\"Process audio segment with random cropping\"\"\"\n        # 随机裁剪\n        if len(audio_data) > cfg.FS * cfg.WINDOW_SIZE:\n            start = np.random.randint(0, len(audio_data) - cfg.FS * cfg.WINDOW_SIZE)\n            audio_data = audio_data[start:start + cfg.FS * cfg.WINDOW_SIZE]\n    \n        # 生成Mel频谱图\n        mel_spec = audio2melspec(audio_data, cfg)\n    \n        # 调整尺寸\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n        \n        return mel_spec.astype(np.float32)\n    \n    \n    #add by xiazhijian\n    def get_lr_scheduler(optimizer):\n        return torch.optim.lr_scheduler.ReduceLROnPlateau(\n            optimizer,\n            mode='max',\n            factor=0.5,\n            patience=3,\n            verbose=True\n        )\n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  \n                in_chans=cfg.in_channels,\n                drop_rate=0.0,    \n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n\n    \n\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        model_dir = Path(cfg.model_path)\n        \n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n    \n                if cfg.use_tta:\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n    \n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n    \n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n    \n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n    \n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n    \n        all_row_ids = []\n        all_predictions = []\n    \n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n    \n        submission_dict = {'row_id': row_ids}\n        \n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n    \n        submission_df = pd.DataFrame(submission_dict)\n    \n        submission_df.set_index('row_id', inplace=True)\n    \n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n    \n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            for col in missing_cols:\n                submission_df[col] = 0.0\n    \n        submission_df = submission_df[sample_sub.columns]\n    \n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n    \n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n    \n        row_ids, predictions = run_inference(cfg, models, species_ids)\n    \n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n    \n        submission_path = 'submission.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    print(\"xiazhijian\")\n    sub = pd.read_csv('submission.csv')\n    cols = sub.columns[1:]\n    groups = sub['row_id'].str.rsplit('_', n=1).str[0]\n    groups = groups.values\n    print(np.unique(groups))\n    for group in np.unique(groups):\n        sub_group = sub[group == groups]\n        predictions = sub_group[cols].values\n        new_predictions = predictions.copy()\n\n        smoothed_predictions = gaussian_filter1d(predictions, sigma=1.0, axis=0)\n\n        \n        for i in range(1, predictions.shape[0]-1):\n            new_predictions[i] = (predictions[i-1] * 0.2) + (predictions[i] * 0.6) + (predictions[i+1] * 0.2)\n        new_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)\n        new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)\n        sub_group[cols] = new_predictions\n        #add by xiazhijian\n        #sub_group[cols] = smoothed_predictions\n\n        #print(new_predictions,smoothed_predictions)\n        \n        sub[group == groups] = sub_group\n    sub.to_csv(\"subm_15.csv\", index=False)\n    \n    end()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:36.050621Z","iopub.execute_input":"2025-03-28T06:59:36.050975Z","iopub.status.idle":"2025-03-28T06:59:37.502914Z","shell.execute_reply.started":"2025-03-28T06:59:36.050948Z","shell.execute_reply":"2025-03-28T06:59:37.501741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"solution = 'SOLUTION_16'\n\n\n#- Mel 频谱图生成 ：\n#- 使用 librosa.feature.melspectrogram 生成 Mel 频谱图。\n#- 参数经过优化： N_FFT=1024 , HOP_LENGTH=512 , N_MELS=148 , FMIN=50 , FMAX=14000 。\n#- 音频分段处理 ：\n#- 将音频分割成 5 秒的片段进行处理。\n#- 对每个片段生成 Mel 频谱图，并调整大小到\nif  solution in ENSEMBLE_SOLUTIONS:\n                                                                \n    begin(solution)\n\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ u')\n\n\n    # The model was trained and fine-tuned using an A100 GPU, achieving improved performance.\n    # (The new model has replaced the model from \"14. EfficientNet B0 PyTorch, Labels TTA, [Inference]\".)\n    # *(The new model named /kaggle/input/lbmore-newtrain)*\n\n\n    # Credits to invisible for the ensemble solution. Original notebook: \n    # https://www.kaggle.com/code/vyacheslavbolotin/birdclef-2025-ensemble-of-solutions/notebook\n    \n    \n    # Your vote directly fuels our progress - if this model helped your workflow,                     \n    # please ⭐ support with an upvote! ⭐ Every vote gets us closer to breakthrough solutions ⭐. \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0')\n    \n    \n    # This notebook is exact copy of the notebook mentioned below but with TTA on Predictions\n    # \n    # - [Copied from Notebook](https://www.kaggle.com/code/kumarandatascientist/lb-0-784-efficientnet-b0-pytorch-inference)  \n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1')\n    \n    \n    import os\n    import gc\n    import warnings\n    import logging\n    import time\n    import math\n    import cv2\n    from pathlib import Path\n    \n    import numpy as np\n    import pandas as pd\n    import librosa\n    import torch\n    import torch.nn as nn\n    import torch.nn.functional as F\n    import timm\n    from tqdm.auto import tqdm\n    \n    warnings.filterwarnings(\"ignore\")\n    logging.basicConfig(level=logging.ERROR)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2')\n    \n    \n    class CFG:\n     \n        test_soundscapes = '/kaggle/input/birdclef-2025/test_soundscapes'\n        submission_csv = '/kaggle/input/birdclef-2025/sample_submission.csv'\n        taxonomy_csv = '/kaggle/input/birdclef-2025/taxonomy.csv'\n        model_path = '/kaggle/input/lbmore-newtrain'  \n        \n        # Audio parameters\n        FS = 32000  \n        WINDOW_SIZE = 5  \n        \n        # Mel spectrogram parameters\n        N_FFT = 2048\n        HOP_LENGTH = 512\n        N_MELS = 158\n        FMIN = 50\n        FMAX = 14000\n        TARGET_SHAPE = (512, 512)\n        \n        model_name = 'efficientnet_b0'\n        in_channels = 1\n        device = 'cpu'  \n        \n        # Inference parameters\n        batch_size = 32\n        use_tta = False  \n        tta_count = 3   \n        threshold = 0.45\n        \n        use_specific_folds = False  # If False, use all found models\n        folds = [0, 1]  # Used only if use_specific_folds is True\n        \n        debug = False\n        debug_count = 3\n    \n    cfg = CFG()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3')\n    \n    \n    print(f\"Using device: {cfg.device}\")\n    print(f\"Loading taxonomy data...\")\n    taxonomy_df = pd.read_csv(cfg.taxonomy_csv)\n    species_ids = taxonomy_df['primary_label'].tolist()\n    num_classes = len(species_ids)\n    print(f\"Number of classes: {num_classes}\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4')\n    \n    \n    class BirdCLEFModel(nn.Module):\n        def __init__(self, cfg, num_classes):\n            super().__init__()\n            self.cfg = cfg\n            \n            self.backbone = timm.create_model(\n                cfg.model_name,\n                pretrained=False,  \n                in_chans=cfg.in_channels,\n                drop_rate=0.0,    \n                drop_path_rate=0.0\n            )\n            \n            if 'efficientnet' in cfg.model_name:\n                backbone_out = self.backbone.classifier.in_features\n                self.backbone.classifier = nn.Identity()\n            elif 'resnet' in cfg.model_name:\n                backbone_out = self.backbone.fc.in_features\n                self.backbone.fc = nn.Identity()\n            else:\n                backbone_out = self.backbone.get_classifier().in_features\n                self.backbone.reset_classifier(0, '')\n            \n            self.pooling = nn.AdaptiveAvgPool2d(1)\n            self.feat_dim = backbone_out\n            self.classifier = nn.Linear(backbone_out, num_classes)\n            \n        def forward(self, x):\n            features = self.backbone(x)\n            \n            if isinstance(features, dict):\n                features = features['features']\n                \n            if len(features.shape) == 4:\n                features = self.pooling(features)\n                features = features.view(features.size(0), -1)\n            \n            logits = self.classifier(features)\n            return logits\n\n        \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 5')\n    \n    \n    def audio2melspec(audio_data, cfg):\n        \"\"\"Convert audio data to mel spectrogram\"\"\"\n        if np.isnan(audio_data).any():\n            mean_signal = np.nanmean(audio_data)\n            audio_data = np.nan_to_num(audio_data, nan=mean_signal)\n    \n        mel_spec = librosa.feature.melspectrogram(\n            y=audio_data,\n            sr=cfg.FS,\n            n_fft=cfg.N_FFT,\n            hop_length=cfg.HOP_LENGTH,\n            n_mels=cfg.N_MELS,\n            fmin=cfg.FMIN,\n            fmax=cfg.FMAX,\n            power=2.0\n        )\n    \n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        mel_spec_norm = (mel_spec_db - mel_spec_db.min()) / (mel_spec_db.max() - mel_spec_db.min() + 1e-8)\n        \n        return mel_spec_norm\n    \n    def process_audio_segment(audio_data, cfg):\n        \"\"\"Process audio segment to get mel spectrogram\"\"\"\n        if len(audio_data) < cfg.FS * cfg.WINDOW_SIZE:\n            audio_data = np.pad(audio_data, \n                              (0, cfg.FS * cfg.WINDOW_SIZE - len(audio_data)), \n                              mode='constant')\n        \n        mel_spec = audio2melspec(audio_data, cfg)\n        \n        # Resize if needed\n        if mel_spec.shape != cfg.TARGET_SHAPE:\n            mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n            \n        return mel_spec.astype(np.float32)\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6')\n    \n    \n    def find_model_files(cfg):\n        \"\"\"\n        Find all .pth model files in the specified model directory\n        \"\"\"\n        model_files = []\n        \n        model_dir = Path(cfg.model_path)\n        \n        for path in model_dir.glob('**/*.pth'):\n            model_files.append(str(path))\n        \n        return model_files\n    \n    def load_models(cfg, num_classes):\n        \"\"\"\n        Load all found model files and prepare them for ensemble\n        \"\"\"\n        models = []\n        \n        model_files = find_model_files(cfg)\n        \n        if not model_files:\n            print(f\"Warning: No model files found under {cfg.model_path}!\")\n            return models\n        \n        print(f\"Found a total of {len(model_files)} model files.\")\n        \n        if cfg.use_specific_folds:\n            filtered_files = []\n            for fold in cfg.folds:\n                fold_files = [f for f in model_files if f\"fold{fold}\" in f]\n                filtered_files.extend(fold_files)\n            model_files = filtered_files\n            print(f\"Using {len(model_files)} model files for the specified folds ({cfg.folds}).\")\n        \n        for model_path in model_files:\n            try:\n                print(f\"Loading model: {model_path}\")\n                checkpoint = torch.load(model_path, map_location=torch.device(cfg.device))\n                \n                model = BirdCLEFModel(cfg, num_classes)\n                model.load_state_dict(checkpoint['model_state_dict'])\n                model = model.to(cfg.device)\n                model.eval()\n                \n                models.append(model)\n            except Exception as e:\n                print(f\"Error loading model {model_path}: {e}\")\n        \n        return models\n    \n    def predict_on_spectrogram(audio_path, models, cfg, species_ids):\n        \"\"\"Process a single audio file and predict species presence for each 5-second segment\"\"\"\n        predictions = []\n        row_ids = []\n        soundscape_id = Path(audio_path).stem\n        \n        try:\n            print(f\"Processing {soundscape_id}\")\n            audio_data, _ = librosa.load(audio_path, sr=cfg.FS)\n            \n            total_segments = int(len(audio_data) / (cfg.FS * cfg.WINDOW_SIZE))\n            \n            for segment_idx in range(total_segments):\n                start_sample = segment_idx * cfg.FS * cfg.WINDOW_SIZE\n                end_sample = start_sample + cfg.FS * cfg.WINDOW_SIZE\n                segment_audio = audio_data[start_sample:end_sample]\n                \n                end_time_sec = (segment_idx + 1) * cfg.WINDOW_SIZE\n                row_id = f\"{soundscape_id}_{end_time_sec}\"\n                row_ids.append(row_id)\n    \n                if cfg.use_tta:\n                    all_preds = []\n                    \n                    for tta_idx in range(cfg.tta_count):\n                        mel_spec = process_audio_segment(segment_audio, cfg)\n                        mel_spec = apply_tta(mel_spec, tta_idx)\n    \n                        mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                        mel_spec = mel_spec.to(cfg.device)\n    \n                        if len(models) == 1:\n                            with torch.no_grad():\n                                outputs = models[0](mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                all_preds.append(probs)\n                        else:\n                            segment_preds = []\n                            for model in models:\n                                with torch.no_grad():\n                                    outputs = model(mel_spec)\n                                    probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                    segment_preds.append(probs)\n                            \n                            avg_preds = np.mean(segment_preds, axis=0)\n                            all_preds.append(avg_preds)\n    \n                    final_preds = np.mean(all_preds, axis=0)\n                else:\n                    mel_spec = process_audio_segment(segment_audio, cfg)\n                    \n                    mel_spec = torch.tensor(mel_spec, dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n                    mel_spec = mel_spec.to(cfg.device)\n                    \n                    if len(models) == 1:\n                        with torch.no_grad():\n                            outputs = models[0](mel_spec)\n                            final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                    else:\n                        segment_preds = []\n                        for model in models:\n                            with torch.no_grad():\n                                outputs = model(mel_spec)\n                                probs = torch.sigmoid(outputs).cpu().numpy().squeeze()\n                                segment_preds.append(probs)\n    \n                        final_preds = np.mean(segment_preds, axis=0)\n                        \n                predictions.append(final_preds)\n                \n        except Exception as e:\n            print(f\"Error processing {audio_path}: {e}\")\n        \n        return row_ids, predictions\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 7')\n    \n    \n    def apply_tta(spec, tta_idx):\n        \"\"\"Apply test-time augmentation\"\"\"\n        if tta_idx == 0:\n            # Original spectrogram\n            return spec\n        elif tta_idx == 1:\n            # Time shift (horizontal flip)\n            return np.flip(spec, axis=1)\n        elif tta_idx == 2:\n            # Frequency shift (vertical flip)\n            return np.flip(spec, axis=0)\n        else:\n            return spec\n    \n    def run_inference(cfg, models, species_ids):\n        \"\"\"Run inference on all test soundscapes\"\"\"\n        test_files = list(Path(cfg.test_soundscapes).glob('*.ogg'))\n        \n        if cfg.debug:\n            print(f\"Debug mode enabled, using only {cfg.debug_count} files\")\n            test_files = test_files[:cfg.debug_count]\n        \n        print(f\"Found {len(test_files)} test soundscapes\")\n    \n        all_row_ids = []\n        all_predictions = []\n    \n        for audio_path in tqdm(test_files):\n            row_ids, predictions = predict_on_spectrogram(str(audio_path), models, cfg, species_ids)\n            all_row_ids.extend(row_ids)\n            all_predictions.extend(predictions)\n        \n        return all_row_ids, all_predictions\n    \n    def create_submission(row_ids, predictions, species_ids, cfg):\n        \"\"\"Create submission dataframe\"\"\"\n        print(\"Creating submission dataframe...\")\n    \n        submission_dict = {'row_id': row_ids}\n        \n        for i, species in enumerate(species_ids):\n            submission_dict[species] = [pred[i] for pred in predictions]\n    \n        submission_df = pd.DataFrame(submission_dict)\n    \n        submission_df.set_index('row_id', inplace=True)\n    \n        sample_sub = pd.read_csv(cfg.submission_csv, index_col='row_id')\n    \n        missing_cols = set(sample_sub.columns) - set(submission_df.columns)\n        if missing_cols:\n            print(f\"Warning: Missing {len(missing_cols)} species columns in submission\")\n            for col in missing_cols:\n                submission_df[col] = 0.0\n    \n        submission_df = submission_df[sample_sub.columns]\n    \n        submission_df = submission_df.reset_index()\n        \n        return submission_df\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8')\n    \n    \n    def main():\n        start_time = time.time()\n        print(\"Starting BirdCLEF-2025 inference...\")\n        print(f\"TTA enabled: {cfg.use_tta} (variations: {cfg.tta_count if cfg.use_tta else 0})\")\n    \n        models = load_models(cfg, num_classes)\n        \n        if not models:\n            print(\"No models found! Please check model paths.\")\n            return\n        \n        print(f\"Model usage: {'Single model' if len(models) == 1 else f'Ensemble of {len(models)} models'}\")\n    \n        row_ids, predictions = run_inference(cfg, models, species_ids)\n    \n        submission_df = create_submission(row_ids, predictions, species_ids, cfg)\n    \n        submission_path = 'submission.csv'\n        submission_df.to_csv(submission_path, index=False)\n        print(f\"Submission saved to {submission_path}\")\n        \n        end_time = time.time()\n        print(f\"Inference completed in {(end_time - start_time)/60:.2f} minutes\")\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9')\n    \n    \n    if __name__ == \"__main__\":\n        main()\n    \n    \n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10')\n    print('cell~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 11')\n    \n    \n    sub = pd.read_csv('submission.csv')\n    \n    cols = sub.columns[1:]\n    groups = sub['row_id'].str.rsplit('_', n=1).str[0]\n    groups = groups.values\n        \n    for group in np.unique(groups):\n        sub_group = sub[group == groups]\n        predictions = sub_group[cols].values\n        new_predictions = predictions.copy()\n        for i in range(1, predictions.shape[0]-1):\n            new_predictions[i] = (predictions[i-1] * 0.2) + (predictions[i] * 0.6) + (predictions[i+1] * 0.2)\n        new_predictions[0] = (predictions[0] * 0.8) + (predictions[1] * 0.2)\n        new_predictions[-1] = (predictions[-1] * 0.8) + (predictions[-2] * 0.2)\n        sub_group[cols] = new_predictions\n        sub[group == groups] = sub_group\n        \n    sub.to_csv(\"subm_16.csv\", index=False)\n    \n    \n    end()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:37.504285Z","iopub.execute_input":"2025-03-28T06:59:37.504610Z","iopub.status.idle":"2025-03-28T06:59:38.732425Z","shell.execute_reply.started":"2025-03-28T06:59:37.504573Z","shell.execute_reply":"2025-03-28T06:59:38.731418Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# 📜\n#这段代码通过 模型集成 的方法，将多个模型的预测结果进行加权平均，从而提高了预测准确率。从 0.76 提升到 0.79 的主要原因是：\n\n#- 增加了模型多样性\n#- 优化了权重分配\n#- 集成了更多高质量的模型\n#这种方法在 Kaggle 等数据科学竞赛中非常常见，是一种有效提升模型性能的策略\ndef ens2(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n\n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] = dfs[list_targets_0[i]]*wts[0] + wts[1]*dfs[list_targets_1[i]]\n                 \n    for col0,col1 in zip(list_targets_0, list_targets_1):\n        del dfs[col0]\n        del dfs[col1]\n        \n    if 'SOLUTION_5' in solution:\n        Geographic_Distribution_of_Primary_Labels()\n        \n    return dfs\n\n\ndef ens3(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    list_targets_2 = [f'{TARGET} 2' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df2 = pd.read_csv(files_subm[2])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    df2 = df2.rename(columns={TARGET : f'{TARGET} 2' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    dfs = pd.merge(dfs,df2,on=['row_id'])\n\n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] =\\\n                dfs[list_targets_0[i]]*wts[0] +\\\n                dfs[list_targets_1[i]]*wts[1] +\\\n                dfs[list_targets_2[i]]*wts[2]\n                 \n    for col0,col1,col2 in zip(list_targets_0, list_targets_1, list_targets_2):\n        del dfs[col0]\n        del dfs[col1]\n        del dfs[col2]\n        \n    if 'SOLUTION_5' in solution:\n        Geographic_Distribution_of_Primary_Labels()\n    return dfs\n\n\ndef ens4(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}\\n')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    list_targets_2 = [f'{TARGET} 2' for TARGET in list_TARGETs]\n    list_targets_3 = [f'{TARGET} 3' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df2 = pd.read_csv(files_subm[2])\n    df3 = pd.read_csv(files_subm[3])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    df2 = df2.rename(columns={TARGET : f'{TARGET} 2' for TARGET in list_TARGETs})\n    df3 = df3.rename(columns={TARGET : f'{TARGET} 3' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    dfs = pd.merge(dfs,df2,on=['row_id'])\n    dfs = pd.merge(dfs,df3,on=['row_id'])\n\n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] =\\\n                dfs[list_targets_0[i]]*wts[0] +\\\n                dfs[list_targets_1[i]]*wts[1] +\\\n                dfs[list_targets_2[i]]*wts[2] +\\\n                dfs[list_targets_3[i]]*wts[3]\n                 \n    for col0,col1,col2,col3 in zip(list_targets_0, list_targets_1, list_targets_2, list_targets_3):\n        del dfs[col0]\n        del dfs[col1]\n        del dfs[col2]\n        del dfs[col3]\n        \n    if 'SOLUTION_5' in solution:\n        Geographic_Distribution_of_Primary_Labels()\n    return dfs\n\n\ndef ens6(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}\\n')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    list_targets_2 = [f'{TARGET} 2' for TARGET in list_TARGETs]\n    list_targets_3 = [f'{TARGET} 3' for TARGET in list_TARGETs]\n    list_targets_4 = [f'{TARGET} 4' for TARGET in list_TARGETs]\n    list_targets_5 = [f'{TARGET} 5' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df2 = pd.read_csv(files_subm[2])\n    df3 = pd.read_csv(files_subm[3])\n    df4 = pd.read_csv(files_subm[4])\n    df5 = pd.read_csv(files_subm[5])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    df2 = df2.rename(columns={TARGET : f'{TARGET} 2' for TARGET in list_TARGETs})\n    df3 = df3.rename(columns={TARGET : f'{TARGET} 3' for TARGET in list_TARGETs})\n    df4 = df4.rename(columns={TARGET : f'{TARGET} 4' for TARGET in list_TARGETs})\n    df5 = df5.rename(columns={TARGET : f'{TARGET} 5' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    dfs = pd.merge(dfs,df2,on=['row_id'])\n    dfs = pd.merge(dfs,df3,on=['row_id'])\n    dfs = pd.merge(dfs,df4,on=['row_id'])\n    dfs = pd.merge(dfs,df5,on=['row_id'])\n    \n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] =\\\n                dfs[list_targets_0[i]]*wts[0] +\\\n                dfs[list_targets_1[i]]*wts[1] +\\\n                dfs[list_targets_2[i]]*wts[2] +\\\n                dfs[list_targets_3[i]]*wts[3] +\\\n                dfs[list_targets_4[i]]*wts[4] +\\\n                dfs[list_targets_5[i]]*wts[5]\n                 \n    for col0,col1,col2,col3,col4,col5 in zip(list_targets_0, list_targets_1, list_targets_2, list_targets_3, list_targets_4, list_targets_5):\n        del dfs[col0]\n        del dfs[col1]\n        del dfs[col2]\n        del dfs[col3]\n        del dfs[col4]\n        del dfs[col5]\n        \n    # if 'SOLUTION_5' in solution:\n    #     Geographic_Distribution_of_Primary_Labels()\n    return dfs\n\n\ndef ens7(lbs        = LB,\n         solution   = ENSEMBLE_SOLUTIONS,\n         wts        = WEIGHTS,\n         files_subm = FILES_SUBM,\n         option     = OPTION):\n\n    soluts = [solut.replace(\"SOLUTION_\",\"\") for solut in solution]\n\n    print(f'Ensemble: {soluts},   LB: {lbs},   weights: {wts}\\n')\n    \n    list_TARGETs = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n    list_targets_0 = [f'{TARGET} 0' for TARGET in list_TARGETs]\n    list_targets_1 = [f'{TARGET} 1' for TARGET in list_TARGETs]\n    list_targets_2 = [f'{TARGET} 2' for TARGET in list_TARGETs]\n    list_targets_3 = [f'{TARGET} 3' for TARGET in list_TARGETs]\n    list_targets_4 = [f'{TARGET} 4' for TARGET in list_TARGETs]\n    list_targets_5 = [f'{TARGET} 5' for TARGET in list_TARGETs]\n    list_targets_6 = [f'{TARGET} 6' for TARGET in list_TARGETs]\n\n    df0 = pd.read_csv(files_subm[0])\n    df1 = pd.read_csv(files_subm[1])\n    df2 = pd.read_csv(files_subm[2])\n    df3 = pd.read_csv(files_subm[3])\n    df4 = pd.read_csv(files_subm[4])\n    df5 = pd.read_csv(files_subm[5])\n    df6 = pd.read_csv(files_subm[6])\n\n    df0 = df0.rename(columns={TARGET : f'{TARGET} 0' for TARGET in list_TARGETs})\n    df1 = df1.rename(columns={TARGET : f'{TARGET} 1' for TARGET in list_TARGETs})\n    df2 = df2.rename(columns={TARGET : f'{TARGET} 2' for TARGET in list_TARGETs})\n    df3 = df3.rename(columns={TARGET : f'{TARGET} 3' for TARGET in list_TARGETs})\n    df4 = df4.rename(columns={TARGET : f'{TARGET} 4' for TARGET in list_TARGETs})\n    df5 = df5.rename(columns={TARGET : f'{TARGET} 5' for TARGET in list_TARGETs})\n    df6 = df6.rename(columns={TARGET : f'{TARGET} 6' for TARGET in list_TARGETs})\n\n    dfs = pd.merge(df0,df1,on=['row_id'])\n    dfs = pd.merge(dfs,df2,on=['row_id'])\n    dfs = pd.merge(dfs,df3,on=['row_id'])\n    dfs = pd.merge(dfs,df4,on=['row_id'])\n    dfs = pd.merge(dfs,df5,on=['row_id'])\n    dfs = pd.merge(dfs,df6,on=['row_id'])\n    \n    for i in range(len(list_TARGETs)):\n        dfs[list_TARGETs[i]] =\\\n                dfs[list_targets_0[i]]*wts[0] +\\\n                dfs[list_targets_1[i]]*wts[1] +\\\n                dfs[list_targets_2[i]]*wts[2] +\\\n                dfs[list_targets_3[i]]*wts[3] +\\\n                dfs[list_targets_4[i]]*wts[4] +\\\n                dfs[list_targets_5[i]]*wts[5] +\\\n                dfs[list_targets_6[i]]*wts[6]\n                 \n    for col0,col1,col2,col3,col4,col5,col6 in zip(list_targets_0, list_targets_1, list_targets_2, list_targets_3, list_targets_4, list_targets_5, list_targets_6):\n        del dfs[col0]\n        del dfs[col1]\n        del dfs[col2]\n        del dfs[col3]\n        del dfs[col4]\n        del dfs[col5]\n        del dfs[col6]\n        \n    # if 'SOLUTION_5' in solution:\n    #     Geographic_Distribution_of_Primary_Labels()\n    return dfs\n\n\nensemble = ens2 \n\nif len(ENSEMBLE_SOLUTIONS)==3: ensemble = ens3\nif len(ENSEMBLE_SOLUTIONS)==4: ensemble = ens4\n#if len(ENSEMBLE_SOLUTIONS)==5: ensemble = ens5\nif len(ENSEMBLE_SOLUTIONS)==6: ensemble = ens6\nif len(ENSEMBLE_SOLUTIONS)==7: ensemble = ens7\n\n\nif exEDA:\n\n    if 'SOLUTION_3' in ENSEMBLE_SOLUTIONS:\n        import IPython\n        print('a small piece of code taken from solution.3 by Prata, Marília \\n')\n        IPython.display(IPython.display.Audio(\"../input/birdclef-2025/train_audio/1139490/CSA36389.ogg\"))\n\n\nimport warnings; warnings.filterwarnings(\"ignore\")\n\n\ndef world_cloud():\n    \n    from wordcloud import WordCloud\n    import matplotlib.pyplot as plt\n\n    path_DS       = '/kaggle/input/birdclef-2025-ensemble-of-solution'\n    \n    path_Solut_1  = path_DS + '/SOLUTION_1__Stefan_Kahl__BirdCLEF_2025_Sample_Submission.py'\n    path_Solut_10 = path_DS + '/SOLUTION_10__Carlo_Lepelaars__BirdCLEF_2025_Simple_Submission.py'\n    path_Solut_11 = path_DS + '/SOLUTION_11__Kadircan_drisolu__EfficientNet_B0_Pytorch_Inference_BirdCLEF_25.py'\n    path_Solut_14 = path_DS + '/SOLUTION_14__Salman_Ahmed__Labels_TTA_EfficientNet_B0_Pytorch_Inference.py'\n    path_Solut_5  = path_DS + '/SOLUTION_5__Jocelyn_Dumlao__BirdCLEF_2025_MFCC_Feature_and_ROC_AUC_Analysis.py'\n    path_Solut_5b = path_DS + '/SOLUTION_5b__Jocelyn_Dumlao__BirdCLEF_2025_Inference_w_SimpleCNN_Spectrogram.py'\n    path_Solut_6  = path_DS + '/SOLUTION_6__MYSO__BirdCLEF_2025_3_Submit_baseline_5s.py'\n    path_Solut_8  = path_DS + '/SOLUTION_8__agcsdedf__BirdCLEF_2025_Base_Submit.py'\n    path_Solut_12 = path_DS + '/SOLUTION_12__agcsdedf__BirdCLEF_2025_OpenVINO_Inf.py'\n\n    ps_to_Soluts  = [\n        path_Solut_1,\n        path_Solut_10,\n        path_Solut_11, \n        path_Solut_14,\n        path_Solut_5, \n        path_Solut_5b,\n        path_Solut_6,\n        path_Solut_8,\n        path_Solut_12,\n    ]\n    \n    title_Soluts  = [\n        \"SOLUTION_1\",\n        \"SOLUTION_10\",\n        \"SOLUTION_11\",\n        \"SOLUTION_14\",\n        \"SOLUTION_5\",\n        \"SOLUTION_5b\",\n        \"SOLUTION_6\",\n        \"SOLUTION_8\",\n        \"SOLUTION_12\",\n    ]\n\n    def del_some_words_from(data):\n        clr_data = data.replace('print',\"\").replace('cell',\"\").replace('cfg',\"\").replace('self',\"\").replace('kaggle',\"\").replace('submission',\"\").replace('import',\"\")\n        # .replace('cell',\"\")\\\n        # .replace('S',\"\")\\\n        # .replace('s',\"\")\\\n        # .replace('path',\"\")\\\n        # .replace('Path',\"\")\\\n        # .replace('birdclef',\"\")\\\n        # .replace('import',\"\")\\\n        # .replace('notebook',\"\")\\\n        # .replace('competition',\"\")\\\n        # .replace('prediction',\"\")\\\n        # .replace('https',\"\")\n        return clr_data\n\n    # read SOLUTION from Dataset and transport to Worldcloud\n    \n    def read_for_Worldcloud(path):\n        with open(path) as f: \n            data = f.read()\n            f.close()\n        clr_data = del_some_words_from(data)\n        return WordCloud(background_color='lightsteelblue').generate(clr_data) # \"floralwhite\"\n\n    \n    wc_from_Soluts = [{\"path\":read_for_Worldcloud(p), \"title\":t} for p,t in zip(ps_to_Soluts,title_Soluts)]\n\n    \n    fig, (ax1,ax10,ax11) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax11]\n    for i in range(3): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (ax14,ax5,ax5b) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax11, ax14,ax5,ax5b]\n    for i in range(3,6,1): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()\n    #-----------\n    fig, (ax6,ax8,ax12) = plt.subplots(ncols=3,figsize=(12,6))\n    axs = [ax1,ax10,ax11, ax14,ax5,ax5b, ax6,ax8,ax12]\n    for i in range(6,9,1): \n        axs[i].imshow(wc_from_Soluts[i]['path'])\n        axs[i].axis(\"off\")\n        axs[i].set_title(wc_from_Soluts[i]['title'],fontsize=10)\n    plt.tight_layout()\n    plt.show()","metadata":{"trusted":true,"_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:38.734137Z","iopub.execute_input":"2025-03-28T06:59:38.734462Z","iopub.status.idle":"2025-03-28T06:59:38.782410Z","shell.execute_reply.started":"2025-03-28T06:59:38.734436Z","shell.execute_reply":"2025-03-28T06:59:38.780788Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"if exSOLUTIONS:\n\n    subm = ensemble()\n    subm.to_csv('submission.csv', index=False)\n\n    world_cloud()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-28T06:59:38.784496Z","iopub.execute_input":"2025-03-28T06:59:38.785102Z","iopub.status.idle":"2025-03-28T06:59:44.462229Z","shell.execute_reply.started":"2025-03-28T06:59:38.785027Z","shell.execute_reply":"2025-03-28T06:59:44.461116Z"}},"outputs":[],"execution_count":null}]}