{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-04-24T15:56:17.394549Z","iopub.execute_input":"2023-04-24T15:56:17.398287Z","iopub.status.idle":"2023-04-24T15:56:17.411495Z","shell.execute_reply.started":"2023-04-24T15:56:17.398222Z","shell.execute_reply":"2023-04-24T15:56:17.408456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torchaudio\nimport torch.nn as nn\nimport torch.nn.functional as F\nfrom torch.utils.data import Dataset, DataLoader\nfrom torchvision.transforms import ToTensor, Compose, Resize\nfrom torchaudio.transforms import AmplitudeToDB, MelSpectrogram, TimeMasking, FrequencyMasking\n\nimport sys\nimport glob\nimport random\nimport matplotlib.pyplot as plt\nfrom IPython.display import Audio\n\n\npackage_path = \"../input/efficientnet-pytorch/EfficientNet-PyTorch/EfficientNet-PyTorch-master/\"\nsys.path.append(package_path)\nimport efficientnet_pytorch","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:18.390321Z","iopub.execute_input":"2023-04-24T15:56:18.390932Z","iopub.status.idle":"2023-04-24T15:56:18.402873Z","shell.execute_reply.started":"2023-04-24T15:56:18.390724Z","shell.execute_reply":"2023-04-24T15:56:18.401734Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def set_seed(seed=42):\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    random.seed(seed)\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed(seed)\n        torch.backends.cudnn.deterministic = True\n        torch.backends.cudnn.benchmark = False\n\nset_seed(42)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:19.258745Z","iopub.execute_input":"2023-04-24T15:56:19.259664Z","iopub.status.idle":"2023-04-24T15:56:19.331952Z","shell.execute_reply.started":"2023-04-24T15:56:19.259611Z","shell.execute_reply":"2023-04-24T15:56:19.330948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# set_seed(42)\n\n# all_audios = glob.glob(\"/kaggle/input/birdclef-2023/train_audio/*/*\")\n# random.shuffle(all_audios)\n# len(all_audios)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"####################### scary stuff ##################################\n\n# I cant think of any other way so :)\n# takes approx 20 min. in cpu\n# thats why saved the list as dataframe and adding that as a data\n\n# train_audios = []\n\n# for file in all_audios:\n#     wvr, sr = torchaudio.load(file)\n#     time = wvr.shape[1] / sr\n#     lst = file.split(\"/\")\n#     for i in range(0, round(time), 5):\n#         a1 = lst[-2]\n#         a2 = lst[-1].split(\".\")[0]\n#         train_audios.append(f\"{a1}_{a2}_{i}\")\n\n\n# len(train_audios)\n\n# df = pd.DataFrame({\"list\": train_audios})\n# df.head()\n\n# df.to_csv(\"train_files_list_5_sec_interval.csv\", index=False)\n\n######################################################################","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(42)\n\ntrain_val_audios = pd.read_csv(\"/kaggle/input/bclef2023-train-audios-5-sec/train_files_list_5_sec_interval.csv\").list.to_numpy()\nrandom.shuffle(train_val_audios)\ntrain_val_audios","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:21.140761Z","iopub.execute_input":"2023-04-24T15:56:21.141441Z","iopub.status.idle":"2023-04-24T15:56:21.495229Z","shell.execute_reply.started":"2023-04-24T15:56:21.141403Z","shell.execute_reply":"2023-04-24T15:56:21.494064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n = int(0.99 * len(train_val_audios))\ntrain_audios = train_val_audios[:n]\nval_audios = train_val_audios[n:]\n\nlen(train_audios), len(val_audios)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:22.703789Z","iopub.execute_input":"2023-04-24T15:56:22.704707Z","iopub.status.idle":"2023-04-24T15:56:22.713303Z","shell.execute_reply.started":"2023-04-24T15:56:22.704656Z","shell.execute_reply":"2023-04-24T15:56:22.712190Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"target_names = [_.split(\"/\")[-1] for _ in glob.glob(\"/kaggle/input/birdclef-2023/train_audio/*\")]\ntarget_names = sorted(target_names)\nlen(target_names)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:25.951382Z","iopub.execute_input":"2023-04-24T15:56:25.951855Z","iopub.status.idle":"2023-04-24T15:56:25.988022Z","shell.execute_reply.started":"2023-04-24T15:56:25.951812Z","shell.execute_reply":"2023-04-24T15:56:25.986960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"str_2_int = {}\n\ncounter = 0\nfor trgt in target_names:\n    str_2_int[trgt] = counter\n    counter += 1\n\nlen(str_2_int)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:27.176390Z","iopub.execute_input":"2023-04-24T15:56:27.176844Z","iopub.status.idle":"2023-04-24T15:56:27.185889Z","shell.execute_reply.started":"2023-04-24T15:56:27.176805Z","shell.execute_reply":"2023-04-24T15:56:27.184752Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"int_2_str = {i:s for s, i in str_2_int.items()}\n\nlen(int_2_str)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:28.041235Z","iopub.execute_input":"2023-04-24T15:56:28.041667Z","iopub.status.idle":"2023-04-24T15:56:28.052939Z","shell.execute_reply.started":"2023-04-24T15:56:28.041629Z","shell.execute_reply":"2023-04-24T15:56:28.051876Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"mel_spectogram = MelSpectrogram(\n    sample_rate=32000,\n    n_fft=1024,\n    hop_length=None,\n    n_mels=64\n)\n\nimg_transform = Compose([\n    Resize((128, 384)),\n])","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:29.317419Z","iopub.execute_input":"2023-04-24T15:56:29.317872Z","iopub.status.idle":"2023-04-24T15:56:29.430042Z","shell.execute_reply.started":"2023-04-24T15:56:29.317830Z","shell.execute_reply":"2023-04-24T15:56:29.428922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AudioDataset(Dataset):\n    def __init__(self, audio_list, mel_spec_transform, img_transform, train=False):\n        self.audio_list = audio_list\n        self.mel_spec_transform = mel_spec_transform\n        self.img_transform = img_transform\n        self.train = train\n\n    def __len__(self):\n        return len(self.audio_list)\n\n    def __getitem__(self, idx):\n        audio_split = self.audio_list[idx].split(\"_\")\n        audio_path = f\"/kaggle/input/birdclef-2023/train_audio/{audio_split[0]}/{audio_split[1]}.ogg\"\n        i = int(audio_split[2])\n        waveform, sr = torchaudio.load(audio_path)\n        waveform = torch.mean(waveform, dim=0, keepdims=True)\n        waveform = waveform[:, i*sr:(i+5)*sr]\n        spectrogram = self.mel_spec_transform(waveform)\n        if self.train:\n            spectrogram = TimeMasking(time_mask_param=8)(spectrogram)\n            spectrogram = FrequencyMasking(freq_mask_param=20)(spectrogram)\n        spectrogram = AmplitudeToDB(top_db=80)(spectrogram)\n        spectrogram = spectrogram.repeat(3, 1, 1)\n        spectrogram = self.img_transform(spectrogram)\n        spectrogram = (spectrogram - spectrogram.min()) / (spectrogram.max() - spectrogram.min())\n        label = audio_path.split(\"/\")[-2]\n        label = str_2_int[label]\n        return spectrogram, label","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:56:30.929790Z","iopub.execute_input":"2023-04-24T15:56:30.930170Z","iopub.status.idle":"2023-04-24T15:56:30.942074Z","shell.execute_reply.started":"2023-04-24T15:56:30.930138Z","shell.execute_reply":"2023-04-24T15:56:30.940982Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# training on a part of the data\n\ntrain_audios = train_audios[50000:]\nval_audios = val_audios[:500]\n\nlen(train_audios), len(val_audios)","metadata":{"execution":{"iopub.status.busy":"2023-04-24T15:58:41.132016Z","iopub.execute_input":"2023-04-24T15:58:41.132710Z","iopub.status.idle":"2023-04-24T15:58:41.139306Z","shell.execute_reply.started":"2023-04-24T15:58:41.132673Z","shell.execute_reply":"2023-04-24T15:58:41.138317Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(42)\n\ntraining_data = AudioDataset(train_audios, mel_spectogram, img_transform, train=True)\nval_data = AudioDataset(val_audios, mel_spectogram, img_transform)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataloader = DataLoader(training_data, batch_size=32, shuffle=True)\nval_dataloader = DataLoader(val_data, batch_size=32, shuffle=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig = plt.figure(figsize=(6, 6))\ncolumns = 2\nrows = 2\nfor i in range(1, columns*rows +1):\n    img = next(iter(train_dataloader))[0][i-1]\n    img = torch.transpose(img, 0, 2)\n    fig.add_subplot(rows, columns, i)\n    plt.imshow(img)\n    plt.axis(\"off\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for x, y in train_dataloader:\n    print(x.shape)\n    print(y)\n    break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for x, y in val_dataloader:\n    print(x.shape)\n    print(y)\n    break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"device = \"cuda\" if torch.cuda.is_available() else \"mps\" if torch.backends.mps.is_available() else \"cpu\"\n\nprint(f\"Using {device} device\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tranied_models_list = glob.glob(\"/kaggle/input/birdclef23-trained-models/*\")\ntranied_models_list = sorted(tranied_models_list)\ntranied_models_list","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, out_features):\n        super().__init__()\n        self.net = efficientnet_pytorch.EfficientNet.from_name(\"efficientnet-b1\")\n        n_features = self.net._fc.in_features\n        self.net._fc = nn.Linear(n_features, out_features, bias=True)\n    \n    def forward(self, x):\n        out = self.net(x)\n        return out","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"set_seed(42)\n\nweight_path = \"/kaggle/input/birdclef23-trained-models/model3_b1.pth\"\nprint(weight_path)\nout_features = len(target_names)\n\nmodel = Model(out_features)\n\nmodel.load_state_dict(torch.load(weight_path))\n\nmodel.to(device);","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def save_model(model, batch):\n    torch.save(model.state_dict(), f\"model_batch{batch}.pth\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_fn = nn.CrossEntropyLoss()\noptimizer = torch.optim.Adam(model.parameters(), lr=0.0005)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"loss_track = []","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(dataloader, model, loss_fn, optimizer):\n    size = len(dataloader.dataset)\n    model.train()\n    for batch, (X, y) in enumerate(dataloader):\n        X, y = X.to(device), y.to(device)\n\n        # Compute prediction error\n        pred = model(X)\n        loss = loss_fn(pred, y)\n\n        # Backpropagation\n        optimizer.zero_grad()\n        loss.backward()\n        optimizer.step()\n        \n        if batch % 10 == 0:\n            loss_track.append(loss.item())\n\n        if batch % 100 == 0:\n            save_model(model, batch)\n            loss, current = loss.item(), (batch + 1) * len(X)\n            print(f\"loss: {loss:>7f}  [{current:>5d}/{size:>5d}]\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def test(dataloader, model, loss_fn):\n    size = len(dataloader.dataset)\n    num_batches = len(dataloader)\n    model.eval()\n    test_loss, correct = 0, 0\n    with torch.no_grad():\n        for X, y in dataloader:\n            X, y = X.to(device), y.to(device)\n            pred = model(X)\n            test_loss += loss_fn(pred, y).item()\n            correct += (pred.argmax(1) == y).type(torch.float).sum().item()\n    test_loss /= num_batches\n    correct /= size\n    print(f\"Test Error: \\n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \\n\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"epochs = 1\nfor t in range(epochs):\n    print(f\"Epoch {t+1}\\n-------------------------------\")\n    train(train_dataloader, model, loss_fn, optimizer)\n    test(val_dataloader, model, loss_fn)\nprint(\"Done!\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(torch.tensor(loss_track).view(-1, 1).mean(1))\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for x, y in val_dataloader:\n    x = x.to(device)\n    y = y.to(device)\n    pred = model(x)\n    print(torch.argmax(pred, 1))\n    print(y)\n    break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"torch.save(model.state_dict(), \"model_final.pth\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}