{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.10.0"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceType":"competition","sourceId":70203,"databundleVersionId":8068726,"isSourceIdPinned":false}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"8f521673-cb54-4ab9-8b20-2c9a975e6600","cell_type":"code","source":"import glob\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport librosa\nimport librosa.display\nimport keras\nfrom keras import layers, models, callbacks\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:20:45.57054Z","iopub.execute_input":"2026-05-18T01:20:45.570969Z","iopub.status.idle":"2026-05-18T01:20:45.576122Z","shell.execute_reply.started":"2026-05-18T01:20:45.570939Z","shell.execute_reply":"2026-05-18T01:20:45.575245Z"}},"outputs":[],"execution_count":null},{"id":"05be18c0-856f-478c-9589-fd2b04d9c418","cell_type":"code","source":"meta_file = glob.glob('/kaggle/input/**/train_metadata.csv', recursive=True)[0]\nDATASET_PATH = os.path.dirname(meta_file)\n\nmetadata = pd.read_csv(f\"{DATASET_PATH}/train_metadata.csv\")\naudio_folder = f\"{DATASET_PATH}/train_audio\"\n\nprint(f'   Total rows      : {len(metadata)}')\nprint(f'   Columns         : {list(metadata.columns)}')\nprint(f'   Unique species  : {metadata[\"primary_label\"].nunique()}')\nmetadata.head(3)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:20:45.941422Z","iopub.execute_input":"2026-05-18T01:20:45.941943Z","iopub.status.idle":"2026-05-18T01:21:17.370717Z","shell.execute_reply.started":"2026-05-18T01:20:45.941917Z","shell.execute_reply":"2026-05-18T01:21:17.369897Z"}},"outputs":[],"execution_count":null},{"id":"4a2b0109-5ed9-4f55-8dfe-53434ab1c88e","cell_type":"code","source":"IMG_HEIGHT = 224   \nIMG_WIDTH  = 224   \nDURATION   = 5     \nSR         = 22050\n\ndef audio_to_image(path):\n    audio, sr = librosa.load(path, sr=SR, duration=DURATION, mono=True)\n    target_length = SR * DURATION\n    if len(audio) < target_length:\n        audio = np.pad(audio, (0, target_length - len(audio)))\n    else:\n        audio = audio[:target_length]\n    spec = librosa.feature.melspectrogram(\n        y=audio,\n        sr=sr,\n        n_mels=IMG_HEIGHT\n    )\n    spec_db = librosa.power_to_db(spec, ref=np.max)\n    spec_resized = librosa.util.fix_length(spec_db, size=IMG_WIDTH, axis=1)\n    spec_norm = (spec_resized - spec_resized.min()) / (spec_resized.max() - spec_resized.min() + 1e-6)\n    return np.expand_dims(spec_norm, axis=-1)\n        ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:46:20.155333Z","iopub.execute_input":"2026-05-18T01:46:20.155958Z","iopub.status.idle":"2026-05-18T01:46:20.161931Z","shell.execute_reply.started":"2026-05-18T01:46:20.155929Z","shell.execute_reply":"2026-05-18T01:46:20.161164Z"}},"outputs":[],"execution_count":null},{"id":"79174acf-2888-4190-a1e8-0bce5ede04ce","cell_type":"code","source":"first_file = os.path.join(audio_folder, metadata_sampled['filename'].iloc[0])\ntest_img = audio_to_image(first_file)\n\nplt.figure(figsize=(6, 3))\nplt.imshow(test_img[:, :, 0], aspect='auto', origin='lower', cmap='magma')\nplt.colorbar(label='Normalized Amplitude')\nplt.title('Sample Mel Spectrogram Image')\nplt.xlabel('Time frames')\nplt.ylabel('Mel frequency bins')\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:46:21.902793Z","iopub.execute_input":"2026-05-18T01:46:21.903238Z","iopub.status.idle":"2026-05-18T01:46:22.20123Z","shell.execute_reply.started":"2026-05-18T01:46:21.903209Z","shell.execute_reply":"2026-05-18T01:46:22.200351Z"}},"outputs":[],"execution_count":null},{"id":"7c8aa2a3-67c3-4f8f-a7bc-1001ae2f079f","cell_type":"code","source":"X = []   \ny = []  \n\ntotal = len(metadata)\n\nfor i, (_, row) in enumerate(metadata.iterrows()):\n    filepath = os.path.join(audio_folder, row['filename'])\n    if not os.path.exists(filepath):\n        continue\n    img = audio_to_image(filepath)\n    if img is not None:\n        X.append(img)\n        y.append(row['primary_label'])\n    if (i + 1) % 100 == 0 or (i + 1) == total:\n        print(f'   Progress: {i+1}/{total} files processed | Collected: {len(X)}')\nX = np.array(X, dtype=np.float32)\ny = np.array(y)\n\nprint(f'   X shape : {X.shape}')\nprint(f'   y shape : {y.shape}')\nprint(f'   Species : {np.unique(y)[:5]}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:46:25.64239Z","iopub.execute_input":"2026-05-18T01:46:25.643158Z","iopub.status.idle":"2026-05-18T01:57:04.404514Z","shell.execute_reply.started":"2026-05-18T01:46:25.64313Z","shell.execute_reply":"2026-05-18T01:57:04.403655Z"}},"outputs":[],"execution_count":null},{"id":"f2f8e482-eee0-4e79-adc4-a4d5f870160c","cell_type":"code","source":"label_encoder = LabelEncoder()\ny_encoded = label_encoder.fit_transform(y)\nNUM_CLASSES = len(label_encoder.classes_)\n\nprint(f'Number of species (NUM_CLASSES) : {NUM_CLASSES}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:17.256882Z","iopub.execute_input":"2026-05-18T01:57:17.25756Z","iopub.status.idle":"2026-05-18T01:57:17.265941Z","shell.execute_reply.started":"2026-05-18T01:57:17.257532Z","shell.execute_reply":"2026-05-18T01:57:17.26517Z"}},"outputs":[],"execution_count":null},{"id":"83546d3a-7eb8-4864-bf15-2f83f75822c4","cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(\n    X,\n    y_encoded,\n    test_size=0.2,\n    random_state=42,\n    stratify=y_encoded\n)\n# X_val, X_test, y_val, y_test = train_test_split(\n#     X_test,\n#     y_test,\n#     test_size=0.5,\n#     random_state=42,\n#     stratify=y_encoded\n# )\n\nX_train.shape, X_test.shape, y_train.shape, y_test.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:17.90469Z","iopub.execute_input":"2026-05-18T01:57:17.905174Z","iopub.status.idle":"2026-05-18T01:57:20.732888Z","shell.execute_reply.started":"2026-05-18T01:57:17.905137Z","shell.execute_reply":"2026-05-18T01:57:20.732064Z"}},"outputs":[],"execution_count":null},{"id":"991d18dc-121c-4487-aaf5-dabcdaad75a2","cell_type":"code","source":"y_train = tf.expand_dims(y_train,-1)\ny_test = tf.expand_dims(y_test,-1)\ny_train.shape, y_test.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:20.734172Z","iopub.execute_input":"2026-05-18T01:57:20.734414Z","iopub.status.idle":"2026-05-18T01:57:20.74173Z","shell.execute_reply.started":"2026-05-18T01:57:20.734394Z","shell.execute_reply":"2026-05-18T01:57:20.740975Z"}},"outputs":[],"execution_count":null},{"id":"320b2ca7-e7a0-40b3-898d-140a2fe38bd0","cell_type":"code","source":"import keras\nfrom keras import layers,models","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:23.374412Z","iopub.execute_input":"2026-05-18T01:57:23.374671Z","iopub.status.idle":"2026-05-18T01:57:23.37884Z","shell.execute_reply.started":"2026-05-18T01:57:23.37465Z","shell.execute_reply":"2026-05-18T01:57:23.378068Z"}},"outputs":[],"execution_count":null},{"id":"59ef7bb1-413d-419a-9047-a3058cb4c9e4","cell_type":"code","source":"input1 = layers.Input(shape=(224,224,1))\ncnn_params = {\n    'kernel_size': (3,3),\n    'activation': 'relu',\n    'use_bias': False\n}\ncnn = layers.Conv2D(filters=32,padding='same',**cnn_params)(input1)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.Conv2D(filters=32,**cnn_params)(cnn)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.MaxPooling2D()(cnn)\ncnn = layers.Dropout(0.2)(cnn)\ncnn = layers.Conv2D(filters=64,padding='same',**cnn_params)(cnn)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.Conv2D(filters=64,**cnn_params)(cnn)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.MaxPooling2D()(cnn)\ncnn = layers.Dropout(0.25)(cnn)\ncnn = layers.Conv2D(filters=128,padding='same',**cnn_params)(cnn)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.Conv2D(filters=128,**cnn_params)(cnn)\ncnn = layers.BatchNormalization()(cnn)\n\ncnn = layers.MaxPooling2D()(cnn)\ncnn = layers.Dropout(0.3)(cnn)\nann_params = {\n    'activation': 'relu',\n    'use_bias': False\n}\nann = layers.Flatten()(cnn)\nann = layers.Dense(units=256,**ann_params)(ann)\nann = layers.BatchNormalization()(ann)\nann = layers.Dropout(0.5)(ann)\n\nann = layers.Dense(units=128,**ann_params)(ann)\nann = layers.BatchNormalization()(ann)\nann = layers.Dropout(0.3)(ann)\n\nann = layers.Dense(units=32,**ann_params)(ann)\nann = layers.BatchNormalization()(ann)\noutput1 = layers.Dense(units=NUM_CLASSES,activation='softmax')(ann)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:24.167338Z","iopub.execute_input":"2026-05-18T01:57:24.167962Z","iopub.status.idle":"2026-05-18T01:57:24.304036Z","shell.execute_reply.started":"2026-05-18T01:57:24.167935Z","shell.execute_reply":"2026-05-18T01:57:24.303051Z"}},"outputs":[],"execution_count":null},{"id":"f56426e2-6b11-45ad-9bfd-cebf1ab73b60","cell_type":"code","source":"model = models.Model(inputs=input1,outputs=output1)\nmodel.compile(\n    optimizer=keras.optimizers.AdamW(learning_rate=1e-3,weight_decay=1e-4),\n    loss='sparse_categorical_crossentropy',\n    metrics=['accuracy',keras.metrics.F1Score(average='weighted')]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:26:57.803411Z","iopub.execute_input":"2026-05-18T01:26:57.804224Z","iopub.status.idle":"2026-05-18T01:26:57.8163Z","shell.execute_reply.started":"2026-05-18T01:26:57.804194Z","shell.execute_reply":"2026-05-18T01:26:57.815507Z"}},"outputs":[],"execution_count":null},{"id":"48739f85-5da1-441c-a28b-3ce40365b140","cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:26:58.065663Z","iopub.execute_input":"2026-05-18T01:26:58.06628Z","iopub.status.idle":"2026-05-18T01:26:58.097614Z","shell.execute_reply.started":"2026-05-18T01:26:58.066255Z","shell.execute_reply":"2026-05-18T01:26:58.097045Z"}},"outputs":[],"execution_count":null},{"id":"a84a76bc-52a3-433f-a9f2-9f0142f39779","cell_type":"code","source":"checkpoint = callbacks.ModelCheckpoint(\n    filepath='kaggle/working/best_cifar10_model.keras',\n    monitor='val_accuracy',\n    save_best_only=True,\n    verbose=1\n)\nearly_stopping = callbacks.EarlyStopping(\n    monitor='val_loss',\n    patience=15,\n    restore_best_weights=True,\n    verbose=1\n)\nreduce_lr = callbacks.ReduceLROnPlateau(\n    monitor='val_loss',\n    factor=0.5,\n    patience=5,\n    min_lr=1e-6,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:33.687127Z","iopub.execute_input":"2026-05-18T01:57:33.687811Z","iopub.status.idle":"2026-05-18T01:57:33.692264Z","shell.execute_reply.started":"2026-05-18T01:57:33.687779Z","shell.execute_reply":"2026-05-18T01:57:33.691532Z"}},"outputs":[],"execution_count":null},{"id":"75356edb-01e7-43ce-8100-14c4f3c17ad2","cell_type":"code","source":"history = model.fit(X_train,y_train,validation_split=0.2,batch_size=128,epochs=100,callbacks=[checkpoint,early_stopping,reduce_lr])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:38:37.858129Z","iopub.execute_input":"2026-05-18T01:38:37.858763Z","iopub.status.idle":"2026-05-18T01:38:40.142142Z","shell.execute_reply.started":"2026-05-18T01:38:37.858734Z","shell.execute_reply":"2026-05-18T01:38:40.141036Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"id":"2030890b-e926-486a-b69f-880937bcb011","cell_type":"code","source":"input2 = layers.Input(shape=(224,224,1))\ncnn2 = layers.Conv2D(3, 1, padding='same', use_bias=False,activation='relu')(input2)\ncnn2 = layers.BatchNormalization()(cnn2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T01:57:36.472358Z","iopub.execute_input":"2026-05-18T01:57:36.473105Z","iopub.status.idle":"2026-05-18T01:57:36.493319Z","shell.execute_reply.started":"2026-05-18T01:57:36.473067Z","shell.execute_reply":"2026-05-18T01:57:36.49266Z"}},"outputs":[],"execution_count":null},{"id":"6ec6e5ca-7582-411d-9dc8-2cf01e208517","cell_type":"code","source":"backbone = keras.applications.EfficientNetV2B0(\n        include_top=False,\n        weights=None, \n        input_tensor=cnn2,\n        include_preprocessing=True\n)\nbackbone.trainable = True\nx = layers.GlobalAveragePooling2D(name='gap')(backbone.output)\nx = layers.BatchNormalization(name='head_bn1')(x)\nx = layers.Dropout(0.5, name='head_drop1')(x)\n\nx = layers.Dense(512, activation='swish', name='head_dense')(x)\nx = layers.BatchNormalization(name='head_bn2')(x)\nx = layers.Dropout(0.4, name='head_drop2')(x)\n\n# Output layer\noutput2 = layers.Dense(NUM_CLASSES, activation='softmax')(x)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:01:36.312848Z","iopub.execute_input":"2026-05-18T02:01:36.313455Z","iopub.status.idle":"2026-05-18T02:01:37.034806Z","shell.execute_reply.started":"2026-05-18T02:01:36.313426Z","shell.execute_reply":"2026-05-18T02:01:37.034208Z"}},"outputs":[],"execution_count":null},{"id":"72843f44-3497-45fb-87ee-076e43a7d4d3","cell_type":"code","source":"model = Model(inputs=input2, outputs=output2)\n\nmodel.compile(\noptimizer=keras.optimizers.Adam(learning_rate=1e-3),\nloss='sparse_categorical_crossentropy',\nmetrics=['accuracy']\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:02:36.962679Z","iopub.execute_input":"2026-05-18T02:02:36.963511Z","iopub.status.idle":"2026-05-18T02:02:36.984671Z","shell.execute_reply.started":"2026-05-18T02:02:36.963481Z","shell.execute_reply":"2026-05-18T02:02:36.983821Z"}},"outputs":[],"execution_count":null},{"id":"0b26a83e-bcdc-43de-b8b3-105b9fda966a","cell_type":"code","source":"history = model.fit(X_train,y_train,validation_split=0.2,batch_size=128,epochs=100,callbacks=[checkpoint,early_stopping,reduce_lr])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:03:19.16528Z","iopub.execute_input":"2026-05-18T02:03:19.165642Z","iopub.status.idle":"2026-05-18T02:20:32.839218Z","shell.execute_reply.started":"2026-05-18T02:03:19.165614Z","shell.execute_reply":"2026-05-18T02:20:32.838415Z"}},"outputs":[],"execution_count":null},{"id":"97585b8a-dda6-4d57-b076-e9ee5fe5fa51","cell_type":"code","source":"model.save('/kaggle/working/final_p2_model.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:21:46.991269Z","iopub.execute_input":"2026-05-18T02:21:46.991531Z","iopub.status.idle":"2026-05-18T02:21:48.069857Z","shell.execute_reply.started":"2026-05-18T02:21:46.99151Z","shell.execute_reply":"2026-05-18T02:21:48.069224Z"}},"outputs":[],"execution_count":null},{"id":"3d34e7ea-5fb9-4a98-bd8e-3077f02de560","cell_type":"code","source":"history_df = pd.DataFrame(history.history)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:22:42.479151Z","iopub.execute_input":"2026-05-18T02:22:42.479853Z","iopub.status.idle":"2026-05-18T02:22:42.48418Z","shell.execute_reply.started":"2026-05-18T02:22:42.479823Z","shell.execute_reply":"2026-05-18T02:22:42.483357Z"}},"outputs":[],"execution_count":null},{"id":"f9b496ec-89e2-4e74-b418-4f468ebc04da","cell_type":"code","source":"history_df.to_csv('/kaggle/working/training_history.csv')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T02:23:05.589079Z","iopub.execute_input":"2026-05-18T02:23:05.589371Z","iopub.status.idle":"2026-05-18T02:23:05.600037Z","shell.execute_reply.started":"2026-05-18T02:23:05.589349Z","shell.execute_reply":"2026-05-18T02:23:05.5993Z"}},"outputs":[],"execution_count":null},{"id":"d398035c-9417-4f67-99b7-5fa96c18d230","cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}