{"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":240861192,"sourceType":"kernelVersion"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"\n","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# BirdCLEF Audio Clip Lightning MLP","metadata":{}},{"cell_type":"code","source":"!pip install lightning","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:11:51.330024Z","iopub.execute_input":"2025-05-20T03:11:51.331219Z","iopub.status.idle":"2025-05-20T03:11:55.699959Z","shell.execute_reply.started":"2025-05-20T03:11:51.331182Z","shell.execute_reply":"2025-05-20T03:11:55.698673Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport random\nimport numpy as np\nimport pandas as pd\nfrom tqdm import tqdm\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import random_split\nfrom torch.utils.data import DataLoader, Dataset, Subset\nfrom torch.utils.data import random_split, SubsetRandomSampler\nfrom torchvision import datasets, transforms, models \nfrom torchvision.datasets import ImageFolder\nfrom torchvision.transforms import ToTensor\nfrom torchvision.utils import make_grid\n\n#the latest environement\nimport lightning.pytorch as L\nfrom lightning.pytorch import LightningDataModule\nfrom lightning.pytorch import LightningModule\nfrom lightning.pytorch import Trainer\n\nimport matplotlib.pyplot as plt\n%matplotlib inline\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\nfrom PIL import Image\nimport shutil\n","metadata":{"papermill":{"duration":13.262195,"end_time":"2023-06-30T09:39:32.607264","exception":false,"start_time":"2023-06-30T09:39:19.345069","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:11:55.702464Z","iopub.execute_input":"2025-05-20T03:11:55.702788Z","iopub.status.idle":"2025-05-20T03:11:55.71559Z","shell.execute_reply.started":"2025-05-20T03:11:55.70276Z","shell.execute_reply":"2025-05-20T03:11:55.714242Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class_names=['Ragoniella pulchella', 'Oxyprora surinamensis', 'Copiphora colombiae']\ndir0='/kaggle/input/birdclef-audio-clip-wav-to-npy/output'\n\npath_labels=[]\nfor dirname, _, filenames in os.walk(dir0):\n    for filename in filenames:\n        path=os.path.join(dirname, filename)\n        label=int(dirname.split('/')[-1])\n        path_labels+=[(path,label)]\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:11:56.219775Z","iopub.execute_input":"2025-05-20T03:11:56.220139Z","iopub.status.idle":"2025-05-20T03:12:01.132033Z","shell.execute_reply.started":"2025-05-20T03:11:56.220109Z","shell.execute_reply":"2025-05-20T03:12:01.130537Z"},"_kg_hide-output":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\npath_label, test_path_label = train_test_split(path_labels, test_size=0.2, random_state=42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:01.374398Z","iopub.execute_input":"2025-05-20T03:12:01.374777Z","iopub.status.idle":"2025-05-20T03:12:01.397933Z","shell.execute_reply.started":"2025-05-20T03:12:01.374751Z","shell.execute_reply":"2025-05-20T03:12:01.396763Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class CustomDataset(Dataset):\n    def __init__(self, path_label, transform=None):\n        self.path_label = path_label  # [(path1, label1), (path2, label2), ...]\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.path_label)\n\n    def __getitem__(self, idx):\n        audio_path, label = self.path_label[idx]\n        audio_data = np.load(audio_path)  # Load 1D audio data\n        \n        # Convert to tensor and ensure it's float32\n        audio_data = torch.from_numpy(audio_data).float()\n        \n        # If audio data is multi-channel, you might want to flatten it\n        # Or you could process each channel separately\n        if audio_data.dim() > 1:\n            audio_data = audio_data.view(-1)  # Flatten to 1D\n            \n        # Apply transform if needed\n        if self.transform:\n            audio_data = self.transform(audio_data)\n            \n        return audio_data, label","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:01.455473Z","iopub.execute_input":"2025-05-20T03:12:01.455905Z","iopub.status.idle":"2025-05-20T03:12:01.483351Z","shell.execute_reply.started":"2025-05-20T03:12:01.455837Z","shell.execute_reply":"2025-05-20T03:12:01.482068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class DataModule(LightningDataModule):\n    def __init__(self, path_label, batch_size=32, test_path_label=None, num_workers=4):\n        super().__init__()\n        self.path_label = path_label\n        self.test_path_label = test_path_label\n        self.batch_size = batch_size\n        self.num_workers = num_workers\n        \n        # Normalization for audio data (adjust mean/std based on your data)\n        self.transform = transforms.Compose([\n            transforms.Lambda(lambda x: (x - x.mean()) / x.std())  # Simple standardization\n        ])\n        \n    def setup(self, stage=None):\n        if stage == 'test':\n            self.test_dataset = CustomDataset(self.test_path_label, self.transform)\n            \n        elif stage == 'fit' or stage is None:\n            full_dataset = CustomDataset(self.path_label, self.transform)\n            \n            # Random split\n            train_size = int(0.8 * len(full_dataset))\n            val_size = len(full_dataset) - train_size\n            self.train_dataset, self.val_dataset = random_split(\n                full_dataset, \n                [train_size, val_size],\n                generator=torch.Generator().manual_seed(42)\n            )\n\n    def train_dataloader(self):\n        return DataLoader(\n            self.train_dataset,\n            batch_size=self.batch_size,\n            shuffle=True,\n            num_workers=self.num_workers,\n            pin_memory=True\n        )\n\n    def val_dataloader(self):\n        return DataLoader(\n            self.val_dataset,\n            batch_size=self.batch_size,\n            num_workers=self.num_workers\n        )\n\n    def test_dataloader(self):\n        return DataLoader(\n            self.test_dataset,\n            batch_size=self.batch_size,\n            num_workers=self.num_workers\n        )","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:01.455473Z","iopub.execute_input":"2025-05-20T03:12:01.455905Z","iopub.status.idle":"2025-05-20T03:12:01.483351Z","shell.execute_reply.started":"2025-05-20T03:12:01.455837Z","shell.execute_reply":"2025-05-20T03:12:01.482068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"class MLPNetwork(LightningModule):\n    def __init__(self, input_size, hidden_size=128, num_classes=6):\n        super().__init__()\n        self.layers = nn.Sequential(\n            nn.Linear(input_size, hidden_size),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(hidden_size, hidden_size//2),\n            nn.ReLU(),\n            nn.Dropout(0.2),\n            nn.Linear(hidden_size//2, num_classes)\n        )\n        \n    def forward(self, x):\n        # Flatten input if it's not already 1D\n        if x.dim() > 2:\n            x = x.view(x.size(0), -1)\n        return self.layers(x)\n    \n    def training_step(self, batch, batch_idx):\n        x, y = batch      \n        y_hat = self(x)\n        loss = F.cross_entropy(y_hat, y)\n        acc = (y_hat.argmax(dim=1) == y).float().mean()\n        self.log(\"train_loss\", loss, prog_bar=True)\n        self.log(\"train_acc\", acc, prog_bar=True)\n        return loss\n    \n    def validation_step(self, batch, batch_idx):\n        x, y = batch\n        #print(f\"Type of y: {type(y)}\")  # Debug: Check if y is str, tuple, etc.\n        #print(f\"Sample y value: {y[:5] if isinstance(y, (list, tuple)) else y}\")  # Inspect first few labels\n        y_hat = self(x)\n        loss = F.cross_entropy(y_hat, y)\n        acc = (y_hat.argmax(dim=1) == y).float().mean()\n        self.log(\"val_loss\", loss, prog_bar=True)\n        self.log(\"val_acc\", acc, prog_bar=True)\n    \n    def test_step(self, batch, batch_idx):\n        x, y = batch\n        y_hat = self(x)\n        loss = F.cross_entropy(y_hat, y)\n        acc = (y_hat.argmax(dim=1) == y).float().mean()\n        self.log(\"test_loss\", loss)\n        self.log(\"test_acc\", acc)\n        \n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=0.001)\n        return optimizer","metadata":{"papermill":{"duration":0.014251,"end_time":"2023-06-30T09:39:33.032042","exception":false,"start_time":"2023-06-30T09:39:33.017791","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:01.455473Z","iopub.execute_input":"2025-05-20T03:12:01.455905Z","iopub.status.idle":"2025-05-20T03:12:01.483351Z","shell.execute_reply.started":"2025-05-20T03:12:01.455837Z","shell.execute_reply":"2025-05-20T03:12:01.482068Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"datamodule = DataModule(path_label=path_label,test_path_label=test_path_label)\ndatamodule.setup(stage=None)\n\nmodel = MLPNetwork(input_size=22050, num_classes=3)\n\ntrainer = L.Trainer(max_epochs=20)\ntrainer.fit(model, datamodule)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:01.54293Z","iopub.execute_input":"2025-05-20T03:12:01.543229Z","iopub.status.idle":"2025-05-20T03:12:02.231699Z","shell.execute_reply.started":"2025-05-20T03:12:01.543202Z","shell.execute_reply":"2025-05-20T03:12:02.230063Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"val_loader = datamodule.val_dataloader()\ntrainer.validate(dataloaders=val_loader)","metadata":{"papermill":{"duration":959.542695,"end_time":"2023-06-30T09:55:32.61869","exception":false,"start_time":"2023-06-30T09:39:33.075995","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:02.232815Z","iopub.status.idle":"2025-05-20T03:12:02.233265Z","shell.execute_reply.started":"2025-05-20T03:12:02.233052Z","shell.execute_reply":"2025-05-20T03:12:02.233071Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"device = torch.device(\"cpu\")   #\"cuda:0\"\n\nmodel.eval()\ny_true=[]\ny_pred=[]\nwith torch.no_grad():\n    for val_data in datamodule.val_dataloader():\n        val_images, val_labels = val_data[0].to(device), val_data[1].to(device)\n        pred = model(val_images).argmax(dim=1)\n        for i in range(len(pred)):\n            y_true.append(val_labels[i].item())\n            y_pred.append(pred[i].item())\n\nprint(classification_report(y_true, y_pred, target_names=class_names, labels=list(range(3)), digits=4))","metadata":{"papermill":{"duration":5.368379,"end_time":"2023-06-30T09:55:39.113208","exception":false,"start_time":"2023-06-30T09:55:33.744829","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:02.23483Z","iopub.status.idle":"2025-05-20T03:12:02.235231Z","shell.execute_reply.started":"2025-05-20T03:12:02.235072Z","shell.execute_reply":"2025-05-20T03:12:02.235092Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"datamodule.setup(stage='test')","metadata":{"papermill":{"duration":0.008862,"end_time":"2023-06-30T09:55:39.131596","exception":false,"start_time":"2023-06-30T09:55:39.122734","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:02.236789Z","iopub.status.idle":"2025-05-20T03:12:02.237104Z","shell.execute_reply.started":"2025-05-20T03:12:02.236975Z","shell.execute_reply":"2025-05-20T03:12:02.236988Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.eval()\ny_true=[]\ny_pred=[]\nwith torch.no_grad():\n    for test_data in datamodule.test_dataloader():\n        test_images, test_labels =test_data[0].to(device), test_data[1].to(device)\n        pred = model(test_images).argmax(dim=1)\n        for i in range(len(pred)):\n            y_true.append(test_labels[i].item())\n            y_pred.append(pred[i].item())","metadata":{"papermill":{"duration":0.009079,"end_time":"2023-06-30T09:55:39.150422","exception":false,"start_time":"2023-06-30T09:55:39.141343","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:02.238719Z","iopub.status.idle":"2025-05-20T03:12:02.239045Z","shell.execute_reply.started":"2025-05-20T03:12:02.238906Z","shell.execute_reply":"2025-05-20T03:12:02.238925Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import classification_report\nprint(classification_report(y_true, y_pred, target_names=class_names, digits=4))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-05-20T03:12:02.240471Z","iopub.status.idle":"2025-05-20T03:12:02.240992Z","shell.execute_reply.started":"2025-05-20T03:12:02.240684Z","shell.execute_reply":"2025-05-20T03:12:02.240702Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}