{"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":"code","source":"!pip install tensorflow librosa numpy pandas matplotlib scikit-learn seaborn\n!pip install soundfile  # لقراءة الملفات الصوتية","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:33:46.803009Z","iopub.status.idle":"2026-05-17T21:33:46.803292Z","shell.execute_reply.started":"2026-05-17T21:33:46.803180Z","shell.execute_reply":"2026-05-17T21:33:46.803194Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 1: Import Libraries\nimport os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport librosa\nimport librosa.display\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\n\nimport tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout\nfrom tensorflow.keras.utils import to_categorical\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:51:22.914491Z","iopub.execute_input":"2026-05-17T21:51:22.914720Z","iopub.status.idle":"2026-05-17T21:51:22.920910Z","shell.execute_reply.started":"2026-05-17T21:51:22.914702Z","shell.execute_reply":"2026-05-17T21:51:22.920115Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 2: Load Metadata\nmetadata = pd.read_csv(\"/kaggle/input/competitions/birdclef-2024/train_metadata.csv\")\n\n# Select only 5 birds for simplicity\nselected_birds = ['comsan', 'comros', 'barswa', 'litegr', 'hoopoe']\ndf = metadata[metadata['primary_label'].isin(selected_birds)].copy()\n\nprint(\"Selected birds:\", df['primary_label'].value_counts())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:51:37.546776Z","iopub.execute_input":"2026-05-17T21:51:37.547078Z","iopub.status.idle":"2026-05-17T21:51:37.620505Z","shell.execute_reply.started":"2026-05-17T21:51:37.547012Z","shell.execute_reply":"2026-05-17T21:51:37.619768Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 5: Updated Mel Function\ndef audio_to_mel(file_path, n_mels=128, duration=5):\n    try:\n        y, sr = librosa.load(file_path, sr=22050, duration=duration, mono=True)\n        mel = librosa.feature.melspectrogram(y=y, sr=sr, n_mels=n_mels, \n                                             fmax=8000, hop_length=512)\n        mel_db = librosa.power_to_db(mel, ref=np.max)\n        return mel_db\n    except:\n        return None","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:53:47.284399Z","iopub.execute_input":"2026-05-17T21:53:47.284652Z","iopub.status.idle":"2026-05-17T21:53:47.289846Z","shell.execute_reply.started":"2026-05-17T21:53:47.284632Z","shell.execute_reply":"2026-05-17T21:53:47.288604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 6: Load Data with Fixed Shape (Important Fix)\nDATA_DIR = \"/kaggle/input/competitions/birdclef-2024/train_audio\"\n\nX = []\ny = []\n\nprint(\"🔄 Loading and processing audio files...\")\n\nfor _, row in df.iterrows():\n    # Try with subfolder first (correct structure)\n    file_path = os.path.join(DATA_DIR, row['primary_label'], row['filename'])\n    \n    if not os.path.exists(file_path):\n        # Try without subfolder as backup\n        file_path = os.path.join(DATA_DIR, row['filename'])\n    \n    if os.path.exists(file_path):\n        mel = audio_to_mel(file_path)\n        if mel is not None:\n            # === FIX: Make all spectrograms same size ===\n            mel = mel[:, :240]                    # Take first 240 time steps\n            if mel.shape[1] < 240:\n                mel = np.pad(mel, ((0,0), (0, 240 - mel.shape[1])), mode='constant')\n            \n            mel = mel[..., np.newaxis]            # Add channel dimension\n            X.append(mel)\n            y.append(row['primary_label'])\n\nX = np.array(X)\nprint(\"✅ Final Data Shape:\", X.shape)\nprint(\"✅ Samples loaded:\", len(y))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:53:55.346243Z","iopub.execute_input":"2026-05-17T21:53:55.346496Z","iopub.status.idle":"2026-05-17T21:54:37.229635Z","shell.execute_reply.started":"2026-05-17T21:53:55.346475Z","shell.execute_reply":"2026-05-17T21:54:37.229101Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 7: Encode Labels\nif len(y) == 0:\n    print(\"❌ No data loaded!\")\nelse:\n    label_encoder = LabelEncoder()\n    y_encoded = label_encoder.fit_transform(y)\n    y_cat = to_categorical(y_encoded)\n\n    print(\"✅ Classes:\", label_encoder.classes_)\n    print(\"Number of classes:\", len(label_encoder.classes_))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:54:58.161304Z","iopub.execute_input":"2026-05-17T21:54:58.161580Z","iopub.status.idle":"2026-05-17T21:54:58.168396Z","shell.execute_reply.started":"2026-05-17T21:54:58.161558Z","shell.execute_reply":"2026-05-17T21:54:58.167606Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 8: Train Test Split\nX_train, X_test, y_train, y_test = train_test_split(\n    X, y_cat, test_size=0.2, random_state=42, stratify=y_encoded\n)\n\nprint(\"Train shape:\", X_train.shape)\nprint(\"Test shape:\", X_test.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:55:04.982968Z","iopub.execute_input":"2026-05-17T21:55:04.983271Z","iopub.status.idle":"2026-05-17T21:55:05.041482Z","shell.execute_reply.started":"2026-05-17T21:55:04.983243Z","shell.execute_reply":"2026-05-17T21:55:05.040729Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 9: Build Simple CNN Model\nmodel = Sequential()\n\nmodel.add(Conv2D(32, (3,3), activation='relu', input_shape=(128, 240, 1)))\nmodel.add(MaxPooling2D(2,2))\n\nmodel.add(Conv2D(64, (3,3), activation='relu'))\nmodel.add(MaxPooling2D(2,2))\n\nmodel.add(Conv2D(128, (3,3), activation='relu'))\nmodel.add(MaxPooling2D(2,2))\n\nmodel.add(Flatten())\nmodel.add(Dense(128, activation='relu'))\nmodel.add(Dropout(0.5))\nmodel.add(Dense(len(label_encoder.classes_), activation='softmax'))\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:55:11.561156Z","iopub.execute_input":"2026-05-17T21:55:11.561399Z","iopub.status.idle":"2026-05-17T21:55:11.745221Z","shell.execute_reply.started":"2026-05-17T21:55:11.561382Z","shell.execute_reply":"2026-05-17T21:55:11.744364Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 10: Compile Model\nmodel.compile(\n    optimizer='adam',\n    loss='categorical_crossentropy',\n    metrics=['accuracy']\n)\n\nprint(\"Model compiled successfully\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:55:27.751626Z","iopub.execute_input":"2026-05-17T21:55:27.751883Z","iopub.status.idle":"2026-05-17T21:55:27.763970Z","shell.execute_reply.started":"2026-05-17T21:55:27.751863Z","shell.execute_reply":"2026-05-17T21:55:27.763266Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 11: Train Model\nhistory = model.fit(\n    X_train, y_train,\n    epochs=10,\n    batch_size=32,\n    validation_split=0.2,\n    verbose=1\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T21:55:35.734669Z","iopub.execute_input":"2026-05-17T21:55:35.734922Z","iopub.status.idle":"2026-05-17T22:01:17.011968Z","shell.execute_reply.started":"2026-05-17T21:55:35.734902Z","shell.execute_reply":"2026-05-17T22:01:17.010634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 12: Evaluate Model\ntest_loss, test_acc = model.evaluate(X_test, y_test, verbose=0)\nprint(f\"Test Accuracy: {test_acc*100:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T22:01:23.136984Z","iopub.execute_input":"2026-05-17T22:01:23.137285Z","iopub.status.idle":"2026-05-17T22:01:25.851825Z","shell.execute_reply.started":"2026-05-17T22:01:23.137265Z","shell.execute_reply":"2026-05-17T22:01:25.850913Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 13: Plot Results\nplt.figure(figsize=(12, 5))\n\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Model Accuracy')\nplt.legend()\n\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Model Loss')\nplt.legend()\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T22:01:28.805006Z","iopub.execute_input":"2026-05-17T22:01:28.805336Z","iopub.status.idle":"2026-05-17T22:01:29.482580Z","shell.execute_reply.started":"2026-05-17T22:01:28.805314Z","shell.execute_reply":"2026-05-17T22:01:29.481432Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Cell 14: Predict Function\ndef predict_bird_sound(file_path):\n    mel = audio_to_mel(file_path)\n    if mel is None:\n        print(\"❌ Error loading audio file\")\n        return\n    \n    # Apply same preprocessing as training\n    mel = mel[:, :240]\n    if mel.shape[1] < 240:\n        mel = np.pad(mel, ((0,0), (0, 240 - mel.shape[1])), mode='constant')\n    \n    mel = mel[..., np.newaxis]\n    mel = np.expand_dims(mel, axis=0)\n    \n    pred = model.predict(mel, verbose=0)\n    predicted_idx = np.argmax(pred)\n    bird_name = label_encoder.inverse_transform([predicted_idx])[0]\n    \n    print(f\"🎯 Predicted Bird: {bird_name}\")\n    print(\"\\nProbabilities:\")\n    for i, prob in enumerate(pred[0]):\n        print(f\"{label_encoder.classes_[i]}: {prob*100:.2f}%\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-17T22:01:58.965313Z","iopub.execute_input":"2026-05-17T22:01:58.965581Z","iopub.status.idle":"2026-05-17T22:01:58.971977Z","shell.execute_reply.started":"2026-05-17T22:01:58.965561Z","shell.execute_reply":"2026-05-17T22:01:58.970884Z"}},"outputs":[],"execution_count":null}]}