{"cells":[{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"!pip install comet_ml","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import comet_ml #at the top of your file\nfrom comet_ml import Experiment\n\n# Create an experiment with your api key:\nexperiment = Experiment(\n    api_key=\"cjZUHKCBKcrudJIeYuUe1zaBT\",\n    project_name=\"species-audio-detection\",\n    workspace=\"kaggle\",\n    log_code=True,\n)","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport cv2\nimport librosa\nimport librosa.display\nimport soundfile\nimport pathlib as pt\nimport os\nimport matplotlib.pyplot as plt\nimport multiprocessing as mp\nfrom itertools import repeat\nimport signal\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import OneHotEncoder\n\nfrom fastai.vision.all import *\nfrom fastai.data.core import DataLoaders\n\nfrom tqdm import tqdm\n\nimport torch.cuda\nif torch.cuda.is_available():\n    print('PyTorch found cuda')\nelse:\n    print('PyTorch could not find cuda')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Prepare data"},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"ROOT = pt.Path('/kaggle/input/rfcx-species-audio-detection')\nTRAIN_TP_CSV = ROOT/\"train_tp.csv\"\nTRAIN_FP_CSV = ROOT/\"train_fp.csv\"\nTRAIN_DIR    = ROOT/\"train\"\nTEST_DIR     = ROOT/\"test\"\n\nprint(list(TRAIN_DIR.glob(\"*\"))[:5])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_path(row):\n    return TRAIN_DIR/\"{}.flac\".format(row)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_audio_tp_df = pd.read_csv(TRAIN_TP_CSV)\ntrain_audio_tp_df[\"tp\"] = True\ntrain_audio_tp_df['audio_path'] = train_audio_tp_df['recording_id'].apply(create_path)\ntrain_audio_tp_df.head(3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_audio_fp_df = pd.read_csv(TRAIN_FP_CSV)\ntrain_audio_fp_df[\"tp\"] = False\ntrain_audio_fp_df['audio_path'] = train_audio_fp_df['recording_id'].apply(create_path)\ntrain_audio_fp_df.head(3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"TP: # {} FP: # {}\".format(len(train_audio_tp_df), len(train_audio_fp_df)))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_train_audio_df = pd.concat([train_audio_tp_df, train_audio_fp_df]).reset_index()\nall_train_audio_df.head(3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"species_ids = sorted(all_train_audio_df['species_id'].unique())\nprint(species_ids)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"_df = all_train_audio_df['species_id'].value_counts().sort_index()\nax = _df.plot(kind='bar')\nax.set_xlabel(\"Species ID\")\nax.set_ylabel(\"Frequency\")\nax.set_title(\"Nr of samples / species\")\nplt.close('all')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_audio_paths = list(TEST_DIR.glob(\"*.flac\"))\ntest_audio_df = pd.DataFrame()\ntest_audio_df['recording_id'] = [p.stem for p in test_audio_paths]\ntest_audio_df['audio_path']   = [p for p in test_audio_paths]\ntest_audio_df.head(3)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"Total training: # {}\".format(len(all_train_audio_df)))\nprint(\"Test: # {}\".format(len(test_audio_df)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Split train data into train and validation"},{"metadata":{"trusted":true},"cell_type":"code","source":"# train_df, valid_df = train_test_split(all_train_df, test_size=0.2, random_state=42)\n# train_df.reset_index(drop=True, inplace=True)\n# valid_df.reset_index(drop=True, inplace=True)\n\n# print(\"Train: # {} Validation: # {}\".format(len(train_df), len(valid_df)))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Audio to spectogram"},{"metadata":{"trusted":true},"cell_type":"code","source":"# idx = 256\n# y, sr = librosa.load(all_train_audio_df.iloc[idx]['audio_path'])\n# fig, ax = plt.subplots(1, 1)\n# ax.plot(y);\n# ax.set_title('Signal - recording id {}'.format(all_train_audio_df.iloc[idx]['recording_id']));\n# ax.set_xlabel('Time (samples)');\n# ax.set_ylabel('Amplitude');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# spec = np.abs(librosa.stft(y, hop_length=512))\n# spec = librosa.amplitude_to_db(spec, ref=np.max)\n# fig, ax = plt.subplots(1, 1)\n# img = librosa.display.specshow(spec, sr=sr, x_axis='time', y_axis='log', ax=ax);\n# ax.set_title('Spectrogram');\n# fig.colorbar(img, ax=ax, format='%+2.0f dB');","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# mel_spec = librosa.feature.melspectrogram(y=y, sr=sr)\n# fig, ax = plt.subplots(1, 1)\n# img = librosa.display.specshow(librosa.power_to_db(mel_spec, ref=np.max), y_axis='mel', x_axis='time')\n# ax.set_title('Melspectogram');\n# fig.colorbar(img, ax=ax, format='%+2.0f dB');\n\n# plt.close('all')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def fig2img(fig):\n    \"\"\"Convert a Matplotlib figure to a PIL Image and return it\"\"\"\n    import io\n    buf = io.BytesIO()\n    fig.savefig(buf)\n    buf.seek(0)\n    img = Image.open(buf).convert('RGB')\n \n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# %matplotlib\n# %matplotlib\n\n# fig, ax = plt.subplots(1, 1, figsize=(0.72, 0.72))\n# img = librosa.display.specshow(librosa.power_to_db(mel_spec, ref=np.max), y_axis='mel', x_axis='time')\n# ax.set_axis_off()\n# ax.axis('tight')\n# # Set whitespace to 0\n# fig.subplots_adjust(left=0, right=1, bottom=0, top=1)\n# # img = fig2img(fig)\n# # img.save(\"pic_melspectogram_example_3.png\")\n# fig.savefig('melspectogram_example.png', dpi=400)#, bbox_inches='tight', pad_inches=0)\n# experiment.log_image('melspectogram_example.png')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Save spectograms"},{"metadata":{"trusted":true},"cell_type":"code","source":"def save_melspectograms(data_df, output_dir, dim_inches=(0.72, 0.72)):\n    for _, row in data_df.iterrows():\n        if 'species_id' in data_df.columns:\n            image_filename = \"s{}_{}_train.png\".format(row['species_id'], row['recording_id'])\n        else:\n            image_filename = \"{}_test.png\".format(row['recording_id'])\n        melspec_path = output_dir/image_filename\n        \n        if melspec_path.exists():\n            continue\n        y, sr = librosa.load(row['audio_path'])\n\n        mel_spec = librosa.feature.melspectrogram(y=y, sr=sr)\n        mel_spec = librosa.power_to_db(mel_spec, ref=np.max)\n\n        fig, ax = plt.subplots(1, 1, figsize=dim_inches)\n        _ = librosa.display.specshow(mel_spec, y_axis='mel', x_axis='time')\n        ax.set_axis_off()\n        ax.axis('tight')\n        # Set whitespace to 0\n        fig.subplots_adjust(left=0, right=1, bottom=0, top=1)\n        fig.savefig(melspec_path, dpi=400)#, bbox_inches='tight', pad_inches=0)\n        plt.close(fig)\n        plt.close('all')\n        del y\n        del mel_spec\n\n    print(\"Done saving from idx {}.\".format(data_df.index[0]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"TRAIN_SPEC_DIR = pt.Path('/kaggle/working/train_specs/')\nTEST_SPEC_DIR = pt.Path('/kaggle/working/test_specs/')\nos.makedirs(TRAIN_SPEC_DIR, exist_ok=True)\nos.makedirs(TEST_SPEC_DIR, exist_ok=True)\n\nprint(\"TRAIN_SPEC_DIR: {} TEST_SPEC_DIR: {}\".format(TRAIN_SPEC_DIR.exists(), TEST_SPEC_DIR.exists()))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def signal_handler(signal, frame):\n    global interrupted\n    interrupted = True\n    \ndef parallelised_saving(data_df, output_dir, batch_nr=2):\n    master_list = []\n    num_proc = mp.cpu_count()\n\n    n_iter = int(np.ceil(len(data_df) / batch_nr))\n    for i in range(n_iter):\n        batch_df = data_df.iloc[i * batch_nr: (i+1) * batch_nr]\n        master_list.append(batch_df)\n\n    print(\"to be saved dfs #\", len(master_list))\n    print(\"CPU cores #\", num_proc)\n\n    signal.signal(signal.SIGINT, signal_handler)\n\n    processes = [None] * num_proc\n    processed_idx = []\n    local_current_index = 0\n\n    interrupted = False\n    finished = False\n    exit_main_loop = False\n\n    while(not interrupted and not exit_main_loop):\n\n        for i in range(num_proc):\n\n            if processes[i] is None and not finished:\n                batch_idx = local_current_index\n#                 print(\"Process number {} is free. Assigning new task.\".format(i))\n                if batch_idx >= len(master_list):\n                    finished = True\n                else:\n                    processed_idx.append(batch_idx)\n#                     print(\"\\tStarting processing of batch nr {}\".format(batch_idx))\n                    processes[i] = mp.Process(target=save_melspectograms, \n                                              args=([master_list[batch_idx], output_dir]))\n                    processes[i].start()\n                    local_current_index = local_current_index + 1\n\n            if(finished and all(v is None for v in processes)):\n                print(\">>> Finished processing!\")\n                exit_main_loop = True\n                break\n\n            if processes[i] is None:\n                continue\n\n            if processes[i].exitcode is not None:\n\n                processes[i].join()\n                processes[i] = None\n\n        time.sleep(0.1)","execution_count":null,"outputs":[]},{"metadata":{"_kg_hide-output":true,"trusted":true},"cell_type":"code","source":"parallelised_saving(train_audio_tp_df, output_dir=TRAIN_SPEC_DIR, batch_nr=64)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"collapsed":true},"cell_type":"code","source":"parallelised_saving(test_audio_df, output_dir=TEST_SPEC_DIR, batch_nr=64)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_melspectograms = list(TRAIN_SPEC_DIR.glob(\"*.png\"))\nprint(\"Train total: #\", len(train_melspectograms))\n\ntest_melspectograms = list(TEST_SPEC_DIR.glob(\"*.png\"))\nprint(\"Test: #\", len(test_melspectograms))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# _i = Image.open(train_melspectograms[0])\n# print(_i.shape)\n# plt.imshow(_i)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Train\n### Prepare data loaders"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_specs_df = pd.DataFrame()\ntrain_specs_df['spec_path']    = train_melspectograms\ntrain_specs_df['recording_id'] = [p.name.split(\"_\")[1] for p in train_melspectograms]\ntrain_specs_df['species_id']   = [p.name.split(\"_\")[0] for p in train_melspectograms]\ntrain_specs_df.head(2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test_specs_df = pd.DataFrame()\ntest_specs_df['spec_path']    = test_melspectograms\ntest_specs_df['recording_id'] = [p.name.split(\"_\")[0] for p in test_melspectograms]\ntest_specs_df.head(2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"help(ImageDataLoaders.from_df)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"data_loaders = ImageDataLoaders.from_df(train_specs_df, path=\"/\", seed=42, fn_col='spec_path', label_col='species_id', item_tfms=[Resize(224)])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Setup resnet34 architecture"},{"metadata":{"trusted":true},"cell_type":"code","source":"learn = cnn_learner(data_loaders, resnet34, metrics=error_rate)\n# learn.model = learn.model.cuda()\n# learn.lr_find()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.fine_tune(2)\n# learn.fit_one_cycle(n_epoch=2, lr_max=0.01)\nlearn.export(\"resnet34_model.pkl\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"experiment.log_model(name=\"resnet34_model_v0\", file_or_folder=\"/resnet34_model.pkl\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Look at some predictions"},{"metadata":{"trusted":true},"cell_type":"code","source":"learn.show_results()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"interp = Interpretation.from_learner(learn)\ninterp.plot_top_losses(9, figsize=(15,10))","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Create submission file"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_dl = data_loaders.test_dl(test_specs_df)\nres_preds = learn.get_preds(dl=test_dl, with_decoded=True) # returns (predictions, _, predicted label)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"preds_values = res_preds[0]\npreds_labels = res_preds[2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_data = {'recording_id': []}\nfor _id in species_ids:\n    submission_data.update({'s{}'.format(_id): []})\n\nfor idx, preds in enumerate(preds_values):\n\n    submission_data['recording_id'].append(test_specs_df.iloc[idx]['recording_id'])\n    for i, p in enumerate(preds):\n        submission_data[\"s{}\".format(i)].append(p.item())\n\nsubmission_df = pd.DataFrame(data=submission_data)\nsubmission_df.to_csv(\"submission_data.csv\", index=False)\nexperiment.log_table(\"submission_data.csv\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"experiment.end()","execution_count":null,"outputs":[]}],"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":4,"nbformat_minor":4}