{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# BirdCLEF 2025 - Bird Sound Classification # \n\nThis notebook covers the complete workflow for the BirdCLEF 2025 competition, including:\n- **Loading and Exploring Data**\n- **Preprocessing and Feature Selection**\n- **Training a Machine Learning Model**\n- **Evaluating Model Performance**\n- **Generating a Submission File**","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.ensemble import RandomForestClassifier\nfrom sklearn.metrics import roc_auc_score\nfrom sklearn.preprocessing import LabelBinarizer, OneHotEncoder","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:22:33.558647Z","iopub.execute_input":"2025-03-18T19:22:33.559085Z","iopub.status.idle":"2025-03-18T19:22:36.637755Z","shell.execute_reply.started":"2025-03-18T19:22:33.559045Z","shell.execute_reply":"2025-03-18T19:22:36.635981Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ## 1️⃣ تحميل البيانات\nprint(\"📥 Loading datasets...\")\ntrain_df = pd.read_csv(\"../input/birdclef-2025/train.csv\")\ntaxonomy_df = pd.read_csv(\"../input/birdclef-2025/taxonomy.csv\")\nsample_submission_df = pd.read_csv(\"../input/birdclef-2025/sample_submission.csv\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:22:36.639640Z","iopub.execute_input":"2025-03-18T19:22:36.640292Z","iopub.status.idle":"2025-03-18T19:22:36.861053Z","shell.execute_reply.started":"2025-03-18T19:22:36.640236Z","shell.execute_reply":"2025-03-18T19:22:36.859871Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ## 2️⃣ استكشاف البيانات\nprint(\"\\n🔍 First few rows of train data:\")\nprint(train_df.head())\nprint(\"\\n📊 Train Data Info:\")\ntrain_df.info()\nprint(\"\\n📊 Taxonomy Data Info:\")\ntaxonomy_df.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:22:39.678637Z","iopub.execute_input":"2025-03-18T19:22:39.679203Z","iopub.status.idle":"2025-03-18T19:22:39.743371Z","shell.execute_reply.started":"2025-03-18T19:22:39.679070Z","shell.execute_reply":"2025-03-18T19:22:39.742128Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n\ntrain_df = train_df.assign(\n    latitude=train_df[\"latitude\"].fillna(train_df[\"latitude\"].mean()),\n    longitude=train_df[\"longitude\"].fillna(train_df[\"longitude\"].mean())\n)\nprint(train_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:22:42.698584Z","iopub.execute_input":"2025-03-18T19:22:42.699032Z","iopub.status.idle":"2025-03-18T19:22:42.721485Z","shell.execute_reply.started":"2025-03-18T19:22:42.698991Z","shell.execute_reply":"2025-03-18T19:22:42.720267Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# استخراج البيانات ذات الأهمية\ntrain_cleaned = train_df[[\"primary_label\", \"latitude\", \"longitude\"]]\n\n# ## 4️⃣ تقسيم البيانات\nprint(\"\\n📌 Splitting the data...\")\nX = train_cleaned[[\"latitude\", \"longitude\"]]\ny = train_cleaned[\"primary_label\"]\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:22:46.018514Z","iopub.execute_input":"2025-03-18T19:22:46.018947Z","iopub.status.idle":"2025-03-18T19:22:46.062693Z","shell.execute_reply.started":"2025-03-18T19:22:46.018913Z","shell.execute_reply":"2025-03-18T19:22:46.061414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestClassifier\nfrom sklearn.preprocessing import LabelBinarizer\nfrom sklearn.metrics import roc_auc_score\nfrom sklearn.model_selection import train_test_split\nimport numpy as np\n\n# ✅ تدريب النموذج الأساسي\nprint(\"\\n🤖 Training RandomForest Model...\")\nmodel = RandomForestClassifier(n_estimators=1000, random_state=42, class_weight=\"balanced\")\nmodel.fit(X_train, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:23:10.918726Z","iopub.execute_input":"2025-03-18T19:23:10.919242Z","iopub.status.idle":"2025-03-18T19:25:06.129414Z","shell.execute_reply.started":"2025-03-18T19:23:10.919202Z","shell.execute_reply":"2025-03-18T19:25:06.128215Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ✅ اختيار أكثر 100 تصنيف شيوعًا\nprint(\"\\n🔎 Selecting top 100 most common labels...\")\ntop_labels = train_cleaned[\"primary_label\"].value_counts().index[:100]\nfiltered_df = train_cleaned[train_cleaned[\"primary_label\"].isin(top_labels)]\n\nX_filtered = filtered_df[[\"latitude\", \"longitude\"]]\ny_filtered = filtered_df[\"primary_label\"]\n\nX_train, X_test, y_train, y_test = train_test_split(\n    X_filtered, y_filtered, test_size=0.2, random_state=42, stratify=y_filtered\n)\n\n# ✅ إعادة تدريب النموذج\nprint(\"\\n⚡ Retraining the model with top 100 labels...\")\nmodel.fit(X_train, y_train)\ny_pred_proba = model.predict_proba(X_test)\n\n# ✅ تحويل y_test إلى One-Hot Encoding\nlb = LabelBinarizer()\ny_test_bin = lb.fit_transform(y_test)\n\n# ✅ ضمان تطابق عدد الأعمدة\nmin_cols = min(y_pred_proba.shape[1], y_test_bin.shape[1])\ny_test_bin, y_pred_proba = y_test_bin[:, :min_cols], y_pred_proba[:, :min_cols]\n\n# ✅ حساب ROC-AUC فقط عند وجود أكثر من فئة\nif len(np.unique(y_test)) > 1:\n    roc_auc = roc_auc_score(y_test_bin, y_pred_proba, average=\"macro\", multi_class=\"ovr\")\n    print(f\"✅ ROC-AUC Score: {roc_auc:.7f}\")\nelse:\n    print(\"⚠️ Skipping ROC-AUC calculation: Only one class present in y_test.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:25:26.681076Z","iopub.execute_input":"2025-03-18T19:25:26.681439Z","iopub.status.idle":"2025-03-18T19:26:38.136459Z","shell.execute_reply.started":"2025-03-18T19:25:26.681410Z","shell.execute_reply":"2025-03-18T19:26:38.135029Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ## 7️⃣ تجهيز ملف الإرسال\nprint(\"\\n📤 Preparing submission file...\")\nsubmission = sample_submission_df.copy()\nrequired_labels = submission.columns[1:]  # استبعاد 'row_id'\n\ny_pred_proba_df = pd.DataFrame(y_pred_proba, columns=lb.classes_)\n\n# التأكد من أن عدد العينات في y_pred_proba_df يطابق submission\nif y_pred_proba_df.shape[0] > submission.shape[0]:\n    y_pred_proba_df = y_pred_proba_df.iloc[:submission.shape[0], :]\nelif y_pred_proba_df.shape[0] < submission.shape[0]:\n    missing_rows = submission.shape[0] - y_pred_proba_df.shape[0]\n    padding = np.zeros((missing_rows, y_pred_proba_df.shape[1]))\n    y_pred_proba_df = pd.concat([y_pred_proba_df, pd.DataFrame(padding, columns=y_pred_proba_df.columns)], ignore_index=True)\n\n# التأكد من أن جميع الفئات المطلوبة موجودة\nfor label in required_labels:\n    if label not in y_pred_proba_df:\n        y_pred_proba_df[label] = 0  # تعيين القيم غير المتوقعة إلى 0\n\n# ترتيب الأعمدة كما هو مطلوب في ملف الإرسال\ny_pred_proba_df = y_pred_proba_df[required_labels]\n\n# تعيين القيم في ملف الإرسال\nsubmission.iloc[:, 1:] = y_pred_proba_df.values\n\n# ضبط القيم داخل النطاق [0, 1]\nsubmission.iloc[:, 1:] = submission.iloc[:, 1:].clip(0, 1)\n\n# حفظ ملف الإرسال\nsubmission.to_csv(\"submission.csv\", index=False)\nprint(\"✅ Submission file saved successfully!\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-03-18T19:26:50.319765Z","iopub.execute_input":"2025-03-18T19:26:50.320215Z","iopub.status.idle":"2025-03-18T19:26:50.423184Z","shell.execute_reply.started":"2025-03-18T19:26:50.320152Z","shell.execute_reply":"2025-03-18T19:26:50.421277Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}