{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport torch\nimport torchaudio\nfrom torch.utils.data import Dataset\nfrom torchvision.transforms import Resize\n\nimport numpy as np\nfrom scipy import signal\n\nimport matplotlib.pyplot as plt\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport os\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        if filename[-3:]!='ogg':\n            print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2022-03-16T05:56:29.258369Z","iopub.execute_input":"2022-03-16T05:56:29.258683Z","iopub.status.idle":"2022-03-16T05:56:34.894847Z","shell.execute_reply.started":"2022-03-16T05:56:29.258595Z","shell.execute_reply":"2022-03-16T05:56:34.893593Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_submission = pd.read_csv('/kaggle/input/birdclef-2022/sample_submission.csv')\n#scored_birds = pd.read_csv('/kaggle/input/birdclef-2022/scored_birds.json')\ntaxonomy = pd.read_csv('/kaggle/input/birdclef-2022/eBird_Taxonomy_v2021.csv')\ntest = pd.read_csv('/kaggle/input/birdclef-2022/test.csv')\ntrain_metadata = pd.read_csv('/kaggle/input/birdclef-2022/train_metadata.csv')","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:34.897489Z","iopub.execute_input":"2022-03-16T05:56:34.897844Z","iopub.status.idle":"2022-03-16T05:56:35.084437Z","shell.execute_reply.started":"2022-03-16T05:56:34.897795Z","shell.execute_reply":"2022-03-16T05:56:35.083705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata.head(5)","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:35.091395Z","iopub.execute_input":"2022-03-16T05:56:35.091748Z","iopub.status.idle":"2022-03-16T05:56:35.118689Z","shell.execute_reply.started":"2022-03-16T05:56:35.091707Z","shell.execute_reply":"2022-03-16T05:56:35.118113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Birds species in danger\n\nIf we suppose that the occurence of each bird species in this dataset is correlated to its extinction rate, we can get an idea of which species are endagered and which species are not. ","metadata":{}},{"cell_type":"code","source":"import plotly.express as px\nimport geopandas as gpd","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:35.119617Z","iopub.execute_input":"2022-03-16T05:56:35.120148Z","iopub.status.idle":"2022-03-16T05:56:36.890595Z","shell.execute_reply.started":"2022-03-16T05:56:35.120118Z","shell.execute_reply":"2022-03-16T05:56:36.889635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"geo_df = gpd.read_file(gpd.datasets.get_path('naturalearth_cities'))\n\n#px.set_mapbox_access_token(open(\".mapbox_token\").read())\nfig = px.scatter_geo(geo_df,\n                    lat=train_metadata['latitude'],\n                    lon=train_metadata['longitude'],\n                    color = train_metadata['primary_label'],\n                    hover_name=train_metadata['primary_label'])\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-10T21:14:07.278398Z","iopub.execute_input":"2022-03-10T21:14:07.278619Z","iopub.status.idle":"2022-03-10T21:14:09.059774Z","shell.execute_reply.started":"2022-03-10T21:14:07.278586Z","shell.execute_reply":"2022-03-10T21:14:09.05875Z"}}},{"cell_type":"code","source":"import seaborn as sns\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(20,10),dpi=400)\ncount = train_metadata['primary_label'].value_counts()\ncount[count.values>100].plot(kind='barh', title='birds not in danger of extinction')\nplt.figure(figsize=(20,20),dpi=400)\ncount[count.values<=100].plot(kind='barh', title='birds in danger of extinction')\n\n#count = count.plot(kind = 'barh')\n#sns.countplot(train_metadata['primary_label'])","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:36.891850Z","iopub.execute_input":"2022-03-16T05:56:36.892116Z","iopub.status.idle":"2022-03-16T05:56:43.725937Z","shell.execute_reply.started":"2022-03-16T05:56:36.892061Z","shell.execute_reply":"2022-03-16T05:56:43.725114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Time plot of a bird's chirp","metadata":{}},{"cell_type":"code","source":"# pick a random file and plot it\nfile_index = 290\n\nsound = r'/kaggle/input/birdclef-2022/train_audio/'+ train_metadata['filename'][file_index]\nwf, sr = torchaudio.load(sound)\nprint(wf.shape)\nwft = wf.t().numpy() # convert from tensor to numpy\nprint(wf.shape)\nprint('sample rate:', sr//1000, 'khz')\nplt.figure(figsize=(18,5))\nplt.plot(wft)","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:43.727468Z","iopub.execute_input":"2022-03-16T05:56:43.727733Z","iopub.status.idle":"2022-03-16T05:56:44.710833Z","shell.execute_reply.started":"2022-03-16T05:56:43.727700Z","shell.execute_reply":"2022-03-16T05:56:44.709964Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Mel Spectrogram with torchaudio","metadata":{"execution":{"iopub.status.busy":"2022-03-03T23:08:10.326039Z","iopub.execute_input":"2022-03-03T23:08:10.326361Z","iopub.status.idle":"2022-03-03T23:08:10.330645Z","shell.execute_reply.started":"2022-03-03T23:08:10.326321Z","shell.execute_reply":"2022-03-03T23:08:10.32978Z"}}},{"cell_type":"markdown","source":"To get the Mel spectrogram, we first apply MelSpectrogram transform from toraudio, then calculate the log2 value of the result to get values in db.","metadata":{}},{"cell_type":"code","source":"# Mel spectrom with torch\nspecgram = torchaudio.transforms.MelSpectrogram(n_fft=4096)(wf)\nspecgram = torchaudio.transforms.AmplitudeToDB()(specgram)\nplt.pcolormesh(specgram[0])","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:44.712341Z","iopub.execute_input":"2022-03-16T05:56:44.712577Z","iopub.status.idle":"2022-03-16T05:56:45.105147Z","shell.execute_reply.started":"2022-03-16T05:56:44.712550Z","shell.execute_reply":"2022-03-16T05:56:45.104309Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Mel spectrogram with Scipy","metadata":{}},{"cell_type":"code","source":"# Mel spectrom with scipy\ndef spectrogram(xs):\n    f, t, spec = signal.spectrogram(xs, fs=sr, nfft=256, window=('hann'))\n    wave_sxx_graph = np.log2(np.absolute(spec))\n    return f,t,wave_sxx_graph","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:45.106570Z","iopub.execute_input":"2022-03-16T05:56:45.107134Z","iopub.status.idle":"2022-03-16T05:56:45.113058Z","shell.execute_reply.started":"2022-03-16T05:56:45.107066Z","shell.execute_reply":"2022-03-16T05:56:45.112364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Calculate spectrogram using math\nt,f,wave_sxx_graph = spectrogram(wft[:,0])\nprint(wave_sxx_graph.shape)\nprint(t.shape)\nprint(f.shape)\n#plt.figure(0)\nplt.pcolormesh(f,t, wave_sxx_graph)\n#plt.figure(1)\n#plt.pcolormesh(t, f, spec[1,:])\n#plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:45.115839Z","iopub.execute_input":"2022-03-16T05:56:45.116442Z","iopub.status.idle":"2022-03-16T05:56:45.884561Z","shell.execute_reply.started":"2022-03-16T05:56:45.116401Z","shell.execute_reply":"2022-03-16T05:56:45.882898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Encode labels","metadata":{}},{"cell_type":"code","source":"global labels\nlabels = pd.Series(train_metadata['primary_label'].unique(),name='bird')\nlabels = labels.reset_index()\nnum=labels.index.size\ndisplay(labels)","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:57:20.166256Z","iopub.execute_input":"2022-03-16T05:57:20.167057Z","iopub.status.idle":"2022-03-16T05:57:20.181058Z","shell.execute_reply.started":"2022-03-16T05:57:20.167015Z","shell.execute_reply":"2022-03-16T05:57:20.180150Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from torch.nn.functional import one_hot\nlabels['onehot_code'] = one_hot(torch.Tensor(labels['index'].values).to(torch.int64), num_classes = num).numpy().tolist()","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:57:21.603907Z","iopub.execute_input":"2022-03-16T05:57:21.604750Z","iopub.status.idle":"2022-03-16T05:57:21.615967Z","shell.execute_reply.started":"2022-03-16T05:57:21.604707Z","shell.execute_reply":"2022-03-16T05:57:21.615113Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### labels.head(10)","metadata":{"execution":{"iopub.status.busy":"2022-03-15T21:18:26.568215Z","iopub.execute_input":"2022-03-15T21:18:26.569137Z","iopub.status.idle":"2022-03-15T21:18:26.592216Z","shell.execute_reply.started":"2022-03-15T21:18:26.569091Z","shell.execute_reply":"2022-03-15T21:18:26.591625Z"}}},{"cell_type":"markdown","source":"# DataLoader and transforms Pytorch","metadata":{"execution":{"iopub.status.busy":"2022-03-03T23:27:48.173772Z","iopub.execute_input":"2022-03-03T23:27:48.174108Z","iopub.status.idle":"2022-03-03T23:27:48.177967Z","shell.execute_reply.started":"2022-03-03T23:27:48.17407Z","shell.execute_reply":"2022-03-03T23:27:48.177027Z"}}},{"cell_type":"markdown","source":"This custom dataloader loads the salples by their index, then apply a transform function on each sample by computing its Mel spectrogram and then resize the Mel spectrum to a constant size of (128,128); This is done by the Resize function from TorchVision which down samples or interpolates the input depending on its shape.","metadata":{}},{"cell_type":"code","source":"annotation_file = r'/kaggle/input/birdclef-2022/train_metadata.csv'\nchirp_dir = r'/kaggle/input/birdclef-2022/train_audio'\nclass CustomChirpDataset(Dataset):\n    def __init__(self, annotations_file, chirp_dir, transform=None, target_transform=False):\n        self.metadata = pd.read_csv(annotations_file)\n        self.chirp_labels = self.metadata['filename']\n        self.chirp_dir = chirp_dir\n        self.transform = transform\n        self.target_transform = target_transform\n\n    def __len__(self):\n        return len(self.chirp_labels)\n\n    def __getitem__(self, idx):\n        chirp_path = os.path.join(self.chirp_dir, self.chirp_labels.iloc[idx])\n        chirp, sr = torchaudio.load(chirp_path)\n        label = self.chirp_labels.iloc[idx]\n        if self.transform:\n            spec = self.melspectrogram(chirp)\n        if self.target_transform:\n            label = self.encode_label(label)\n        return spec, label\n    def encode_label(self,label):\n        label,filename = os.path.split(label)\n        onehot_label = labels[labels['bird']==label]['onehot_code'].values[0]\n        return onehot_label\n    def melspectrogram(self,chirp):\n        spectrum = torchaudio.transforms.MelSpectrogram(n_fft = 1000, n_mels=128)(chirp)\n        spectrum = torchaudio.transforms.AmplitudeToDB()(spectrum)\n        spectrum = torch.unsqueeze(spectrum, dim=0)\n        # resize input to so all spectrograms have the same (128,128)\n        spectrum = Resize((128, 128))(spectrum)\n        return spectrum[0,0,:,:]","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:57:29.043215Z","iopub.execute_input":"2022-03-16T05:57:29.043644Z","iopub.status.idle":"2022-03-16T05:57:29.053117Z","shell.execute_reply.started":"2022-03-16T05:57:29.043614Z","shell.execute_reply":"2022-03-16T05:57:29.052386Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Test dataloader","metadata":{}},{"cell_type":"code","source":"# init dataset\ndataset = CustomChirpDataset(annotation_file, chirp_dir, transform=True, target_transform=True)\nfor j in [0,1000,2000,3000,4000,5000]:\n    #plt.subplot(1,6, j//1000 +1)\n    plt.figure(figsize = (18,6))\n    # select some chirp\n    chirp,label = dataset.__getitem__(j)\n    print(chirp.shape)\n    plt.pcolormesh(chirp)\n    \n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:57:35.178522Z","iopub.execute_input":"2022-03-16T05:57:35.178789Z","iopub.status.idle":"2022-03-16T05:57:37.235462Z","shell.execute_reply.started":"2022-03-16T05:57:35.178761Z","shell.execute_reply":"2022-03-16T05:57:37.234596Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2022-03-16T05:56:46.085272Z","iopub.status.idle":"2022-03-16T05:56:46.085765Z","shell.execute_reply.started":"2022-03-16T05:56:46.085592Z","shell.execute_reply":"2022-03-16T05:56:46.085615Z"},"trusted":true},"execution_count":null,"outputs":[]}]}