{"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":"gpu","dataSources":[{"sourceId":91844,"databundleVersionId":11361821,"sourceType":"competition"},{"sourceId":11177155,"sourceType":"datasetVersion","datasetId":6976177}],"dockerImageVersionId":30918,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:37.848664Z","iopub.execute_input":"2025-04-05T06:34:37.848967Z","iopub.status.idle":"2025-04-05T06:34:37.852483Z","shell.execute_reply.started":"2025-04-05T06:34:37.848944Z","shell.execute_reply":"2025-04-05T06:34:37.851667Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data = pd.read_csv(\"/kaggle/input/bird-cliff2025-data/df_melfrequencies.csv\")\ndata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:37.856849Z","iopub.execute_input":"2025-04-05T06:34:37.857045Z","iopub.status.idle":"2025-04-05T06:34:38.312967Z","shell.execute_reply.started":"2025-04-05T06:34:37.857029Z","shell.execute_reply":"2025-04-05T06:34:38.312184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data.class_names.value_counts().plot(kind='hist')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:38.313934Z","iopub.execute_input":"2025-04-05T06:34:38.314253Z","iopub.status.idle":"2025-04-05T06:34:38.595203Z","shell.execute_reply.started":"2025-04-05T06:34:38.314219Z","shell.execute_reply":"2025-04-05T06:34:38.594395Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## One hot encoding for target variable ###\nfrom sklearn.preprocessing import LabelEncoder\n\nprimary_labelencoder = LabelEncoder()\n\ndata['class_names'] = primary_labelencoder.fit_transform(data['class_names'])\n\n##X vars ##\ncols  = data.columns.difference(['class_names'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:38.596509Z","iopub.execute_input":"2025-04-05T06:34:38.596738Z","iopub.status.idle":"2025-04-05T06:34:38.896424Z","shell.execute_reply.started":"2025-04-05T06:34:38.596718Z","shell.execute_reply":"2025-04-05T06:34:38.895770Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrainx , testx , trainy , testy = train_test_split(data[cols] ,data['class_names']  , random_state = 0 , test_size = 0.25)\nprint(trainx.shape)\nprint(testx.shape)\nprint(trainy.shape)\nprint(testy.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:38.897645Z","iopub.execute_input":"2025-04-05T06:34:38.898231Z","iopub.status.idle":"2025-04-05T06:34:38.997758Z","shell.execute_reply.started":"2025-04-05T06:34:38.898205Z","shell.execute_reply":"2025-04-05T06:34:38.997014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf \nfrom tensorflow.keras import layers , models , callbacks\n\ninput_dim = trainx.shape[1]\nmodel = models.Sequential(\n    [\n        layers.Input(shape = (input_dim , )) , \n        layers.Dense(4096 , activation = 'relu') ,\n        layers.Dropout(0.25) ,\n        layers.Dense(3072 , activation = 'relu') ,\n        layers.Dropout(0.25) ,\n        layers.Dense(2048 , activation = 'relu') ,\n        layers.Dropout(0.25) ,\n        layers.Dense(1024 , activation = 'relu') , \n        layers.Dropout(0.25) ,\n        layers.Dense(502 , activation = 'relu') , \n        layers.Dropout(0.25) ,\n        layers.Dense(206 , activation = 'softmax')\n    ]\n)\n\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:38.998481Z","iopub.execute_input":"2025-04-05T06:34:38.998683Z","iopub.status.idle":"2025-04-05T06:34:41.124642Z","shell.execute_reply.started":"2025-04-05T06:34:38.998666Z","shell.execute_reply":"2025-04-05T06:34:41.123984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(model.summary())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:41.125355Z","iopub.execute_input":"2025-04-05T06:34:41.125558Z","iopub.status.idle":"2025-04-05T06:34:41.145371Z","shell.execute_reply.started":"2025-04-05T06:34:41.125532Z","shell.execute_reply":"2025-04-05T06:34:41.144547Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer = 'adam' , metrics = ['accuracy'] , loss = 'sparse_categorical_crossentropy')\ncheck_point_callback  =  callbacks.ModelCheckpoint(\n    filepath='best_model.keras',\n    mode = 'max' ,\n    verbose = 1 , \n    monitor = 'val_accuracy' , \n    save_best_only = True , \n)\n\nearly_stop_callback =  callbacks.EarlyStopping(monitor = 'val_accuracy' , \n                                               patience = 25 , \n                                               restore_best_weights = True ,\n                                              mode = 'max' )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:41.146359Z","iopub.execute_input":"2025-04-05T06:34:41.146571Z","iopub.status.idle":"2025-04-05T06:34:41.158583Z","shell.execute_reply.started":"2025-04-05T06:34:41.146546Z","shell.execute_reply":"2025-04-05T06:34:41.157948Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"history  = model.fit(x =  trainx , y = trainy , epochs = 1000 , batch_size = 256 , validation_data = (testx , testy) , \n          callbacks = [check_point_callback , early_stop_callback ]  )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:34:41.160615Z","iopub.execute_input":"2025-04-05T06:34:41.160831Z","iopub.status.idle":"2025-04-05T06:36:51.192521Z","shell.execute_reply.started":"2025-04-05T06:34:41.160812Z","shell.execute_reply":"2025-04-05T06:36:51.191589Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\n\n\n# Load trained model\nmodel = load_model('/kaggle/working/best_model.keras')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:36:51.193662Z","iopub.execute_input":"2025-04-05T06:36:51.193886Z","iopub.status.idle":"2025-04-05T06:36:52.161527Z","shell.execute_reply.started":"2025-04-05T06:36:51.193868Z","shell.execute_reply":"2025-04-05T06:36:52.160630Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"proba = model.predict(testx)  # Get probability predictions\npred_indices = np.argmax(proba, axis=1)  ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:36:52.162478Z","iopub.execute_input":"2025-04-05T06:36:52.162786Z","iopub.status.idle":"2025-04-05T06:36:53.300138Z","shell.execute_reply.started":"2025-04-05T06:36:52.162756Z","shell.execute_reply":"2025-04-05T06:36:53.299196Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"pred_indices","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:36:53.301127Z","iopub.execute_input":"2025-04-05T06:36:53.301450Z","iopub.status.idle":"2025-04-05T06:36:53.306564Z","shell.execute_reply.started":"2025-04-05T06:36:53.301414Z","shell.execute_reply":"2025-04-05T06:36:53.305803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\n# Assuming you saved your model history object as `history`\nplt.figure(figsize=(12, 5))\n\n# 🔹 Accuracy Plot\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Val Accuracy')\nplt.title('Model Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.grid(True)\n\n# 🔸 Loss Plot\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Val Loss')\nplt.title('Model Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\nplt.grid(True)\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:36:53.307500Z","iopub.execute_input":"2025-04-05T06:36:53.307830Z","iopub.status.idle":"2025-04-05T06:36:53.720562Z","shell.execute_reply.started":"2025-04-05T06:36:53.307799Z","shell.execute_reply":"2025-04-05T06:36:53.719741Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"## metrics \nfrom sklearn.metrics import classification_report, confusion_matrix, accuracy_score, f1_score, precision_score, recall_score\n\n# Assuming `testy` and `pred_indices` are your actual and predicted labels\nprint(\"Accuracy:\", accuracy_score(testy, pred_indices))\nprint(\"Precision:\", precision_score(testy, pred_indices, average='macro'))\nprint(\"Recall:\", recall_score(testy, pred_indices, average='macro'))\nprint(\"F1 Score:\", f1_score(testy, pred_indices, average='macro'))\n\n# Detailed report\nprint(\"\\n📋 Classification Report:\\n\")\nprint(classification_report(testy, pred_indices, digits=4))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:36:53.721333Z","iopub.execute_input":"2025-04-05T06:36:53.721539Z","iopub.status.idle":"2025-04-05T06:36:53.762952Z","shell.execute_reply.started":"2025-04-05T06:36:53.721520Z","shell.execute_reply":"2025-04-05T06:36:53.762005Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport librosa\nimport numpy as np\nimport pandas as pd\nfrom tensorflow.keras.models import load_model\nfrom tqdm import tqdm\n\n# Load model\nmodel = load_model('/kaggle/working/best_model.keras')\n\n# Load label encoder used during training\nprimary_labelencoder = LabelEncoder()\nclass_labels = sorted(os.listdir('/kaggle/input/birdclef-2025/train_audio/'))\nprimary_labelencoder.fit(class_labels)  # Fit encoder on original labels\n\n# Paths\ntest_dir = '/kaggle/input/birdclef-2025/test_soundscapes'\nsample_sub = pd.read_csv('/kaggle/input/birdclef-2025/sample_submission.csv')\n\n# Parameters\nsr = 32000          # sampling rate\nduration = 5        # seconds\nn_mfcc = 40         # same as used during training\n\n# Feature extraction\ndef extract_mfcc(y, sr, n_mfcc):\n    mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=n_mfcc)\n    return np.mean(mfcc.T, axis=0)\n\n# Final prediction storage\nsubmission_rows = []\n\n# Iterate through soundscapes\nfor filename in tqdm(sorted(os.listdir(test_dir))):\n    if not filename.endswith('.ogg'):\n        continue\n    try :\n        file_path = os.path.join(test_dir, filename)\n        y, _ = librosa.load(file_path, sr=sr)\n        soundscape_id = filename.replace('.ogg', '')\n    \n        for i in range(0, 60, duration):\n            start_sample = i * sr\n            end_sample = (i + duration) * sr\n            segment = y[start_sample:end_sample]\n    \n            # Pad if needed\n            if len(segment) < duration * sr:\n                segment = np.pad(segment, (0, duration * sr - len(segment)))\n    \n            # Extract features and reshape\n            mfcc = extract_mfcc(segment, sr=sr, n_mfcc=n_mfcc)\n            input_features = np.expand_dims(mfcc, axis=0)\n    \n            # Predict probabilities\n            probs = model.predict(input_features, verbose=0)[0]\n    \n            # Convert indices back to original species IDs\n            mapped_labels = primary_labelencoder.inverse_transform(range(len(probs)))\n    \n            # Create a dictionary of {species_id: probability}\n            prob_dict = dict(zip(mapped_labels, probs))\n    \n            # Ensure submission columns match sample_submission.csv order\n            ordered_probs = [prob_dict.get(species, 0) for species in sample_sub.columns[1:]]\n    \n            # Append row\n            row_id = f\"{soundscape_id}_{i + duration}\"\n            submission_rows.append([row_id] + ordered_probs)\n    except Exception as e:\n        print(e)\n\n# Build submission DataFrame\nsubmission_df = pd.DataFrame(submission_rows, columns=['row_id'] + list(sample_sub.columns[1:]))\n\n# Save CSV\nsubmission_df.to_csv(\"submission.csv\", index=False)\nprint(\"submission.csv created\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-05T06:37:10.362134Z","iopub.execute_input":"2025-04-05T06:37:10.362418Z","iopub.status.idle":"2025-04-05T06:37:11.349256Z","shell.execute_reply.started":"2025-04-05T06:37:10.362397Z","shell.execute_reply":"2025-04-05T06:37:11.348486Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}