{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.11","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"},{"sourceId":189366517,"sourceType":"kernelVersion"}],"dockerImageVersionId":31040,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport librosa\n\nimport torch\nimport torch.nn as nn\nimport os\nimport random\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\nfrom ast import literal_eval\nimport timm\nimport kaggle_metric_utilities\n\nimport pandas.api.types\n\nimport sklearn.metrics\nfrom sklearn.model_selection import StratifiedKFold\nfrom tqdm import tqdm\nimport gc\n\nfrom warnings import filterwarnings\nfilterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:02.991971Z","iopub.execute_input":"2025-07-08T19:50:02.992233Z","iopub.status.idle":"2025-07-08T19:50:15.864511Z","shell.execute_reply.started":"2025-07-08T19:50:02.992207Z","shell.execute_reply":"2025-07-08T19:50:15.863906Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Configuration","metadata":{}},{"cell_type":"code","source":"class Config:\n    train_dir = \"/kaggle/input/birdclef-2025/train_audio\"\n    seed =42\n    train_csv = \"/kaggle/input/birdclef-2025/train.csv\"\n    sample_csv = \"/kaggle/input/birdclef-2025/sample_submission.csv\"\n    test_soundscapes = \"/kaggle/input/birdclef-2025/test_soundscapes\"\n\n    sr = int(32e3)\n    num_classes = 206\n    n_fft = 1024\n    hop_length = 500\n\n    n_mels = 128\n    fmin = 50\n    fmax = 16000\n    power = 2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:15.866048Z","iopub.execute_input":"2025-07-08T19:50:15.866434Z","iopub.status.idle":"2025-07-08T19:50:15.870682Z","shell.execute_reply.started":"2025-07-08T19:50:15.866414Z","shell.execute_reply":"2025-07-08T19:50:15.870009Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Helper Function","metadata":{}},{"cell_type":"code","source":"def set_seed(seed: int = Config.seed) -> None:\n    random.seed(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed(seed)\n        torch.cuda.manual_seed_all(seed)\n\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = False\n\n    print(f\"[INFO] Set Seed: {seed}\")\n\nset_seed()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:15.871452Z","iopub.execute_input":"2025-07-08T19:50:15.871743Z","iopub.status.idle":"2025-07-08T19:50:15.962658Z","shell.execute_reply.started":"2025-07-08T19:50:15.871724Z","shell.execute_reply":"2025-07-08T19:50:15.962051Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Dataset loading","metadata":{}},{"cell_type":"code","source":"from IPython.display import HTML\n\nHTML(\"<style>div.output_area pre {font-size: 10px;}</style>\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:15.963403Z","iopub.execute_input":"2025-07-08T19:50:15.963627Z","iopub.status.idle":"2025-07-08T19:50:15.968903Z","shell.execute_reply.started":"2025-07-08T19:50:15.963608Z","shell.execute_reply":"2025-07-08T19:50:15.968372Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_df = pd.read_csv(Config.train_csv) \n\nfor col in ('secondary_labels', 'type'):\n    data_df[col] = data_df[col].apply(lambda x: \"###\".join(literal_eval(x))) #stringifying the secondary label\n\ndata_df['filename'] = data_df['filename'].apply(lambda x: Config.train_dir + \"/\" + x) #adapting the file name to the train audio\ndata_df.sample(10)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:15.969528Z","iopub.execute_input":"2025-07-08T19:50:15.969776Z","iopub.status.idle":"2025-07-08T19:50:16.534220Z","shell.execute_reply.started":"2025-07-08T19:50:15.969750Z","shell.execute_reply":"2025-07-08T19:50:16.533471Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"The basic pipeline while using audio files are  converting to the spectrogram and this spectogram acts as an image for the model.","metadata":{}},{"cell_type":"code","source":"#Null check\ndata_df.isnull().sum()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:16.534910Z","iopub.execute_input":"2025-07-08T19:50:16.535128Z","iopub.status.idle":"2025-07-08T19:50:16.554500Z","shell.execute_reply.started":"2025-07-08T19:50:16.535111Z","shell.execute_reply":"2025-07-08T19:50:16.553701Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"We dont have any null values in any all the features except latitude and longitude, sisnce we dont need to use it,we dont need to deal with this.","metadata":{}},{"cell_type":"code","source":"#Distributuion of the ratings\n\nplt.figure(figsize = (15,3))\nsns.histplot(data_df, x ='rating')\nplt.xticks(np.arange(0,5.5,0.5))\nplt.show();","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:16.556525Z","iopub.execute_input":"2025-07-08T19:50:16.556727Z","iopub.status.idle":"2025-07-08T19:50:16.798348Z","shell.execute_reply.started":"2025-07-08T19:50:16.556711Z","shell.execute_reply":"2025-07-08T19:50:16.797705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Distribution of the primary label\nplt.figure(figsize = (15,3))\nsns.histplot(data_df, x ='primary_label')\nplt.xticks(rotation =90)\nplt.show();","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:16.799093Z","iopub.execute_input":"2025-07-08T19:50:16.799330Z","iopub.status.idle":"2025-07-08T19:50:17.866885Z","shell.execute_reply.started":"2025-07-08T19:50:16.799299Z","shell.execute_reply":"2025-07-08T19:50:17.866142Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Distribution of the primary label with different ratings\nfor r in range(0,6):\n    plt.figure(figsize = (20,3))\n    sns.countplot(data_df[data_df['rating']== float(r)], x ='primary_label')\n    plt.title(f\"Rating {r}\")\n    plt.xticks(rotation =90)\n    plt.show();","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:17.867639Z","iopub.execute_input":"2025-07-08T19:50:17.867849Z","iopub.status.idle":"2025-07-08T19:50:23.215077Z","shell.execute_reply.started":"2025-07-08T19:50:17.867833Z","shell.execute_reply":"2025-07-08T19:50:23.214288Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Since we will be converting audio files into spectogram for a specific length of the audio, we need to know that how the length of audionis varying, So lets check that.","metadata":{}},{"cell_type":"code","source":"#statistics of audio duration\n\ndurations = []\nfor idx, row in data_df.sample(100).iterrows():\n    data, _ = librosa.load(row['filename'],sr= Config.sr)\n    durations.append(librosa.get_duration(y=data, sr = Config.sr))\n\nd_df = pd.DataFrame(columns = [\"durations\"],data = durations)\n\nplt.figure(figsize = (10,5))\nplt.title(\"Distribution of audio lengths\")\nsns.histplot(d_df, x = \"durations\")\nplt.show();\n\nd_df.describe()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:23.215890Z","iopub.execute_input":"2025-07-08T19:50:23.216174Z","iopub.status.idle":"2025-07-08T19:50:41.321412Z","shell.execute_reply.started":"2025-07-08T19:50:23.216149Z","shell.execute_reply":"2025-07-08T19:50:41.320797Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Analyzing Class distribution","metadata":{}},{"cell_type":"code","source":"# Plot species frequency\nspecies_counts = data_df['primary_label'].value_counts()\nplt.figure(figsize=(12, 6))\nspecies_counts[:50].plot(kind='bar')  # Top 50 species\nplt.title(\"Class Imbalance (Top 50 Species)\")\nplt.xlabel(\"Species ID\")\nplt.ylabel(\"Count\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:41.322309Z","iopub.execute_input":"2025-07-08T19:50:41.322627Z","iopub.status.idle":"2025-07-08T19:50:42.068483Z","shell.execute_reply.started":"2025-07-08T19:50:41.322612Z","shell.execute_reply":"2025-07-08T19:50:42.067844Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Check out spectograms","metadata":{}},{"cell_type":"code","source":"def show_signal(file_path):\n    class_, collector = file_path.split(\"/\")[-2:]\n\n    y, sr = librosa.load(file_path, sr = Config.sr)\\\n\n    fig, axes = plt.subplots(2,2, figsize = (20, 10))\n    \n    fig.suptitle(f\"class: {class_} | collector: {collector}\", fontsize =16)\n\n    #plottinig raw signal\n    librosa.display.waveshow(y, sr=sr, ax=axes[0,0])\n    axes[0,0].set_title(\"Raw signal\")\n    \n\n    #plotting fourier transformed signal\n    ft = np.abs(librosa.stft(\n        y,\n        n_fft = Config.n_fft,\n        hop_length = Config.hop_length\n    ))\n    im1 = librosa.display.specshow(\n        ft,\n        sr = sr,\n        x_axis = 'time',\n        y_axis = 'linear',\n        ax = axes[0, 1]\n    )\n    fig.colorbar(im1, ax = axes[0, 1])\n    axes[0, 1].set_title(\"Spectrogram\")\n\n    #plotting log scaled fourier transformes signal\n    ft_db = librosa.amplitude_to_db(ft, ref = np.max)\n    im2 = librosa.display.specshow(\n        ft_db,\n        sr = sr,\n        x_axis = 'time',\n        y_axis = 'log',\n        ax = axes[1, 0]\n    )\n    fig.colorbar(im2, ax = axes[1, 0])\n    axes[1, 0].set_title(\"Log scaled spectrogram\")\n\n    #plotting mel spectrogram\n    mel_sp = librosa.feature.melspectrogram(\n        y = y,\n        sr = Config.sr,\n        fmin = Config.fmin,\n        fmax = Config.fmax,\n        power = Config.power,\n        n_mels = Config.n_mels,\n        \n    )\n    mel_sp = librosa.power_to_db(mel_sp, ref = np.max)\n    im3 = librosa.display.specshow(\n        mel_sp,\n        y_axis = 'mel',\n        sr = Config.sr,\n        fmin = Config.fmin,\n        x_axis = 'time',\n        fmax = Config.fmax,\n        ax = axes[1, 1]\n    )\n\n    fig.colorbar(im3, ax = axes[1, 0])\n    axes[1, 1].set_title(\"Mel spectrogram\")\n\n    plt.show()\n\nshow_signal(data_df['filename'].values[0])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:42.069225Z","iopub.execute_input":"2025-07-08T19:50:42.069434Z","iopub.status.idle":"2025-07-08T19:50:49.476577Z","shell.execute_reply.started":"2025-07-08T19:50:42.069419Z","shell.execute_reply":"2025-07-08T19:50:49.475798Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for idx, row in data_df.sample(10).iterrows():show_signal(row['filename'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:50:49.477427Z","iopub.execute_input":"2025-07-08T19:50:49.477641Z","iopub.status.idle":"2025-07-08T19:51:19.658481Z","shell.execute_reply.started":"2025-07-08T19:50:49.477624Z","shell.execute_reply":"2025-07-08T19:51:19.657720Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Now we need to do the same spectrogram conversion while we are creating dataset.","metadata":{}},{"cell_type":"markdown","source":"# Dataset","metadata":{}},{"cell_type":"code","source":"label_mapper = {\n    label: idx\n    for idx, label in enumerate(sorted(data_df['primary_label'].unique()))\n}\n\nrev_mapper = {\n    idx: label\n    for label, idx in label_mapper.items()\n}\n\nclass BirdClefDataset(torch.utils.data.Dataset):\n    def __init__(self, df, mode =\"train\"):\n        self.df = df\n        self.mode = mode\n        \n    def __len__(self): return len(self.df)\n\n    def process(self, audio_path):\n        data, _ = librosa.load(audio_path, sr = Config.sr)\n\n        data = data * 1024 #scaling\n\n        chunk_duration = 10\n        min_len = chunk_duration * Config.sr\n\n        #if the audio signal is less than min_len\n        if len(data) < min_len:\n            cnt = int(np.ceil(min_len / len(data)))\n            data = np.tile(data, cnt)\n            \n        #making the data length divisible by min_len\n        leftover = len(data) % min_len\n        if leftover > 0 :\n            front_crop = leftover // 2\n            back_crop = leftover - front_crop\n            data = data[front_crop : len(data) - back_crop]\n\n\n        #Truncating the signal to min_len\n        data = data[:min_len] \n        data = data.reshape(-1, min_len)\n        \n        #creating mel spectrogram\n        mel_sp = librosa.feature.melspectrogram(\n            y =data,\n            sr = Config.sr,\n            fmin = Config.fmin,\n            fmax = Config.fmax,\n            power = Config.power,\n            n_mels = Config.n_mels,\n            n_fft = Config.n_fft,\n            hop_length = Config.hop_length\n            \n        )\n\n        mel_sp = librosa.power_to_db(mel_sp, ref = 1)\n        \n        #Normalizing the feature values\n        eps = 1e-12\n        mel_sp = (mel_sp - mel_sp.min())/ (mel_sp.max() - mel_sp.min() + eps)\n        \n        mel_sp = mel_sp[:, :,:640]\n        return mel_sp\n\n    \n    \n    def __getitem__(self, idx):\n        row = self.df.loc[idx,:]\n        filename = row['filename']\n\n    #TODO: Spectrogram conversion\n        x = self.process(filename)\n\n        if self.mode ==\"train\":\n            y =label_mapper[row['primary_label']]\n            return x, y\n\n        return x\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:19.659328Z","iopub.execute_input":"2025-07-08T19:51:19.659550Z","iopub.status.idle":"2025-07-08T19:51:19.670527Z","shell.execute_reply.started":"2025-07-08T19:51:19.659533Z","shell.execute_reply":"2025-07-08T19:51:19.669976Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"mel_sp = BirdClefDataset(data_df).process(data_df['filename'].values[0])\nprint(mel_sp.shape)\n\n#Trasnform from C, H, W -> H, W, C\nplt.imshow(mel_sp.reshape(128,640, -1))\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2025-07-08T19:51:19.671507Z","iopub.execute_input":"2025-07-08T19:51:19.671760Z","iopub.status.idle":"2025-07-08T19:51:19.930919Z","shell.execute_reply.started":"2025-07-08T19:51:19.671736Z","shell.execute_reply":"2025-07-08T19:51:19.930276Z"},"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Model","metadata":{}},{"cell_type":"code","source":"class Model(nn.Module):\n    def __init__(self, model_name: str):\n        super().__init__()\n        self.base_model = timm.create_model(\n            model_name = model_name,\n            num_classes = Config.num_classes,\n            pretrained = False,\n            in_chans = 1\n        )\n    def forward(self, x):\n        return self.base_model(x)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:19.931711Z","iopub.execute_input":"2025-07-08T19:51:19.932040Z","iopub.status.idle":"2025-07-08T19:51:19.936208Z","shell.execute_reply.started":"2025-07-08T19:51:19.932018Z","shell.execute_reply":"2025-07-08T19:51:19.935586Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Checking Dataset and Model class\n\ntmp_ds = BirdClefDataset(data_df.sample(10).reset_index())\nmodel = Model(\"tf_efficientnet_b0\")\n\nfor i in range(10):\n    x, y = tmp_ds[i]\n\n    model.eval()\n\n    preds = model(torch.tensor([x]))\n    preds = torch.argmax(torch.softmax(preds, dim=1), dim = 1).item()\n    plt.imshow(x.reshape(128, 640, -1))\n    plt.title(f\"Label:{rev_mapper[y]} | {x.shape} | model_pred: {rev_mapper[preds]}\") \n    plt.show()\n\ndel model\ndel tmp_ds","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:19.936980Z","iopub.execute_input":"2025-07-08T19:51:19.937227Z","iopub.status.idle":"2025-07-08T19:51:23.093279Z","shell.execute_reply.started":"2025-07-08T19:51:19.937204Z","shell.execute_reply":"2025-07-08T19:51:23.092672Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Training","metadata":{}},{"cell_type":"code","source":"class ParticipantVisibleError(Exception):\n    pass\n\n\ndef score(solution: pd.DataFrame, submission: pd.DataFrame, row_id_column_name: str) -> float:\n    '''\n    Version of macro-averaged ROC-AUC score that ignores all classes that have no true positive labels.\n    '''\n    del solution[row_id_column_name]\n    del submission[row_id_column_name]\n\n    if not pandas.api.types.is_numeric_dtype(submission.values):\n        bad_dtypes = {x: submission[x].dtype  for x in submission.columns if not pandas.api.types.is_numeric_dtype(submission[x])}\n        raise ParticipantVisibleError(f'Invalid submission data types found: {bad_dtypes}')\n\n    solution_sums = solution.sum(axis=0)\n    scored_columns = list(solution_sums[solution_sums > 0].index.values)\n    assert len(scored_columns) > 0\n\n    return kaggle_metric_utilities.safe_call_score(sklearn.metrics.roc_auc_score, solution[scored_columns].values, submission[scored_columns].values, average='macro')\n\ndef cal_score(labels, preds):\n    labels = np.concatenate(labels)\n    preds = np.concatenate(preds)\n\n    labels_df = pd.DataFrame(labels > 0.5, columns = list(label_mapper.keys()))\n    pred_df = pd.DataFrame(preds, columns = list(label_mapper.keys()))\n\n    labels_df['id'] = np.arange(len(labels_df))\n    pred_df['id'] = np.arange(len(pred_df))\n\n    return score(labels_df, pred_df, row_id_column_name = 'id')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:23.094029Z","iopub.execute_input":"2025-07-08T19:51:23.094247Z","iopub.status.idle":"2025-07-08T19:51:23.100870Z","shell.execute_reply.started":"2025-07-08T19:51:23.094231Z","shell.execute_reply":"2025-07-08T19:51:23.100127Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n#Training configs\n\nepochs = 5\nnum_folds = 3\ndevice = \"cuda\" if torch.cuda.is_available() else \"CPU\"\nlr = 1e-4\ntarget_col = 'primary_label'\ndf = data_df\n\nskf = StratifiedKFold(\n    n_splits = num_folds,\n    shuffle = True,\n    random_state = Config.seed\n    \n)\n\ndf['kfold'] = -1\n\nfor fold, (train_idx, val_idx) in enumerate(skf.split(X= df, y= df[target_col])):\n    df.loc[val_idx, 'kfold'] = fold","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:23.101720Z","iopub.execute_input":"2025-07-08T19:51:23.101964Z","iopub.status.idle":"2025-07-08T19:51:23.140595Z","shell.execute_reply.started":"2025-07-08T19:51:23.101942Z","shell.execute_reply":"2025-07-08T19:51:23.140091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:23.141283Z","iopub.execute_input":"2025-07-08T19:51:23.141521Z","iopub.status.idle":"2025-07-08T19:51:23.155852Z","shell.execute_reply.started":"2025-07-08T19:51:23.141497Z","shell.execute_reply":"2025-07-08T19:51:23.155179Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for fold in range(num_folds):\n    train_df = df[df['kfold'] != fold].reset_index(drop = True)\n    val_df = df[df['kfold'] == fold].reset_index(drop = True)\n\n    train_ds = BirdClefDataset(train_df)\n    val_ds = BirdClefDataset(val_df)\n\n    train_loader = torch.utils.data.DataLoader(\n        train_ds,\n        batch_size = 8,\n        shuffle = True,\n        num_workers = 2,\n        drop_last = True\n    )\n\n    val_loader = torch.utils.data.DataLoader(\n        val_ds,\n        batch_size = 16,\n        shuffle = False,\n        num_workers = 2,\n        drop_last = False\n    )\n\n    # Initializing the model\n    model = Model(model_name = \"tf_efficientnet_b0\").to(device)\n\n\n    criterion = nn.CrossEntropyLoss()\n    optimizer = torch.optim.Adam(model.parameters(), lr = lr)\n\n\n    best_auc = 0\n\n    #per fold training\n    for epoch in range (epochs):\n        model.train()\n\n        pred_train =[]\n        label_train =[]\n\n        running_loss = 0.0\n\n        for(x, y) in tqdm (train_loader, desc = \"Training\"):\n            x, y = x.to(device), y.to(device)\n\n            #Converting to One hot encoding\n            y_one_hot = nn.functional.one_hot(\n                y,\n                num_classes = Config.num_classes\n            ).float()\n            \n            optimizer.zero_grad()\n            outputs = model(x)\n\n            loss = criterion(outputs, y)\n            loss.backward()\n\n            optimizer.step()\n\n            running_loss += loss.item()\n\n            probs = torch.softmax(outputs, dim = 1)\n            pred_train.append(probs.detach().cpu().numpy())\n            label_train.append(y_one_hot.detach().cpu().numpy())\n            \n        # Validation\n        model.eval()\n    \n        pred_val =[]\n        label_val =[]\n    \n        running_val_loss = 0.0\n    \n        with torch.no_grad():\n            for (x, y) in tqdm (val_loader, desc = \"Validation\"):\n                x, y = x.to(device), y.to(device)\n        \n                 #Converting to One hot encoding\n                y_one_hot = nn.functional.one_hot(\n                    y,\n                    num_classes = Config.num_classes\n                ).float()\n                    \n                outputs = model(x)\n        \n                loss = criterion(outputs, y)\n            \n                running_val_loss += loss.item()\n        \n                probs = torch.softmax(outputs, dim = 1)\n                pred_val.append(probs.detach().cpu().numpy())\n                label_val.append(y_one_hot.detach().cpu().numpy())\n\n        # Computing AUC and loss\n        auc_train = cal_score (label_train, pred_train)\n        auc_val = cal_score(label_val, pred_val)\n        \n        avg_train_loss = running_loss / len(train_loader)\n        avg_val_loss =  running_loss / len(val_loader)\n        \n        print(f\"[Fold]: {fold} | [EPOCH]: {epoch} | Loss: {avg_train_loss:.4f} | Val_loss: {avg_val_loss:.4f}\")\n        print(f\"[Fold]: {fold} | [EPOCH]: {epoch} | Train AUC: {auc_train:.4f} | Val AUC: {auc_val:.4f}\")\n        \n        \n        if best_auc <= auc_val:\n            best_auc = auc_val\n            torch.save(\n                model.state_dict(),\n                f\"fold_{fold}_epoch_{epoch}_effnetB0_val_auc_{auc_val}_val_loss_{avg_val_loss}.pth\"\n            )\n\n    del train_df, val_df, train_ds, val_ds, train_loader, val_loader, criterion, optimizer\n    gc.collect()\n    torch.cuda.empty_cache() ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-07-08T19:51:23.156749Z","iopub.execute_input":"2025-07-08T19:51:23.157040Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}