{"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":"import numpy as np\nimport pandas as pd\nimport os\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport IPython.display as ipd\nfrom tqdm import tqdm\nfrom PIL import Image\nimport tensorflow as tf\nimport cv2\nimport skimage.io\nimport librosa\nimport librosa.display\nimport sklearn.model_selection as sk\nimport tensorflow as tf\nfrom keras.callbacks import EarlyStopping\nfrom keras.callbacks import ModelCheckpoint","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_datadir = \"../input/birdclef-2021/train_short_audio\"\nsoundscapes = '../input/birdclef-2021/train_soundscapes'\ntrain_csv = \"../input/birdclef-2021/train_metadata.csv\"\ntest_csv = \"../input/birdclef-2021/test.csv\"\ntrain_soundscape = \"../input/birdclef-2021/train_soundscape_labels.csv\"\noutput_dir = \"../output/kaggle/working\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_rate = 32000\nsignal_length = 5\n\nduration = 15\noffset = 0.0\nhop_length = 512 # number of samples per time-step in spectrogram\nn_mels = 128 # number of bins in spectrogram. Height of image\ntime_steps = 384 # number of time-steps. Width of image\nthreshold = 0.1\nfmin = 500\nfmax = 12500\n\nspec_shape = (48, 128)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata = pd.read_csv(train_csv)\ndf_train_soundscape = pd.read_csv(train_soundscape)\ndf_test = pd.read_csv(test_csv)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata.hist(column='rating', figsize=(10, 5))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"is_good_quality =  df_train_metadata['rating'] > 3","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata_filtered = df_train_metadata[is_good_quality]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata_filtered.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"good_quality_audios = df_train_metadata_filtered['filename'].tolist()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(good_quality_audios))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata_filtered['primary_label'].value_counts()[:200].plot(kind=\"bar\", figsize=(25, 12), rot=90)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_train_metadata_filtered.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"filtered_files = set(df_train_metadata_filtered['filename'].tolist())","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(filtered_files)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def scale_minmax(x, min=0.0, max=1.0):\n    x_std = (x - x.min()) / (x.max() - x.min())\n    x_scaled = x_std * (max - min) + min\n    return x_scaled","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def extract_links_and_labels(data_dir):\n    audio_clips = []\n    folder_names = []\n    file_names = []\n    birds = os.listdir(data_dir)\n    labels = []\n    for bird in birds:\n        for clip in os.listdir(data_dir + \"/\" + bird):\n            if clip in filtered_files:\n                folder_names.append(bird)\n                file_names.append(clip.split(\".ogg\")[0])\n                audio_clips.append(data_dir +  \"/\" + bird + \"/\" + clip)\n                labels.append(bird)\n    return folder_names, file_names, audio_clips, labels","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"folder_names, file_names, train_audio_clips, labels = extract_links_and_labels(train_datadir)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_audio_clips)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf kaggle/working\n!mkdir train_images","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_spectrograms(filepath, primary_label, directory):\n    \n    # Open the file with librosa (limited to the first 15 seconds)\n    sig, rate = librosa.load(filepath, sr=sample_rate, offset=None, duration=duration)\n    # Split signal into five second chunks\n    sig_splits = []\n    for i in range(0, len(sig), int(signal_length * sample_rate)):\n        split = sig[i:i + int(signal_length * sample_rate)]\n\n        # End of signal?\n        if len(split) < int(signal_length * sample_rate):\n            break\n        sig_splits.append(split)\n    \n    # Extract mel spectrograms for each audio chunk\n    s_cnt = 5\n    saved_samples = []\n    for chunk in sig_splits:\n        hop_length = int(signal_length * sample_rate / (spec_shape[1] - 1))\n        mel_spec = librosa.feature.melspectrogram(y=chunk, \n                                                  sr=sample_rate, \n                                                  n_fft=1024, \n                                                  hop_length=hop_length, \n                                                  n_mels=spec_shape[0], \n                                                  fmin=fmin, \n                                                  fmax=fmax)\n\n        mel_spec = np.log(mel_spec + 1e-9) # add small number to avoid log(0)\n\n        # min-max scale to fit inside 8-bit range\n        mel_spec = scale_minmax(mel_spec, 0, 255).astype(np.uint8)\n        mel_spec = np.flip(mel_spec, axis=0) # put low frequencies at the bottom in image\n        mel_spec = 255 - mel_spec # invert. make black==more energy\n\n        folder_dir = directory + primary_label\n        # Save as image file        \n        if not os.path.exists(folder_dir):\n            os.makedirs(folder_dir)\n        s_cnt_str = str(s_cnt)\n        save_path = os.path.join(folder_dir, \n                                 filepath.rsplit(os.sep, 1)[-1].rsplit('.', 1)[0] + '_' + s_cnt_str + '.png')\n        skimage.io.imsave(save_path, mel_spec)\n        saved_samples.append(save_path)\n        s_cnt += 5\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for i in tqdm(range(len(train_audio_clips))):\n#     get_spectrograms(train_audio_clips[i], folder_names[i], './train_images/') ","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def imagetensor(imagedir):  \n    counter = 0\n    for i, im in enumerate(os.listdir(imagedir)):\n        if counter == counter_limit:\n            counter = 0\n            return images\n        image= cv2.imread(os.path.join(imagedir, im), 0)\n        image.resize(spec_shape)\n        if i == 0:\n            images= np.expand_dims(np.array(image, dtype= float) / 255, axis= 0)\n            counter += 1\n        else:\n            image= np.expand_dims(np.array(image, dtype= float) / 255, axis= 0)\n            images= np.append(images, image, axis= 0)\n            counter += 1\n    return images","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# labels = []\n# for label in os.listdir('./train_images/'):\n#     if (not '.ipynb' in label and \n#         not 'h5'in label and \n#         not '.npy' in label and \n#         not '.txt' in label and \n#         not 'out' in label):\n#         labels.append(label)\n# print(len(labels))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# counter_limit = 500\n# x_train = np.array([])\n# y_train = []\n# for idx, label in tqdm(enumerate(tqdm(labels))):\n#     if idx == 0:\n#         x_train= imagetensor('./train_images/' + label)\n#         y_train.extend([label] * len(x_train))\n#     else:\n#         images = imagetensor('./train_images/' + label)\n#         y_train.extend([label] * len(images))\n#         x_train = np.vstack((x_train, images))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# inputs = x_train.reshape((x_train.shape[0],x_train.shape[1],x_train.shape[2], 1))\n# outputs = pd.get_dummies(pd.Series(y_train)).to_numpy()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print(inputs.shape, outputs.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# np.savez_compressed('batch_reduced_48_128', x=inputs, y=outputs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# b = os.path.getsize(\"batch_reduced_48_128.npz\")\n# print(b)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# batch_1 = np.load('batch_reduced_48_128.npz')\n\n# inputs = batch_1['x']\n# outputs = batch_1['y']","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# SPEC_SHAPE = inputs[0].shape\n# OUTPUT_SHAPE = outputs[0].shape\n# SEED = 8000","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# from sklearn.utils import shuffle\n# inputs, outputs = shuffle(inputs, outputs)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # Make sure your experiments are reproducible\n# tf.random.set_seed(SEED)\n\n# # Build a simple model as a sequence of  convolutional blocks.\n# # Each block has the sequence CONV --> RELU --> BNORM --> MAXPOOL.\n# # Finally, perform global average pooling and add 2 dense layers.\n# # The last layer is our classification layer and is softmax activated.\n# # (Well it's a multi-label task so sigmoid might actually be a better choice)\n# model = tf.keras.Sequential([\n    \n#     # First conv block\n#     tf.keras.layers.Conv2D(16, (3, 3), \n#                            activation='relu', \n#                            input_shape=(SPEC_SHAPE[0], SPEC_SHAPE[1], 1)),\n#     tf.keras.layers.BatchNormalization(),\n#     tf.keras.layers.MaxPooling2D((2, 2)),\n    \n#     # Second conv block\n#     tf.keras.layers.Conv2D(32, (3, 3), activation='relu'),\n#     tf.keras.layers.BatchNormalization(),\n#     tf.keras.layers.MaxPooling2D((2, 2)), \n    \n#     # Third conv block\n#     tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n#     tf.keras.layers.BatchNormalization(),\n#     tf.keras.layers.MaxPooling2D((2, 2)), \n    \n#     # Fourth conv block\n#     tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n#     tf.keras.layers.BatchNormalization(),\n#     tf.keras.layers.MaxPooling2D((2, 2)),\n    \n#     # Global pooling instead of flatten()\n#     tf.keras.layers.GlobalAveragePooling2D(), \n    \n#     # Dense block\n#     tf.keras.layers.Dense(256, activation='relu'),   \n#     tf.keras.layers.Dropout(0.5),  \n#     tf.keras.layers.Dense(256, activation='relu'),   \n#     tf.keras.layers.Dropout(0.5),\n    \n#     # Classification layer\n#     tf.keras.layers.Dense(OUTPUT_SHAPE[0], activation='softmax')\n# ])\n# print('MODEL HAS {} PARAMETERS.'.format(model.count_params()))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.compile(\n#     optimizer=tf.keras.optimizers.Adam(learning_rate=0.0015),\n#     loss=tf.keras.losses.CategoricalCrossentropy(),\n#     metrics=['accuracy', tf.keras.metrics.AUC()]\n# )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.summary()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# early_stopping_monitor = EarlyStopping(\n#     monitor='val_accuracy',\n#     patience=100,\n#     verbose=1,\n#     mode='auto',\n#     restore_best_weights=True\n# )\n\n# mcp_save = ModelCheckpoint(\n#     './best_model.h5', \n#     save_best_only=True, \n#     monitor='val_accuracy',\n#     verbose=1\n# )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model.fit(\n#     inputs, \n#     outputs, \n#     epochs=1000,\n#     batch_size=256, \n#     validation_split=0.2, \n#     callbacks=[early_stopping_monitor, mcp_save]\n# )","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!mkdir train_soundscapes","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"soundscape_links = []\nfilenames = []\nfor soundscape in os.listdir(soundscapes):\n    soundscape_link = soundscapes + '/' + soundscape\n    soundscape_links.append(soundscape_link)\n    filenames.append(soundscape.split('.')[0])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"duration = 600\nfor i in tqdm(range(len(soundscape_links))):\n    get_spectrograms(soundscape_links[i], filenames[i], 'train_soundscapes/')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sorted_complete_links = []\nsorted_col = []\ncounter = 5\nfor soundscape in os.listdir('./train_soundscapes'):\n    counter = 5\n    for img_path in os.listdir('./train_soundscapes/' + soundscape):\n        while counter <= 600:\n            folder_name = img_path.split('_')[0] + '_' + img_path.split('_')[1] + '_' + img_path.split('_')[2]\n            file_name = img_path.split('_')[0] + '_' + img_path.split('_')[1] + '_' + img_path.split('_')[2] + '_' + str(counter) + '.png'\n            counter += 5\n            sorted_complete_links.append('./train_soundscapes/' + folder_name + '/' + file_name)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(sorted_complete_links)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def imagetensor_2():  \n    counter = 0\n    for link in sorted_complete_links:\n        image= cv2.imread(link, 0)\n        image.resize(spec_shape)\n        if counter == 0:\n            images= np.expand_dims(np.array(image, dtype= float) / 255, axis= 0)\n            counter += 1\n        else:\n            image= np.expand_dims(np.array(image, dtype= float) / 255, axis= 0)\n            images= np.append(images, image, axis= 0)\n            counter += 1\n    return images","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_test = imagetensor_2()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(x_test.shape)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"x_test = x_test.reshape((2400, 48, 128, 1))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# np.savez_compressed('test_batch_reduced_48_128', x=x_test)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf train_images","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf train_soundscapes","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!rm -rf batch_reduced_48_128.npz","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow import keras\nmodel = keras.models.load_model('../input/birds-2/best_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save('best_model.h5')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"p = model.predict(x_test)\ny_prob = np.argmax(p, axis=1)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"primary_labels = []\nfor folder_name in folder_names:\n    if not folder_name in primary_labels:\n        primary_labels.append(folder_name)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(primary_labels)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sorted_file_links = []\nfor link in soundscape_links:\n    counter = 5\n    while (counter <= 600):\n        curr_link = link.split('/')[-1].split('_')[0] + '_' + link.split('/')[-1].split('_')[1] + '_' + str(counter)\n        sorted_file_links.append(curr_link)\n        counter += 5\nprint(sorted_file_links[-1])","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission = []\nfor i in range(len(p)):\n    data = {}\n    label = sorted_file_links[i]\n    data['row_id'] = label\n    if (p[i][y_prob[i]]) < threshold:\n        data['birds'] = 'nocall'\n    else:\n        data['birds'] = primary_labels[y_prob[i]]\n    submission.append(data)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_submission = pd.DataFrame(submission)\ndf_submission.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_submission.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}