{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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,"sourceType":"competition"},{"sourceId":11800527,"sourceType":"datasetVersion","datasetId":7410601}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport librosa\nimport matplotlib.pyplot as plt\nimport cv2\n\nimport pickle\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nimport torch.optim as optim\nfrom torch.optim import lr_scheduler\nfrom torch.utils.data import Dataset, DataLoader\nimport torchvision.models as models\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:04:53.759796Z","iopub.execute_input":"2025-05-21T06:04:53.759981Z","iopub.status.idle":"2025-05-21T06:05:06.186112Z","shell.execute_reply.started":"2025-05-21T06:04:53.759962Z","shell.execute_reply":"2025-05-21T06:05:06.185041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CFG:\n    \n    seed = 42\n    debug = True  \n    apex = False\n    print_freq = 100\n    num_workers = 2\n    \n    OUTPUT_DIR = '/kaggle/working/'\n\n    train_csv = '/kaggle/input/birdclef-2025/train.csv'\n    train_datadir = '/kaggle/input/birdclef-2025/train_audio'\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\n    model = models.efficientnet_b0()\n\n    class CustomResNet(nn.Module):\n        def __init__(self, model):\n            super(CustomResNet, self).__init__()\n            self.model = model\n            self.part = nn.Sequential(\n                model.conv1,\n                model.bn1,\n                model.relu,\n                model.maxpool,\n                model.layer1,\n                model.layer2,\n                model.layer3\n            )\n        def forward(self, x):\n            x = self.part(x)\n            return x\n    \n    pretrained = True\n    in_channels = 1\n\n    LOAD_DATA = True  \n    sample_rate = 32000\n    target_duration = 5.0\n    target_shape = (256, 256)\n    \n    n_fft = 1024\n    hop_length = 512\n    n_mels = 128\n    f_min = 20\n    f_max = 16000\n    \n    device = 'cuda' if torch.cuda.is_available() else 'cpu'\n    epochs = 10  \n    batch_size = 32  \n    criterion = 'BCEWithLogitsLoss'\n\n    n_fold = 5\n    selected_folds = [0, 1, 2, 3, 4]   \n\n    optimizer = 'AdamW'\n    lr = 5e-4 \n    weight_decay = 1e-5\n  \n    scheduler = 'CosineAnnealingLR'\n    min_lr = 1e-6\n    T_max = epochs\n\n    aug_prob = 0.5  \n    mixup_alpha = 0.5  \n    \n    def update_debug_settings(self):\n        if self.debug:\n            self.epochs = 2\n            self.selected_folds = [0]\n\ncfg = CFG()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:06:02.443042Z","iopub.execute_input":"2025-05-21T06:06:02.443301Z","iopub.status.idle":"2025-05-21T06:06:02.530827Z","shell.execute_reply.started":"2025-05-21T06:06:02.443286Z","shell.execute_reply":"2025-05-21T06:06:02.530043Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"tax_df   = pd.read_csv(\"/kaggle/input/birdclef-2025/taxonomy.csv\")   # has columns [\"common_name\",\"class_name\",…]\ntrain_df = pd.read_csv('/kaggle/input/birdclef-2025/train.csv')\n\n# 2) identify all common_names that belong to class Aves\naves_names = tax_df.loc[\n    tax_df[\"class_name\"] == \"Aves\", \n    \"common_name\"\n].unique()\n\n# 3) filter out any rows in train_df whose common_name is in that list\nfiltered = train_df[train_df[\"common_name\"].isin(aves_names)]\n\n# 4) save result\nfiltered.to_csv(\"train_only_aves.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:05:14.138511Z","iopub.execute_input":"2025-05-21T06:05:14.138881Z","iopub.status.idle":"2025-05-21T06:05:14.484937Z","shell.execute_reply.started":"2025-05-21T06:05:14.138856Z","shell.execute_reply":"2025-05-21T06:05:14.484000Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df = pd.read_csv(\"/kaggle/input/birdclef-2025/train.csv\")\nlen(df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:05:20.782268Z","iopub.execute_input":"2025-05-21T06:05:20.782614Z","iopub.status.idle":"2025-05-21T06:05:20.865468Z","shell.execute_reply.started":"2025-05-21T06:05:20.782592Z","shell.execute_reply":"2025-05-21T06:05:20.864546Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_only_aves.","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"file_path = \"/kaggle/input/train-audio-human-timestamps/train_audio_speech_timestamps.pkl\"\n\ntry:\n    with open(file_path, 'rb') as file:\n        human_segments = pickle.load(file)\nexcept FileNotFoundError:\n    print(f\"Error: File not found at {file_path}\")\nexcept EOFError:\n    print(\"Error: Incomplete data in pickle file\")\nexcept Exception as e:\n    print(f\"An unexpected error occurred: {e}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:05:23.874240Z","iopub.execute_input":"2025-05-21T06:05:23.874541Z","iopub.status.idle":"2025-05-21T06:05:23.889063Z","shell.execute_reply.started":"2025-05-21T06:05:23.874519Z","shell.execute_reply":"2025-05-21T06:05:23.887690Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_dataset = pd.read_csv(cfg.train_csv)\naudio, _ = librosa.load(cfg.train_datadir + \"/\" + train_dataset[\"filename\"][0])\n\nprint(len(audio))\nmel_spec = audio2melspec(cfg, audio)\n\n# Plot\nplt.figure(figsize=(10, 4))\nlibrosa.display.specshow(mel_spec, sr=cfg.sample_rate, x_axis='time', y_axis='mel', fmax= cfg.f_max, cmap='magma')\nplt.colorbar(format='%+2.0f dB')\nplt.title('Mel-frequency spectrogram')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T19:30:26.895780Z","iopub.execute_input":"2025-05-19T19:30:26.896282Z","iopub.status.idle":"2025-05-19T19:30:44.910726Z","shell.execute_reply.started":"2025-05-19T19:30:26.896244Z","shell.execute_reply":"2025-05-19T19:30:44.909534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def audio2melspec(cfg, audio_data):\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.sample_rate,\n        n_fft= cfg.n_fft,\n        hop_length= cfg.hop_length,\n        n_mels= cfg.n_mels,\n        fmin= cfg.f_min,\n        fmax= cfg.f_max,\n        power=2.0,\n        pad_mode=\"reflect\",\n        norm='slaney',\n        htk=True,\n        center=True,\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\ndef process_audio_segment(audio_data):\n    \"\"\"Process audio segment to get mel spectrogram\"\"\"\n    if len(audio_data) < n_length:\n        audio_data = np.pad(audio_data,\n                          (0, n_length - len(audio_data)),\n                          mode='constant')\n\n    mel_spec = audio2melspec(audio_data)\n\n    if mel_spec.shape != img_size:\n        mel_spec = cv2.resize(mel_spec, img_size, interpolation=cv2.INTER_LINEAR)\n\n    return mel_spec.astype(np.float32)\n\ndef remove_human_voice(audio, sr, segments, mode='excise'):\n    \"\"\"\n    Remove or zero‐out human‐voice intervals from a 1D audio array.\n    \"\"\"\n    if not segments:\n        return audio\n\n    if mode == 'excise':\n        mask = np.ones(len(audio), dtype=bool)\n        for seg in segments:\n            i0 = int(seg['start'] * sr)\n            i1 = int(seg['end']   * sr)\n            mask[i0:i1] = False\n        return audio[mask]\n\n    elif mode == 'zero':\n        out = audio.copy()\n        for seg in segments:\n            i0 = int(seg['start'] * sr)\n            i1 = int(seg['end']   * sr)\n            out[i0:i1] = 0.0\n        return out\n\n    else:\n        raise ValueError(f\"Unknown mode {mode!r}\")\ndef preprocess_audio_to_dict(\n    cfg,\n    human_segments: dict,\n    mode: str = 'excise',\n    n_length: int = 16000,\n    img_size: tuple = (256, 256),\n    path_col: str = 'filename'\n) -> dict:\n    \"\"\"\n    For each entry in cfg.train_csv[path_col]:\n      1. load at cfg.sample_rate\n      2. remove human‐voice segments if present\n      3. pad/truncate to n_length\n      4. compute & normalize mel‐spectrogram\n      5. resize to img_size\n\n    Returns:\n      spect_dict: { filename (str) → mel‐spec np.ndarray of shape img_size }\n    \"\"\"\n    spect_dict = {}\n    df = pd.read_csv(cfg.train_csv)\n\n    for fname in df[path_col]:\n        fp = cfg.train_datadir + \"/\" +fname\n\n        # 1) load\n        audio, sr = librosa.load(fp, sr=cfg.sample_rate, mono=True)\n\n        # 2) remove voice\n        segments = human_segments.get(fp, [])\n        audio = remove_human_voice(audio, sr, segments, mode=mode)\n\n        # 3) pad / truncate\n        if len(audio) < n_length:\n            audio = np.pad(audio, (0, n_length - len(audio)), mode='constant')\n        else:\n            audio = audio[:n_length]\n\n        # 4) mel‐spec\n        mel = audio2melspec(cfg, audio)\n\n        # 5) resize if needed\n        if mel.shape != img_size:\n            mel = cv2.resize(mel, img_size, interpolation=cv2.INTER_LINEAR)\n\n        spect_dict[fname] = mel.astype(np.float32)\n\n    return spect_dict\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:11:58.599475Z","iopub.execute_input":"2025-05-21T06:11:58.599834Z","iopub.status.idle":"2025-05-21T06:11:58.617803Z","shell.execute_reply.started":"2025-05-21T06:11:58.599811Z","shell.execute_reply":"2025-05-21T06:11:58.616592Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:09:21.482273Z","iopub.execute_input":"2025-05-21T06:09:21.482573Z","iopub.status.idle":"2025-05-21T06:09:21.508734Z","shell.execute_reply.started":"2025-05-21T06:09:21.482553Z","shell.execute_reply":"2025-05-21T06:09:21.507777Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df = pd.read_csv(cfg.train_csv)\nmel_specs = preprocess_audio_to_dict(\n    cfg,\n    human_segments,\n    mode='excise',      # fully cut out speech segments\n    n_length=5*32000,   # e.g. 5-second clips at 32 kHz\n    img_size=(256,256),\n    path_col='filename'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:12:02.418620Z","iopub.execute_input":"2025-05-21T06:12:02.418958Z","iopub.status.idle":"2025-05-21T06:36:16.125481Z","shell.execute_reply.started":"2025-05-21T06:12:02.418937Z","shell.execute_reply":"2025-05-21T06:36:16.124628Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# 2. save to .npy\nnp.save('mel_specs.npy', mel_specs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:57:01.213309Z","iopub.execute_input":"2025-05-21T06:57:01.213605Z","iopub.status.idle":"2025-05-21T06:57:42.933909Z","shell.execute_reply.started":"2025-05-21T06:57:01.213587Z","shell.execute_reply":"2025-05-21T06:57:42.932876Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_prepped.to_csv(\"mel_specs.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T19:27:14.947848Z","iopub.execute_input":"2025-05-19T19:27:14.948211Z","iopub.status.idle":"2025-05-19T19:27:14.960294Z","shell.execute_reply.started":"2025-05-19T19:27:14.948181Z","shell.execute_reply":"2025-05-19T19:27:14.958748Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_prepped2.to_pickle('mel_specs.pkl')      \n# reading\nwith open('/kaggle/working/mel_specs.pkl', 'rb') as f:\n    df_restored = pickle.load(f)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T21:42:33.963410Z","iopub.execute_input":"2025-05-19T21:42:33.964846Z","iopub.status.idle":"2025-05-19T21:42:37.966468Z","shell.execute_reply.started":"2025-05-19T21:42:33.964811Z","shell.execute_reply":"2025-05-19T21:42:37.964952Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with open('/kaggle/working/mel_specs.pkl', 'rb') as f:\n    df_restored = pickle.load(f)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T21:43:53.025533Z","iopub.execute_input":"2025-05-19T21:43:53.026341Z","iopub.status.idle":"2025-05-19T21:43:54.603099Z","shell.execute_reply.started":"2025-05-19T21:43:53.026313Z","shell.execute_reply":"2025-05-19T21:43:54.602004Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from IPython.display import FileLink\n\n# display a link\ndisplay(FileLink('mel_specs.npy'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-21T06:58:33.426770Z","iopub.execute_input":"2025-05-21T06:58:33.427649Z","iopub.status.idle":"2025-05-21T06:58:33.433005Z","shell.execute_reply.started":"2025-05-21T06:58:33.427618Z","shell.execute_reply":"2025-05-21T06:58:33.432138Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Plot\nplt.figure(figsize=(10, 4))\nlibrosa.display.specshow(df_prepped[\"mel_spec\"].iloc[3], sr=cfg.sample_rate, x_axis='time', y_axis='mel', fmax= cfg.f_max, cmap='magma')\nplt.colorbar(format='%+2.0f dB')\nplt.title('Mel-frequency spectrogram')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-14T06:32:54.343752Z","iopub.execute_input":"2025-05-14T06:32:54.344073Z","iopub.status.idle":"2025-05-14T06:32:54.711810Z","shell.execute_reply.started":"2025-05-14T06:32:54.344048Z","shell.execute_reply":"2025-05-14T06:32:54.710686Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_prepped2 = df_prepped[['primary_label', 'filename', 'mel_spec']]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-19T21:26:25.693275Z","iopub.execute_input":"2025-05-19T21:26:25.693652Z","iopub.status.idle":"2025-05-19T21:26:25.705590Z","shell.execute_reply.started":"2025-05-19T21:26:25.693628Z","shell.execute_reply":"2025-05-19T21:26:25.704505Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}