{"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\nimport matplotlib.pyplot as plt\nimport torch\nimport pytorch_lightning as pl\nfrom torch.utils.data import Dataset, DataLoader\nfrom sklearn import model_selection\nimport torchvision.transforms as transforms\nimport torchvision.io \nimport librosa\nfrom PIL import Image\nimport albumentations as alb\nimport torch.multiprocessing as mp\nimport warnings\n\nwarnings.filterwarnings('ignore')\nfrom pytorch_lightning.callbacks import ModelCheckpoint, BackboneFinetuning, EarlyStopping\nimport torch.nn as nn\nfrom torch.nn.functional import cross_entropy\nimport torchmetrics\nimport timm\nfrom pathlib import Path\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\nfor 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","_kg_hide-input":true,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-03-26T22:24:13.870390Z","iopub.execute_input":"2023-03-26T22:24:13.870965Z","iopub.status.idle":"2023-03-26T22:24:41.802655Z","shell.execute_reply.started":"2023-03-26T22:24:13.870929Z","shell.execute_reply":"2023-03-26T22:24:41.800673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Goal of the Competition**\n\nBirds are excellent indicators of biodiversity change since they are highly mobile and have diverse habitat requirements. Changes in species assemblage and the number of birds can thus indicate the success or failure of a restoration project. However, frequently conducting traditional observer-based bird biodiversity surveys over large areas is expensive and logistically challenging. In comparison, passive acoustic monitoring (PAM) combined with new analytical tools based on machine learning allows conservationists to sample much greater spatial scales with higher temporal resolution and explore the relationship between restoration interventions and biodiversity in depth.\n\n\nFor this competition, you'll use your machine-learning skills to identify Eastern African bird species by sound. Specifically, you'll develop computational solutions to process continuous audio data and recognize the species by their calls. The best entries will be able to train reliable classifiers with limited training data. If successful, you'll help advance ongoing efforts to protect avian biodiversity in Africa, including those led by the Kenyan conservation organization NATURAL STATE.\n\n**I will continue to work and update this notebook. Please upvote it if you find it useful in this interesting challenge!**\n\n## **Loading Data Files and Exploratory Data Analysis**\n\n**train_audio/** The training data consists of short recordings of individual bird calls generously uploaded by users of xenocanto.org. These files have been downsampled to 32 kHz where applicable to match the test set audio and converted to the ogg format. The training data should have nearly all relevant files; we expect there is no benefit to looking for more on xenocanto.org.\n\n**The code below will load the audio file into a variable named audio and its sample rate into a variable named sr. You can then use these variables to perform further processing on the audio data.**","metadata":{}},{"cell_type":"code","source":"import librosa\n\nfile_path = '/kaggle/input/birdclef-2023/train_audio/litegr/XC748836.ogg'\naudio, sr = librosa.load(file_path)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:24:41.805618Z","iopub.execute_input":"2023-03-26T22:24:41.806459Z","iopub.status.idle":"2023-03-26T22:24:54.467343Z","shell.execute_reply.started":"2023-03-26T22:24:41.806393Z","shell.execute_reply":"2023-03-26T22:24:54.466170Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"To play the audio data, you can use the **IPython.display.Audio** module. This will play the audio file directly in the notebook. You can adjust the volume of the audio using the volume parameter (default is 1.0) and the length of the audio using the duration parameter (default is the length of the audio). This will play the audio file with half volume for only the first 5 seconds.","metadata":{}},{"cell_type":"code","source":"from IPython.display import Audio\nAudio(audio, rate=sr)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:24:54.468760Z","iopub.execute_input":"2023-03-26T22:24:54.469682Z","iopub.status.idle":"2023-03-26T22:24:54.492010Z","shell.execute_reply.started":"2023-03-26T22:24:54.469640Z","shell.execute_reply":"2023-03-26T22:24:54.490874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**train_metadata.csv A wide range of metadata is provided for the training data. The most directly relevant fields are:**\n\n* primary_label - a code for the bird species. You can review detailed information about the bird codes by appending the code to https://ebird.org/species/, such as https://ebird.org/species/amecro for the American Crow.\n* latitude & longitude: coordinates for where the recording was taken. Some bird species may have local call 'dialects,' so you may want to seek geographic diversity in your training data.\n* author - The user who provided the recording.\n* filename: the name of the associated audio file.\n\nWe will now conduct exploratory data analysis of this dataset. We first plot a histogram of the latitude and longitude values in the top two subplots, a scatterplot of the latitude and longitude values in the bottom left subplot, and a bar chart of the top 10 authors with the most recordings in the bottom right subplot.","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nfile_path = '/kaggle/input/birdclef-2023/train_metadata.csv'\ndf = pd.read_csv(file_path)\n\n# Set up a figure with subplots\nfig, axs = plt.subplots(2, 2, figsize=(12, 8))\n\n# Plot a histogram of the latitude values\ndf['latitude'].hist(bins=50, ax=axs[0, 0])\naxs[0, 0].set_title('Distribution of Latitude')\naxs[0, 0].set_xlabel('Latitude')\naxs[0, 0].set_ylabel('Count')\n\n# Plot a histogram of the longitude values\ndf['longitude'].hist(bins=50, ax=axs[0, 1])\naxs[0, 1].set_title('Distribution of Longitude')\naxs[0, 1].set_xlabel('Longitude')\naxs[0, 1].set_ylabel('Count')\n\n# Plot a scatterplot of the latitude and longitude values\ndf.plot.scatter(x='longitude', y='latitude', alpha=0.1, ax=axs[1, 0])\naxs[1, 0].set_title('Geographic Distribution of Recordings')\naxs[1, 0].set_xlabel('Longitude')\naxs[1, 0].set_ylabel('Latitude')\n\n# Print the top 10 authors with the most recordings\ndf['author'].value_counts().nlargest(10).plot.bar(ax=axs[1, 1])\naxs[1, 1].set_title('Top 10 Authors with the Most Recordings')\naxs[1, 1].set_xlabel('Author')\naxs[1, 1].set_ylabel('Count')\n\n# Adjust the layout of the subplots\nplt.tight_layout()\n\n# Print the number of recordings for each bird species\nprint(df['primary_label'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:24:54.494643Z","iopub.execute_input":"2023-03-26T22:24:54.495639Z","iopub.status.idle":"2023-03-26T22:24:55.993384Z","shell.execute_reply.started":"2023-03-26T22:24:54.495595Z","shell.execute_reply":"2023-03-26T22:24:55.992149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We will now create a heatmap with a color gradient representing the density of points at each latitude-longitude location. The cmap parameter sets the color scheme for the heatmap, and fill=True adds shading to the plot to improve visibility.","metadata":{}},{"cell_type":"code","source":"import seaborn as sns\n\nsns.kdeplot(data=df, x='longitude', y='latitude', cmap=\"YlGnBu\", fill=True)\nplt.title('Heatmap of Latitude and Longitude')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:24:55.994742Z","iopub.execute_input":"2023-03-26T22:24:55.995917Z","iopub.status.idle":"2023-03-26T22:25:07.621124Z","shell.execute_reply.started":"2023-03-26T22:24:55.995866Z","shell.execute_reply":"2023-03-26T22:25:07.620094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import plotly.express as px\n\n# Create the heatmap using Plotly Express\nfig = px.density_heatmap(df, x='longitude', y='latitude', color_continuous_scale=\"YlGnBu\")\n\n# Set the title of the heatmap\nfig.update_layout(title='Interactive Heatmap of Latitude and Longitude')\n\n# Display the heatmap\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:07.623096Z","iopub.execute_input":"2023-03-26T22:25:07.623490Z","iopub.status.idle":"2023-03-26T22:25:10.349586Z","shell.execute_reply.started":"2023-03-26T22:25:07.623450Z","shell.execute_reply":"2023-03-26T22:25:10.348209Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**eBird_Taxonomy_v2021.csv** - Data on the relationships between different species.","metadata":{}},{"cell_type":"code","source":"taxonomy = pd.read_csv('/kaggle/input/birdclef-2023/eBird_Taxonomy_v2021.csv')\ntaxonomy","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.351500Z","iopub.execute_input":"2023-03-26T22:25:10.352488Z","iopub.status.idle":"2023-03-26T22:25:10.466138Z","shell.execute_reply.started":"2023-03-26T22:25:10.352431Z","shell.execute_reply":"2023-03-26T22:25:10.464938Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **Model Training & Prediction**","metadata":{}},{"cell_type":"code","source":"class Config:\n    num_classes = 264\n    batch_size = 12\n    PRECISION = 16    \n    seed = 2023\n    model = \"tf_efficientnet_b0_ns\"\n    pretrained = False\n    use_mixup = False\n    mixup_alpha = 0.2   \n    DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')    \n\n    data_root = \"/kaggle/input/birdclef-2023/\"\n    train_images = \"/kaggle/input/split-creating-melspecs-stage-1/specs/train/\"\n    valid_images = \"/kaggle/input/split-creating-melspecs-stage-1/specs/valid/\"\n    train_path = \"/kaggle/input/bc2023-train-val-df/train.csv\"\n    valid_path = \"/kaggle/input/bc2023-train-val-df/valid.csv\"\n    \n    test_path = '/kaggle/input/birdclef-2023/test_soundscapes/'\n    SR = 32000\n    DURATION = 5\n    LR = 5e-4\n    \n    model_ckpt = '/kaggle/input/birdclef-2023-pytorch-lightning-training-w-cmap/exp1/last.ckpt'","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.467655Z","iopub.execute_input":"2023-03-26T22:25:10.468014Z","iopub.status.idle":"2023-03-26T22:25:10.475265Z","shell.execute_reply.started":"2023-03-26T22:25:10.467979Z","shell.execute_reply":"2023-03-26T22:25:10.473951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pl.seed_everything(Config.seed, workers=True)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.477254Z","iopub.execute_input":"2023-03-26T22:25:10.477631Z","iopub.status.idle":"2023-03-26T22:25:10.499922Z","shell.execute_reply.started":"2023-03-26T22:25:10.477594Z","shell.execute_reply":"2023-03-26T22:25:10.498770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def config_to_dict(cfg):\n    return dict((name, getattr(cfg, name)) for name in dir(cfg) if not name.startswith('__'))","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.501815Z","iopub.execute_input":"2023-03-26T22:25:10.502836Z","iopub.status.idle":"2023-03-26T22:25:10.509546Z","shell.execute_reply.started":"2023-03-26T22:25:10.502781Z","shell.execute_reply":"2023-03-26T22:25:10.508202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def compute_melspec(y, sr, n_mels, fmin, fmax):\n    \"\"\"\n    Computes a mel-spectrogram and puts it at decibel scale\n    Arguments:\n        y {np array} -- signal\n        params {AudioParams} -- Parameters to use for the spectrogram. Expected to have the attributes sr, n_mels, f_min, f_max\n    Returns:\n        np array -- Mel-spectrogram\n    \"\"\"\n    melspec = lb.feature.melspectrogram(\n        y=y, sr=sr, n_mels=n_mels, fmin=fmin, fmax=fmax,\n    )\n\n    melspec = lb.power_to_db(melspec).astype(np.float32)\n    return melspec\n\ndef mono_to_color(X, eps=1e-6, mean=None, std=None):\n    mean = mean or X.mean()\n    std = std or X.std()\n    X = (X - mean) / (std + eps)\n    \n    _min, _max = X.min(), X.max()\n\n    if (_max - _min) > eps:\n        V = np.clip(X, _min, _max)\n        V = 255 * (V - _min) / (_max - _min)\n        V = V.astype(np.uint8)\n    else:\n        V = np.zeros_like(X, dtype=np.uint8)\n\n    return V\n\ndef crop_or_pad(y, length, is_train=True, start=None):\n    if len(y) < length:\n        y = np.concatenate([y, np.zeros(length - len(y))])\n        \n        n_repeats = length // len(y)\n        epsilon = length % len(y)\n        \n        y = np.concatenate([y]*n_repeats + [y[:epsilon]])\n        \n    elif len(y) > length:\n        if not is_train:\n            start = start or 0\n        else:\n            start = start or np.random.randint(len(y) - length)\n\n        y = y[start:start + length]\n\n    return y","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.514108Z","iopub.execute_input":"2023-03-26T22:25:10.514601Z","iopub.status.idle":"2023-03-26T22:25:10.527941Z","shell.execute_reply.started":"2023-03-26T22:25:10.514564Z","shell.execute_reply":"2023-03-26T22:25:10.526809Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train = pd.read_csv(Config.train_path)\nConfig.num_classes = len(df_train.primary_label.unique())","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.529232Z","iopub.execute_input":"2023-03-26T22:25:10.529768Z","iopub.status.idle":"2023-03-26T22:25:10.685696Z","shell.execute_reply.started":"2023-03-26T22:25:10.529734Z","shell.execute_reply":"2023-03-26T22:25:10.684419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_test = pd.DataFrame(\n     [(path.stem, *path.stem.split(\"_\"), path) for path in Path(Config.test_path).glob(\"*.ogg\")],\n    columns = [\"filename\", \"name\" ,\"id\", \"path\"]\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.687035Z","iopub.execute_input":"2023-03-26T22:25:10.687422Z","iopub.status.idle":"2023-03-26T22:25:10.695092Z","shell.execute_reply.started":"2023-03-26T22:25:10.687387Z","shell.execute_reply":"2023-03-26T22:25:10.693798Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import albumentations as A\ndef get_train_transform():\n    return A.Compose([\n        A.HorizontalFlip(p=0.5),\n        A.OneOf([\n                A.Cutout(max_h_size=5, max_w_size=16),\n                A.CoarseDropout(max_holes=4),\n            ], p=0.5),\n    ])","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.696617Z","iopub.execute_input":"2023-03-26T22:25:10.697630Z","iopub.status.idle":"2023-03-26T22:25:10.708504Z","shell.execute_reply.started":"2023-03-26T22:25:10.697578Z","shell.execute_reply":"2023-03-26T22:25:10.707327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import librosa as lb\nimport librosa.display as lbd\nimport soundfile as sf\nfrom  soundfile import SoundFile \n\nclass BirdDataset(Dataset):\n    def __init__(self, data, sr=Config.SR, n_mels=128, fmin=0, fmax=None, duration=Config.DURATION, step=None, res_type=\"kaiser_fast\", resample=True):\n        \n        self.data = data\n        \n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax or self.sr//2\n\n        self.duration = duration\n        self.audio_length = self.duration*self.sr\n        self.step = step or self.audio_length\n        \n        self.res_type = res_type\n        self.resample = resample\n\n    def __len__(self):\n        return len(self.data)\n    \n    @staticmethod\n    def normalize(image):\n        image = image.astype(\"float32\", copy=False) / 255.0\n        image = np.stack([image, image, image])\n        return image\n    \n    \n    def audio_to_image(self, audio):\n        melspec = compute_melspec(audio, self.sr, self.n_mels, self.fmin, self.fmax) \n        image = mono_to_color(melspec)\n        image = self.normalize(image)\n        return image\n\n    def read_file(self, filepath):\n        audio, orig_sr = sf.read(filepath, dtype=\"float32\")\n\n        if self.resample and orig_sr != self.sr:\n            audio = lb.resample(audio, orig_sr, self.sr, res_type=self.res_type)\n          \n        audios = []\n        for i in range(self.audio_length, len(audio) + self.step, self.step):\n            start = max(0, i - self.audio_length)\n            end = start + self.audio_length\n            audios.append(audio[start:end])\n            \n        if len(audios[-1]) < self.audio_length:\n            audios = audios[:-1]\n            \n        images = [self.audio_to_image(audio) for audio in audios]\n        images = np.stack(images)\n        \n        return images\n    \n        \n    def __getitem__(self, idx):\n        return self.read_file(self.data.loc[idx, \"path\"])","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.710172Z","iopub.execute_input":"2023-03-26T22:25:10.710670Z","iopub.status.idle":"2023-03-26T22:25:10.729480Z","shell.execute_reply.started":"2023-03-26T22:25:10.710634Z","shell.execute_reply":"2023-03-26T22:25:10.727970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds_test = BirdDataset(\n    df_test, \n    sr = Config.SR,\n    duration = Config.DURATION,\n)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.731818Z","iopub.execute_input":"2023-03-26T22:25:10.732255Z","iopub.status.idle":"2023-03-26T22:25:10.744238Z","shell.execute_reply.started":"2023-03-26T22:25:10.732201Z","shell.execute_reply":"2023-03-26T22:25:10.743248Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def show_batch(img_ds, num_items, num_rows, num_cols, predict_arr=None):\n    fig = plt.figure(figsize=(12, 6))    \n    img_index = np.random.randint(0, len(img_ds), num_items)\n    for index, img_index in enumerate(img_index):  # list first 9 images\n        img = img_ds[img_index][0]   \n        \n        ax = fig.add_subplot(num_rows, num_cols, index + 1, xticks=[], yticks=[])\n        if isinstance(img, torch.Tensor):\n            img = img.detach().numpy()\n        if isinstance(img, np.ndarray):\n            img = img.transpose(1, 2, 0)\n            ax.imshow(img)        \n            \n        title = f\"Spec\"\n        ax.set_title(title)  ","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.745642Z","iopub.execute_input":"2023-03-26T22:25:10.746691Z","iopub.status.idle":"2023-03-26T22:25:10.758223Z","shell.execute_reply.started":"2023-03-26T22:25:10.746652Z","shell.execute_reply":"2023-03-26T22:25:10.756933Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_batch(ds_test, 2, 2, 1)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:10.759777Z","iopub.execute_input":"2023-03-26T22:25:10.760349Z","iopub.status.idle":"2023-03-26T22:25:22.283119Z","shell.execute_reply.started":"2023-03-26T22:25:10.760310Z","shell.execute_reply":"2023-03-26T22:25:22.281887Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.optim.lr_scheduler import CosineAnnealingLR, CosineAnnealingWarmRestarts, ReduceLROnPlateau, OneCycleLR\n\ndef get_optimizer(lr, params):\n    model_optimizer = torch.optim.Adam(\n            filter(lambda p: p.requires_grad, params), \n            lr=lr,\n            weight_decay=Config.weight_decay\n        )\n    interval = \"epoch\"\n    \n    lr_scheduler = CosineAnnealingWarmRestarts(\n                            model_optimizer, \n                            T_0=Config.epochs, \n                            T_mult=1, \n                            eta_min=1e-6, \n                            last_epoch=-1\n                        )\n\n    return {\n        \"optimizer\": model_optimizer, \n        \"lr_scheduler\": {\n            \"scheduler\": lr_scheduler,\n            \"interval\": interval,\n            \"monitor\": \"val_loss\",\n            \"frequency\": 1\n        }\n    }","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:22.285094Z","iopub.execute_input":"2023-03-26T22:25:22.285911Z","iopub.status.idle":"2023-03-26T22:25:22.295615Z","shell.execute_reply.started":"2023-03-26T22:25:22.285845Z","shell.execute_reply":"2023-03-26T22:25:22.294527Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sklearn.metrics\n\ndef padded_cmap(solution, submission, padding_factor=5):\n    solution = solution#.drop(['row_id'], axis=1, errors='ignore')\n    submission = submission#.drop(['row_id'], axis=1, errors='ignore')\n    new_rows = []\n    for i in range(padding_factor):\n        new_rows.append([1 for i in range(len(solution.columns))])\n    new_rows = pd.DataFrame(new_rows)\n    new_rows.columns = solution.columns\n    padded_solution = pd.concat([solution, new_rows]).reset_index(drop=True).copy()\n    padded_submission = pd.concat([submission, new_rows]).reset_index(drop=True).copy()\n    score = sklearn.metrics.average_precision_score(\n        padded_solution.values,\n        padded_submission.values,\n        average='macro',\n    )\n    return score\n\ndef map_score(solution, submission):\n    solution = solution#.drop(['row_id'], axis=1, errors='ignore')\n    submission = submission#.drop(['row_id'], axis=1, errors='ignore')\n    score = sklearn.metrics.average_precision_score(\n        solution.values,\n        submission.values,\n        average='micro',\n    )\n    return score","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:22.297448Z","iopub.execute_input":"2023-03-26T22:25:22.298288Z","iopub.status.idle":"2023-03-26T22:25:22.314781Z","shell.execute_reply.started":"2023-03-26T22:25:22.298235Z","shell.execute_reply":"2023-03-26T22:25:22.313673Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BirdClefModel(pl.LightningModule):\n    def __init__(self, model_name=Config.model, num_classes = Config.num_classes, pretrained = Config.pretrained):\n        super().__init__()\n        self.num_classes = num_classes\n\n        self.backbone = timm.create_model(model_name, pretrained=pretrained)\n\n        if 'res' in model_name:\n            self.in_features = self.backbone.fc.in_features\n            self.backbone.fc = nn.Linear(self.in_features, num_classes)\n        elif 'dense' in model_name:\n            self.in_features = self.backbone.classifier.in_features\n            self.backbone.classifier = nn.Linear(self.in_features, num_classes)\n        elif 'efficientnet' in model_name:\n            self.in_features = self.backbone.classifier.in_features\n            self.backbone.classifier = nn.Sequential(\n                nn.Linear(self.in_features, num_classes)\n            )\n        \n        self.loss_function = nn.BCEWithLogitsLoss() \n\n    def forward(self,images):\n        logits = self.backbone(images)\n        return logits\n        \n    def configure_optimizers(self):\n        return get_optimizer(lr=Config.LR, params=self.parameters())\n\n    def training_step(self, batch, batch_idx):\n        image, target = batch        \n\n        y_pred = self(image)\n        loss = self.loss_function(y_pred,target)\n\n        self.log(\"train_loss\", loss, on_step=True, on_epoch=True, prog_bar=True)\n        return loss        \n\n    def validation_step(self, batch, batch_idx):\n        image, target = batch     \n        y_pred = self(image)\n        val_loss = self.loss_function(y_pred, target)\n        self.log(\"val_loss\", val_loss, on_step=True, on_epoch=True, logger=True, prog_bar=True)\n        \n        return {\"val_loss\": val_loss, \"logits\": y_pred, \"targets\": target}\n    \n    def train_dataloader(self):\n        return self._train_dataloader \n    \n    def validation_dataloader(self):\n        return self._validation_dataloader\n    \n    def validation_epoch_end(self,outputs):\n        avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()\n        output_val = torch.cat([x['logits'] for x in outputs],dim=0).sigmoid().cpu().detach().numpy()\n        target_val = torch.cat([x['targets'] for x in outputs],dim=0).cpu().detach().numpy()\n        \n        # print(output_val.shape)\n        val_df = pd.DataFrame(target_val, columns = birds)\n        pred_df = pd.DataFrame(output_val, columns = birds)\n        \n        avg_score = padded_cmap(val_df, pred_df, padding_factor = 5)\n        avg_score2 = padded_cmap(val_df, pred_df, padding_factor = 3)\n        avg_score3 = sklearn.metrics.label_ranking_average_precision_score(target_val,output_val)\n        \n#         competition_metrics(output_val,target_val)\n        print(f'epoch {self.current_epoch} validation loss {avg_loss}')\n        print(f'epoch {self.current_epoch} validation C-MAP score pad 5 {avg_score}')\n        print(f'epoch {self.current_epoch} validation C-MAP score pad 3 {avg_score2}')\n        print(f'epoch {self.current_epoch} validation AP score {avg_score3}')\n        \n        \n        val_df.to_pickle('val_df.pkl')\n        pred_df.to_pickle('pred_df.pkl')\n        \n        \n        return {'val_loss': avg_loss,'val_cmap':avg_score}","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:22.316627Z","iopub.execute_input":"2023-03-26T22:25:22.317421Z","iopub.status.idle":"2023-03-26T22:25:22.337939Z","shell.execute_reply.started":"2023-03-26T22:25:22.317370Z","shell.execute_reply":"2023-03-26T22:25:22.336987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict(data_loader, model):\n        \n    model.to('cpu')\n    model.eval()    \n    predictions = []\n    for en in range(len(ds_test)):\n        print(en)\n        images = torch.from_numpy(ds_test[en])\n        print(images.shape)\n        with torch.no_grad():\n            outputs = model(images).sigmoid().detach().cpu().numpy()\n            print(outputs.shape)\n#             pred_batch.extend(outputs.detach().cpu().numpy())\n#         pred_batch = np.vstack(pred_batch)\n        predictions.append(outputs)\n            \n    \n    return predictions","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:22.340044Z","iopub.execute_input":"2023-03-26T22:25:22.340866Z","iopub.status.idle":"2023-03-26T22:25:22.356433Z","shell.execute_reply.started":"2023-03-26T22:25:22.340811Z","shell.execute_reply":"2023-03-26T22:25:22.355282Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\n\nprint(f\"Create Dataloader...\")\n\nds_test = BirdDataset(\n    df_test, \n    sr = Config.SR,\n    duration = Config.DURATION,\n)\n\n\naudio_model = BirdClefModel()\n\nprint(\"Model Creation\")\n\nmodel = BirdClefModel.load_from_checkpoint(Config.model_ckpt, train_dataloader=None,validation_dataloader=None) \nprint(\"Running Inference..\")\n\npreds = predict(ds_test, model)   \n\ngc.collect()\ntorch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:22.358186Z","iopub.execute_input":"2023-03-26T22:25:22.358644Z","iopub.status.idle":"2023-03-26T22:25:36.003994Z","shell.execute_reply.started":"2023-03-26T22:25:22.358599Z","shell.execute_reply":"2023-03-26T22:25:36.002790Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filenames = df_test.filename.values.tolist()\n\nbird_cols = list(pd.get_dummies(df_train['primary_label']).columns)\nsub_df = pd.DataFrame(columns=['row_id']+bird_cols)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:36.005305Z","iopub.execute_input":"2023-03-26T22:25:36.005648Z","iopub.status.idle":"2023-03-26T22:25:36.028225Z","shell.execute_reply.started":"2023-03-26T22:25:36.005613Z","shell.execute_reply":"2023-03-26T22:25:36.026928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for i, file in enumerate(filenames):\n    pred = preds[i]\n    num_rows = len(pred)\n    row_ids = [f'{file}_{(i+1)*5}' for i in range(num_rows)]\n    df = pd.DataFrame(columns=['row_id']+bird_cols)\n    \n    df['row_id'] = row_ids\n    df[bird_cols] = pred\n    \n    sub_df = pd.concat([sub_df,df]).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:36.029817Z","iopub.execute_input":"2023-03-26T22:25:36.030309Z","iopub.status.idle":"2023-03-26T22:25:36.146564Z","shell.execute_reply.started":"2023-03-26T22:25:36.030259Z","shell.execute_reply":"2023-03-26T22:25:36.145647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_df.to_csv('submission.csv',index=False)","metadata":{"execution":{"iopub.status.busy":"2023-03-26T22:25:36.147936Z","iopub.execute_input":"2023-03-26T22:25:36.148822Z","iopub.status.idle":"2023-03-26T22:25:36.192287Z","shell.execute_reply.started":"2023-03-26T22:25:36.148776Z","shell.execute_reply":"2023-03-26T22:25:36.191138Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## **To Be Continued...**","metadata":{}}]}