{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"from torch.utils.data import Dataset, DataLoader, random_split\nfrom torchvision import transforms\nfrom tqdm.notebook import tqdm\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport pandas as pd\nimport numpy as np\nimport torch\nimport time\nimport glob\nimport os\n\nclass SpectrogramsDataset(Dataset):\n    \"\"\"Face Landmarks dataset.\"\"\"\n\n    def __init__(self, csv_file, root_dir, transform=None):\n        \"\"\"\n        Args:\n            csv_file (string): Path to the csv file with class id details.\n            root_dir (string): Directory with all the images.\n            transform (callable, optional): Optional transform to be applied\n                on a sample.\n        \"\"\"\n        self.audio_data = pd.read_csv(csv_file)\n        self.audio_data[\"class_label\"] = self.audio_data[\"species_id\"].astype(str) + \"_\" + self.audio_data[\"songtype_id\"].astype(str)\n        self.class_names = list(np.unique(self.audio_data[\"class_label\"]))\n        #self.audio_data.set_index(\"recording_id\")\n        print(self.class_names)\n        self.list_imgs = glob.glob(root_dir + \"*.png\")\n        self.transform = transform\n        self.num_classes = len(self.class_names)\n    def __len__(self):\n        return len(self.audio_data)\n\n    def __getitem__(self, idx):\n        img_path = self.list_imgs[idx]\n        image = Image.open(img_path).convert(\"RGB\")\n        label  = torch.tensor(self.class_names.index(self.audio_data.loc[self.audio_data[\"recording_id\"] == os.path.split(img_path)[1].split(\"_idx_\")[0]][\"class_label\"].values[0]))\n        if self.transform:\n            image = self.transform(image)\n        return image, label\n    \n    \ntrain_transforms = transforms.Compose([\n        #transforms.RandomResizedCrop(224),\n        #transforms.RandomHorizontalFlip(),\n        transforms.ToTensor()\n    ])\n\nbatch_size = 4\ncsv_file = \"/kaggle/input/rfcx-species-audio-detection/train_tp.csv\"\nroot_dir = \"/kaggle/input/true-positive-centered-10-second-spectrograms/true_pos_specs/\"\ndataset = SpectrogramsDataset(csv_file, root_dir, train_transforms)\ntrainset, valset = random_split(dataset, [int(0.8 * len(dataset)), len(dataset) - int(0.8 * len(dataset))])\ntrainloader = DataLoader(trainset, batch_size=batch_size, shuffle=True)\nvalloader = DataLoader(valset, batch_size=batch_size, shuffle=True)\nprint(dataset.num_classes)\nprint(len(trainset))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import torch.nn as nn\nimport torch.nn.functional as F\nfrom torchvision import models\n\nclass CUSTOMCNN(nn.Module):\n    def __init__(self, n_classes):\n        super(CUSTOMCNN, self).__init__()\n        self.conv1 = nn.Conv2d(3, 64, kernel_size=(3, 3))\n        self.conv2 = nn.Conv2d(64, 32, kernel_size=(3, 3))\n        self.conv22 = nn.Conv2d(32, 64, kernel_size=(3, 3))\n        self.conv3 = nn.Conv2d(64, 128, kernel_size=(3, 3))\n        self.conv4 = nn.Conv2d(128, 256, kernel_size=(3, 3))\n        self.conv5 = nn.Conv2d(256, 512, kernel_size=(3, 3))\n        self.conv6 = nn.Conv2d(512, 1024, kernel_size=(2, 2))\n        self.linear1 = nn.Linear(2048, 500)\n        #self.linear2 = nn.Linear(500, n_classes)\n        self.linear3 = nn.Linear(500, n_classes)\n\n    def forward(self, x):\n        \"\"\"\n        Args:\n          x of shape (batch_size, 1, 28, 28): Input images.\n        Returns:\n          y of shape (batch_size, 10): Outputs of the network.\n        \"\"\"\n        x = F.max_pool2d(F.relu(self.conv2(self.conv1(x))), kernel_size=(2,3))\n        x = F.max_pool2d(F.relu(self.conv22(x)), kernel_size=(2,2))\n        x = F.max_pool2d(F.relu(self.conv3(x)), kernel_size=(2,2))\n        x = F.max_pool2d(F.relu(self.conv4(x)), kernel_size=(2,2))\n        x = F.max_pool2d(F.relu(self.conv5(x)), kernel_size=(2,2))\n        x = F.max_pool2d(F.relu(self.conv6(x)), kernel_size=(2,2))\n        x = x.view(-1, 2048)\n        x = F.relu(self.linear1(x))\n        #x = F.relu(self.linear2(x))\n        x = self.linear3(x)\n        return x\n    \n\nclass VGGNet(nn.Module):\n    def __init__(self, n_classes=16):\n        \"\"\"\n        Args:\n          n_channels (int): Number of channels in the first convolutional layer. The number of channels in the following layers are the multipliers of n_channels. Hence, parameters of the layers to follow can be defined using this variable.    \"\"\"\n        super(VGGNet, self).__init__()\n        self.conv1_1 = nn.Conv2d(3, 16, kernel_size=(3,3), padding=1)\n        self.batchnorm_16 = nn.BatchNorm2d(16)\n        self.conv1_2 = nn.Conv2d(16, 16, kernel_size=(3,3), padding=1)\n        self.conv1_3 = nn.Conv2d(16, 16, kernel_size=(3,3), padding=1)\n        self.maxpool2d_1 = nn.MaxPool2d(kernel_size=(2,2), stride=2)\n        self.conv2_1 = nn.Conv2d(16, 32, kernel_size=(3,3), padding=1)\n        self.batchnorm_32 = nn.BatchNorm2d(32)\n        self.conv2_2 = nn.Conv2d(32, 32, kernel_size=(3,3), padding=1)\n        self.conv2_3 = nn.Conv2d(32, 32, kernel_size=(3,3), padding=1)\n        self.maxpool2d_2 = nn.MaxPool2d(kernel_size=(2,2), stride=2)\n        self.conv3 = nn.Conv2d(32, 48, kernel_size=(3,3))\n        self.batchnorm_48 = nn.BatchNorm2d(48)\n        self.conv4 = nn.Conv2d(48, 32, kernel_size=(1,1))\n        self.conv5 = nn.Conv2d(32, 16, kernel_size=(1,1))\n        self.avgpool = nn.AvgPool2d(5)\n        self.fc1 = nn.Linear(2560,n_classes)\n        \n \n    def forward(self, x, verbose=False):\n        \"\"\"\n        Args:\n          x of shape (batch_size, 1, 28, 28): Input images.\n          verbose: True if you want to print the shapes of the intermediate variables.\n        \n        Returns:\n          y of shape (batch_size, 10): Outputs of the network.\n        \"\"\" \n        batch_size = x.shape[0]\n        x = F.relu(self.batchnorm_16(self.conv1_1(x)))\n        x = F.relu(self.batchnorm_16(self.conv1_2(x)))\n        x = F.relu(self.batchnorm_16(self.conv1_3(x)))\n        x = self.maxpool2d_1(x)\n        x = F.relu(self.batchnorm_32(self.conv2_1(x)))\n        x = F.relu(self.batchnorm_32(self.conv2_2(x)))\n        x = F.relu(self.batchnorm_32(self.conv2_3(x)))\n        x = self.maxpool2d_2(x)\n        x = F.relu(self.batchnorm_48(self.conv3(x)))\n        x = F.relu(self.batchnorm_32(self.conv4(x)))\n        x = F.relu(self.batchnorm_16(self.conv5(x)))\n        x = self.fc1(self.avgpool(x).view(batch_size,2560))\n        return x\n    \nclass RESNET34(nn.Module):\n    def __init__(self, n_classes):\n        super(RESNET34, self).__init__()\n        self.model_ft = models.resnet34(pretrained=True)\n        num_ftrs = self.model_ft.fc.in_features\n\n        self.model_ft.fc = nn.Linear(num_ftrs, n_classes)\n\n    def forward(self, x):\n        return self.model_ft(x)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"num_epochs = 30\nmodel = VGGNet(dataset.num_classes)\noptimizer = torch.optim.Adam(model.parameters(), lr = 0.001)\ncriterion = nn.CrossEntropyLoss()\ntloss, tacc = [], []\nvloss, vacc = [], []\ndevice = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\nprint(device)\nsince = time.time()\nmodel.to(device)\n\nfor epoch in tqdm(range(num_epochs)):\n    print('Epoch {}/{}'.format(epoch+1, num_epochs))\n    print('-' * 10)\n    model.train()  # Set model to training mode\n    running_loss = 0.0\n    running_corrects = 0.0\n    # Iterate over data.\n    for inputs, labels in trainloader:\n        with torch.set_grad_enabled(True):\n            inputs = inputs.to(device)\n            labels = labels.to(device)\n\n            optimizer.zero_grad()\n            outputs = model(inputs)\n            _, preds = torch.max(outputs, 1)\n            loss = criterion(outputs, labels)\n            loss.backward()\n            optimizer.step()\n        \n        running_loss += loss.item()\n        running_corrects += (torch.sum(preds== labels.data)).item()\n    epoch_loss = running_loss / len(trainset)\n    epoch_acc = (running_corrects)/ len(trainset)\n    print('Training Loss: {:.4f} Training Acc: {:.4f}'.format(epoch_loss, epoch_acc))\n    \n    running_loss = 0.0\n    \n    running_corrects = 0.0\n    model.eval()\n    for inputs, labels in valloader:\n        inputs = inputs.to(device)\n        labels = labels.to(device)\n\n        outputs = model(inputs)\n        _, preds = torch.max(outputs, 1)\n        loss = criterion(outputs, labels)\n        running_loss += loss.item()\n        running_corrects += (torch.sum(preds== labels.data)).item()\n    epoch_loss = running_loss / len(valset)\n    epoch_acc = (running_corrects) / len(valset)\n    print('Val Loss: {:.4f} Val Acc: {:.4f}'.format(epoch_loss, epoch_acc))\n    tloss.append(epoch_loss)\n    tacc.append(epoch_acc)\n\n\ntime_elapsed = time.time() - since\nprint('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))\nprint( model, [tloss, tacc, vloss, vacc])\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}