{"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":"nvidiaTeslaT4","dataSources":[{"sourceType":"competition","sourceId":70203,"databundleVersionId":8068726}],"dockerImageVersionId":31329,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ====================================\n# Step 1: Import Libraries\n# ====================================\n\nimport numpy as np                          # عمليات حسابية\nimport pandas as pd                         # قراءة ملفات CSV وجداول\nimport matplotlib.pyplot as plt             # رسم بياني\nimport librosa                              # معالجة الصوت\nimport librosa.display                      # عرض الصوت بصرياً\nimport os                                   # التعامل مع الملفات والمجلدات\nimport random                               # اختيار عشوائي\nimport warnings\nwarnings.filterwarnings('ignore')           # إخفاء التحذيرات غير المهمة\n\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom sklearn.model_selection import train_test_split   # تقسيم الداتا\nfrom sklearn.preprocessing import LabelEncoder         # تحويل أسماء الطيور لأرقام\n\nprint(f\"TensorFlow version: {tf.__version__}\")\nprint(f\"GPU Available: {len(tf.config.list_physical_devices('GPU')) > 0}\")\nprint(\"All libraries loaded successfully!\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2026-05-10T14:00:40.822941Z","iopub.execute_input":"2026-05-10T14:00:40.823227Z","iopub.status.idle":"2026-05-10T14:01:12.495607Z","shell.execute_reply.started":"2026-05-10T14:00:40.823203Z","shell.execute_reply":"2026-05-10T14:01:12.494742Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\n# المسار الصحيح للداتا\nBASE_PATH = '/kaggle/input/competitions/birdclef-2024'\n\n# بنقرا ملف الـ metadata\n# read_csv = بتقرا ملف CSV (جدول زي Excel)\nmetadata = pd.read_csv(BASE_PATH + '/train_metadata.csv')\n\n# نشوف حجم الجدول (كام صف × كام عمود)\nrows = metadata.shape[0]\ncols = metadata.shape[1]\nprint(\"Table size:\")\nprint(f\"  Rows (recordings): {rows}\")\nprint(f\"  Columns (features): {cols}\")\n\n# نشوف كام نوع طير\nnum_species = metadata['primary_label'].nunique()\nprint(f\"\\nTotal bird species: {num_species}\")\n\n# نشوف أول 5 صفوف\nprint(\"\\nFirst 5 rows:\")\nmetadata.head()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T22:40:38.812528Z","iopub.execute_input":"2026-05-09T22:40:38.812981Z","iopub.status.idle":"2026-05-09T22:40:39.111760Z","shell.execute_reply.started":"2026-05-09T22:40:38.812951Z","shell.execute_reply":"2026-05-09T22:40:39.110941Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 3: Explore Bird Species\n# (استكشاف أنواع الطيور)\n# ====================================\n\n# نشوف أكتر 15 نوع طير عندهم تسجيلات\nspecies_counts = metadata['primary_label'].value_counts()\n\n# أكتر 15\nprint(\"Top 15 species (most recordings):\")\nprint(species_counts.head(15))\n\n# أقل 5\nprint(\"\\nBottom 5 species (least recordings):\")\nprint(species_counts.tail(5))\n\n# نرسم أكتر 20 نوع\ntop_20 = species_counts.head(20)\n\nplt.figure(figsize=(12, 5))\nplt.bar(top_20.index, top_20.values, color='skyblue')\nplt.title('Top 20 Bird Species by Number of Recordings')\nplt.xlabel('Species')\nplt.ylabel('Number of Recordings')\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T22:57:08.099713Z","iopub.execute_input":"2026-05-09T22:57:08.100486Z","iopub.status.idle":"2026-05-09T22:57:08.437234Z","shell.execute_reply.started":"2026-05-09T22:57:08.100453Z","shell.execute_reply":"2026-05-09T22:57:08.436340Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 4: Listen to a Bird Sound\n# (نسمع عينة صوتية)\n# ====================================\n\nimport IPython.display as ipd\n\n# ناخد أول تسجيل من الداتا\nfirst_file = metadata['filename'].iloc[0]\nfirst_species = metadata['primary_label'].iloc[0]\nfile_path = BASE_PATH + '/train_audio/' + first_file\n\nprint(f\"Species: {first_species}\")\nprint(f\"File: {first_file}\")\n\n# نشغل الصوت\nipd.Audio(file_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T22:57:22.420812Z","iopub.execute_input":"2026-05-09T22:57:22.421481Z","iopub.status.idle":"2026-05-09T22:57:22.467888Z","shell.execute_reply.started":"2026-05-09T22:57:22.421448Z","shell.execute_reply":"2026-05-09T22:57:22.467129Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 5: Convert Audio to Spectrogram\n# (تحويل صوت لصورة)\n# ====================================\n\nimport librosa\nimport librosa.display\n\n# ناخد أول ملف صوت\nfirst_file = metadata['filename'].iloc[0]\nfirst_species = metadata['primary_label'].iloc[0]\nfile_path = BASE_PATH + '/train_audio/' + first_file\n\n# بنحمل الصوت\n# y = الموجة الصوتية (أرقام بتمثل الصوت)\n# sr = معدل العينات (كام رقم في الثانية)\ny, sr = librosa.load(file_path, sr=32000, duration=5)\n\nprint(f\"Species: {first_species}\")\nprint(f\"Audio length: {len(y)} samples\")\nprint(f\"Sample rate: {sr} Hz\")\nprint(f\"Duration: {len(y) / sr:.1f} seconds\")\n\n# بنحول الصوت لـ Mel Spectrogram\nmel_spec = librosa.feature.melspectrogram(\n    y=y,\n    sr=sr,\n    n_mels=128,\n    fmax=16000\n)\n\n# بنحوله لـ decibels عشان يبان أوضح\nmel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n\n# بنرسم الـ Spectrogram\nplt.figure(figsize=(12, 4))\nlibrosa.display.specshow(\n    mel_spec_db,\n    sr=sr,\n    x_axis='time',\n    y_axis='mel'\n)\nplt.colorbar(label='dB')\nplt.title(f'Mel Spectrogram - {first_species}')\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:08:49.842663Z","iopub.execute_input":"2026-05-09T23:08:49.843425Z","iopub.status.idle":"2026-05-09T23:09:05.502654Z","shell.execute_reply.started":"2026-05-09T23:08:49.843395Z","shell.execute_reply":"2026-05-09T23:09:05.501908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 6: Prepare Full Dataset\n# (تحضير الداتا كلها)\n# ====================================\n\n# --- الإعدادات ---\nSAMPLE_RATE = 32000       # معدل العينات\nDURATION = 5              # كل مقطع 5 ثواني\nN_MELS = 128              # ارتفاع الصورة\nMAX_SPECIES = 30          # عدد أنواع الطيور\nSAMPLES_PER_SPECIES = 100 # عدد التسجيلات من كل نوع\n\n# --- نختار أشهر 30 نوع ---\ntop_species = metadata['primary_label'].value_counts().head(MAX_SPECIES).index.tolist()\nprint(f\"Selected {len(top_species)} species\")\n\n# نفلتر الداتا عشان ناخد الأنواع دي بس\nfiltered_data = metadata[metadata['primary_label'].isin(top_species)]\nprint(f\"Total recordings available: {len(filtered_data)}\")\n\n# ناخد عينة متساوية من كل نوع\nsampled_data = filtered_data.groupby('primary_label').head(SAMPLES_PER_SPECIES)\nsampled_data = sampled_data.reset_index(drop=True)\nprint(f\"Recordings we will use: {len(sampled_data)}\")\n\n# --- نحول أسماء الطيور لأرقام ---\nlabel_encoder = LabelEncoder()\nsampled_data['label_encoded'] = label_encoder.fit_transform(sampled_data['primary_label'])\n\n# نشوف النتيجة\nprint(f\"\\nExample encoding:\")\nfor i in range(5):\n    name = label_encoder.classes_[i]\n    print(f\"  {name} = {i}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:10:15.796340Z","iopub.execute_input":"2026-05-09T23:10:15.797083Z","iopub.status.idle":"2026-05-09T23:10:15.830039Z","shell.execute_reply.started":"2026-05-09T23:10:15.797052Z","shell.execute_reply":"2026-05-09T23:10:15.829119Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 7: Convert All Audio to Spectrograms\n# (تحويل كل الأصوات لصور)\n# ====================================\n\ndef audio_to_spectrogram(file_path):\n    \"\"\"\n    بتاخد مسار ملف صوت وبتحوله لـ Mel Spectrogram\n    بترجع الصورة كمصفوفة أرقام\n    \"\"\"\n    try:\n        # بنحمل الصوت (أول 5 ثواني)\n        y, sr = librosa.load(file_path, sr=SAMPLE_RATE, duration=DURATION)\n\n        # لو الصوت أقصر من 5 ثواني، نكمله بأصفار (صمت)\n        target_length = SAMPLE_RATE * DURATION\n        if len(y) < target_length:\n            y = np.pad(y, (0, target_length - len(y)))\n\n        # بنحول لـ Mel Spectrogram\n        mel_spec = librosa.feature.melspectrogram(\n            y=y,\n            sr=SAMPLE_RATE,\n            n_mels=N_MELS,\n            fmax=16000\n        )\n\n        # بنحوله لـ decibels\n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n\n        return mel_spec_db\n\n    except Exception as e:\n        # لو حصل مشكلة في الملف، نرجع None\n        return None\n\n\n# --- نحول كل الملفات ---\nspectrograms = []\nlabels = []\nskipped = 0\n\ntotal = len(sampled_data)\n\nfor i in range(total):\n    # نجيب المسار واسم الطير\n    filename = sampled_data['filename'].iloc[i]\n    label = sampled_data['label_encoded'].iloc[i]\n    file_path = BASE_PATH + '/train_audio/' + filename\n\n    # نحول الصوت لـ Spectrogram\n    spec = audio_to_spectrogram(file_path)\n\n    if spec is not None:\n        spectrograms.append(spec)\n        labels.append(label)\n    else:\n        skipped = skipped + 1\n\n    # نطبع التقدم كل 200 ملف\n    if (i + 1) % 200 == 0:\n        print(f\"Processed {i + 1} / {total} files...\")\n\n# نحولهم لـ numpy arrays\nX = np.array(spectrograms)\ny = np.array(labels)\n\nprint(f\"\\nDone!\")\nprint(f\"Successfully processed: {len(X)} files\")\nprint(f\"Skipped (errors): {skipped} files\")\nprint(f\"Data shape: {X.shape}\")\nprint(f\"Labels shape: {y.shape}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:11:28.383080Z","iopub.execute_input":"2026-05-09T23:11:28.383554Z","iopub.status.idle":"2026-05-09T23:13:18.511781Z","shell.execute_reply.started":"2026-05-09T23:11:28.383521Z","shell.execute_reply":"2026-05-09T23:13:18.511079Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 8: Prepare Data for Model\n# (تجهيز الداتا للموديل)\n# ====================================\n\n# الـ CNN محتاج بُعد إضافي (Channel) - زي الألوان في الصور\n# الصور العادية عندها 3 channels (أحمر، أخضر، أزرق)\n# احنا عندنا channel واحد بس (أبيض وأسود)\nX = X.reshape(X.shape[0], X.shape[1], X.shape[2], 1)\nprint(f\"Data shape after reshape: {X.shape}\")\n\n# نعمل Normalization - نخلي القيم بين 0 و 1\n# ده بيساعد الموديل يتعلم أسرع\nX_min = X.min()\nX_max = X.max()\nX = (X - X_min) / (X_max - X_min)\nprint(f\"Values range: {X.min():.2f} to {X.max():.2f}\")\n\n# نقسم الداتا: 80% تدريب + 20% تحقق\nX_train, X_val, y_train, y_val = train_test_split(\n    X, y,\n    test_size=0.2,\n    random_state=42,\n    stratify=y\n)\n\nprint(f\"\\nTraining data: {X_train.shape[0]} samples\")\nprint(f\"Validation data: {X_val.shape[0]} samples\")\nprint(f\"Number of classes: {len(np.unique(y))}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:15:31.368188Z","iopub.execute_input":"2026-05-09T23:15:31.368921Z","iopub.status.idle":"2026-05-09T23:15:31.890669Z","shell.execute_reply.started":"2026-05-09T23:15:31.368892Z","shell.execute_reply":"2026-05-09T23:15:31.889638Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 9: Build CNN Model\n# (بناء الشبكة العصبية)\n# ====================================\n\n# عدد الأنواع (الفئات)\nnum_classes = len(np.unique(y))\n\n# بنبني الموديل طبقة طبقة\nmodel = models.Sequential()\n\n# --- طبقات الـ Convolution (استخراج الأنماط من الصور) ---\n\n# الطبقة الأولى: 32 فلتر، كل فلتر حجمه 3×3\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu',\n                        input_shape=(128, 313, 1)))\nmodel.add(layers.MaxPooling2D((2, 2)))\n\n# الطبقة التانية: 64 فلتر\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\n\n# الطبقة التالتة: 128 فلتر\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\n\n# --- طبقات التصنيف ---\n\n# بنحول الصورة لسطر واحد من الأرقام\nmodel.add(layers.Flatten())\n\n# طبقة Dense عادية\nmodel.add(layers.Dense(128, activation='relu'))\n\n# Dropout - بيطفي 50% من الخلايا عشوائياً أثناء التدريب (يمنع الحفظ)\nmodel.add(layers.Dropout(0.5))\n\n# الطبقة الأخيرة: عدد الخلايا = عدد أنواع الطيور\nmodel.add(layers.Dense(num_classes, activation='softmax'))\n\n# نشوف ملخص الموديل\nmodel.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:15:46.862055Z","iopub.execute_input":"2026-05-09T23:15:46.862479Z","iopub.status.idle":"2026-05-09T23:15:49.444787Z","shell.execute_reply.started":"2026-05-09T23:15:46.862449Z","shell.execute_reply":"2026-05-09T23:15:49.443978Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 10: Compile & Train the Model\n# (تجهيز وتدريب الموديل)\n# ====================================\n\n# --- تجهيز الموديل ---\nmodel.compile(\n    optimizer='adam',\n    loss='sparse_categorical_crossentropy',\n    metrics=['accuracy']\n)\n\n# --- تدريب الموديل ---\nhistory = model.fit(\n    X_train, y_train,\n    epochs=20,\n    batch_size=32,\n    validation_data=(X_val, y_val),\n    verbose=1\n)\n\nprint(\"\\nTraining completed!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:18:01.314103Z","iopub.execute_input":"2026-05-09T23:18:01.314846Z","iopub.status.idle":"2026-05-09T23:19:17.311073Z","shell.execute_reply.started":"2026-05-09T23:18:01.314809Z","shell.execute_reply":"2026-05-09T23:19:17.310143Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 11: Plot Training Results\n# (رسم نتائج التدريب)\n# ====================================\n\nhistory_dict = history.history\nepochs = range(1, len(history_dict['loss']) + 1)\n\n# رسمتين جنب بعض\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))\n\n# --- الرسمة الأولى: Loss ---\nax1.plot(epochs, history_dict['loss'], 'bo-', label='Training Loss')\nax1.plot(epochs, history_dict['val_loss'], 'ro-', label='Validation Loss')\nax1.set_title('Training and Validation Loss')\nax1.set_xlabel('Epochs')\nax1.set_ylabel('Loss')\nax1.legend()\nax1.grid(True)\n\n# --- الرسمة التانية: Accuracy ---\nax2.plot(epochs, history_dict['accuracy'], 'bo-', label='Training Accuracy')\nax2.plot(epochs, history_dict['val_accuracy'], 'ro-', label='Validation Accuracy')\nax2.set_title('Training and Validation Accuracy')\nax2.set_xlabel('Epochs')\nax2.set_ylabel('Accuracy')\nax2.legend()\nax2.grid(True)\n\nplt.tight_layout()\nplt.show()\n\nprint(\"Training Accuracy went UP (good)\")\nprint(\"Validation Accuracy stopped improving after epoch ~6 (overfitting)\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:23:34.109346Z","iopub.execute_input":"2026-05-09T23:23:34.110173Z","iopub.status.idle":"2026-05-09T23:23:34.433697Z","shell.execute_reply.started":"2026-05-09T23:23:34.110143Z","shell.execute_reply":"2026-05-09T23:23:34.432723Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 12: Predictions & Results\n# (التنبؤ وعرض النتائج)\n# ====================================\n\n# نخلي الموديل يتنبأ بداتا التحقق\npredictions = model.predict(X_val)\n\n# نحسب الدقة النهائية\nval_loss, val_accuracy = model.evaluate(X_val, y_val, verbose=0)\nprint(f\"Final Validation Accuracy: {val_accuracy * 100:.2f}%\")\nprint(f\"Final Validation Loss: {val_loss:.4f}\")\n\n# نشوف 10 أمثلة\nprint(\"\\nSample Predictions:\")\nprint(\"=\" * 60)\n\nfor i in range(10):\n    # الموديل اتنبأ بإيه\n    predicted_class = np.argmax(predictions[i])\n    predicted_name = label_encoder.inverse_transform([predicted_class])[0]\n    confidence = predictions[i][predicted_class] * 100\n\n    # الإجابة الصح\n    actual_class = y_val[i]\n    actual_name = label_encoder.inverse_transform([actual_class])[0]\n\n    # صح ولا غلط\n    status = \"Correct\" if predicted_class == actual_class else \"Wrong\"\n\n    print(f\"  {i+1}. Predicted: {predicted_name:20s} | Actual: {actual_name:20s} | {confidence:.1f}% | {status}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-09T23:23:49.500345Z","iopub.execute_input":"2026-05-09T23:23:49.501016Z","iopub.status.idle":"2026-05-09T23:23:51.353583Z","shell.execute_reply.started":"2026-05-09T23:23:49.500986Z","shell.execute_reply":"2026-05-09T23:23:51.352824Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ====================================\n# Step 1: Import Libraries\n# ====================================\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport librosa\nimport librosa.display\nimport os\nimport warnings\nwarnings.filterwarnings('ignore')\nimport tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import LabelEncoder\nimport IPython.display as ipd\n\n# ====================================\n# Step 2: Load and Explore Metadata\n# ====================================\nBASE_PATH = '/kaggle/input/competitions/birdclef-2024'\nSAMPLE_RATE = 32000\nDURATION = 5\nN_MELS = 128\nMAX_SPECIES = 30\nSAMPLES_PER_SPECIES = 100\n\nmetadata = pd.read_csv(BASE_PATH + '/train_metadata.csv')\nprint(f\"Total recordings: {len(metadata)}\")\nprint(f\"Total bird species: {metadata['primary_label'].nunique()}\")\n\n# ====================================\n# Step 3: Filter and Sample Top Species\n# ====================================\ntop_species = metadata['primary_label'].value_counts().head(MAX_SPECIES).index.tolist()\nfiltered_data = metadata[metadata['primary_label'].isin(top_species)]\nsampled_data = filtered_data.groupby('primary_label').head(SAMPLES_PER_SPECIES)\nsampled_data = sampled_data.reset_index(drop=True)\nprint(f\"Selected {len(top_species)} species, {len(sampled_data)} recordings\")\n\n# ====================================\n# Step 4: Encode Labels\n# ====================================\nlabel_encoder = LabelEncoder()\nsampled_data['label_encoded'] = label_encoder.fit_transform(sampled_data['primary_label'])\n\n# ====================================\n# Step 5: Visualize Top 20 Bird Species\n# ====================================\nspecies_counts = metadata['primary_label'].value_counts().head(20)\nplt.figure(figsize=(12, 5))\nplt.bar(species_counts.index, species_counts.values, color='skyblue')\nplt.title('Top 20 Bird Species by Number of Recordings')\nplt.xlabel('Species')\nplt.ylabel('Number of Recordings')\nplt.xticks(rotation=45)\nplt.tight_layout()\nplt.show()\n\n# ====================================\n# Step 6: Load and Visualize a Sample Mel Spectrogram\n# ====================================\nfirst_file = metadata['filename'].iloc[0]\nfirst_species = metadata['primary_label'].iloc[0]\nfile_path = BASE_PATH + '/train_audio/' + first_file\ny_audio, sr = librosa.load(file_path, sr=SAMPLE_RATE, duration=DURATION)\nmel_spec = librosa.feature.melspectrogram(y=y_audio, sr=sr, n_mels=N_MELS, fmax=16000)\nmel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\nplt.figure(figsize=(12, 4))\nlibrosa.display.specshow(mel_spec_db, sr=sr, x_axis='time', y_axis='mel')\nplt.colorbar(label='dB')\nplt.title(f'Mel Spectrogram - {first_species}')\nplt.tight_layout()\nplt.show()\n\n# ====================================\n# Step 7: Convert Audio Files to Mel Spectrograms\n# ====================================\ndef audio_to_spectrogram(file_path):\n    try:\n        y_audio, sr = librosa.load(file_path, sr=SAMPLE_RATE, duration=DURATION)\n        target_length = SAMPLE_RATE * DURATION\n        if len(y_audio) < target_length:\n            y_audio = np.pad(y_audio, (0, target_length - len(y_audio)))\n        mel_spec = librosa.feature.melspectrogram(y=y_audio, sr=SAMPLE_RATE, n_mels=N_MELS, fmax=16000)\n        mel_spec_db = librosa.power_to_db(mel_spec, ref=np.max)\n        return mel_spec_db\n    except:\n        return None\n\nspectrograms = []\nlabels = []\nskipped = 0\ntotal = len(sampled_data)\n\nfor i in range(total):\n    filename = sampled_data['filename'].iloc[i]\n    label = sampled_data['label_encoded'].iloc[i]\n    file_path = BASE_PATH + '/train_audio/' + filename\n    spec = audio_to_spectrogram(file_path)\n    if spec is not None:\n        spectrograms.append(spec)\n        labels.append(label)\n    else:\n        skipped = skipped + 1\n    if (i + 1) % 200 == 0:\n        print(f\"Processed {i + 1} / {total} files...\")\n\n# ====================================\n# Step 8: Build Feature Matrix and Normalize Data\n# ====================================\nX = np.array(spectrograms)\ny = np.array(labels)\nprint(f\"Done! {len(X)} files processed, {skipped} skipped\")\nprint(f\"Data shape: {X.shape}\")\n\nX = X.reshape(X.shape[0], X.shape[1], X.shape[2], 1)\nX_min = X.min()\nX_max = X.max()\nX = (X - X_min) / (X_max - X_min)\n\n# ====================================\n# Step 9: Split Data into Training and Validation Sets\n# ====================================\nX_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)\nprint(f\"Training: {X_train.shape[0]}, Validation: {X_val.shape[0]}\")\n\n# ====================================\n# Step 10: Build the CNN Model — Convolution, ReLU, Max Pooling, Flatten, Dense, Dropout\n# ====================================\nnum_classes = len(np.unique(y))\nmodel = models.Sequential()\nmodel.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(128, 313, 1)))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(64, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Conv2D(128, (3, 3), activation='relu'))\nmodel.add(layers.MaxPooling2D((2, 2)))\nmodel.add(layers.Flatten())\nmodel.add(layers.Dense(128, activation='relu'))\nmodel.add(layers.Dropout(0.5))\nmodel.add(layers.Dense(num_classes, activation='softmax'))\nmodel.summary()\n\n# ====================================\n# Step 11: Compile and Train the Model\n# ====================================\nmodel.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])\nhistory = model.fit(X_train, y_train, epochs=20, batch_size=32, validation_data=(X_val, y_val), verbose=1)\nprint(\"\\nTraining completed!\")\n\n# ====================================\n# Step 12: Visualize Training History — Loss and Accuracy\n# ====================================\nhistory_dict = history.history\nepochs_range = range(1, len(history_dict['loss']) + 1)\nfig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14, 5))\nax1.plot(epochs_range, history_dict['loss'], 'bo-', label='Training Loss')\nax1.plot(epochs_range, history_dict['val_loss'], 'ro-', label='Validation Loss')\nax1.set_title('Training and Validation Loss')\nax1.set_xlabel('Epochs')\nax1.set_ylabel('Loss')\nax1.legend()\nax1.grid(True)\nax2.plot(epochs_range, history_dict['accuracy'], 'bo-', label='Training Accuracy')\nax2.plot(epochs_range, history_dict['val_accuracy'], 'ro-', label='Validation Accuracy')\nax2.set_title('Training and Validation Accuracy')\nax2.set_xlabel('Epochs')\nax2.set_ylabel('Accuracy')\nax2.legend()\nax2.grid(True)\nplt.tight_layout()\nplt.show()\n\n# ====================================\n# Step 13: Evaluate Model Performance\n# ====================================\nval_loss, val_accuracy = model.evaluate(X_val, y_val, verbose=0)\nprint(f\"Final Validation Accuracy: {val_accuracy * 100:.2f}%\")\nprint(f\"Final Validation Loss: {val_loss:.4f}\")\n\n# ====================================\n# Step 14: Generate and Display Sample Predictions\n# ====================================\npredictions = model.predict(X_val)\nprint(\"\\nSample Predictions:\")\nprint(\"=\" * 60)\nfor i in range(10):\n    predicted_class = np.argmax(predictions[i])\n    predicted_name = label_encoder.inverse_transform([predicted_class])[0]\n    confidence = predictions[i][predicted_class] * 100\n    actual_class = y_val[i]\n    actual_name = label_encoder.inverse_transform([actual_class])[0]\n    status = \"Correct\" if predicted_class == actual_class else \"Wrong\"\n    print(f\"  {i+1}. Predicted: {predicted_name:20s} | Actual: {actual_name:20s} | {confidence:.1f}% | {status}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-05-18T22:24:55.419046Z","iopub.execute_input":"2026-05-18T22:24:55.419880Z","iopub.status.idle":"2026-05-18T22:24:57.725771Z","shell.execute_reply.started":"2026-05-18T22:24:55.419844Z","shell.execute_reply":"2026-05-18T22:24:57.724663Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}