{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceType":"competition","sourceId":70203,"databundleVersionId":8068726}],"dockerImageVersionId":31328,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This project is implemented and runs on Kaggle Notebooks environment\nBird Sound Classification Project (Deep Learning - CNN)\n\nEnvironment: Kaggle Notebooks\nDataset: BirdCLEF 2024 Kaggle Competition\n\nNotebook Link:\nhttps://www.kaggle.com/code/hanaatahaah/sound-recognition\n\nNote: This project is fully runnable on Kaggle without any local setup.","metadata":{}},{"cell_type":"code","source":"import os\n\nos.listdir('/kaggle/input/competitions')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T17:15:56.391736Z","iopub.execute_input":"2026-05-14T17:15:56.392157Z","iopub.status.idle":"2026-05-14T17:15:56.398867Z","shell.execute_reply.started":"2026-05-14T17:15:56.392121Z","shell.execute_reply":"2026-05-14T17:15:56.397874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/competitions/birdclef-2024\"\n\nprint(os.listdir(BASE_PATH))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:28:06.228073Z","iopub.execute_input":"2026-05-14T16:28:06.228508Z","iopub.status.idle":"2026-05-14T16:28:06.234779Z","shell.execute_reply.started":"2026-05-14T16:28:06.228476Z","shell.execute_reply":"2026-05-14T16:28:06.233859Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport librosa\nimport librosa.display\nimport matplotlib.pyplot as plt\n\nfrom sklearn.model_selection import train_test_split\n\nfrom tensorflow.keras import layers\nfrom tensorflow.keras import models\nfrom tensorflow.keras.utils import to_categorical","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:34:02.427053Z","iopub.execute_input":"2026-05-14T16:34:02.427422Z","iopub.status.idle":"2026-05-14T16:34:34.027367Z","shell.execute_reply.started":"2026-05-14T16:34:02.427395Z","shell.execute_reply":"2026-05-14T16:34:34.026318Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"BASE_PATH = \"/kaggle/input/competitions/birdclef-2024\"\n\nAUDIO_PATH = os.path.join(BASE_PATH, \"train_audio\")\n\nMETADATA_PATH = os.path.join(BASE_PATH, \"train_metadata.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:34:41.572672Z","iopub.execute_input":"2026-05-14T16:34:41.573015Z","iopub.status.idle":"2026-05-14T16:34:41.579570Z","shell.execute_reply.started":"2026-05-14T16:34:41.572981Z","shell.execute_reply":"2026-05-14T16:34:41.577258Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"metadata = pd.read_csv(METADATA_PATH)\n\nmetadata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:35:09.089914Z","iopub.execute_input":"2026-05-14T16:35:09.090492Z","iopub.status.idle":"2026-05-14T16:35:09.279590Z","shell.execute_reply.started":"2026-05-14T16:35:09.090440Z","shell.execute_reply":"2026-05-14T16:35:09.278429Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"metadata['primary_label'].nunique()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:35:58.001320Z","iopub.execute_input":"2026-05-14T16:35:58.001651Z","iopub.status.idle":"2026-05-14T16:35:58.009708Z","shell.execute_reply.started":"2026-05-14T16:35:58.001620Z","shell.execute_reply":"2026-05-14T16:35:58.008581Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TARGET_BIRDS = [\n    \"asbfly\",\n    \"barswa\",\n    \"blakit1\",\n    \"cbrbar\",\n    \"cmnmyn\"\n]\n\nmetadata = metadata[\n    metadata['primary_label'].isin(TARGET_BIRDS)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:36:46.506597Z","iopub.execute_input":"2026-05-14T16:36:46.506912Z","iopub.status.idle":"2026-05-14T16:36:46.513563Z","shell.execute_reply.started":"2026-05-14T16:36:46.506880Z","shell.execute_reply":"2026-05-14T16:36:46.512346Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"metadata = metadata.groupby(\n    'primary_label'\n).head(30)\n\nmetadata.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:36:49.851840Z","iopub.execute_input":"2026-05-14T16:36:49.852148Z","iopub.status.idle":"2026-05-14T16:36:49.864795Z","shell.execute_reply.started":"2026-05-14T16:36:49.852120Z","shell.execute_reply":"2026-05-14T16:36:49.863648Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"metadata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:37:24.688452Z","iopub.execute_input":"2026-05-14T16:37:24.689727Z","iopub.status.idle":"2026-05-14T16:37:24.711991Z","shell.execute_reply.started":"2026-05-14T16:37:24.689683Z","shell.execute_reply":"2026-05-14T16:37:24.711036Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE = 128\n\ndef audio_to_mel(path):\n\n    audio, sr = librosa.load(\n        path,\n        duration=5\n    )\n\n    mel = librosa.feature.melspectrogram(\n        y=audio,\n        sr=sr,\n        n_mels=IMG_SIZE\n    )\n\n    mel_db = librosa.power_to_db(\n        mel,\n        ref=np.max\n    )\n\n    return mel_db","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:37:57.469654Z","iopub.execute_input":"2026-05-14T16:37:57.469978Z","iopub.status.idle":"2026-05-14T16:37:57.475588Z","shell.execute_reply.started":"2026-05-14T16:37:57.469947Z","shell.execute_reply":"2026-05-14T16:37:57.474561Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"metadata[['primary_label', 'filename']].head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:40:08.617654Z","iopub.execute_input":"2026-05-14T16:40:08.618052Z","iopub.status.idle":"2026-05-14T16:40:08.629990Z","shell.execute_reply.started":"2026-05-14T16:40:08.618020Z","shell.execute_reply":"2026-05-14T16:40:08.629089Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample = metadata.iloc[0]\n\nlabel = sample['primary_label']\n\nfilename = sample['filename']\n\npath = os.path.join(\n    AUDIO_PATH,\n    filename\n)\n\nprint(path)\n\nmel = audio_to_mel(path)\n\nprint(mel.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:40:35.875674Z","iopub.execute_input":"2026-05-14T16:40:35.875983Z","iopub.status.idle":"2026-05-14T16:40:46.543600Z","shell.execute_reply.started":"2026-05-14T16:40:35.875954Z","shell.execute_reply":"2026-05-14T16:40:46.542909Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(figsize=(10,4))\n\nlibrosa.display.specshow(\n    mel,\n    x_axis='time',\n    y_axis='mel'\n)\n\nplt.colorbar()\n\nplt.title(label)\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:41:14.953745Z","iopub.execute_input":"2026-05-14T16:41:14.954071Z","iopub.status.idle":"2026-05-14T16:41:15.290072Z","shell.execute_reply.started":"2026-05-14T16:41:14.954036Z","shell.execute_reply":"2026-05-14T16:41:15.289097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = []\ny = []\n\nTARGET_BIRDS = metadata['primary_label'].unique().tolist()\n\nlabel_map = {\n    label: idx\n    for idx, label in enumerate(TARGET_BIRDS)\n}\n\nprint(\"Classes:\", TARGET_BIRDS)\nprint(\"Map:\", label_map)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:51:29.626026Z","iopub.execute_input":"2026-05-14T16:51:29.626443Z","iopub.status.idle":"2026-05-14T16:51:29.633748Z","shell.execute_reply.started":"2026-05-14T16:51:29.626412Z","shell.execute_reply":"2026-05-14T16:51:29.632711Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"for _, row in metadata.iterrows():\n\n    label = row['primary_label']\n    filename = row['filename']\n\n    path = os.path.join(\n        AUDIO_PATH,\n        filename\n    )\n\n    try:\n        mel = audio_to_mel(path)\n\n        mel = mel[:, :IMG_SIZE]\n\n        if mel.shape[1] < IMG_SIZE:\n            pad = IMG_SIZE - mel.shape[1]\n            mel = np.pad(mel, ((0,0),(0,pad)))\n\n        X.append(mel)\n        y.append(label_map[label])\n\n    except:\n        pass","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:51:55.092942Z","iopub.execute_input":"2026-05-14T16:51:55.093286Z","iopub.status.idle":"2026-05-14T16:51:57.669428Z","shell.execute_reply.started":"2026-05-14T16:51:55.093251Z","shell.execute_reply":"2026-05-14T16:51:57.668665Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = np.array(X)\ny = np.array(y)\n\nprint(\"X shape:\", X.shape)\nprint(\"y shape:\", y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:52:21.903584Z","iopub.execute_input":"2026-05-14T16:52:21.904174Z","iopub.status.idle":"2026-05-14T16:52:21.912094Z","shell.execute_reply.started":"2026-05-14T16:52:21.904137Z","shell.execute_reply":"2026-05-14T16:52:21.911011Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = X[..., np.newaxis]\n\nprint(\"X shape after channel:\", X.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:52:42.879327Z","iopub.execute_input":"2026-05-14T16:52:42.879632Z","iopub.status.idle":"2026-05-14T16:52:42.885663Z","shell.execute_reply.started":"2026-05-14T16:52:42.879606Z","shell.execute_reply":"2026-05-14T16:52:42.884405Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.utils import to_categorical\n\ny = to_categorical(y)\n\nprint(\"y shape:\", y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:53:18.464078Z","iopub.execute_input":"2026-05-14T16:53:18.464485Z","iopub.status.idle":"2026-05-14T16:53:18.471112Z","shell.execute_reply.started":"2026-05-14T16:53:18.464452Z","shell.execute_reply":"2026-05-14T16:53:18.470136Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_train, X_test, y_train, y_test = train_test_split(\n    X,\n    y,\n    test_size=0.2,\n    random_state=42\n)\n\nprint(X_train.shape)\n\nprint(X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:44:33.269769Z","iopub.execute_input":"2026-05-14T16:44:33.270070Z","iopub.status.idle":"2026-05-14T16:44:33.279578Z","shell.execute_reply.started":"2026-05-14T16:44:33.270044Z","shell.execute_reply":"2026-05-14T16:44:33.278327Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model = models.Sequential([\n\n    layers.Input(shape=(128,128,1)),\n\n    layers.Conv2D(32, (3,3), activation='relu'),\n    layers.MaxPooling2D((2,2)),\n\n    layers.Conv2D(64, (3,3), activation='relu'),\n    layers.MaxPooling2D((2,2)),\n\n    layers.Flatten(),\n\n    layers.Dense(128, activation='relu'),\n    layers.Dropout(0.3),\n\n    layers.Dense(len(TARGET_BIRDS), activation='softmax')\n])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:55:00.889071Z","iopub.execute_input":"2026-05-14T16:55:00.889766Z","iopub.status.idle":"2026-05-14T16:55:00.968495Z","shell.execute_reply.started":"2026-05-14T16:55:00.889733Z","shell.execute_reply":"2026-05-14T16:55:00.967481Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(\n    optimizer='adam',\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:56:16.974852Z","iopub.execute_input":"2026-05-14T16:56:16.975179Z","iopub.status.idle":"2026-05-14T16:56:16.984987Z","shell.execute_reply.started":"2026-05-14T16:56:16.975152Z","shell.execute_reply":"2026-05-14T16:56:16.984065Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:56:19.697179Z","iopub.execute_input":"2026-05-14T16:56:19.697548Z","iopub.status.idle":"2026-05-14T16:56:19.719568Z","shell.execute_reply.started":"2026-05-14T16:56:19.697517Z","shell.execute_reply":"2026-05-14T16:56:19.718767Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history = model.fit(\n    X_train,\n    y_train,\n    epochs=10,\n    batch_size=16,\n    validation_data=(X_test, y_test)\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:56:23.640394Z","iopub.execute_input":"2026-05-14T16:56:23.640730Z","iopub.status.idle":"2026-05-14T16:56:45.399674Z","shell.execute_reply.started":"2026-05-14T16:56:23.640700Z","shell.execute_reply":"2026-05-14T16:56:45.398682Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"loss, accuracy = model.evaluate(X_test, y_test)\n\nprint(\"Test Loss:\", loss)\nprint(\"Test Accuracy:\", accuracy)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:57:08.181837Z","iopub.execute_input":"2026-05-14T16:57:08.182145Z","iopub.status.idle":"2026-05-14T16:57:08.402252Z","shell.execute_reply.started":"2026-05-14T16:57:08.182118Z","shell.execute_reply":"2026-05-14T16:57:08.401039Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\n\nplt.title('Model Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\n\nplt.legend(['Train', 'Validation'])\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:57:20.135095Z","iopub.execute_input":"2026-05-14T16:57:20.136337Z","iopub.status.idle":"2026-05-14T16:57:20.303442Z","shell.execute_reply.started":"2026-05-14T16:57:20.136296Z","shell.execute_reply":"2026-05-14T16:57:20.301986Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\n\nplt.title('Model Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\n\nplt.legend(['Train', 'Validation'])\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:57:34.723724Z","iopub.execute_input":"2026-05-14T16:57:34.724083Z","iopub.status.idle":"2026-05-14T16:57:34.865710Z","shell.execute_reply.started":"2026-05-14T16:57:34.724052Z","shell.execute_reply":"2026-05-14T16:57:34.864804Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"sample = X_test[0]\n\nprediction = model.predict(\n    sample.reshape(1, 128, 128, 1)\n)\n\npredicted_class = np.argmax(prediction)\n\nprint(\"Predicted:\", TARGET_BIRDS[predicted_class])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-14T16:57:51.857418Z","iopub.execute_input":"2026-05-14T16:57:51.859563Z","iopub.status.idle":"2026-05-14T16:57:52.015241Z","shell.execute_reply.started":"2026-05-14T16:57:51.859511Z","shell.execute_reply":"2026-05-14T16:57:52.014138Z"}},"outputs":[],"execution_count":null}]}