{"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":"#Alexandre HOMO et Mathis DA SILVA Master BMC\n\n# Introduction\n\n# L'objectif de ce projet est la classification de différentes espèces d'oiseaux en se basant sur leurs chants. \n# Il existe environ 10 000 espèces d'oiseaux. Les oiseaux sont d'excelents indicateurs du niveau de qualité d'un environnement.\n# Cependant,il est souvent plus simple d'entendre les oiseaux que de les observer directement. Le traitement des donneées à la \n# main est long et fastideux. C'est pourquoi le machine learning semble être une solution adaptée.","metadata":{"execution":{"iopub.status.busy":"2021-12-31T17:32:48.614395Z","iopub.execute_input":"2021-12-31T17:32:48.615051Z","iopub.status.idle":"2021-12-31T17:32:48.619584Z","shell.execute_reply.started":"2021-12-31T17:32:48.615002Z","shell.execute_reply":"2021-12-31T17:32:48.618432Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Méthodologie\n\n# Pour faire la classification, nous allons utiliser un réseau de neurone convolutionnel (CNN)\n# Ce dernier requiert des images comme fichiers d'entrées. Puisque nos données sont des fichiers audio au format mp3, \n# nous allons devoir effectuer des transformations afin d'obtenir des fichiers interprétables par le CNN.\n\n# 1er script\n# Nous allons faire une transformée de Fourier en utilisant l'algorithme Fast Fourier Transform. \n# Cela permet de passer nos sons du domaine temporel au domaine fréquentiel. \n# Ces spectres au domaine fréquentiel sont plus discriminants pour différentcier les oiseaux.\n# Le problème de la transformée de Fourier est que l'on perd l'information temporelle. Or, les chants d'oisaux evoluent dans le \n# temps.\n# La solution est d'utiliser la transformés de Fourier à court terme, qui permet de faire des transformées\n# de Fourier sur plusieurs intervalles de temps.\n# On obtient alors des spectrogrammes. On convertie ces spectrogrammes à l'echelle de mel. \n# Cette echelle permet de prendre en considération le fait que l'ouie humaine ne perçoit pas les différentes férequences sur une echelle linéaire\n\n# 2eme script\n# Une fois que nous avons obtenus ces fichiers nous allons passer ces images dans un algorithme de CNN afin de faire la \n# classification.","metadata":{"execution":{"iopub.status.busy":"2021-12-31T17:32:48.627899Z","iopub.execute_input":"2021-12-31T17:32:48.628573Z","iopub.status.idle":"2021-12-31T17:32:48.634375Z","shell.execute_reply.started":"2021-12-31T17:32:48.628521Z","shell.execute_reply":"2021-12-31T17:32:48.633274Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# 1er script : Preprocessing ","metadata":{"execution":{"iopub.status.busy":"2021-12-31T17:32:48.636786Z","iopub.execute_input":"2021-12-31T17:32:48.637559Z","iopub.status.idle":"2021-12-31T17:32:48.647676Z","shell.execute_reply.started":"2021-12-31T17:32:48.637509Z","shell.execute_reply":"2021-12-31T17:32:48.646839Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Import des packages necéssaires aux preprocessing\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n\nimport os\nimport math\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n#         print(os.path.join(dirname, filename))\n        pass\n\nimport cv2\nimport pathlib\nimport librosa\nimport librosa.display\nimport skimage\nimport skimage.io\nfrom IPython.display import Audio\nfrom matplotlib import pyplot as plt\nimport seaborn as sns\nimport warnings\nimport tensorflow as tf\n\nfrom scipy.ndimage.measurements import center_of_mass\n\nfrom keras import Sequential\nfrom keras import layers\nfrom keras.models import Sequential\nfrom keras.layers import Dense, LSTM, Dropout, GRU, Bidirectional, Conv2D, MaxPooling2D,  Activation, Flatten, experimental, BatchNormalization, MaxPool2D\nfrom keras.optimizers import SGD\nfrom keras.wrappers.scikit_learn import KerasClassifier\nfrom sklearn.metrics import mean_squared_error, f1_score\nfrom sklearn.preprocessing import LabelEncoder, OneHotEncoder\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.utils import shuffle\n\nwarnings.filterwarnings('ignore')","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":0.972288,"end_time":"2020-09-05T03:32:33.381778","exception":false,"start_time":"2020-09-05T03:32:32.40949","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:32:48.648981Z","iopub.execute_input":"2021-12-31T17:32:48.64939Z","iopub.status.idle":"2021-12-31T17:33:02.311917Z","shell.execute_reply.started":"2021-12-31T17:32:48.649348Z","shell.execute_reply":"2021-12-31T17:33:02.310891Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Convert to mono types and Sampling Rate: 44100 (Hz) \nconfig = {\n    \"sample_rate\": 44100 ## \n}","metadata":{"papermill":{"duration":0.019261,"end_time":"2020-09-05T03:32:43.819369","exception":false,"start_time":"2020-09-05T03:32:43.800108","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.313431Z","iopub.execute_input":"2021-12-31T17:33:02.313747Z","iopub.status.idle":"2021-12-31T17:33:02.318131Z","shell.execute_reply.started":"2021-12-31T17:33:02.313703Z","shell.execute_reply":"2021-12-31T17:33:02.317116Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Ci-desssous les cellules contiennent le code nécessaire afin de convertir nos fichiers audio en spectrogrammes de mel.","metadata":{"execution":{"iopub.status.busy":"2021-12-31T17:33:02.32062Z","iopub.execute_input":"2021-12-31T17:33:02.321Z","iopub.status.idle":"2021-12-31T17:33:02.331331Z","shell.execute_reply.started":"2021-12-31T17:33:02.320957Z","shell.execute_reply":"2021-12-31T17:33:02.330492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def spectrogram_image(y, sr,):       \n    \n    \"\"\"\n    y: audio samples: numpy array (2, n)\n    sr: sample rate: number\n    \"\"\"\n    \n    HOP_SIZE = 1024       \n    N_MELS = 128              \n    WINDOW_TYPE = 'hann' \n    FEATURE = 'mel'      \n    FMIN = 1400 \n    \n    y_chunks= librosa.effects.split(y) \n    \n    mfccs_final = []\n    \n    for chunk in y_chunks:\n        \n        mels = librosa.feature.melspectrogram(y=y,sr=sr,\n                                        hop_length=HOP_SIZE, \n                                        n_mels=N_MELS, \n                                        htk=True, \n                                        fmin=FMIN, \n                                        fmax=sr/2) \n\n        mels = librosa.power_to_db(mels**2,ref=np.max)\n        mfccs = librosa.feature.mfcc(S=mels, n_mfcc=40) \n\n        mfcss_img = np.reshape(mfccs, (*mfccs.shape, 1))\n        \n        ## resize and rescale image\n        resize_and_rescale = tf.keras.Sequential([\n            layers.experimental.preprocessing.Resizing(40, 40),\n            layers.experimental.preprocessing.Rescaling(1./255)\n        ])\n        \n        mfcss_img = resize_and_rescale(mfcss_img)\n\n        mfcss_image = np.reshape(mfcss_img, (mfcss_img.shape[0], mfcss_img.shape[1]))\n        mfccs_final.append(mfcss_image)\n    \n    return np.array(mfccs_final)","metadata":{"papermill":{"duration":0.029803,"end_time":"2020-09-05T03:32:43.859317","exception":false,"start_time":"2020-09-05T03:32:43.829514","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.333015Z","iopub.execute_input":"2021-12-31T17:33:02.333351Z","iopub.status.idle":"2021-12-31T17:33:02.347491Z","shell.execute_reply.started":"2021-12-31T17:33:02.333319Z","shell.execute_reply":"2021-12-31T17:33:02.346411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def gen_label_encoder():\n    return LabelEncoder()\n\ndef save_image(y, out):\n    skimage.io.imsave(out, y)","metadata":{"papermill":{"duration":0.025655,"end_time":"2020-09-05T03:32:43.899179","exception":false,"start_time":"2020-09-05T03:32:43.873524","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.348995Z","iopub.execute_input":"2021-12-31T17:33:02.349777Z","iopub.status.idle":"2021-12-31T17:33:02.362095Z","shell.execute_reply.started":"2021-12-31T17:33:02.349713Z","shell.execute_reply":"2021-12-31T17:33:02.361301Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"raw_datasets = pd.read_csv(\"/kaggle/input/birdsong-recognition/train.csv\")\n\ndatasets = raw_datasets.loc[:, \n            ['location', 'rating', 'ebird_code', 'duration', 'filename', 'time', 'primary_label', 'sampling_rate',\n             'length', 'channels', 'pitch', 'bird_seen', 'background', 'bitrate_of_mp3', 'volume', 'file_type']]\n\ndatasets = datasets[datasets.rating >= 4.]","metadata":{"papermill":{"duration":0.43954,"end_time":"2020-09-05T03:32:44.350974","exception":false,"start_time":"2020-09-05T03:32:43.911434","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.363241Z","iopub.execute_input":"2021-12-31T17:33:02.363864Z","iopub.status.idle":"2021-12-31T17:33:02.912556Z","shell.execute_reply.started":"2021-12-31T17:33:02.36382Z","shell.execute_reply":"2021-12-31T17:33:02.911787Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## Loading data\nlabel_encoder = gen_label_encoder()\n\ndatasets['duration'] = datasets.duration.astype(float)\ndatasets['label'] = label_encoder.fit_transform(datasets.ebird_code.to_numpy())","metadata":{"papermill":{"duration":0.028668,"end_time":"2020-09-05T03:32:44.389957","exception":false,"start_time":"2020-09-05T03:32:44.361289","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.914917Z","iopub.execute_input":"2021-12-31T17:33:02.915349Z","iopub.status.idle":"2021-12-31T17:33:02.926217Z","shell.execute_reply.started":"2021-12-31T17:33:02.915303Z","shell.execute_reply":"2021-12-31T17:33:02.925364Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def data_generator(datasets):\n    while True:\n        for index, row in datasets.iterrows():\n            audio_p = f'/kaggle/input/birdsong-recognition/train_audio/{row.ebird_code}/{row.filename}'\n            if os.path.isfile(audio_p):   \n                try:\n                    audio_numpy, _ = librosa.load(audio_p, mono=True, sr=None)\n                    audio_numpy, _ = librosa.effects.trim(audio_numpy, top_db=20)\n                    audio_name = row.filename\n                    \n                    audio_mfccs = spectrogram_image(\n                        audio_numpy, \n                        config['sample_rate']\n                    )\n                    \n                    yield (\n                        audio_mfccs, \n                        tf.keras.utils.to_categorical(\n                            row.label, \n                            num_classes=len(datasets.ebird_code.unique()), \n                        ),\n                        row.ebird_code, \n                        row.filename)\n                    \n                except Exception as e:\n                    print(f\"ignore error data {audio_name}\")\n                    raise e\n                    pass\n        else:\n            break\n","metadata":{"papermill":{"duration":0.028335,"end_time":"2020-09-05T03:32:44.428585","exception":false,"start_time":"2020-09-05T03:32:44.40025","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.927625Z","iopub.execute_input":"2021-12-31T17:33:02.92821Z","iopub.status.idle":"2021-12-31T17:33:02.936757Z","shell.execute_reply.started":"2021-12-31T17:33:02.928162Z","shell.execute_reply":"2021-12-31T17:33:02.935954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for mfccs, encoded_y, ebird_code, filename in data_generator(datasets):\n           \n    HOP_SIZE = 1024       \n    N_MELS = 128            \n    \n    path = pathlib.Path(f'/kaggle/working/{ebird_code}')\n    \n    if not path.exists():\n        path.mkdir(parents=True, exist_ok=True)\n          \n    index = 0\n    [file_path, _] = os.path.splitext(os.path.join(*path.parts, filename))\n    for mfcc in mfccs:  \n        save_image(mfcc, out=f\"{file_path}.{index}.png\")\n        index += 1","metadata":{"papermill":{"duration":29395.468977,"end_time":"2020-09-05T11:42:39.908135","exception":false,"start_time":"2020-09-05T03:32:44.439158","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2021-12-31T17:33:02.937751Z","iopub.execute_input":"2021-12-31T17:33:02.938157Z","iopub.status.idle":"2022-01-01T01:34:32.055081Z","shell.execute_reply.started":"2021-12-31T17:33:02.938119Z","shell.execute_reply":"2022-01-01T01:34:32.051463Z"},"trusted":true},"execution_count":null,"outputs":[]}]}