{"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":11984079,"sourceType":"datasetVersion","datasetId":7297651}],"dockerImageVersionId":31012,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<h1 style='color:red;'>crtl+F fix</h1>\nverificar as linhas comentadas com fix","metadata":{}},{"cell_type":"code","source":"%matplotlib inline\n\nimport os\nimport random\nimport time\nimport math\n\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport librosa\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import roc_auc_score\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, Subset\n\nfrom tqdm.auto import tqdm\nimport timm","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.744673Z","iopub.execute_input":"2025-05-28T13:34:16.745030Z","iopub.status.idle":"2025-05-28T13:34:16.753370Z","shell.execute_reply.started":"2025-05-28T13:34:16.745006Z","shell.execute_reply":"2025-05-28T13:34:16.752537Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class cfg:\n\n    debug = False\n    \n    output_dir = '/kaggle/working/'\n    root = '/kaggle/input/birdclef-2025/'\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 = '/kaggle/input/model-weights/veloso.pth'  \n    \n    SR = 32000\n    TARGET_SHAPE = (256, 256)\n    TARGET_DURATION = 5.0\n    N_FFT = 1024\n    HOP_LENGTH = 500\n    N_MELS = 128\n    FMIN = 40\n    FMAX = 15000\n    POWER = 2\n    is_normalized = False\n    \n                        \n    model_name = 'efficientnet_b0'  \n    is_pre_trained = False #fix\n    input_channels = 1\n    \n    optimizer = 'AdamW'\n    lr = 5e-4 \n    weight_decay = 1e-5\n    epochs = 10  \n    batch_size = 32  \n    criterion = 'BCEWithLogitsLoss'\n    n_folds = 5\n\n\n    device = 'cpu'\n    gpu_on = True\n    if gpu_on:\n        device = 'cuda' if torch.cuda.is_available() else 'cpu'\n        \n\n    def load_spectrograms(self):\n        if self.is_files_loaded:\n            loaded_specs = '/kaggle/input/birdclef25-mel-spectrograms/birdclef2025_melspec_5sec_256_256.npy'\n            return np.load(loaded_specs, allow_pickle=True).item()\n        \ncfg = cfg()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.754795Z","iopub.execute_input":"2025-05-28T13:34:16.755407Z","iopub.status.idle":"2025-05-28T13:34:16.772455Z","shell.execute_reply.started":"2025-05-28T13:34:16.755386Z","shell.execute_reply":"2025-05-28T13:34:16.771392Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def audio_to_melspec(data: np.ndarray, cfg: object) -> np.ndarray:\n    mel_spec = librosa.feature.melspectrogram(\n            y=data,\n            sr=cfg.SR,\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=cfg.POWER\n        )\n    \n    mel_spec = librosa.power_to_db(mel_spec, ref=np.max)\n    \n    if cfg.is_normalized:\n        mel_spec_norm = (mel_spec - mel_spec.min()) / (mel_spec.max() - mel_spec.min() + 1e-8)\n        return mel_spec_norm\n        \n    return mel_spec\n\ndef process_audio_slice(audio: np.ndarray, cfg: object) -> np.ndarray:\n    \n    target_samples = int(cfg.TARGET_DURATION * cfg.SR)\n    \n    if len(audio) < target_samples:\n        audio = np.pad(audio, \n                       (0, target_samples - len(audio)), \n                       mode='constant')\n        \n    mel_spec = audio_to_melspec(audio, cfg)                # cria o mel-espectrograma\n    \n    if mel_spec.shape != cfg.TARGET_SHAPE:                 # resize pro input da cnn\n        mel_spec = cv2.resize(mel_spec, cfg.TARGET_SHAPE, interpolation=cv2.INTER_LINEAR)\n    \n    return mel_spec","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.773343Z","iopub.execute_input":"2025-05-28T13:34:16.773608Z","iopub.status.idle":"2025-05-28T13:34:16.787483Z","shell.execute_reply.started":"2025-05-28T13:34:16.773589Z","shell.execute_reply":"2025-05-28T13:34:16.786652Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CNN(nn.Module):\n    def __init__(self, cfg):\n        super().__init__()\n        self.cfg = cfg\n        self.num_classes = len(pd.read_csv(cfg.taxonomy_csv)) #fix \n        \n        # Backbone: Camadas iniciais de um modelo. Faz a extração das características\n        self.backbone = timm.create_model(\n            cfg.model_name,\n            pretrained=cfg.is_pre_trained,          #fix   # Se false, reseta os pesos pré treinados.\n            in_chans=cfg.input_channels,                   # Número de canais de entrada.\n            drop_rate=0.0,\n            drop_path_rate=0.0,\n        )\n        self.backbone = self.backbone.to(cfg.device)\n        \n        # Remove a camada final do backbone e passa a diante para conectar no meu nn.Linear\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        # Head: Parte da rede neural responsável por fazer a predição.\n        self.pooling = nn.AdaptiveAvgPool2d(1)         # Fixa o tamanho da feature map\n        self.feat_dim = backbone_out\n        self.classifier = nn.Linear(backbone_out, self.num_classes).to(cfg.device)    # Classificação final\n\n    def forward(self, x):\n        features = self.backbone(x)\n        if isinstance(features, dict):\n            features = features['features']\n        if len(features.shape) == 4:\n            features = self.pooling(features)\n            features = features.view(features.size((0), -1))\n        logits = self.classifier(features)\n        return logits","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.789174Z","iopub.execute_input":"2025-05-28T13:34:16.789425Z","iopub.status.idle":"2025-05-28T13:34:16.812150Z","shell.execute_reply.started":"2025-05-28T13:34:16.789405Z","shell.execute_reply":"2025-05-28T13:34:16.811120Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def load_model(cfg):\n    checkpoint = torch.load(cfg.model, map_location=torch.device(cfg.device), weights_only=True)\n    model = CNN(cfg)\n    model.load_state_dict(checkpoint)\n    model = model.to(cfg.device)\n    model.eval()\n    return model","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.813109Z","iopub.execute_input":"2025-05-28T13:34:16.813326Z","iopub.status.idle":"2025-05-28T13:34:16.832859Z","shell.execute_reply.started":"2025-05-28T13:34:16.813310Z","shell.execute_reply":"2025-05-28T13:34:16.832006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def predict_audio_slice(audio_slice, model, cfg):\n    \n    mel_spec = process_audio_slice(audio_slice, cfg)\n    mel_spec = torch.tensor(mel_spec).unsqueeze(0).unsqueeze(0)\n    mel_spec = mel_spec.to(cfg.device)\n\n    predictions = []\n    \n    with torch.no_grad():\n        outputs = model(mel_spec)\n        final_preds = torch.sigmoid(outputs).cpu().numpy().squeeze()\n        \n    predictions.append(final_preds)\n    return predictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.833792Z","iopub.execute_input":"2025-05-28T13:34:16.834084Z","iopub.status.idle":"2025-05-28T13:34:16.854092Z","shell.execute_reply.started":"2025-05-28T13:34:16.834062Z","shell.execute_reply":"2025-05-28T13:34:16.853167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"'''\nfrom Stefan Kahl's Notebook\nhttps://www.kaggle.com/code/stefankahl/birdclef-2025-sample-submission/notebook\n'''\n\nimport os\nimport librosa\nimport numpy as np\nimport pandas as pd\n\n\n# Set seed\nnp.random.seed(42)\n\ncheckpoint = torch.load(cfg.model, map_location=torch.device(cfg.device), weights_only=True)\nmodel = CNN(cfg)\nmodel.load_state_dict(checkpoint)\nmodel = model.to(cfg.device)\nmodel.eval()\n\n# Class labels from train audio\nclass_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\n\n\n# List of test soundscapes (only visible during submission)\n\ntest_soundscape_path = '/kaggle/input/birdclef-2025/test_soundscapes/'\ntest_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n\n\nsave = True\n\nif cfg.debug:\n    test_soundscape_path = '/kaggle/input/birdclef-2025/train_soundscapes'\n    test_soundscapes = [os.path.join(test_soundscape_path, afile) for afile in sorted(os.listdir(test_soundscape_path)) if afile.endswith('.ogg')]\n    save = False\n\n# Open each soundscape and make predictions for 5-second segments\n# Use pandas df with 'row_id' plus class labels as columns\npredictions = pd.DataFrame(columns=['row_id'] + class_labels)\nfor idx, soundscape in enumerate(test_soundscapes):\n    if cfg.debug:\n        if idx == 5:\n            break\n    \n    # Load audio\n    sig, rate = librosa.load(path=soundscape, sr=None)\n\n    # Split into 5-second chunks\n    chunks = []\n    for i in range(0, len(sig), rate*5):\n        chunk = sig[i:i+rate*5]\n        chunks.append(chunk)\n        \n    # Make predictions for each chunk\n    for i, chunk in enumerate(chunks):\n        # Get row id  (soundscape id + end time of 5s chunk)\n        row_id = os.path.basename(soundscape).split('.')[0] + f'_{i * 5 + 5}'\n        \n        # Make prediction (let's use random scores for now)\n        # scores = model.predict...\n        scores = predict_audio_slice(chunk, model, cfg)[0]\n        \n        # Append to predictions as new row\n        new_row = pd.DataFrame([[row_id] + list(scores)], columns=['row_id'] + class_labels)\n        predictions = pd.concat([predictions, new_row], axis=0, ignore_index=True)\n        \n# Save prediction as csv\nif save:\n    predictions.to_csv('submission.csv', index=False)\npredictions.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-28T13:34:16.855970Z","iopub.execute_input":"2025-05-28T13:34:16.856529Z","iopub.status.idle":"2025-05-28T13:34:17.075600Z","shell.execute_reply.started":"2025-05-28T13:34:16.856506Z","shell.execute_reply":"2025-05-28T13:34:17.074780Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}