{"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":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":172284497,"sourceType":"kernelVersion"}],"dockerImageVersionId":30559,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# BirdClef2024 5s's Mel Pytorch Lightning CNN","metadata":{"papermill":{"duration":0.004496,"end_time":"2023-10-20T03:51:55.074593","exception":false,"start_time":"2023-10-20T03:51:55.070097","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"https://www.kaggle.com/code/stpeteishii/birdclef2024-sound-to-5s-s-mel","metadata":{}},{"cell_type":"markdown","source":"https://www.kaggle.com/code/stpeteishii/embryo-quality-pytorch-lightning-cnn","metadata":{}},{"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\nfrom pytorch_lightning import LightningModule\nfrom pytorch_lightning import Trainer\nimport pytorch_lightning as pl\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","metadata":{"papermill":{"duration":16.57467,"end_time":"2023-10-20T03:52:11.653276","exception":false,"start_time":"2023-10-20T03:51:55.078606","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-04-16T12:02:22.747249Z","iopub.execute_input":"2024-04-16T12:02:22.747549Z","iopub.status.idle":"2024-04-16T12:02:37.727606Z","shell.execute_reply.started":"2024-04-16T12:02:22.747522Z","shell.execute_reply":"2024-04-16T12:02:37.726802Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dir0='/kaggle/input/birdclef2024-sound-to-5s-s-mel/mel/'","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:37.729111Z","iopub.execute_input":"2024-04-16T12:02:37.729436Z","iopub.status.idle":"2024-04-16T12:02:37.733715Z","shell.execute_reply.started":"2024-04-16T12:02:37.729408Z","shell.execute_reply":"2024-04-16T12:02:37.732823Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"classes=[]\npaths=[]\nfor dirname, _, filenames in os.walk(dir0):\n    for filename in filenames:\n        if not filename.endswith('.txt'):\n            classes+=[dirname.split('/')[-1]]\n            paths+=[(os.path.join(dirname, filename))]","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:37.734644Z","iopub.execute_input":"2024-04-16T12:02:37.734923Z","iopub.status.idle":"2024-04-16T12:02:39.248161Z","shell.execute_reply.started":"2024-04-16T12:02:37.734899Z","shell.execute_reply":"2024-04-16T12:02:39.247048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"N=list(range(len(classes)))\nclass_names=sorted(set(classes))\nprint(class_names)\nprint(len(class_names))\nnormal_mapping=dict(zip(class_names,N)) \nreverse_mapping=dict(zip(N,class_names))       \n\ndata=pd.DataFrame(columns=['path','class','label'])\ndata['path']=paths\ndata['class']=classes\ndata['label']=data['class'].map(normal_mapping)\nprint(len(data))","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.251070Z","iopub.execute_input":"2024-04-16T12:02:39.251790Z","iopub.status.idle":"2024-04-16T12:02:39.278343Z","shell.execute_reply.started":"2024-04-16T12:02:39.251732Z","shell.execute_reply":"2024-04-16T12:02:39.277545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"transform=transforms.Compose([\n        transforms.RandomRotation(10),      # rotate +/- 10 degrees\n        transforms.RandomHorizontalFlip(),  # reverse 50% of images\n        transforms.Resize(224),             # resize shortest side to 224 pixels\n        transforms.CenterCrop(224),         # crop longest side to 224 pixels at center\n        transforms.ToTensor(),\n        transforms.Normalize([0.485, 0.456, 0.406],\n                             [0.229, 0.224, 0.225])\n])","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.279403Z","iopub.execute_input":"2024-04-16T12:02:39.279692Z","iopub.status.idle":"2024-04-16T12:02:39.285445Z","shell.execute_reply.started":"2024-04-16T12:02:39.279668Z","shell.execute_reply":"2024-04-16T12:02:39.284507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_path_label_list(df):\n    path_label_list = []\n    for _, row in df.iterrows():\n        path = row['path']\n        label = row['label']\n        path_label_list.append((path, label))\n    return path_label_list\n\npath_label = create_path_label_list(data)\npath_label = random.sample(path_label,len(path_label))\nprint(len(path_label))\nprint(path_label[0:3])","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.286580Z","iopub.execute_input":"2024-04-16T12:02:39.286870Z","iopub.status.idle":"2024-04-16T12:02:39.868511Z","shell.execute_reply.started":"2024-04-16T12:02:39.286847Z","shell.execute_reply":"2024-04-16T12:02:39.867545Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CustomDataset(torch.utils.data.Dataset):\n    def __init__(self, path_label, transform=None):\n        self.path_label = path_label\n        self.transform = transform\n\n    def __len__(self):\n        return len(self.path_label)\n\n    def __getitem__(self, idx):\n        path, label = self.path_label[idx]\n        img = Image.open(path).convert('RGB')\n\n        if self.transform is not None:\n            img = self.transform(img)\n\n        return img, label","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.869933Z","iopub.execute_input":"2024-04-16T12:02:39.870759Z","iopub.status.idle":"2024-04-16T12:02:39.877096Z","shell.execute_reply.started":"2024-04-16T12:02:39.870721Z","shell.execute_reply":"2024-04-16T12:02:39.876074Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageDataset(pl.LightningDataModule):\n    def __init__(self, path_label, batch_size=32):\n        super().__init__()\n        self.path_label = path_label\n        self.batch_size = batch_size\n        self.transform = transforms.Compose([\n            transforms.Resize(224),             # resize shortest side to 224 pixels\n            transforms.CenterCrop(224),         # crop longest side to 224 pixels at center            \n            transforms.ToTensor(),\n            transforms.Normalize([0.485, 0.456, 0.406],\n                                 [0.229, 0.224, 0.225])\n        ])\n\n    def setup(self, stage=None):\n        dataset = CustomDataset(self.path_label, self.transform)\n        dataset_size = len(dataset)\n        train_size = int(0.7 * dataset_size) \n        val_size = dataset_size - train_size\n        print(train_size,val_size)\n\n        self.train_dataset = torch.utils.data.Subset(dataset, range(train_size))\n        self.val_dataset = torch.utils.data.Subset(dataset, range(train_size, dataset_size))\n\n    def __len__(self):\n        if self.train_dataset is not None:\n            return len(self.train_dataset)\n        elif self.val_dataset is not None:\n            return len(self.val_dataset)\n        else:\n            return 0        \n\n    def __getitem__(self, index):\n        if self.train_dataset is not None:\n            return self.train_dataset[index]\n        elif self.test_dataset is not None:\n            return self.test_dataset[index]\n        else:\n            raise IndexError(\"Index out of range. The dataset is empty.\")\n\n    def train_dataset(self):\n        return DataLoader(self.train_dataset, batch_size=self.batch_size, shuffle=True)\n\n    def val_dataset(self):\n        return DataLoader(self.val_dataset, batch_size=self.batch_size)\n","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.878258Z","iopub.execute_input":"2024-04-16T12:02:39.878853Z","iopub.status.idle":"2024-04-16T12:02:39.890266Z","shell.execute_reply.started":"2024-04-16T12:02:39.878822Z","shell.execute_reply":"2024-04-16T12:02:39.889534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class DataModule(pl.LightningDataModule):\n    \n    def __init__(self, transform=transform, batch_size=16):\n        super().__init__()\n        self.root_dir = dir0\n        self.transform = transform\n        self.batch_size = batch_size\n\n    def setup(self, stage=None):\n        data_set = datasets.ImageFolder(root=self.root_dir, transform=self.transform)\n        \n        n_data = len(dataset)\n        n_train = int(0.7 * n_data)\n        n_val = n_data - n_train\n        train_dataset, val_dataset =  random_split(dataset, [n_train, n_val])\n\n        self.train_dataset = DataLoader(train_dataset, batch_size=self.batch_size, shuffle=True)\n        self.val_dataset = DataLoader(val_dataset, batch_size=self.batch_size)\n    \n    def train_dataloader(self):\n        return self.train_dataset\n\n    def val_dataloader(self):\n        return self.val_dataset\n    \n    def test_dataloader(self):\n        return self.test_dataset","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.891394Z","iopub.execute_input":"2024-04-16T12:02:39.891717Z","iopub.status.idle":"2024-04-16T12:02:39.903414Z","shell.execute_reply.started":"2024-04-16T12:02:39.891694Z","shell.execute_reply":"2024-04-16T12:02:39.902665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ConvolutionalNetwork(LightningModule):\n    \n    def __init__(self):\n        super(ConvolutionalNetwork, self).__init__()\n        self.conv1 = nn.Conv2d(3, 6, 3, 1)\n        self.conv2 = nn.Conv2d(6, 16, 3, 1)\n        self.fc1 = nn.Linear(16 * 54 * 54, 120)\n        self.fc2 = nn.Linear(120, 84)\n        self.fc3 = nn.Linear(84, 20)\n        self.fc4 = nn.Linear(20, len(class_names))\n\n    def forward(self, X):\n        X = F.relu(self.conv1(X))\n        X = F.max_pool2d(X, 2, 2)\n        X = F.relu(self.conv2(X))\n        X = F.max_pool2d(X, 2, 2)\n        X = X.view(-1, 16 * 54 * 54)\n        X = F.relu(self.fc1(X))\n        X = F.relu(self.fc2(X))\n        X = F.relu(self.fc3(X))\n        X = self.fc4(X)\n        return F.log_softmax(X, dim=1)\n\n    def configure_optimizers(self):\n        optimizer = torch.optim.Adam(self.parameters(), lr=0.001)\n        return optimizer\n\n    def training_step(self, train_batch, batch_idx):\n        X, y = train_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"train_loss\", loss)\n        self.log(\"train_acc\", acc)\n        return loss\n\n    def validation_step(self, val_batch, batch_idx):\n        X, y = val_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"val_loss\", loss)\n        self.log(\"val_acc\", acc)\n\n    def test_step(self, test_batch, batch_idx):\n        X, y = test_batch\n        y_hat = self(X)\n        loss = F.cross_entropy(y_hat, y)\n        pred = y_hat.argmax(dim=1, keepdim=True)\n        acc = pred.eq(y.view_as(pred)).sum().item() / y.shape[0]\n        self.log(\"test_loss\", loss)\n        self.log(\"test_acc\", acc)","metadata":{"papermill":{"duration":0.017788,"end_time":"2023-10-20T04:07:32.45877","exception":false,"start_time":"2023-10-20T04:07:32.440982","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-04-16T12:02:39.906722Z","iopub.execute_input":"2024-04-16T12:02:39.907033Z","iopub.status.idle":"2024-04-16T12:02:39.921701Z","shell.execute_reply.started":"2024-04-16T12:02:39.907009Z","shell.execute_reply":"2024-04-16T12:02:39.920860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dataset = ImageDataset(path_label)\ndataset.setup() \ntrain_dataloader = dataset.train_dataloader\nval_dataloader = dataset.val_dataloader\n#test_dataloader = dataset.test_dataloader\ndatamodule = DataModule()\nmodel = ConvolutionalNetwork()","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-04-16T12:02:39.922708Z","iopub.execute_input":"2024-04-16T12:02:39.923013Z","iopub.status.idle":"2024-04-16T12:02:39.997042Z","shell.execute_reply.started":"2024-04-16T12:02:39.922989Z","shell.execute_reply":"2024-04-16T12:02:39.996142Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"trainer = pl.Trainer(max_epochs=20)\ntrainer.fit(model, datamodule)\nval_loader = datamodule.val_dataloader()\ntrainer.test(dataloaders=val_loader)","metadata":{"execution":{"iopub.status.busy":"2024-04-16T12:02:39.998031Z","iopub.execute_input":"2024-04-16T12:02:39.998279Z","iopub.status.idle":"2024-04-16T12:05:11.338677Z","shell.execute_reply.started":"2024-04-16T12:02:39.998258Z","shell.execute_reply":"2024-04-16T12:05:11.337832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for images, labels in datamodule.val_dataloader():\n    break\nim=make_grid(images,nrow=8)\n\nplt.figure(figsize=(12,12))\nplt.imshow(np.transpose(im.numpy(),(1,2,0)))\n\ninv_normalize=transforms.Normalize(mean=[-0.485/0.229,-0.456/0.224,-0.406/0.225],\n                                   std=[1/0.229,1/0.224,1/0.225])\nim=inv_normalize(im)\n\nplt.figure(figsize=(12,12))\nplt.imshow(np.transpose(im.numpy(),(1,2,0)))","metadata":{"papermill":{"duration":1.491702,"end_time":"2023-10-20T04:08:20.662404","exception":false,"start_time":"2023-10-20T04:08:19.170702","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-04-16T12:05:11.339793Z","iopub.execute_input":"2024-04-16T12:05:11.340082Z","iopub.status.idle":"2024-04-16T12:05:12.539607Z","shell.execute_reply.started":"2024-04-16T12:05:11.340057Z","shell.execute_reply":"2024-04-16T12:05:12.538686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = torch.device(\"cpu\")   #\"cuda:0\"\n\nmodel.eval()\ny_true=[]\ny_pred=[]\nwith torch.no_grad():\n    for test_data in datamodule.val_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())\n\nprint(classification_report(y_true,y_pred,target_names=class_names,digits=4))","metadata":{"papermill":{"duration":1.445697,"end_time":"2023-10-20T04:08:22.122719","exception":false,"start_time":"2023-10-20T04:08:20.677022","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2024-04-16T12:05:12.540943Z","iopub.execute_input":"2024-04-16T12:05:12.541257Z","iopub.status.idle":"2024-04-16T12:05:27.062306Z","shell.execute_reply.started":"2024-04-16T12:05:12.541230Z","shell.execute_reply":"2024-04-16T12:05:27.060951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}