{"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":"markdown","source":"# Training data (Short audio)\n\nThe training data for this competition consists of a collection of so-called “focal recordings”. These recordings were made using semi-professional equipment (often using highly directional microphones) and primarily focus on one single species. All recordings were contributed by Xeno-canto (https://www.xeno-canto.org), one of the largest digital archives for bird sounds. Each recording comes with metadata specifying things like recording date, recording location, and (of course) the bird species that was recorded.\n\nTo get a better understanding of the metadata, let’s look at a few entries.","metadata":{}},{"cell_type":"code","source":"import pandas as pd\nimport os\nimport warnings\nwarnings.filterwarnings(action='ignore')\nimport IPython.display as ipd\nimport numpy as np\nimport folium\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport descartes\nimport geopandas as gpd\nfrom shapely.geometry import Point, Polygon\nimport geopandas as gpd\nimport geopy.distance\nfrom shapely.geometry import Point\n\nfrom datetime import datetime, timedelta\n\nfrom bokeh.layouts import column, row\nfrom bokeh.models import ColumnDataSource, LinearAxis, Range1d\nfrom bokeh.models.tools import HoverTool\nfrom bokeh.palettes import BuGn4\nfrom bokeh.plotting import figure, output_notebook, show\nfrom bokeh.transform import cumsum\n\noutput_notebook()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:30:56.518066Z","iopub.execute_input":"2021-05-24T07:30:56.518492Z","iopub.status.idle":"2021-05-24T07:30:59.276175Z","shell.execute_reply.started":"2021-05-24T07:30:56.518402Z","shell.execute_reply":"2021-05-24T07:30:59.275041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import time\nimport librosa\nimport sklearn\nimport librosa.display\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom IPython.display import Audio\nfrom tqdm import tqdm\ntqdm.pandas()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:30:59.278435Z","iopub.execute_input":"2021-05-24T07:30:59.279059Z","iopub.status.idle":"2021-05-24T07:31:01.059949Z","shell.execute_reply.started":"2021-05-24T07:30:59.279002Z","shell.execute_reply":"2021-05-24T07:31:01.058927Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## configuring setup, constants and parameters\nPATH_TRAIN = \"../input/birdclef-2021/train_metadata.csv\"\nPATH_TRAIN_SOUNDSCAPE = \"../input/birdclef-2021/train_soundscape_labels.csv\"\nPATH_TEST = \"../input/birdclef-2021/test.csv\"\nPATH_TEST_RECORDING_DATE_LOC = \"../input/birdclef-2021/test_soundscapes/test_set_recording_dates.csv\"\n#PATH_EBIRD_CLEMENTS = \"../input/ebirdclements-checklist/eBird-Clements-v2019-integrated-checklist-August-2019.csv\"\nPATH_AUDIO = \"../input/birdclef-2021/train_short_audio\"","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.061699Z","iopub.execute_input":"2021-05-24T07:31:01.062311Z","iopub.status.idle":"2021-05-24T07:31:01.068164Z","shell.execute_reply.started":"2021-05-24T07:31:01.062261Z","shell.execute_reply":"2021-05-24T07:31:01.066838Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(PATH_TRAIN,)\ntrain.head()","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-24T07:31:01.069602Z","iopub.execute_input":"2021-05-24T07:31:01.069996Z","iopub.status.idle":"2021-05-24T07:31:01.661888Z","shell.execute_reply.started":"2021-05-24T07:31:01.069966Z","shell.execute_reply":"2021-05-24T07:31:01.660818Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\" The data has \",train.shape[0],\" rows\")\nprint(\"\\n The data has \",train.shape[1],\" columns. \\n The columns are: \",train.columns.values)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.665310Z","iopub.execute_input":"2021-05-24T07:31:01.665679Z","iopub.status.idle":"2021-05-24T07:31:01.673773Z","shell.execute_reply.started":"2021-05-24T07:31:01.665643Z","shell.execute_reply":"2021-05-24T07:31:01.672635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.info()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.676918Z","iopub.execute_input":"2021-05-24T07:31:01.677234Z","iopub.status.idle":"2021-05-24T07:31:01.771202Z","shell.execute_reply.started":"2021-05-24T07:31:01.677205Z","shell.execute_reply":"2021-05-24T07:31:01.770122Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# train[\"date\"] = train[\"date\"].astype('datetime64[ns]')","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.772461Z","iopub.execute_input":"2021-05-24T07:31:01.772950Z","iopub.status.idle":"2021-05-24T07:31:01.776699Z","shell.execute_reply.started":"2021-05-24T07:31:01.772906Z","shell.execute_reply":"2021-05-24T07:31:01.775661Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.dtypes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.778260Z","iopub.execute_input":"2021-05-24T07:31:01.778702Z","iopub.status.idle":"2021-05-24T07:31:01.795205Z","shell.execute_reply.started":"2021-05-24T07:31:01.778659Z","shell.execute_reply":"2021-05-24T07:31:01.793937Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TODO Correct/Impute Date if aything is wrong.","metadata":{}},{"cell_type":"code","source":"train.groupby(\"date\")[\"common_name\"].count().reset_index()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.797159Z","iopub.execute_input":"2021-05-24T07:31:01.797627Z","iopub.status.idle":"2021-05-24T07:31:01.837531Z","shell.execute_reply.started":"2021-05-24T07:31:01.797580Z","shell.execute_reply":"2021-05-24T07:31:01.836367Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.dtypes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.838956Z","iopub.execute_input":"2021-05-24T07:31:01.839376Z","iopub.status.idle":"2021-05-24T07:31:01.848980Z","shell.execute_reply.started":"2021-05-24T07:31:01.839332Z","shell.execute_reply":"2021-05-24T07:31:01.848050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create some time features\n\ntrain['year'] = train['date'].apply(lambda x: x.split('-')[0]).astype(int)\ntrain['month'] = train['date'].apply(lambda x: x.split('-')[1]).astype(int)\ntrain['day_of_month'] = train['date'].apply(lambda x: x.split('-')[2]).astype(int)\ntrain[\"hour\"] = pd.to_numeric(train.time.str.split(\":\", expand = True)[0], errors = \"coerce\")","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:01.850337Z","iopub.execute_input":"2021-05-24T07:31:01.850841Z","iopub.status.idle":"2021-05-24T07:31:02.333029Z","shell.execute_reply.started":"2021-05-24T07:31:01.850809Z","shell.execute_reply":"2021-05-24T07:31:02.331946Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"year\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.334315Z","iopub.execute_input":"2021-05-24T07:31:02.334620Z","iopub.status.idle":"2021-05-24T07:31:02.343014Z","shell.execute_reply.started":"2021-05-24T07:31:02.334590Z","shell.execute_reply":"2021-05-24T07:31:02.341741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"year\"][train[\"year\"] == 0] = 2015\ntrain[\"year\"][train[\"year\"] == 199] = 1990\ntrain[\"year\"][train[\"year\"] == 201] = 2010\ntrain[\"year\"][train[\"year\"] == 202] = 2020\ntrain[\"year\"][train[\"year\"] == 2104] = 2014","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.344831Z","iopub.execute_input":"2021-05-24T07:31:02.345246Z","iopub.status.idle":"2021-05-24T07:31:02.385992Z","shell.execute_reply.started":"2021-05-24T07:31:02.345202Z","shell.execute_reply":"2021-05-24T07:31:02.385223Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"month\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.386995Z","iopub.execute_input":"2021-05-24T07:31:02.387397Z","iopub.status.idle":"2021-05-24T07:31:02.393608Z","shell.execute_reply.started":"2021-05-24T07:31:02.387366Z","shell.execute_reply":"2021-05-24T07:31:02.392930Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"month\"][train[\"month\"] == 0] = 6","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.394624Z","iopub.execute_input":"2021-05-24T07:31:02.395140Z","iopub.status.idle":"2021-05-24T07:31:02.408673Z","shell.execute_reply.started":"2021-05-24T07:31:02.395110Z","shell.execute_reply":"2021-05-24T07:31:02.407845Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"day_of_month\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.409738Z","iopub.execute_input":"2021-05-24T07:31:02.410157Z","iopub.status.idle":"2021-05-24T07:31:02.423728Z","shell.execute_reply.started":"2021-05-24T07:31:02.410127Z","shell.execute_reply":"2021-05-24T07:31:02.422775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"day_of_month\"][train[\"day_of_month\"] == 0] = 16","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.425331Z","iopub.execute_input":"2021-05-24T07:31:02.425672Z","iopub.status.idle":"2021-05-24T07:31:02.436112Z","shell.execute_reply.started":"2021-05-24T07:31:02.425641Z","shell.execute_reply":"2021-05-24T07:31:02.434888Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.438077Z","iopub.execute_input":"2021-05-24T07:31:02.438588Z","iopub.status.idle":"2021-05-24T07:31:02.484179Z","shell.execute_reply.started":"2021-05-24T07:31:02.438543Z","shell.execute_reply":"2021-05-24T07:31:02.482928Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Recreate train[\"date\"] with imputed values\ntrain['date'] = pd.to_datetime(pd.DataFrame({'year':train['year'],\n                             'month':train['month'],\n                             'day':train['day_of_month']}))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.485459Z","iopub.execute_input":"2021-05-24T07:31:02.485763Z","iopub.status.idle":"2021-05-24T07:31:02.519011Z","shell.execute_reply.started":"2021-05-24T07:31:02.485735Z","shell.execute_reply":"2021-05-24T07:31:02.518083Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['latitude'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.523274Z","iopub.execute_input":"2021-05-24T07:31:02.523622Z","iopub.status.idle":"2021-05-24T07:31:02.535675Z","shell.execute_reply.started":"2021-05-24T07:31:02.523587Z","shell.execute_reply":"2021-05-24T07:31:02.534406Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train['longitude'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.537232Z","iopub.execute_input":"2021-05-24T07:31:02.537562Z","iopub.status.idle":"2021-05-24T07:31:02.548094Z","shell.execute_reply.started":"2021-05-24T07:31:02.537532Z","shell.execute_reply":"2021-05-24T07:31:02.547021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.550003Z","iopub.execute_input":"2021-05-24T07:31:02.550415Z","iopub.status.idle":"2021-05-24T07:31:02.577404Z","shell.execute_reply.started":"2021-05-24T07:31:02.550370Z","shell.execute_reply":"2021-05-24T07:31:02.576386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.dtypes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.578713Z","iopub.execute_input":"2021-05-24T07:31:02.578983Z","iopub.status.idle":"2021-05-24T07:31:02.586818Z","shell.execute_reply.started":"2021-05-24T07:31:02.578956Z","shell.execute_reply":"2021-05-24T07:31:02.585731Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n# Test data\n\nIf you’re already familiar with the training soundscapes, the hidden test set should not be a surprise. It contains 20 soundscape recordings of 10-minute duration for each of the four recording sites. Again, you need to predict audible species for 5-second chunks of the audio data. The submission file needs to contain the ID of the processed audio chunk  (fileID_site_time) and all audible species as a list of space-delimited eBird codes.\n\nLet’s look at one example:\n\nWhen analyzing file “*1234_SSW_20170101.ogg*” (that’s a mock filename), the audio chunk ending at second *00:00:35* of the entire file would have the unique ID “*1234_SSW_35*”. If your classifier thinks that species “bluwa1” and “redwa2” (again, mock codes) vocalize during this time, the final submission entry should look like this:\n\n*1234_SSW_35 bluwa1 redwa2*\n\nA submission for this file should include **ALL** segments, starting at 5 seconds. Like this:\n \n*1234_SSW_5 nocall*  \n*1234_SSW_10 bluwa1*  \n*1234_SSW_15 nocall*  \n*1234_SSW_20 bluwa1 redwa2*  \n*1234_SSW_25 nocall*  \n*1234_SSW_30 nocall* \n\nAnd so on...\n\n\nMake yourself familiar with the training and test data, also make sure to check out our other notebooks, let us know if you have any comments and - of course - don’t hesitate to start a forum thread if you have any questions.","metadata":{}},{"cell_type":"code","source":"test_csv = pd.read_csv(PATH_TEST)\nsample_sub= pd.read_csv(\"../input/birdclef-2021/sample_submission.csv\")","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.588282Z","iopub.execute_input":"2021-05-24T07:31:02.588615Z","iopub.status.idle":"2021-05-24T07:31:02.615017Z","shell.execute_reply.started":"2021-05-24T07:31:02.588584Z","shell.execute_reply":"2021-05-24T07:31:02.613962Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_csv.columns","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.617633Z","iopub.execute_input":"2021-05-24T07:31:02.618079Z","iopub.status.idle":"2021-05-24T07:31:02.624380Z","shell.execute_reply.started":"2021-05-24T07:31:02.618033Z","shell.execute_reply":"2021-05-24T07:31:02.623215Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_csv.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.626036Z","iopub.execute_input":"2021-05-24T07:31:02.626627Z","iopub.status.idle":"2021-05-24T07:31:02.643656Z","shell.execute_reply.started":"2021-05-24T07:31:02.626576Z","shell.execute_reply":"2021-05-24T07:31:02.642650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.645806Z","iopub.execute_input":"2021-05-24T07:31:02.646237Z","iopub.status.idle":"2021-05-24T07:31:02.656877Z","shell.execute_reply.started":"2021-05-24T07:31:02.646193Z","shell.execute_reply":"2021-05-24T07:31:02.655665Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# df_ebird_clements = pd.read_csv(PATH_EBIRD_CLEMENTS, encoding = \"ISO-8859-1\")\n# df_ebird_clements","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.658460Z","iopub.execute_input":"2021-05-24T07:31:02.658914Z","iopub.status.idle":"2021-05-24T07:31:02.667861Z","shell.execute_reply.started":"2021-05-24T07:31:02.658866Z","shell.execute_reply":"2021-05-24T07:31:02.666714Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#df_ebird_clements.columns","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.669393Z","iopub.execute_input":"2021-05-24T07:31:02.669834Z","iopub.status.idle":"2021-05-24T07:31:02.679577Z","shell.execute_reply.started":"2021-05-24T07:31:02.669789Z","shell.execute_reply":"2021-05-24T07:31:02.678482Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Use this information later if required https://www.kaggle.com/jmreuter/a-birder-s-eye-view-of-the-metadata-with-taxonomy/","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.680644Z","iopub.execute_input":"2021-05-24T07:31:02.680922Z","iopub.status.idle":"2021-05-24T07:31:02.692554Z","shell.execute_reply.started":"2021-05-24T07:31:02.680895Z","shell.execute_reply":"2021-05-24T07:31:02.691329Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TRAINING & TEST RECORDING LOCATIONS  \n\nWe can extract location data from txt located in the test_soundscapes folder.","metadata":{}},{"cell_type":"code","source":"# latitude, longitude\nCOL = ['COL', 5.57,-75.85,200,'Jardín, Departamento de Antioquia','Colombia']\nCOR = ['COR',10.12,-84.51,200,'Alajuela, San Ramón','Costa Rica']\nSNE = ['SNE', 38.49,-119.95,200,'Sierra Nevada, California','USA'] \nSSW = ['SSW', 42.47,-76.45,200,'Ithaca, New York','USA']\nalias = ['COL','COR','SNE','SSW']\ncolumns = ['alias','latitude','longitude','size','location','country']\ndata = [COL, COR, SNE, SSW]\n\ndf_recording_loc = pd.DataFrame(data,columns=columns)\ndf_recording_loc","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.694019Z","iopub.execute_input":"2021-05-24T07:31:02.694371Z","iopub.status.idle":"2021-05-24T07:31:02.716687Z","shell.execute_reply.started":"2021-05-24T07:31:02.694338Z","shell.execute_reply":"2021-05-24T07:31:02.715737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":" ## Test recording location with date  \n Description of test site parameters, such as location and date.  \n Explore which birds were at the right place and in the right time to have a chance of making into a test set recording.\n All birds were likely to be observed at the test sites, but were they there at the right time?  \n \n Answer : Each recording site is assigned a circular region of 200 km in radius. If any of the birds were previously \nrecorded in the same month as the test recordings on that site, the bird could potentially be present in test recordings.\n","metadata":{}},{"cell_type":"markdown","source":"Let's retrieve all months, when the recording took place, in the **test set**. Together with location, lets check all species that were observed in the right place and in the right time.","metadata":{}},{"cell_type":"code","source":"test_recording_date_loc = pd.read_csv(PATH_TEST_RECORDING_DATE_LOC)\ntest_recording_date_loc[\"date\"] = pd.to_datetime(test_recording_date_loc[\"date\"].astype(str), format=\"%Y%m%d\")\ntest_recording_date_loc[\"month\"] = test_recording_date_loc[\"date\"].apply(lambda x: x.month).astype(int)\n\ntest_recording_date_loc.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.728279Z","iopub.execute_input":"2021-05-24T07:31:02.729136Z","iopub.status.idle":"2021-05-24T07:31:02.754741Z","shell.execute_reply.started":"2021-05-24T07:31:02.729085Z","shell.execute_reply":"2021-05-24T07:31:02.753951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_recording_loc.values","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.756575Z","iopub.execute_input":"2021-05-24T07:31:02.757057Z","iopub.status.idle":"2021-05-24T07:31:02.762738Z","shell.execute_reply.started":"2021-05-24T07:31:02.757008Z","shell.execute_reply":"2021-05-24T07:31:02.761827Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"site_params = dict([(site, []) for site in test_recording_date_loc[\"site\"].unique()])\nfor row in test_recording_date_loc.iterrows():\n    site_params[row[1][\"site\"]].append(row[1][\"month\"])\n\nfor site in site_params:\n    site_params[site] = {\"months\" : list(set(site_params[site]))}\n\nfor spatial in df_recording_loc.values:\n    site_params[spatial[0]][\"latlon\"] = (spatial[1], spatial[2])\n    site_params[spatial[0]][\"R\"] = 200.0\n    \nsite_params","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.764293Z","iopub.execute_input":"2021-05-24T07:31:02.764732Z","iopub.status.idle":"2021-05-24T07:31:02.788913Z","shell.execute_reply.started":"2021-05-24T07:31:02.764685Z","shell.execute_reply":"2021-05-24T07:31:02.787202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"site_params.items()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.790452Z","iopub.execute_input":"2021-05-24T07:31:02.791001Z","iopub.status.idle":"2021-05-24T07:31:02.798340Z","shell.execute_reply.started":"2021-05-24T07:31:02.790954Z","shell.execute_reply":"2021-05-24T07:31:02.797377Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def right_place_time(lat, lon, month):\n    \"\"\"\n    Calculate if an observation was made within test site parameters (coordinates and time)\n    \"\"\"\n    check = False\n    for site, params in site_params.items():\n        # Check within site\n        check_site = (geopy.distance.distance(params[\"latlon\"], (lat, lon)).km < params[\"R\"]) and (month in params[\"months\"])\n        check = check or (check_site > 0)\n\n    return check","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.799652Z","iopub.execute_input":"2021-05-24T07:31:02.800048Z","iopub.status.idle":"2021-05-24T07:31:02.811841Z","shell.execute_reply.started":"2021-05-24T07:31:02.800017Z","shell.execute_reply":"2021-05-24T07:31:02.810463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"right_place_time(42.3005, -72.5877, 9)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.813747Z","iopub.execute_input":"2021-05-24T07:31:02.814418Z","iopub.status.idle":"2021-05-24T07:31:02.833902Z","shell.execute_reply.started":"2021-05-24T07:31:02.814369Z","shell.execute_reply":"2021-05-24T07:31:02.831020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"right_place_time(42.47, -76.5877, 1)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.835781Z","iopub.execute_input":"2021-05-24T07:31:02.836205Z","iopub.status.idle":"2021-05-24T07:31:02.848123Z","shell.execute_reply.started":"2021-05-24T07:31:02.836169Z","shell.execute_reply":"2021-05-24T07:31:02.846646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"right_place_time(42.47, -76.5877, 2)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.849774Z","iopub.execute_input":"2021-05-24T07:31:02.850285Z","iopub.status.idle":"2021-05-24T07:31:02.865292Z","shell.execute_reply.started":"2021-05-24T07:31:02.850247Z","shell.execute_reply":"2021-05-24T07:31:02.864431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.columns","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.866707Z","iopub.execute_input":"2021-05-24T07:31:02.867236Z","iopub.status.idle":"2021-05-24T07:31:02.882060Z","shell.execute_reply.started":"2021-05-24T07:31:02.867185Z","shell.execute_reply":"2021-05-24T07:31:02.880824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.dtypes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.883648Z","iopub.execute_input":"2021-05-24T07:31:02.883985Z","iopub.status.idle":"2021-05-24T07:31:02.897039Z","shell.execute_reply.started":"2021-05-24T07:31:02.883954Z","shell.execute_reply":"2021-05-24T07:31:02.895948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.898556Z","iopub.execute_input":"2021-05-24T07:31:02.898866Z","iopub.status.idle":"2021-05-24T07:31:02.930480Z","shell.execute_reply.started":"2021-05-24T07:31:02.898837Z","shell.execute_reply":"2021-05-24T07:31:02.929419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"latitude\"].isna().any()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.931857Z","iopub.execute_input":"2021-05-24T07:31:02.932157Z","iopub.status.idle":"2021-05-24T07:31:02.944436Z","shell.execute_reply.started":"2021-05-24T07:31:02.932128Z","shell.execute_reply":"2021-05-24T07:31:02.943339Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"hour\"].isna().any()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.946333Z","iopub.execute_input":"2021-05-24T07:31:02.946808Z","iopub.status.idle":"2021-05-24T07:31:02.956438Z","shell.execute_reply.started":"2021-05-24T07:31:02.946758Z","shell.execute_reply":"2021-05-24T07:31:02.955651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"right_place_time\"] = train.progress_apply(lambda r: right_place_time(r['latitude'], r['longitude'], r[\"month\"]), axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:31:02.957915Z","iopub.execute_input":"2021-05-24T07:31:02.958541Z","iopub.status.idle":"2021-05-24T07:32:34.774008Z","shell.execute_reply.started":"2021-05-24T07:31:02.958485Z","shell.execute_reply":"2021-05-24T07:32:34.773205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.775016Z","iopub.execute_input":"2021-05-24T07:32:34.775547Z","iopub.status.idle":"2021-05-24T07:32:34.801548Z","shell.execute_reply.started":"2021-05-24T07:32:34.775497Z","shell.execute_reply":"2021-05-24T07:32:34.800474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train[\"right_place_time\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.803064Z","iopub.execute_input":"2021-05-24T07:32:34.803691Z","iopub.status.idle":"2021-05-24T07:32:34.821614Z","shell.execute_reply.started":"2021-05-24T07:32:34.803644Z","shell.execute_reply":"2021-05-24T07:32:34.820512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Percentage of records withing test sites at matching times of year: {:.2f}%\".format(100*len(train[train[\"right_place_time\"]])/len(train)))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.823197Z","iopub.execute_input":"2021-05-24T07:32:34.823617Z","iopub.status.idle":"2021-05-24T07:32:34.835419Z","shell.execute_reply.started":"2021-05-24T07:32:34.823581Z","shell.execute_reply":"2021-05-24T07:32:34.834476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Of {} species {} were observed within sites at the same time of year\".format(train[\"primary_label\"].nunique(), train[train[\"right_place_time\"]][\"primary_label\"].nunique()))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.836819Z","iopub.execute_input":"2021-05-24T07:32:34.837327Z","iopub.status.idle":"2021-05-24T07:32:34.859443Z","shell.execute_reply.started":"2021-05-24T07:32:34.837292Z","shell.execute_reply":"2021-05-24T07:32:34.858412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## TRAINING SOUNDSCAPE : COUNTS INFORMATION  \n\nLet's view the value counts difference between nocall and call labels in the training soundscape data.\nSplitting the whole soundscape recording into 5 second segments, let's also see how many segments exist in each recording, in the training soundscape data.","metadata":{}},{"cell_type":"code","source":"# Training Given Environment Recordings\ntrain_soundscape = pd.read_csv(PATH_TRAIN_SOUNDSCAPE)\ntrain_soundscape.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.862434Z","iopub.execute_input":"2021-05-24T07:32:34.862831Z","iopub.status.idle":"2021-05-24T07:32:34.885908Z","shell.execute_reply.started":"2021-05-24T07:32:34.862798Z","shell.execute_reply":"2021-05-24T07:32:34.885046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_soundscape.shape","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.888609Z","iopub.execute_input":"2021-05-24T07:32:34.889040Z","iopub.status.idle":"2021-05-24T07:32:34.894582Z","shell.execute_reply.started":"2021-05-24T07:32:34.889000Z","shell.execute_reply":"2021-05-24T07:32:34.893648Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#tdf0 = pd.read_csv('../input/birdclef-2021/train_metadata.csv')\nval = train_soundscape.birds.value_counts() \ny = val.to_list() \nx = val.index.to_list()\n\nprint('CALLS vs NOCALLS INFO in All Recordings')\nprint('*****************************************')\nprint(f\"Training Soundscape Identifiers: {train_soundscape[train_soundscape.birds!='nocall'].shape[0]}\")\nprint(f\"Training Soundscapes Nocalls: {train_soundscape[train_soundscape.birds=='nocall'].shape[0]}\")\n\nprint('\\nTRAINING SOUNDSCAPE RECORDINGS:')\nprint('***********************************')\ntrain_soundscape.site.value_counts() # 2/4 TEST LOCATIONS","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.896125Z","iopub.execute_input":"2021-05-24T07:32:34.896585Z","iopub.status.idle":"2021-05-24T07:32:34.917259Z","shell.execute_reply.started":"2021-05-24T07:32:34.896512Z","shell.execute_reply":"2021-05-24T07:32:34.916038Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 1. Primary species\n\nMost importantly, the metadata specifies the audible species for each recording. The primary species annotation consists of three data fields: *primary_label, scientific_name, and common_name*[](http://). All labels have to be considered as “weak labels” since we do know which species is audible in the recording, but we do not know the exact timestamps of the vocalizations. Training with weakly labeled data is one of the core challenges of this competition.\n\nLet’s look at the number of different species.","metadata":{}},{"cell_type":"code","source":"train['primary_label'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.918609Z","iopub.execute_input":"2021-05-24T07:32:34.918894Z","iopub.status.idle":"2021-05-24T07:32:34.945369Z","shell.execute_reply.started":"2021-05-24T07:32:34.918867Z","shell.execute_reply":"2021-05-24T07:32:34.944353Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train['primary_label'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.947266Z","iopub.execute_input":"2021-05-24T07:32:34.947602Z","iopub.status.idle":"2021-05-24T07:32:34.967386Z","shell.execute_reply.started":"2021-05-24T07:32:34.947569Z","shell.execute_reply":"2021-05-24T07:32:34.966656Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Our dataset contains recordings for **397** different *primary* species, all of them defined by their **eBird code** (the codes that we use as primary label). Just as Xeno-canto is a digital platform that collects audio recordings, eBird (https://ebird.org) is a citizen science project that collects observations of birds. eBird uses unique species codes to reference birds. You can access additional information on each bird species by combining the base URL “https://ebird.org/species/” with a species code from the *primary_label* columns of the metadata.\n\nHere are a few examples:\n\nGolden-crowned Kinglet: https://ebird.org/species/gockin  \nRed-winged Blackbird: https://ebird.org/species/rewbla  \nAmerican Goldfinch: https://ebird.org/species/amegfi\n\nLet’s take a look at the number of recordings for each species in the training data:","metadata":{}},{"cell_type":"markdown","source":"## Bird (or Species)  \nprimary_label is the target variable that needs to be predicted. Let's look at its distribution. There are two features with the same information: common_name is just a prettier (and complete) version of primary_name. Note that the values from primary_name are used for predictions.","metadata":{}},{"cell_type":"code","source":"df_bird = train.groupby(\"common_name\")[\"filename\"].count().reset_index().rename(columns = {\"filename\": \"recordings\"}).sort_values(\"recordings\")\n\nsource = ColumnDataSource(df_bird)\ntooltips = [\n    (\"Bird Species\", \"@common_name\"),\n    (\"Recordings\", \"@recordings\")\n]\n\nv = figure(plot_width = 1000, plot_height = 6000, y_range = df_bird.common_name.values, tooltips = tooltips, title = \"Count of Bird Species\")\nv.hbar(\"common_name\", right = \"recordings\", source = source, height = 0.75, color = \"steelblue\", alpha = 0.6)\n\nv.xaxis.axis_label = \"Count\"\nv.yaxis.axis_label = \"Species\"\n\nshow(v)\n# df_bird.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:34.968532Z","iopub.execute_input":"2021-05-24T07:32:34.968985Z","iopub.status.idle":"2021-05-24T07:32:35.037325Z","shell.execute_reply.started":"2021-05-24T07:32:34.968946Z","shell.execute_reply":"2021-05-24T07:32:35.036337Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"\n\n## 2. Background species\n\nThe metadata for each recording lists the number of audible background species. The data field “*seconday_labels*” contains lists of eBird codes (i.e., primary labels) that recordists annotated. It is important to note that these lists might be incomplete, and you might be able to hear background species, although none are specified in the metadata. Therefore, lists of secondary labels are not very reliable, but they might still be useful for multi-label training (e.g., through loss masking for background species).\n\nLet's look at some values:","metadata":{}},{"cell_type":"code","source":"train['secondary_labels'].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:35.038901Z","iopub.execute_input":"2021-05-24T07:32:35.039316Z","iopub.status.idle":"2021-05-24T07:32:35.069224Z","shell.execute_reply.started":"2021-05-24T07:32:35.039273Z","shell.execute_reply":"2021-05-24T07:32:35.067908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see that the majority of recordings does not have an annotation of background species. Yet, it is highly likely that most of them actually contain one or more additional species. The data also shows us that the Red-winged Blackbird (rewbla), American Robin (amerob), House Sparrow (houspa), and Northern Cardinal (norcar) appear to be some of the most common background species.\n\n**Please note, secondary lables only contain labels of species that are actually represented in the data set.**\n\n## 3. Location, location, location\n\nEach recording comes with a recording location specified in the metadata. Data fields “*latitude*” and “*longitude*” contain GPS coordinates as provided by the recordist. In combination with the recording data (data field “*date*”), this information can be very useful to map distribution and migration patterns. Why is it important? Not all birds occur at all locations at all times! \n\nLet's look at a few examples:\n","metadata":{}},{"cell_type":"code","source":"# Code adapted from: https://www.kaggle.com/andradaolteanu/birdcall-recognition-eda-and-audio-fe\n# Make sure to ckeck out the entire nootebook. It's brilliant.\n\n\n\n# SHP file\nworld_map = gpd.read_file(\"../input/world-shapefile/world_shapefile.shp\")\n\n# Coordinate reference system\ncrs = {\"init\" : \"epsg:4326\"}\n\n# Lat and Long need to be of type float, not object\nspecies_list = ['norcar', 'houspa', 'wesblu', 'banana']\ndata = train[train['primary_label'].isin(species_list)]\ndata[\"latitude\"] = data[\"latitude\"].astype(float)\ndata[\"longitude\"] = data[\"longitude\"].astype(float)\n\n# Create geometry\ngeometry = [Point(xy) for xy in zip(data[\"longitude\"], data[\"latitude\"])]\n\n# Geo Dataframe\ngeo_df = gpd.GeoDataFrame(data, crs=crs, geometry=geometry)\n\n# Create ID for species\nspecies_id = geo_df[\"primary_label\"].value_counts().reset_index()\nspecies_id.insert(0, 'ID', range(0, 0 + len(species_id)))\n\nspecies_id.columns = [\"ID\", \"primary_label\", \"count\"]\n\n# Add ID to geo_df\ngeo_df = pd.merge(geo_df, species_id, how=\"left\", on=\"primary_label\")\n\n# === PLOT ===\nfig, ax = plt.subplots(figsize = (16, 10))\nworld_map.plot(ax=ax, alpha=0.4, color=\"grey\")\n\npalette = iter(sns.hls_palette(len(species_id)))\nfor i in range(len(species_list)):\n    geo_df[geo_df[\"ID\"] == i].plot(ax=ax, \n                                   markersize=20, \n                                   color=next(palette), \n                                   marker=\"o\", \n                                   label = species_id['primary_label'].values[i]);\n    \nax.legend()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:35.070933Z","iopub.execute_input":"2021-05-24T07:32:35.071242Z","iopub.status.idle":"2021-05-24T07:32:36.837765Z","shell.execute_reply.started":"2021-05-24T07:32:35.071213Z","shell.execute_reply":"2021-05-24T07:32:36.836597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"As we can see, different species occur over different spatial scales. According to the recording locations, the House Sparrow (houspa) has occurrences around the globe, the Northern Cardinal (norcar) appears to be a typical East coast species of the U.S., the Western Bluebird (wesblu) a West coast species. The Bananaquit (banana) seems to only occur in Central and South America. \n\nLocation data can help us to create subsets of the training data for each of the four test data recording locations (which we will explore later). But be aware: The range of certain species may not be fully reflected by recording location data, and the actual range may differ from what we can see in the data. Yet, recording locations are a good starting point.\n\nPlease note that the training data only contains species that are likely to occur at the recording locations of the test data, even though sometimes the majority of the recordings were made in Europe. If you want to know more about the range of a certain species, please take a look at the associated eBird entry.\n\n","metadata":{}},{"cell_type":"markdown","source":"## 4.Time of the Recording","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(16, 6))\ntrain = train.sort_values(['year']).reset_index(drop=True)\nax = sns.countplot(train['year'], palette=\"hls\")\n\n\nplt.title(\"Audio Files Registration per Year Made\", fontsize=16)\nplt.xticks(rotation=90, fontsize=13)\nplt.yticks(fontsize=13)\nplt.ylabel(\"Frequency\", fontsize=14)\nplt.xlabel(\"\");","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:36.839664Z","iopub.execute_input":"2021-05-24T07:32:36.840077Z","iopub.status.idle":"2021-05-24T07:32:37.520329Z","shell.execute_reply.started":"2021-05-24T07:32:36.840025Z","shell.execute_reply":"2021-05-24T07:32:37.519267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Majority of the data was registered between 2013 and 2020, and from March to July\n\n0000, 0199, 0201, 0202, 2104 are likley wrong years","metadata":{}},{"cell_type":"code","source":"plt.figure(figsize=(16, 6))\n\ntrain = train.sort_values(['month']).reset_index(drop=True)\nax = sns.countplot(train['month'], palette=\"hls\")\n\nplt.title(\"Audio Files Registration per Month Made\", fontsize=16)\nplt.xticks(fontsize=13)\nplt.yticks(fontsize=13)\nplt.ylabel(\"Frequency\", fontsize=14)\nplt.xlabel(\"\");","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:37.521728Z","iopub.execute_input":"2021-05-24T07:32:37.522034Z","iopub.status.idle":"2021-05-24T07:32:37.771087Z","shell.execute_reply.started":"2021-05-24T07:32:37.522004Z","shell.execute_reply":"2021-05-24T07:32:37.770243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Majority of the data was registered between March and July\n\n00 is months which are not known","metadata":{}},{"cell_type":"markdown","source":"## Datetime  \nLet's look at when these recordings were taken.","metadata":{}},{"cell_type":"code","source":"df_date = train.groupby(\"date\")[\"common_name\"].count().reset_index().rename(columns = {\"common_name\": \"recordings\"})\ndf_date.head(10)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:37.772355Z","iopub.execute_input":"2021-05-24T07:32:37.772826Z","iopub.status.idle":"2021-05-24T07:32:37.795468Z","shell.execute_reply.started":"2021-05-24T07:32:37.772786Z","shell.execute_reply":"2021-05-24T07:32:37.794728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_date.date = pd.to_datetime(df_date.date, errors = \"coerce\")\ndf_date.dropna(inplace = True)\ndf_date[\"weekday\"] = df_date.date.dt.day_name()\nsource_1 = ColumnDataSource(df_date)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:37.796513Z","iopub.execute_input":"2021-05-24T07:32:37.796960Z","iopub.status.idle":"2021-05-24T07:32:37.839907Z","shell.execute_reply.started":"2021-05-24T07:32:37.796921Z","shell.execute_reply":"2021-05-24T07:32:37.839028Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 5. Rating\n\nXeno-canto has a rating system for the quality of each recording. Ratings are assigned by users, and we adapted this rating scheme for the training data. In our case, ratings range from 0.5 to 5.0 (the latter being the best possible rating) and reflect the overall quality assigned by users and the number of background species. A value of “0” means that this particular recording does not have a rating, and it is by that the fallback value.\n\nLet's see how rating values are distributed across the training data:","metadata":{}},{"cell_type":"markdown","source":"## Recording quality ratings by species\n\nHere's the description for ratings from xeno-canto:\n\nUse the following general guidelines when rating recordings on xeno-canto. Ratings are obviously subjective, and will inevitably vary slightly between different individuals, but these guidelines should improve consistency.  \n  \nA: Loud and Clear  \nB: Clear, but bird a bit distant, or some interference with other sound sources  \nC: Moderately clear, or quite some interference  \nD: Faint recording, or much interference  \nE: Barely audible  \nNote that the A-E character classifications described on the xeno-canto website were sensibly converted to numeric classifications for the metadata, with 1 being the worst and 5 being the Best.","metadata":{}},{"cell_type":"code","source":"# Code adapted from https://www.kaggle.com/shahules/bird-watch-complete-eda-fe\n# Again, make sure to check out the entire notebook.\nimport plotly.graph_objects as go\n\nhist_data = train['rating'].values.tolist()\nfig = go.Figure(data=[go.Histogram(x=hist_data)], \n                layout=go.Layout(margin=go.layout.Margin(l=0, r=0, b=10, t=50)))\nfig.update_layout(title='Number of recordings per rating')\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:37.841002Z","iopub.execute_input":"2021-05-24T07:32:37.841452Z","iopub.status.idle":"2021-05-24T07:32:38.752062Z","shell.execute_reply.started":"2021-05-24T07:32:37.841408Z","shell.execute_reply":"2021-05-24T07:32:38.750860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Overall, the training data contains high-quality recordings and the majority of samples is rated with 3.5 or higher. Whenever we had to limit the amount of recordings per species for the training data, we used the 500 top-rated samples. Sub-sampling training data based on user rating might help to extract high-quality training samples.\n\nOther data fields of the metadata might be of value at some point during development, here is a brief description for each of them:\n\n* **type**: Represents the type of the vocalization, with “song” and “call” as the most common. Excluding or including recordings of certain call types might help to diversify training data. Learn more about how and why birds vocalize here: https://academy.allaboutbirds.org/birdsong/\n\n* **author**: Acknowledgement to the recordists who contributed the recording. Some recordists focus on a specific subsets of species, so there might be some value in these data.\n\n* **filename**: A reference to the sound file in the training data.\n\n* **license**: All recordings have an open source license which is noted in this field. Make sure to respect the license when sharing the data.\n\n* **time**: Time of recording as stated by the recordist. Might be of value to distinguish between birds that vocalize during the day and those which only vocalize during the night. Can be used to diversify the training data.\n\n* **url**: A link to the original recording on Xeno-canto.\n\n","metadata":{}},{"cell_type":"markdown","source":"**Recordings**  \nThe main data is the audio files of the bird recordings. Let's hear the first sample from few of the species.","metadata":{}},{"cell_type":"code","source":"# df_bird_map = train[[\"primary_label\", \"common_name\"]].drop_duplicates()\n\n# for primary_label in os.listdir(PATH_AUDIO)[:20]:\n#     species = df_bird_map[df_bird_map.primary_label == primary_label].common_name.values[0]\n#     audio_file = os.listdir(f\"{PATH_AUDIO}/{primary_label}\")[0]\n#     audio_path = f\"{PATH_AUDIO}/{primary_label}/{audio_file}\"\n#     ipd.display(ipd.HTML(f\"<h2>{primary_label} ({species})</h2>\"))\n#     ipd.display(ipd.Audio(audio_path))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.753717Z","iopub.execute_input":"2021-05-24T07:32:38.754151Z","iopub.status.idle":"2021-05-24T07:32:38.757849Z","shell.execute_reply.started":"2021-05-24T07:32:38.754103Z","shell.execute_reply":"2021-05-24T07:32:38.756730Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training data (Soundscapes)\n\nOne of the major obstacles in this competition is the significant gap between training and test recordings. There is a distinct shift in acoustic domains between the two and it can be very challenging to train classifiers that generalize well enough to bridge the gap. Yet, training with target samples (i.e., soundscapes) is often not possible - somebody has to annotate the data for each new deployment, for each new recording location. However, we decided to include some examples of soundscape recordings (i.e., test recordings) that can be used for validation, or even for training. These 20 recordings represent 2 of the 4 test recording locations. Yet, they might not be 100% representative, some species might be missing and only audible in the hidden test set, recording equipment might differ. But they should nonetheless provide a good overview of what to expect in the hidden test data.\n\nLet’s take a look at the label data for this set of recordings.","metadata":{}},{"cell_type":"code","source":"train_soundscapes = pd.read_csv('../input/birdclef-2021/train_soundscape_labels.csv',)\ntrain_soundscapes","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.759050Z","iopub.execute_input":"2021-05-24T07:32:38.759423Z","iopub.status.idle":"2021-05-24T07:32:38.792823Z","shell.execute_reply.started":"2021-05-24T07:32:38.759384Z","shell.execute_reply":"2021-05-24T07:32:38.791612Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_soundscapes[\"site\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.794217Z","iopub.execute_input":"2021-05-24T07:32:38.794631Z","iopub.status.idle":"2021-05-24T07:32:38.803383Z","shell.execute_reply.started":"2021-05-24T07:32:38.794598Z","shell.execute_reply":"2021-05-24T07:32:38.802197Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We can see a few data fields and here’s a brief description for each of them:\n\n* **row_id**: Unique identifier of a 5-second segment of each soundscape file. Use this create the submission file entry.\n\n* **site**: Recording site of the soundscape data. In this competition, we included recordings from 4 different sites (COL = Colombia, COR = Costa Rica, SNE = Sierra Nevada, SSW = Sapsucker Woods). **Make sure to take a look at the “test_soundscape_metadata” which contains more information on each location**. Training soundscapes only represent two of the four locations (COR and SSW).\n\n* **audio_id**: Identifier used to reference audio recordings. Filenames contain the file ID, recording site and recording date (yyyymmdd).\n\n* **seconds**: End time of the 5-second segment for which this entry states the label. A value of 85 would mean that this particular segment starts at 00:01:20 and lasts until 00:01:25 of the audio file.\n\n* **birds**: primary label (i.e., eBird code) of the audible species of this segment. “nocall” references a segment without any bird vocalization. Segments can have more than one bird, in that case, eBird codes are separated by space. “nocall” can never appear together with other codes.\n\nLet’s look at the most common entries for “birds”:","metadata":{}},{"cell_type":"code","source":"train_soundscapes.shape, train_soundscapes.describe()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.805142Z","iopub.execute_input":"2021-05-24T07:32:38.805728Z","iopub.status.idle":"2021-05-24T07:32:38.833305Z","shell.execute_reply.started":"2021-05-24T07:32:38.805681Z","shell.execute_reply":"2021-05-24T07:32:38.832478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(train_soundscapes['birds'].value_counts())","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.834562Z","iopub.execute_input":"2021-05-24T07:32:38.834876Z","iopub.status.idle":"2021-05-24T07:32:38.843135Z","shell.execute_reply.started":"2021-05-24T07:32:38.834847Z","shell.execute_reply":"2021-05-24T07:32:38.842144Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"“Nocall” seems to be the most common, which is no surprise: Birds only vocalize occasionally during a recording. Yet, some recordings contain very dense acoustic scenes with multiple birds vocalizing at the same time. Why is “nocall” important? There’s a simple reason: Your classifier should be able to suppress false positives for these segments, which is important for ornithologists when confronted with the detections. One of the core challenges of this competition is to reduce the number of false positives (precision) without losing too many true positives (recall).\n\nIt is up to you if you use training soundscapes for validation (since they represent the hidden test set) or if you use annotated segments for training (to cope with the shift in acoustic domains). But be aware: Training with soundscape data for a few species might introduce unwanted biases when overfitting to one recording site.","metadata":{}},{"cell_type":"code","source":"train","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.844285Z","iopub.execute_input":"2021-05-24T07:32:38.844682Z","iopub.status.idle":"2021-05-24T07:32:38.890924Z","shell.execute_reply.started":"2021-05-24T07:32:38.844651Z","shell.execute_reply":"2021-05-24T07:32:38.889647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"Of {} species {} were observed within sites at the same time of year\".format(train[\"primary_label\"].nunique(), train[train[\"right_place_time\"]][\"primary_label\"].nunique()))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.894090Z","iopub.execute_input":"2021-05-24T07:32:38.894409Z","iopub.status.idle":"2021-05-24T07:32:38.914626Z","shell.execute_reply.started":"2021-05-24T07:32:38.894377Z","shell.execute_reply":"2021-05-24T07:32:38.913397Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_of_test_site_birds = train[train[\"right_place_time\"]][\"primary_label\"].unique()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.915790Z","iopub.execute_input":"2021-05-24T07:32:38.916324Z","iopub.status.idle":"2021-05-24T07:32:38.925093Z","shell.execute_reply.started":"2021-05-24T07:32:38.916285Z","shell.execute_reply":"2021-05-24T07:32:38.923905Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"list_of_test_site_birds, len(list_of_test_site_birds)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.926561Z","iopub.execute_input":"2021-05-24T07:32:38.926912Z","iopub.status.idle":"2021-05-24T07:32:38.946348Z","shell.execute_reply.started":"2021-05-24T07:32:38.926879Z","shell.execute_reply":"2021-05-24T07:32:38.945561Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train.loc[train['primary_label'].isin(list_of_test_site_birds)]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:38.947612Z","iopub.execute_input":"2021-05-24T07:32:38.948085Z","iopub.status.idle":"2021-05-24T07:32:39.007428Z","shell.execute_reply.started":"2021-05-24T07:32:38.948047Z","shell.execute_reply":"2021-05-24T07:32:39.006569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered = train.loc[train['primary_label'].isin(list_of_test_site_birds)]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.008767Z","iopub.execute_input":"2021-05-24T07:32:39.009067Z","iopub.status.idle":"2021-05-24T07:32:39.026988Z","shell.execute_reply.started":"2021-05-24T07:32:39.009036Z","shell.execute_reply":"2021-05-24T07:32:39.026035Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.028461Z","iopub.execute_input":"2021-05-24T07:32:39.028846Z","iopub.status.idle":"2021-05-24T07:32:39.057096Z","shell.execute_reply.started":"2021-05-24T07:32:39.028811Z","shell.execute_reply":"2021-05-24T07:32:39.055784Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered[\"primary_label\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.058583Z","iopub.execute_input":"2021-05-24T07:32:39.058921Z","iopub.status.idle":"2021-05-24T07:32:39.080448Z","shell.execute_reply.started":"2021-05-24T07:32:39.058891Z","shell.execute_reply":"2021-05-24T07:32:39.079237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered[train_filtered.rating.isin([0, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])][\"primary_label\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.082077Z","iopub.execute_input":"2021-05-24T07:32:39.082438Z","iopub.status.idle":"2021-05-24T07:32:39.115037Z","shell.execute_reply.started":"2021-05-24T07:32:39.082406Z","shell.execute_reply":"2021-05-24T07:32:39.114056Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered = train_filtered[train_filtered.rating.isin([0, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.116577Z","iopub.execute_input":"2021-05-24T07:32:39.117003Z","iopub.status.idle":"2021-05-24T07:32:39.132248Z","shell.execute_reply.started":"2021-05-24T07:32:39.116960Z","shell.execute_reply":"2021-05-24T07:32:39.131047Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist_data = train_filtered['rating'].values.tolist()\nfig = go.Figure(data=[go.Histogram(x=hist_data)], \n                layout=go.Layout(margin=go.layout.Margin(l=0, r=0, b=10, t=50)))\nfig.update_layout(title='Number of recordings per rating')\n\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.133973Z","iopub.execute_input":"2021-05-24T07:32:39.134308Z","iopub.status.idle":"2021-05-24T07:32:39.589876Z","shell.execute_reply.started":"2021-05-24T07:32:39.134276Z","shell.execute_reply":"2021-05-24T07:32:39.588821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_bird = train_filtered.groupby(\"common_name\")[\"filename\"].count().reset_index().rename(columns = {\"filename\": \"recordings\"}).sort_values(\"recordings\")\n\nsource = ColumnDataSource(df_bird)\ntooltips = [\n    (\"Bird Species\", \"@common_name\"),\n    (\"Recordings\", \"@recordings\")\n]\n\nv = figure(plot_width = 1000, plot_height = 4000, y_range = df_bird.common_name.values, tooltips = tooltips, title = \"Count of Bird Species\")\nv.hbar(\"common_name\", right = \"recordings\", source = source, height = 0.75, color = \"steelblue\", alpha = 0.6)\n\nv.xaxis.axis_label = \"Count\"\nv.yaxis.axis_label = \"Species\"\n\nshow(v)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.591170Z","iopub.execute_input":"2021-05-24T07:32:39.591453Z","iopub.status.idle":"2021-05-24T07:32:39.651013Z","shell.execute_reply.started":"2021-05-24T07:32:39.591425Z","shell.execute_reply":"2021-05-24T07:32:39.649801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered[\"primary_label\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.652663Z","iopub.execute_input":"2021-05-24T07:32:39.653079Z","iopub.status.idle":"2021-05-24T07:32:39.671748Z","shell.execute_reply.started":"2021-05-24T07:32:39.653035Z","shell.execute_reply":"2021-05-24T07:32:39.670446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!nvidia-smi","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:39.675470Z","iopub.execute_input":"2021-05-24T07:32:39.675959Z","iopub.status.idle":"2021-05-24T07:32:40.412331Z","shell.execute_reply.started":"2021-05-24T07:32:39.675908Z","shell.execute_reply":"2021-05-24T07:32:40.411019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -q pysndfx SoundFile audiomentations pretrainedmodels efficientnet_pytorch resnest","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:40.414075Z","iopub.execute_input":"2021-05-24T07:32:40.414411Z","iopub.status.idle":"2021-05-24T07:32:55.658792Z","shell.execute_reply.started":"2021-05-24T07:32:40.414382Z","shell.execute_reply":"2021-05-24T07:32:55.657578Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport librosa as lb\nimport librosa.display as lbd\nimport soundfile as sf\nfrom  soundfile import SoundFile\nimport pandas as pd\nfrom  IPython.display import Audio\nfrom pathlib import Path\n\nimport torch\nfrom torch import nn, optim\nfrom  torch.utils.data import Dataset, DataLoader\n\nfrom resnest.torch import resnest50\n\nfrom matplotlib import pyplot as plt\n\nimport os, random, gc\nimport re, time, json\nfrom  ast import literal_eval\n\n\nfrom IPython.display import Audio\nfrom sklearn.metrics import label_ranking_average_precision_score\n\nfrom tqdm.notebook import tqdm\nimport joblib","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:55.660261Z","iopub.execute_input":"2021-05-24T07:32:55.660628Z","iopub.status.idle":"2021-05-24T07:32:56.749103Z","shell.execute_reply.started":"2021-05-24T07:32:55.660596Z","shell.execute_reply":"2021-05-24T07:32:56.748231Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from efficientnet_pytorch import EfficientNet\nimport pretrainedmodels\nimport resnest.torch as resnest_torch","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:56.750130Z","iopub.execute_input":"2021-05-24T07:32:56.750583Z","iopub.status.idle":"2021-05-24T07:32:58.199113Z","shell.execute_reply.started":"2021-05-24T07:32:56.750542Z","shell.execute_reply":"2021-05-24T07:32:58.198204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=42):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\nseed_everything()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.200207Z","iopub.execute_input":"2021-05-24T07:32:58.200672Z","iopub.status.idle":"2021-05-24T07:32:58.209933Z","shell.execute_reply.started":"2021-05-24T07:32:58.200628Z","shell.execute_reply":"2021-05-24T07:32:58.208609Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_CLASSES = 273\nSR = 32_000\nDURATION = 7\n\nMAX_READ_SAMPLES = 7 # Each record will have 10 melspecs at most, you can increase this on Colab with High Memory Enabled\nDATA_ROOT = Path(\"../input/birdclef-2021\")\nMEL_PATHS = sorted(Path(\"../input\").glob(\"kkiller-birdclef-mels-computer-d7-part?/rich_train_metadata.csv\"))\nTRAIN_LABEL_PATHS = sorted(Path(\"../input\").glob(\"kkiller-birdclef-mels-computer-d7-part?/LABEL_IDS.json\"))\n\nMODEL_ROOT = Path(\".\")","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.211358Z","iopub.execute_input":"2021-05-24T07:32:58.211747Z","iopub.status.idle":"2021-05-24T07:32:58.239193Z","shell.execute_reply.started":"2021-05-24T07:32:58.211716Z","shell.execute_reply":"2021-05-24T07:32:58.238020Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MEL_PATHS, TRAIN_LABEL_PATHS","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.240563Z","iopub.execute_input":"2021-05-24T07:32:58.240864Z","iopub.status.idle":"2021-05-24T07:32:58.247281Z","shell.execute_reply.started":"2021-05-24T07:32:58.240834Z","shell.execute_reply":"2021-05-24T07:32:58.246113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_BATCH_SIZE = 50\nTRAIN_NUM_WORKERS = 2\n\nVAL_BATCH_SIZE = 64\nVAL_NUM_WORKERS = 2\n\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nprint(\"Device:\", DEVICE)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.248815Z","iopub.execute_input":"2021-05-24T07:32:58.249167Z","iopub.status.idle":"2021-05-24T07:32:58.262417Z","shell.execute_reply.started":"2021-05-24T07:32:58.249136Z","shell.execute_reply":"2021-05-24T07:32:58.261596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"temp = pd.read_csv(str('../input/kkiller-birdclef-mels-computer-d7-part1/rich_train_metadata.csv'), index_col=0)\ntemp.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.263366Z","iopub.execute_input":"2021-05-24T07:32:58.263654Z","iopub.status.idle":"2021-05-24T07:32:58.493300Z","shell.execute_reply.started":"2021-05-24T07:32:58.263626Z","shell.execute_reply":"2021-05-24T07:32:58.492436Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_df(mel_paths=MEL_PATHS, train_label_paths=TRAIN_LABEL_PATHS):\n  df = None\n  LABEL_IDS = {}\n    \n  for file_path in mel_paths:\n    temp = pd.read_csv(str(file_path), index_col=0)\n    temp[\"impath\"] = temp.apply(lambda row: file_path.parent/\"audio_images/{}/{}.npy\".format(row.primary_label, row.filename), axis=1) \n    df = temp if df is None else df.append(temp)\n    \n  df[\"secondary_labels\"] = df[\"secondary_labels\"].apply(literal_eval)\n\n  for file_path in train_label_paths:\n    with open(str(file_path)) as f:\n      LABEL_IDS.update(json.load(f))\n\n  return LABEL_IDS, df","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.495115Z","iopub.execute_input":"2021-05-24T07:32:58.495570Z","iopub.status.idle":"2021-05-24T07:32:58.503988Z","shell.execute_reply.started":"2021-05-24T07:32:58.495501Z","shell.execute_reply":"2021-05-24T07:32:58.502776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_IDS, df = get_df()\n\nprint(df.shape)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:32:58.505126Z","iopub.execute_input":"2021-05-24T07:32:58.505397Z","iopub.status.idle":"2021-05-24T07:33:02.608358Z","shell.execute_reply.started":"2021-05-24T07:32:58.505370Z","shell.execute_reply":"2021-05-24T07:33:02.607400Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:33:02.609642Z","iopub.execute_input":"2021-05-24T07:33:02.609924Z","iopub.status.idle":"2021-05-24T07:33:02.766459Z","shell.execute_reply.started":"2021-05-24T07:33:02.609897Z","shell.execute_reply":"2021-05-24T07:33:02.763308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_filtered","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:33:02.767998Z","iopub.execute_input":"2021-05-24T07:33:02.768302Z","iopub.status.idle":"2021-05-24T07:33:02.810114Z","shell.execute_reply.started":"2021-05-24T07:33:02.768274Z","shell.execute_reply":"2021-05-24T07:33:02.808957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create some time features\n\ndf['year'] = df['date'].apply(lambda x: x.split('-')[0]).astype(int)\ndf['month'] = df['date'].apply(lambda x: x.split('-')[1]).astype(int)\ndf['day_of_month'] = df['date'].apply(lambda x: x.split('-')[2]).astype(int)\ndf[\"hour\"] = pd.to_numeric(df.time.str.split(\":\", expand = True)[0], errors = \"coerce\")\n\ndf[\"year\"][df[\"year\"] == 0] = 2015\ndf[\"year\"][df[\"year\"] == 199] = 1990\ndf[\"year\"][df[\"year\"] == 201] = 2010\ndf[\"year\"][df[\"year\"] == 202] = 2020\ndf[\"year\"][df[\"year\"] == 2104] = 2014\n\ndf[\"month\"][df[\"month\"] == 0] = 6\ndf[\"day_of_month\"][df[\"day_of_month\"] == 0] = 16\n#Recreate train[\"date\"] with imputed values\ndf['date'] = pd.to_datetime(pd.DataFrame({'year':df['year'],\n                             'month':df['month'],\n                             'day':df['day_of_month']}))\n","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:33:02.811624Z","iopub.execute_input":"2021-05-24T07:33:02.811931Z","iopub.status.idle":"2021-05-24T07:33:03.191085Z","shell.execute_reply.started":"2021-05-24T07:33:02.811902Z","shell.execute_reply":"2021-05-24T07:33:03.190156Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"right_place_time\"] = df.progress_apply(lambda r: right_place_time(r['latitude'], r['longitude'], r[\"month\"]), axis=1)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:33:03.192718Z","iopub.execute_input":"2021-05-24T07:33:03.193455Z","iopub.status.idle":"2021-05-24T07:34:34.642149Z","shell.execute_reply.started":"2021-05-24T07:33:03.193405Z","shell.execute_reply":"2021-05-24T07:34:34.641076Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df[\"right_place_time\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:34.643831Z","iopub.execute_input":"2021-05-24T07:34:34.644172Z","iopub.status.idle":"2021-05-24T07:34:34.655064Z","shell.execute_reply.started":"2021-05-24T07:34:34.644140Z","shell.execute_reply":"2021-05-24T07:34:34.654137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered = df.loc[df['primary_label'].isin(list_of_test_site_birds)]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:34.656549Z","iopub.execute_input":"2021-05-24T07:34:34.656969Z","iopub.status.idle":"2021-05-24T07:34:34.677902Z","shell.execute_reply.started":"2021-05-24T07:34:34.656926Z","shell.execute_reply":"2021-05-24T07:34:34.676635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered[\"primary_label\"].nunique()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:34.679583Z","iopub.execute_input":"2021-05-24T07:34:34.680288Z","iopub.status.idle":"2021-05-24T07:34:34.696295Z","shell.execute_reply.started":"2021-05-24T07:34:34.680236Z","shell.execute_reply":"2021-05-24T07:34:34.695202Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered = df_filtered[df_filtered.rating.isin([0, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0])]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:34.698247Z","iopub.execute_input":"2021-05-24T07:34:34.698706Z","iopub.status.idle":"2021-05-24T07:34:34.721631Z","shell.execute_reply.started":"2021-05-24T07:34:34.698661Z","shell.execute_reply":"2021-05-24T07:34:34.720425Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist_data = df_filtered['rating'].values.tolist()\nfig = go.Figure(data=[go.Histogram(x=hist_data)], \n                layout=go.Layout(margin=go.layout.Margin(l=0, r=0, b=10, t=50)))\nfig.update_layout(title='Number of recordings per rating')\n\nfig.show()\n","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:34.724308Z","iopub.execute_input":"2021-05-24T07:34:34.724702Z","iopub.status.idle":"2021-05-24T07:34:35.181184Z","shell.execute_reply.started":"2021-05-24T07:34:34.724656Z","shell.execute_reply":"2021-05-24T07:34:35.179988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_bird = df_filtered.groupby(\"common_name\")[\"filename\"].count().reset_index().rename(columns = {\"filename\": \"recordings\"}).sort_values(\"recordings\")\n\nsource = ColumnDataSource(df_bird)\ntooltips = [\n    (\"Bird Species\", \"@common_name\"),\n    (\"Recordings\", \"@recordings\")\n]\n\nv = figure(plot_width = 1000, plot_height = 4000, y_range = df_bird.common_name.values, tooltips = tooltips, title = \"Count of Bird Species\")\nv.hbar(\"common_name\", right = \"recordings\", source = source, height = 0.75, color = \"steelblue\", alpha = 0.6)\n\nv.xaxis.axis_label = \"Count\"\nv.yaxis.axis_label = \"Species\"\n\nshow(v)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.182941Z","iopub.execute_input":"2021-05-24T07:34:35.183332Z","iopub.status.idle":"2021-05-24T07:34:35.243937Z","shell.execute_reply.started":"2021-05-24T07:34:35.183294Z","shell.execute_reply":"2021-05-24T07:34:35.242974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_IDS = {label: label_id for label_id,label in enumerate(sorted(df_filtered[\"primary_label\"].unique()))}\nINV_LABEL_CODE = {val: key for key,val in LABEL_IDS.items()}","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.245668Z","iopub.execute_input":"2021-05-24T07:34:35.246074Z","iopub.status.idle":"2021-05-24T07:34:35.255464Z","shell.execute_reply.started":"2021-05-24T07:34:35.246022Z","shell.execute_reply":"2021-05-24T07:34:35.254162Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_IDS","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.257147Z","iopub.execute_input":"2021-05-24T07:34:35.257572Z","iopub.status.idle":"2021-05-24T07:34:35.280105Z","shell.execute_reply.started":"2021-05-24T07:34:35.257511Z","shell.execute_reply":"2021-05-24T07:34:35.279163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_IDS['acafly']","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.281638Z","iopub.execute_input":"2021-05-24T07:34:35.282050Z","iopub.status.idle":"2021-05-24T07:34:35.294737Z","shell.execute_reply.started":"2021-05-24T07:34:35.282008Z","shell.execute_reply":"2021-05-24T07:34:35.293658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc\ndel [[df, train, train_filtered, df_bird]]\ngc.collect()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.296388Z","iopub.execute_input":"2021-05-24T07:34:35.296847Z","iopub.status.idle":"2021-05-24T07:34:35.501141Z","shell.execute_reply.started":"2021-05-24T07:34:35.296801Z","shell.execute_reply":"2021-05-24T07:34:35.499738Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered[\"label_id\"] = df_filtered['primary_label'].map(LABEL_IDS)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.502900Z","iopub.execute_input":"2021-05-24T07:34:35.503412Z","iopub.status.idle":"2021-05-24T07:34:35.519587Z","shell.execute_reply.started":"2021-05-24T07:34:35.503368Z","shell.execute_reply":"2021-05-24T07:34:35.518674Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered[\"label_id\"].min(), df_filtered[\"label_id\"].max()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.520903Z","iopub.execute_input":"2021-05-24T07:34:35.521202Z","iopub.status.idle":"2021-05-24T07:34:35.527896Z","shell.execute_reply.started":"2021-05-24T07:34:35.521174Z","shell.execute_reply":"2021-05-24T07:34:35.526862Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered[[\"label_id\",\"primary_label\"]]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.529074Z","iopub.execute_input":"2021-05-24T07:34:35.529372Z","iopub.status.idle":"2021-05-24T07:34:35.553025Z","shell.execute_reply.started":"2021-05-24T07:34:35.529344Z","shell.execute_reply":"2021-05-24T07:34:35.551733Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered.reset_index(drop=True, inplace=True)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.554436Z","iopub.execute_input":"2021-05-24T07:34:35.554928Z","iopub.status.idle":"2021-05-24T07:34:35.566412Z","shell.execute_reply.started":"2021-05-24T07:34:35.554879Z","shell.execute_reply":"2021-05-24T07:34:35.565412Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.569979Z","iopub.execute_input":"2021-05-24T07:34:35.570473Z","iopub.status.idle":"2021-05-24T07:34:35.613111Z","shell.execute_reply.started":"2021-05-24T07:34:35.570422Z","shell.execute_reply":"2021-05-24T07:34:35.612063Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_filtered[\"fold\"].value_counts()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.614839Z","iopub.execute_input":"2021-05-24T07:34:35.615267Z","iopub.status.idle":"2021-05-24T07:34:35.624960Z","shell.execute_reply.started":"2021-05-24T07:34:35.615220Z","shell.execute_reply":"2021-05-24T07:34:35.623786Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_model(name, num_classes=NUM_CLASSES):\n    \"\"\"\n    Loads a pretrained model. \n    Supports ResNest, ResNext-wsl, EfficientNet, ResNext and ResNet.\n\n    Arguments:\n        name {str} -- Name of the model to load\n\n    Keyword Arguments:\n        num_classes {int} -- Number of classes to use (default: {1})\n\n    Returns:\n        torch model -- Pretrained model\n    \"\"\"\n    if \"resnest\" in name:\n        #model = getattr(resnest_torch, name)(pretrained=True)\n        pretrained_weights = torch.load('../input/timm-resnest-weights/resnest50-528c19ca.pth')\n        model = getattr(resnest_torch, name)(pretrained=False)\n        model.load_state_dict(pretrained_weights)\n    elif \"wsl\" in name:\n        model = torch.hub.load(\"facebookresearch/WSL-Images\", name)\n    elif name.startswith(\"resnext\") or  name.startswith(\"resnet\"):\n        model = torch.hub.load(\"pytorch/vision:v0.6.0\", name, pretrained=True)\n    elif name.startswith(\"tf_efficientnet_b\"):\n        model = getattr(timm.models.efficientnet, name)(pretrained=True)\n    elif \"efficientnet-b\" in name:\n        model = EfficientNet.from_pretrained(name)\n    else:\n        model = pretrainedmodels.__dict__[name](pretrained='imagenet')\n\n    if hasattr(model, \"fc\"):\n        nb_ft = model.fc.in_features\n        model.fc = nn.Linear(nb_ft, num_classes)\n    elif hasattr(model, \"_fc\"):\n        nb_ft = model._fc.in_features\n        model._fc = nn.Linear(nb_ft, num_classes)\n    elif hasattr(model, \"classifier\"):\n        nb_ft = model.classifier.in_features\n        model.classifier = nn.Linear(nb_ft, num_classes)\n    elif hasattr(model, \"last_linear\"):\n        nb_ft = model.last_linear.in_features\n        model.last_linear = nn.Linear(nb_ft, num_classes)\n\n    return model","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.627225Z","iopub.execute_input":"2021-05-24T07:34:35.627676Z","iopub.status.idle":"2021-05-24T07:34:35.641480Z","shell.execute_reply.started":"2021-05-24T07:34:35.627625Z","shell.execute_reply":"2021-05-24T07:34:35.640358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"np.load(str(\"../input/kkiller-birdclef-mels-computer-d7-part1/audio_images/acafly/XC109605.ogg.npy\"))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.642832Z","iopub.execute_input":"2021-05-24T07:34:35.643154Z","iopub.status.idle":"2021-05-24T07:34:35.684969Z","shell.execute_reply.started":"2021-05-24T07:34:35.643123Z","shell.execute_reply":"2021-05-24T07:34:35.684145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(np.load(str(\"../input/kkiller-birdclef-mels-computer-d7-part1/audio_images/acafly/XC109605.ogg.npy\")))","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.686169Z","iopub.execute_input":"2021-05-24T07:34:35.686440Z","iopub.status.idle":"2021-05-24T07:34:35.692424Z","shell.execute_reply.started":"2021-05-24T07:34:35.686415Z","shell.execute_reply":"2021-05-24T07:34:35.691624Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_data(df):\n    def load_row(row):\n        # impath = TRAIN_IMAGES_ROOT/f\"{row.primary_label}/{row.filename}.npy\"\n        return row.filename, np.load(str(row.impath))[:MAX_READ_SAMPLES]\n    pool = joblib.Parallel(4)\n    mapper = joblib.delayed(load_row)\n    tasks = [mapper(row) for row in df.itertuples(False)]\n    res = pool(tqdm(tasks))\n    res = dict(res)\n    return res","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.693895Z","iopub.execute_input":"2021-05-24T07:34:35.694189Z","iopub.status.idle":"2021-05-24T07:34:35.705873Z","shell.execute_reply.started":"2021-05-24T07:34:35.694153Z","shell.execute_reply":"2021-05-24T07:34:35.704824Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Save a copy of df_filtered and use it for Inference\ndf_filtered.to_csv(\"train_metadata_filtered_rich.csv\", index=False)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T07:34:35.707165Z","iopub.execute_input":"2021-05-24T07:34:35.707440Z","iopub.status.idle":"2021-05-24T07:34:37.276006Z","shell.execute_reply.started":"2021-05-24T07:34:35.707413Z","shell.execute_reply":"2021-05-24T07:34:37.275210Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# We cache the train set to reduce training time\n\naudio_image_store = load_data(df_filtered)\nlen(audio_image_store)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:16:53.074022Z","iopub.execute_input":"2021-05-24T02:16:53.074362Z","iopub.status.idle":"2021-05-24T02:19:04.541397Z","shell.execute_reply.started":"2021-05-24T02:16:53.07433Z","shell.execute_reply":"2021-05-24T02:19:04.539346Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"shape:\", next(iter(audio_image_store.values())).shape)\nlbd.specshow(next(iter(audio_image_store.values()))[0])","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:17.615049Z","iopub.execute_input":"2021-05-24T02:19:17.616783Z","iopub.status.idle":"2021-05-24T02:19:17.713903Z","shell.execute_reply.started":"2021-05-24T02:19:17.616731Z","shell.execute_reply":"2021-05-24T02:19:17.712835Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(\"shape:\", next(iter(audio_image_store.values())).shape)\nlbd.specshow(next(iter(audio_image_store.values()))[1])","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:19.127183Z","iopub.execute_input":"2021-05-24T02:19:19.127524Z","iopub.status.idle":"2021-05-24T02:19:19.210222Z","shell.execute_reply.started":"2021-05-24T02:19:19.127492Z","shell.execute_reply":"2021-05-24T02:19:19.2092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class BirdClefDataset(Dataset):\n\n    def __init__(self, audio_image_store, meta, sr=SR, is_train=True, num_classes=NUM_CLASSES, duration=DURATION):\n        \n        self.audio_image_store = audio_image_store\n        self.meta = meta.copy().reset_index(drop=True)\n        self.sr = sr\n        self.is_train = is_train\n        self.num_classes = num_classes\n        self.duration = duration\n        self.audio_length = self.duration*self.sr\n    \n    @staticmethod\n    def normalize(image):\n        image = image.astype(\"float32\", copy=False) / 255.0\n        image = np.stack([image, image, image])\n        return image\n\n    def __len__(self):\n        return len(self.meta)\n    \n    def __getitem__(self, idx):\n        row = self.meta.iloc[idx]\n        image = self.audio_image_store[row.filename]\n\n        image = image[np.random.choice(len(image))]\n        image = self.normalize(image)\n        \n        \n        t = np.zeros(self.num_classes, dtype=np.float32) + 0.0025 # Label smoothing\n        t[row.label_id] = 0.995\n        \n        return image, t","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:22.100745Z","iopub.execute_input":"2021-05-24T02:19:22.101073Z","iopub.status.idle":"2021-05-24T02:19:22.110958Z","shell.execute_reply.started":"2021-05-24T02:19:22.101037Z","shell.execute_reply":"2021-05-24T02:19:22.110092Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = BirdClefDataset(audio_image_store, meta=df_filtered, sr=SR, duration=DURATION, is_train=True)\nlen(ds)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:24.510065Z","iopub.execute_input":"2021-05-24T02:19:24.51051Z","iopub.status.idle":"2021-05-24T02:19:24.556353Z","shell.execute_reply.started":"2021-05-24T02:19:24.510471Z","shell.execute_reply":"2021-05-24T02:19:24.555287Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:25.589826Z","iopub.execute_input":"2021-05-24T02:19:25.590153Z","iopub.status.idle":"2021-05-24T02:19:25.596288Z","shell.execute_reply.started":"2021-05-24T02:19:25.590122Z","shell.execute_reply":"2021-05-24T02:19:25.595169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x, y = ds[np.random.choice(len(ds))]\n# x, y = ds[0]\nx.shape, y.shape, np.where(y >= 0.5)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:26.189423Z","iopub.execute_input":"2021-05-24T02:19:26.18978Z","iopub.status.idle":"2021-05-24T02:19:26.204308Z","shell.execute_reply.started":"2021-05-24T02:19:26.189751Z","shell.execute_reply":"2021-05-24T02:19:26.203232Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y[:5]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:27.828337Z","iopub.execute_input":"2021-05-24T02:19:27.828662Z","iopub.status.idle":"2021-05-24T02:19:27.836183Z","shell.execute_reply.started":"2021-05-24T02:19:27.828634Z","shell.execute_reply":"2021-05-24T02:19:27.835001Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"lbd.specshow(x[0])","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:30.196374Z","iopub.execute_input":"2021-05-24T02:19:30.196684Z","iopub.status.idle":"2021-05-24T02:19:30.289726Z","shell.execute_reply.started":"2021-05-24T02:19:30.196653Z","shell.execute_reply":"2021-05-24T02:19:30.289019Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_step( xb, yb, net, criterion, optimizer, scheduler=None):\n  xb, yb = xb.to(DEVICE), yb.to(DEVICE)\n        \n  optimizer.zero_grad()\n  o = net(xb)\n  loss = criterion(o, yb)\n  loss.backward()\n  optimizer.step()\n  \n  with torch.no_grad():\n      l = loss.item()\n\n      o = o.sigmoid()\n      yb = (yb > 0.5 )*1.0\n      lrap = label_ranking_average_precision_score(yb.cpu().numpy(), o.cpu().numpy())\n\n      o = (o > 0.5)*1.0\n\n      prec = (o*yb).sum()/(1e-6 + o.sum())\n      rec = (o*yb).sum()/(1e-6 + yb.sum())\n      f1 = 2*prec*rec/(1e-6+prec+rec)\n\n  if  scheduler is not None:\n    scheduler.step()\n\n  return l, lrap, f1.item(), rec.item(), prec.item()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:31.029517Z","iopub.execute_input":"2021-05-24T02:19:31.029937Z","iopub.status.idle":"2021-05-24T02:19:31.037816Z","shell.execute_reply.started":"2021-05-24T02:19:31.029891Z","shell.execute_reply":"2021-05-24T02:19:31.036907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@torch.no_grad()\ndef evaluate(net, criterion, val_laoder):\n    net.eval()\n\n    os, y = [], []\n    val_laoder = tqdm(val_laoder, leave = False, total=len(val_laoder))\n\n    for icount, (xb, yb) in  enumerate(val_laoder):\n\n        y.append(yb.to(DEVICE))\n\n        xb = xb.to(DEVICE)\n        o = net(xb)\n\n        os.append(o)\n\n    y = torch.cat(y)\n    o = torch.cat(os)\n\n    l = criterion(o, y).item()\n    \n    o = o.sigmoid()\n    y = (y > 0.5)*1.0\n\n    lrap = label_ranking_average_precision_score(y.cpu().numpy(), o.cpu().numpy())\n\n    o = (o > 0.5)*1.0\n\n    prec = ((o*y).sum()/(1e-6 + o.sum())).item()\n    rec = ((o*y).sum()/(1e-6 + y.sum())).item()\n    f1 = 2*prec*rec/(1e-6+prec+rec)\n\n    return l, lrap, f1, rec, prec, \n","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:32.054991Z","iopub.execute_input":"2021-05-24T02:19:32.055352Z","iopub.status.idle":"2021-05-24T02:19:32.065615Z","shell.execute_reply.started":"2021-05-24T02:19:32.055316Z","shell.execute_reply":"2021-05-24T02:19:32.064502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_epoch(net, criterion, optimizer, scheduler, train_laoder, val_laoder):\n  net.train()\n  l, lrap, prec, rec, f1, icount = 0.,0.,0.,0., 0., 0\n  train_laoder = tqdm(train_laoder, leave = False)\n  epoch_bar = train_laoder\n  \n  for (xb, yb) in  epoch_bar:\n      # epoch_bar.set_description(\"----|----|----|----|---->\")\n      _l, _lrap, _f1, _rec, _prec = one_step(xb, yb, net, criterion, optimizer)\n      l += _l\n      lrap += _lrap\n      f1 += _f1\n      rec += _rec\n      prec += _prec\n\n      icount += 1\n        \n      if hasattr(epoch_bar, \"set_postfix\") and not icount%10:\n          epoch_bar.set_postfix(\n            loss=\"{:.6f}\".format(l/icount),\n            lrap=\"{:.3f}\".format(lrap/icount),\n            prec=\"{:.3f}\".format(prec/icount),\n            rec=\"{:.3f}\".format(rec/icount),\n            f1=\"{:.3f}\".format(f1/icount),\n          )\n  \n  scheduler.step()\n\n  l /= icount\n  lrap /= icount\n  f1 /= icount\n  rec /= icount\n  prec /= icount\n  \n  l_val, lrap_val, f1_val, rec_val, prec_val = evaluate(net, criterion, val_laoder)\n  \n  return (l, l_val), (lrap, lrap_val), (f1, f1_val), (rec, rec_val), (prec, prec_val)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:33.34902Z","iopub.execute_input":"2021-05-24T02:19:33.349351Z","iopub.status.idle":"2021-05-24T02:19:33.358787Z","shell.execute_reply.started":"2021-05-24T02:19:33.349318Z","shell.execute_reply":"2021-05-24T02:19:33.357908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AutoSave:\n  def __init__(self, top_k=2, metric=\"f1\", mode=\"min\", root=None, name=\"ckpt\"):\n    self.top_k = top_k\n    self.logs = []\n    self.metric = metric\n    self.mode = mode\n    self.root = Path(root or MODEL_ROOT)\n    assert self.root.exists()\n    self.name = name\n\n    self.top_models = []\n    self.top_metrics = []\n\n  def log(self, model, metrics):\n    metric = metrics[self.metric]\n    rank = self.rank(metric)\n\n    self.top_metrics.insert(rank+1, metric)\n    if len(self.top_metrics) > self.top_k:\n      self.top_metrics.pop(0)\n\n    self.logs.append(metrics)\n    self.save(model, metric, rank, metrics[\"epoch\"])\n\n\n  def save(self, model, metric, rank, epoch):\n    t = time.strftime(\"%Y%m%d%H%M%S\")\n    name = \"{}_epoch_{:02d}_{}_{:.04f}_{}\".format(self.name, epoch, self.metric, metric, t)\n    name = re.sub(r\"[^\\w_-]\", \"\", name) + \".pth\"\n    path = self.root.joinpath(name)\n\n    old_model = None\n    self.top_models.insert(rank+1, name)\n    if len(self.top_models) > self.top_k:\n      old_model = self.root.joinpath(self.top_models[0])\n      self.top_models.pop(0)      \n\n    torch.save(model.state_dict(), path.as_posix())\n\n    if old_model is not None:\n      old_model.unlink()\n\n    self.to_json()\n\n\n  def rank(self, val):\n    r = -1\n    for top_val in self.top_metrics:\n      if val <= top_val:\n        return r\n      r += 1\n\n    return r\n  \n  def to_json(self):\n    # t = time.strftime(\"%Y%m%d%H%M%S\")\n    name = \"{}_logs\".format(self.name)\n    name = re.sub(r\"[^\\w_-]\", \"\", name) + \".json\"\n    path = self.root.joinpath(name)\n\n    with path.open(\"w\") as f:\n      json.dump(self.logs, f, indent=2)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:34.168533Z","iopub.execute_input":"2021-05-24T02:19:34.168844Z","iopub.status.idle":"2021-05-24T02:19:34.183529Z","shell.execute_reply.started":"2021-05-24T02:19:34.168815Z","shell.execute_reply":"2021-05-24T02:19:34.181909Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_fold(model_name, fold, train_set, val_set, epochs=20, save=True, save_root=None):\n\n  save_root = Path(save_root) or MODEL_ROOT\n\n  saver = AutoSave(root=save_root, name=f\"birdclef_{model_name}_fold{fold}\", metric=\"f1_val\")\n\n  net = get_model(model_name).to(DEVICE)\n\n  criterion = nn.BCEWithLogitsLoss()\n\n  optimizer = optim.Adam(net.parameters(), lr=8e-4)\n  scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, eta_min=1e-5, T_max=epochs)\n\n  train_data = BirdClefDataset(audio_image_store, meta=df_filtered.iloc[train_set].reset_index(drop=True),\n                           sr=SR, duration=DURATION, is_train=True)\n  train_laoder = DataLoader(train_data, batch_size=TRAIN_BATCH_SIZE, num_workers=TRAIN_NUM_WORKERS, shuffle=True, pin_memory=True)\n\n  val_data = BirdClefDataset(audio_image_store, meta=df_filtered.iloc[val_set].reset_index(drop=True),  sr=SR, duration=DURATION, is_train=False)\n  val_laoder = DataLoader(val_data, batch_size=VAL_BATCH_SIZE, num_workers=VAL_NUM_WORKERS, shuffle=False)\n\n  epochs_bar = tqdm(list(range(epochs)), leave=False)\n  for epoch  in epochs_bar:\n    epochs_bar.set_description(f\"--> [EPOCH {epoch:02d}]\")\n    net.train()\n\n    (l, l_val), (lrap, lrap_val), (f1, f1_val), (rec, rec_val), (prec, prec_val) = one_epoch(\n        net=net,\n        criterion=criterion,\n        optimizer=optimizer,\n        scheduler=scheduler,\n        train_laoder=train_laoder,\n        val_laoder=val_laoder,\n      )\n\n    epochs_bar.set_postfix(\n    loss=\"({:.6f}, {:.6f})\".format(l, l_val),\n    prec=\"({:.3f}, {:.3f})\".format(prec, prec_val),\n    rec=\"({:.3f}, {:.3f})\".format(rec, rec_val),\n    f1=\"({:.3f}, {:.3f})\".format(f1, f1_val),\n    lrap=\"({:.3f}, {:.3f})\".format(lrap, lrap_val),\n    )\n\n    print(\n        \"[{epoch:02d}] loss: {loss} lrap: {lrap} f1: {f1} rec: {rec} prec: {prec}\".format(\n            epoch=epoch,\n            loss=\"({:.6f}, {:.6f})\".format(l, l_val),\n            prec=\"({:.3f}, {:.3f})\".format(prec, prec_val),\n            rec=\"({:.3f}, {:.3f})\".format(rec, rec_val),\n            f1=\"({:.3f}, {:.3f})\".format(f1, f1_val),\n            lrap=\"({:.3f}, {:.3f})\".format(lrap, lrap_val),\n        )\n    )\n\n    if save:\n      metrics = {\n          \"loss\": l, \"lrap\": lrap, \"f1\": f1, \"rec\": rec, \"prec\": prec,\n          \"loss_val\": l_val, \"lrap_val\": lrap_val, \"f1_val\": f1_val, \"rec_val\": rec_val, \"prec_val\": prec_val,\n          \"epoch\": epoch,\n      }\n\n      saver.log(net, metrics)","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:34.995529Z","iopub.execute_input":"2021-05-24T02:19:34.995865Z","iopub.status.idle":"2021-05-24T02:19:35.010911Z","shell.execute_reply.started":"2021-05-24T02:19:34.995834Z","shell.execute_reply":"2021-05-24T02:19:35.009948Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def train(model_name, epochs=20, save=True, n_splits=5, seed=177, save_root=None, suffix=\"\", folds=None):\n  gc.collect()\n  torch.cuda.empty_cache()\n\n  save_root = save_root or MODEL_ROOT/f\"{model_name}{suffix}\"\n  save_root.mkdir(exist_ok=True, parents=True)\n\n  #pdb.set_trace()\n\n  fold_bar = tqdm(df_filtered.reset_index().groupby(\"fold\").index.apply(list).items(), total=df_filtered.fold.max()+1)\n  \n  for fold, val_set in fold_bar:\n      if folds and not fold in folds:\n        continue\n      \n      print(f\"\\n############################### [FOLD {fold}]\")\n      fold_bar.set_description(f\"[FOLD {fold}]\")\n      train_set = np.setdiff1d(df_filtered.index, val_set)\n        \n      one_fold(model_name, fold=fold, train_set=train_set , val_set=val_set , epochs=epochs, save=save, save_root=save_root)\n    \n      gc.collect()\n      torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:19:36.877677Z","iopub.execute_input":"2021-05-24T02:19:36.878001Z","iopub.status.idle":"2021-05-24T02:19:36.887977Z","shell.execute_reply.started":"2021-05-24T02:19:36.877969Z","shell.execute_reply":"2021-05-24T02:19:36.886959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MODEL_NAMES = [\n      \"efficientnet-b5\",\n]","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:23:23.657087Z","iopub.execute_input":"2021-05-24T02:23:23.657442Z","iopub.status.idle":"2021-05-24T02:23:23.661058Z","shell.execute_reply.started":"2021-05-24T02:23:23.657408Z","shell.execute_reply":"2021-05-24T02:23:23.660214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for model_name in MODEL_NAMES:\n  print(\"\\n\\n###########################################\", model_name.upper())\n  try:\n    train(model_name, epochs=20, suffix=f\"_sr{SR}_d{DURATION}_v1_v1\", folds=[0])\n  except Exception as e:\n    # print(f\"Error {model_name} : \\n{e}\")\n    raise ValueError() from  e","metadata":{"execution":{"iopub.status.busy":"2021-05-24T02:23:25.217674Z","iopub.execute_input":"2021-05-24T02:23:25.217993Z","iopub.status.idle":"2021-05-24T05:23:50.747249Z","shell.execute_reply.started":"2021-05-24T02:23:25.217961Z","shell.execute_reply":"2021-05-24T05:23:50.746275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}