{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport soundfile as sf\nimport matplotlib.pyplot as plt\nfrom tqdm import tqdm_notebook as tqdm\nfrom sklearn.model_selection import train_test_split\nimport torch\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, Dataset, sampler, Subset\nfrom torchvision.datasets import DatasetFolder, ImageFolder\nfrom torchvision.transforms import Compose\nimport torchvision.models as models\nimport torchaudio\nfrom torchaudio.transforms import MelSpectrogram, AmplitudeToDB, Resample\nfrom fastai.vision.all import *\nimport librosa\n%matplotlib inline","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Classes"},{"metadata":{"trusted":true},"cell_type":"code","source":"path = \"../input/birdclef-2021/\"\n\nclasses = os.listdir(path+\"train_short_audio\")\nclasses.sort()\nprint(classes, len(classes))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Helper Functions"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Source: https://www.kaggle.com/drcapa/birdclef-2021-starter\ndef plot_audio_file(data):\n    \"\"\" Plot the audio data\"\"\"\n    \n    sr = 32000\n    fig = plt.figure(figsize=(8, 4))\n    x = range(len(data))\n    y = data\n    plt.plot(x, y)\n    plt.plot(x, y, color='red')\n    plt.legend(loc='upper center')\n    plt.grid()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Dataset and Transformations\n\nWe will leverage the functionality of DatasetFolder from torchvision and expand it to read audio files from the \"train_short_audio\" folder."},{"metadata":{"trusted":true},"cell_type":"code","source":"def to_tensor(x):\n    return torch.Tensor(x)\n\ndef expand_dim(x):\n    return x.unsqueeze(0)\n\ndef padding(x):\n    t_size = 32000*5\n    size = t_size//len(x) + 1\n    x = torch.cat([x]*size, 0)\n    return x[0:t_size]\n    \n\ntransforms = Compose([\n    to_tensor,\n    padding,\n    MelSpectrogram(sample_rate=32000, n_mels=128),\n    AmplitudeToDB(),\n    expand_dim\n])\n\n\ndef loader(file):\n    data, samplerate = sf.read(file)\n    return data\n\nclass BirdClefShort(DatasetFolder):\n    #https://pytorch.org/vision/stable/_modules/torchvision/datasets/folder.html#DatasetFolder\n    #Modify code to return a One Hot vector instead of the ID of the class\n    def _find_classes(self, dir: str):\n        \"\"\"\n        Finds the class folders in a dataset.\n\n        Args:\n            dir (string): Root directory path.\n\n        Returns:\n            tuple: (classes, class_to_idx) where classes are relative to (dir), and class_to_idx is a dictionary.\n\n        Ensures:\n            No class is a subdirectory of another.\n        \"\"\"\n        classes = [d.name for d in os.scandir(dir) if d.is_dir()]\n        classes.sort()\n        class_to_idx = {cls_name: np.eye(len(classes))[i] for i, cls_name in enumerate(classes)}\n        return classes, class_to_idx\n\nmain_ds = BirdClefShort(\"../input/birdclef-2021/train_short_audio\", loader=loader, extensions=\".ogg\", transform=transforms, target_transform=to_tensor)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize=(16,16))\nplt.imshow(main_ds[12][0].numpy().transpose(1,2,0), cmap='hot')\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_ids, valid_ids = train_test_split(range(len(main_ds)), test_size=0.33, random_state=2021)\ntrain_ds, valid_ds = Subset(main_ds, train_ids), Subset(main_ds, valid_ids)\n\ndls = DataLoaders.from_dsets(train_ds, valid_ds, batch_size=64, num_workers=4, shuffle=True)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Model"},{"metadata":{"trusted":true},"cell_type":"code","source":"model = models.resnet18(pretrained=True)\nmodel.conv1= nn.Conv2d(1, model.conv1.out_channels, \n                      kernel_size=model.conv1.kernel_size[0], \n                      stride=model.conv1.stride[0], \n                      padding=model.conv1.padding[0])\n\nnum_ftrs = model.fc.in_features\nmodel.fc = nn.Linear(num_ftrs, len(classes))\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Train"},{"metadata":{"trusted":true},"cell_type":"code","source":"cbs=[SaveModelCallback(monitor='f1_score',comp=np.greater)]\n\nif torch.cuda.is_available(): dls.cuda(), model.cuda()\nlearn = Learner(dls, model, metrics= [accuracy_multi, F1ScoreMulti()], loss_func= nn.BCEWithLogitsLoss(), opt_func=ranger, cbs=cbs)\n#if mixed_precision_training: learn.to_fp16()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.fit_one_cycle(3, lr_max=1e-3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.save(\"last\", with_opt=False)\ntorch.save(learn.model.state_dict(),f'model_classic.pth')","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}