{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\n# import numpy as np # linear algebra\n# import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# # Input data files are available in the read-only \"../input/\" directory\n# # For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import all the required libraries.\n\nimport numpy as np\nimport pandas as pd\n\nimport librosa\nfrom librosa import display\n\nimport soundfile as sf\n\nimport os\nfrom os import path\n\nimport sklearn\nfrom sklearn.model_selection import train_test_split\n\nfrom sklearn.preprocessing import LabelEncoder, StandardScaler\n\nfrom sklearn.ensemble import RandomForestClassifier\n\n%matplotlib inline\nimport matplotlib.pyplot as plt\n\nimport pathlib\nimport csv \n\n# Import necessary libraries for metrics\nfrom sklearn.metrics import accuracy_score\nfrom sklearn.metrics import precision_score\nfrom sklearn.metrics import recall_score\nfrom sklearn.metrics import f1_score\n\n# # Keras\n# import keras\n# from keras import layers\n# from keras.models import Sequential\n# from keras.layers import Activation, Dense, Dropout, Conv2D, Flatten, MaxPooling2D\n# from keras.layers import GlobalMaxPooling2D, GlobalAveragePooling1D, AveragePooling2D, Input, Add\n# from tensorflow.keras.optimizers import SGD\n\nfrom datetime import datetime\n\nimport warnings\nwarnings.filterwarnings('ignore')\n\nimport random\n\nprint('Libraries have been imported')","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:14:00.092866Z","iopub.execute_input":"2022-04-27T16:14:00.093246Z","iopub.status.idle":"2022-04-27T16:14:02.633072Z","shell.execute_reply.started":"2022-04-27T16:14:00.093146Z","shell.execute_reply":"2022-04-27T16:14:02.632088Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Selecting the 21 species for the competition\n# contained in the file scored_birds.json provided by Kaggle\n\nimport json\n \n# Opening JSON file\nf = open('../input/birdclef-2022/scored_birds.json')\n \n# returns JSON object as a dictionary\nbirds = json.load(f)\n \nprint(birds)\n","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:15:39.510055Z","iopub.execute_input":"2022-04-27T16:15:39.510402Z","iopub.status.idle":"2022-04-27T16:15:39.519767Z","shell.execute_reply.started":"2022-04-27T16:15:39.510354Z","shell.execute_reply":"2022-04-27T16:15:39.518705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Reading csv data back into dataframe\n\nbirds_fe = pd.read_csv('../input/birds-fe128csv/birds_fe128.csv')\n\nbirds_fe.head()","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:17:20.040431Z","iopub.execute_input":"2022-04-27T16:17:20.040712Z","iopub.status.idle":"2022-04-27T16:17:20.377797Z","shell.execute_reply.started":"2022-04-27T16:17:20.040681Z","shell.execute_reply":"2022-04-27T16:17:20.377176Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Drop features\nbirds_fe.drop(columns=['species', 'filename', 'duration'], inplace=True)\nbirds_fe.head()\n","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:19:18.453584Z","iopub.execute_input":"2022-04-27T16:19:18.454209Z","iopub.status.idle":"2022-04-27T16:19:18.489147Z","shell.execute_reply.started":"2022-04-27T16:19:18.454155Z","shell.execute_reply":"2022-04-27T16:19:18.488319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Dataframe features\n\nbirds_fe.info(verbose=True)","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:24:57.653817Z","iopub.execute_input":"2022-04-27T16:24:57.654105Z","iopub.status.idle":"2022-04-27T16:24:57.678247Z","shell.execute_reply.started":"2022-04-27T16:24:57.654076Z","shell.execute_reply":"2022-04-27T16:24:57.677319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Building the model","metadata":{}},{"cell_type":"code","source":"# Encoding the Labels\ngenre_list = birds_fe.iloc[:, -1]\nencoder = LabelEncoder()\n\n# Fittng the data\ny = encoder.fit_transform(genre_list)\n\n# Dividing data into training and Testing set\nX = birds_fe.iloc[:, :-1]\nX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)\n\n# Scaling the Feature columns\nscaler = StandardScaler()\nX_train = scaler.fit_transform(X_train)\nX_test = scaler.transform(X_test)\n\nprint('Labels encoded. Train and Test Datasets, created and standardized.')\n","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:27:11.109537Z","iopub.execute_input":"2022-04-27T16:27:11.109811Z","iopub.status.idle":"2022-04-27T16:27:11.155769Z","shell.execute_reply.started":"2022-04-27T16:27:11.109784Z","shell.execute_reply":"2022-04-27T16:27:11.154781Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Modeling Random Forests Classifier\\n')\n\nnow = datetime.now()\nstart = now.strftime(\"%H:%M:%S\")\nprint(\"start =\", start)\n\nclf = RandomForestClassifier(bootstrap=False,\n                             max_depth=50,\n                             max_features='auto',\n                             min_samples_leaf=1,\n                             min_samples_split=2,\n                             n_estimators=2800,\n                             random_state=0\n                            )\n\nrfc = clf.fit(X_train, y_train)\n      \n# predicting labels\ny_pred = clf.predict(X_test)\n\n# accuracy: (tp + tn) / (p + n)\naccuracy = accuracy_score(y_test, y_pred)\nprint('Accuracy: %f' % accuracy)\n\n# precision tp / (tp + fp)\nprecision = precision_score(y_test, y_pred, average='micro')\nprint('Precision: %f' % precision)\n\n# recall: tp / (tp + fn)\nrecall = recall_score(y_test, y_pred, average='micro')\nprint('Recall: %f' % recall)\n\n# f1: 2 tp / (2 tp + fp + fn)\nf1 = f1_score(y_test, y_pred, average='micro')\nprint('F1 score: %f' % f1)\n\nnow = datetime.now()\nfinish = now.strftime(\"%H:%M:%S\")\nprint(\"\\nend =\", finish)\n\nprint('Ready')","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:32:09.463460Z","iopub.execute_input":"2022-04-27T16:32:09.463744Z","iopub.status.idle":"2022-04-27T16:33:31.393641Z","shell.execute_reply.started":"2022-04-27T16:32:09.463710Z","shell.execute_reply":"2022-04-27T16:33:31.392095Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Part 1:\n\n# Directory where sound files have been placed\n# test_audio_dir = '/kaggle/input/birdclef-2022/test_soundscapes/'\ntest_audio_dir = '../input/birdclef-2022/test_soundscapes/'\n\n# All sound files will be splitted into 5-second chunks\nchunk_size = 5   \n\n# Getting all the file names from directory\nfile_list = [f.split('.')[0] for f in sorted(os.listdir(test_audio_dir))]\nprint('Number of test soundscapes found:', len(file_list))\n\n# Header for the datafrane containing all features\n\nl = []\n\nfor f in ['chroma_stft', 'chroma_cqt', 'chroma_cens']:\n    for i in range(0,36):\n        l += [f+str(i)]\n\nfor i in range(0,256):\n    l += ['mel_spct'+str(i)]\n\nfor i in range(0,256):\n    l += ['mfcc' + str(i)]\n    \nl += ['spec_cent', 'spec_bw']\n\nfor i in range(0,7):\n    l += ['spec_con' + str(i)]\n\nl += ['spec_flt', 'rolloff_min', 'rolloff_25', 'rolloff_50', 'rolloff_75', 'rolloff_max']\n\nfor i in range(0,6):\n    l += ['tonnetz' + str(i)]\n\nl += ['zcr']\n\n# This is where results are stored before writing the submission file\ndict_pred = {'row_id': [], 'target': []}\n\n# Part 2:\n\n# Traverse all files inside the folder and make chunks of each audio file\nfor afile in file_list: \n    file_path = test_audio_dir + afile + '.ogg'\n    print(f\"Making chunks of size {chunk_size}s of file: {afile}\")\n\n    # Load the file\n    sig, sr = librosa.load(file_path)\n    \n    # Get number of samples for <chunk_size> seconds\n    buffer = chunk_size * sr\n    samples_total = len(sig)\n    samples_wrote = 0\n    \n    counter = 1\n    \n    # each file is chopped up into several chunks.\n    # each chunk is preprocessed and its features extracted to make a prediction\n    while samples_wrote < samples_total:\n        # check if the buffer is not exceeding total samples \n        if buffer > (samples_total - samples_wrote):\n            buffer = samples_total - samples_wrote\n\n        chunk = sig[samples_wrote : (samples_wrote + buffer)]\n        chunk_end_time = counter * 5\n        print(\"Chunk Nº \", counter, \" - Chunk End Time \", chunk_end_time)\n\n        # chunk_features holds all extracted features from the chunk.\n        # this file is fully rewritten for each chunk\n        \n        chunk_features = []\n\n        # Feature extraction from chunk\n        duration = librosa.get_duration(y=y, sr=sr)\n        chroma_stft = librosa.feature.chroma_stft(y=chunk, sr=sr, n_chroma=36)\n        chroma_cqt = librosa.feature.chroma_cqt(y=chunk, sr=sr, n_chroma=36)\n        chroma_cens = librosa.feature.chroma_cens(y=chunk, sr=sr, n_chroma=36)\n        mel_spct = librosa.feature.melspectrogram(y=chunk, sr=sr, n_mels=128)\n        mfcc = librosa.feature.mfcc(y=chunk, sr=sr, n_mfcc=128)\n        spec_cent = librosa.feature.spectral_centroid(y=chunk, sr=sr)\n        spec_bw = librosa.feature.spectral_bandwidth(y=chunk, sr=sr)\n        spec_con = librosa.feature.spectral_contrast(y=chunk, sr=sr)\n        spec_flt = librosa.feature.spectral_flatness(y=chunk)\n        rolloff_min = librosa.feature.spectral_rolloff(y=chunk, sr=sr, roll_percent=0.01)\n        rolloff_25 = librosa.feature.spectral_rolloff(y=chunk, sr=sr, roll_percent=0.25)\n        rolloff_50 = librosa.feature.spectral_rolloff(y=chunk, sr=sr, roll_percent=0.50)\n        rolloff_75 = librosa.feature.spectral_rolloff(y=chunk, sr=sr, roll_percent=0.75)\n        rolloff_max = librosa.feature.spectral_rolloff(y=chunk, sr=sr, roll_percent=0.99)\n        tonnetz = librosa.feature.tonnetz(y=chunk, sr=sr)\n        zcr = librosa.feature.zero_crossing_rate(chunk)\n        \n        # Extract chunk features\n        for k in range(0,36):\n            chunk_features.append(np.mean(chroma_stft[k,:]))\n        \n        for k in range(0,36):\n            chunk_features.append(np.mean(chroma_cqt[k,:]))\n         \n        for k in range(0,36):\n            chunk_features.append(np.mean(chroma_cens[k,:]))\n            \n        for i in range(0,mel_spct.shape[0]):\n            chunk_features.append(np.mean(mel_spct[i,:]))\n        \n        for e in mfcc:\n            chunk_features.append(np.mean(e))\n        \n        chunk_features.append(np.mean(spec_cent))\n        \n        chunk_features.append(np.mean(spec_bw))\n        \n        for k in range(0,spec_con.shape[0]):\n            chunk_features.append(np.mean(spec_con[k,:]))\n            \n        chunk_features.append(np.mean(spec_flt))\n    \n        chunk_features.append(np.mean(rolloff_min[0]))\n        chunk_features.append(np.mean(rolloff_25[0]))\n        chunk_features.append(np.mean(rolloff_50[0]))\n        chunk_features.append(np.mean(rolloff_75[0]))\n        chunk_features.append(np.mean(rolloff_max[0]))\n\n        for i in range(0,6):\n            chunk_features.append(np.mean(tonnetz[i]))\n        \n        chunk_features.append(np.mean(zcr))   \n\n        # Scaling the features extracted from the chunk\n        chunk_scaled = scaler.transform([chunk_features])\n        \n        # and predicting labels\n        chunk_pred = clf.predict_proba(chunk_scaled) # Random Forest Model\n        max_val = chunk_pred[0][np.argmax(chunk_pred)]\n        j = 0\n        for k in clf.classes_:\n            bird = birds[k]\n            row_id = afile + '_' + bird + '_' + str(chunk_end_time)\n            \n            # Put the result into our prediction dict and \n            # apply a \"confidence\" threshold of 0.5\n            dict_pred['row_id'].append(row_id)\n            dict_pred['target'].append(True if chunk_pred[0][j]>=max_val else False)\n            j += 1\n\n        # next chunk\n        counter += 1\n        samples_wrote += buffer\n\n#Part 03\n\n# All sound files have been now splitted and the chunks, predicted.\n# With the resulting dictionary make a new data frame and look at some results\n\nresults = pd.DataFrame(dict_pred, columns = ['row_id', 'target'])\n    \n# Convert results to csv\n# results.to_csv(\"/kaggle/working/submission.csv\", index=False)\nresults.to_csv(\"./submission.csv\", index=False)\n\nprint('Results have been subnitted')\n","metadata":{"execution":{"iopub.status.busy":"2022-04-27T16:43:18.824722Z","iopub.execute_input":"2022-04-27T16:43:18.825010Z","iopub.status.idle":"2022-04-27T16:43:37.552765Z","shell.execute_reply.started":"2022-04-27T16:43:18.824979Z","shell.execute_reply":"2022-04-27T16:43:37.551622Z"},"trusted":true},"execution_count":null,"outputs":[]}]}