{"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":"# Importing Libraries ","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19"}},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/bird-lib-20230309095737/')\nimport timm","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:54.632331Z","iopub.execute_input":"2023-03-16T23:17:54.632762Z","iopub.status.idle":"2023-03-16T23:17:57.227404Z","shell.execute_reply.started":"2023-03-16T23:17:54.632728Z","shell.execute_reply":"2023-03-16T23:17:57.226204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import torch\nimport torch.nn as nn\nfrom torch.utils.data import DataLoader, Dataset, random_split\nimport torch.nn.functional as F\nimport torchaudio\nfrom torchaudio import transforms\nfrom IPython.display import Audio\nimport torchvision\nfrom sklearn.preprocessing import OneHotEncoder, LabelEncoder\nfrom sklearn.model_selection import StratifiedKFold\nfrom sklearn.metrics import roc_auc_score\nimport numpy as np\nimport pandas as pd\nimport os\nimport glob\nimport math, random","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:57.229644Z","iopub.execute_input":"2023-03-16T23:17:57.230470Z","iopub.status.idle":"2023-03-16T23:17:58.485907Z","shell.execute_reply.started":"2023-03-16T23:17:57.230427Z","shell.execute_reply":"2023-03-16T23:17:58.484435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed):\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\n\nseed = 42\nseed_everything(seed)","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.487731Z","iopub.execute_input":"2023-03-16T23:17:58.488149Z","iopub.status.idle":"2023-03-16T23:17:58.502009Z","shell.execute_reply.started":"2023-03-16T23:17:58.488111Z","shell.execute_reply":"2023-03-16T23:17:58.500540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Configuration ⚙️","metadata":{}},{"cell_type":"code","source":"class CFG:\n    isOneHot = False\n    rate = 32000\n    num_classes = 264","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.503574Z","iopub.execute_input":"2023-03-16T23:17:58.504170Z","iopub.status.idle":"2023-03-16T23:17:58.509571Z","shell.execute_reply.started":"2023-03-16T23:17:58.504135Z","shell.execute_reply":"2023-03-16T23:17:58.508467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AudioUtil():\n  @staticmethod\n  def open(audio_file):\n    sig, sr = torchaudio.load(audio_file)\n    return (sig, sr)\n\n  @staticmethod\n  def rechannel(aud, new_channel):\n    sig, sr = aud\n\n    if (sig.shape[0] == new_channel):\n      # Nothing to do\n      return aud\n\n    if (new_channel == 1):\n      # Convert from stereo to mono by selecting only the first channel\n      resig = sig[:1, :]\n    else:\n      # Convert from mono to stereo by duplicating the first channel\n      resig = torch.cat([sig, sig, sig])\n\n    return ((resig, sr))\n\n  @staticmethod\n  def resample(aud, newsr):\n    sig, sr = aud\n\n    if (sr == newsr):\n      # Nothing to do\n      return aud\n\n    num_channels = sig.shape[0]\n    # Resample first channel\n    resig = torchaudio.transforms.Resample(sr, newsr)(sig[:1,:])\n    if (num_channels > 1):\n      # Resample the second channel and merge both channels\n      retwo = torchaudio.transforms.Resample(sr, newsr)(sig[1:,:])\n      resig = torch.cat([resig, retwo])\n\n    return ((resig, newsr))\n\n  @staticmethod\n  def pad_trunc(aud, max_ms):\n    sig, sr = aud\n    num_rows, sig_len = sig.shape\n    max_len = sr//1000 * max_ms\n\n    if (sig_len > max_len):\n      # Truncate the signal to the given length\n      sig = sig[:,:max_len]\n\n    elif (sig_len < max_len):\n      # Length of padding to add at the beginning and end of the signal\n      pad_begin_len = random.randint(0, max_len - sig_len)\n      pad_end_len = max_len - sig_len - pad_begin_len\n\n      # Pad with 0s\n      pad_begin = torch.zeros((num_rows, pad_begin_len))\n      pad_end = torch.zeros((num_rows, pad_end_len))\n\n      sig = torch.cat((pad_begin, sig, pad_end), 1)\n      \n    return (sig, sr)\n\n  @staticmethod\n  def time_shift(aud, shift_limit):\n    sig,sr = aud\n    _, sig_len = sig.shape\n    shift_amt = int(random.random() * shift_limit * sig_len)\n    return (sig.roll(shift_amt), sr)\n\n  @staticmethod\n  def spectro_gram(aud, n_mels=64, n_fft=1024, hop_len=None):\n    sig,sr = aud\n    top_db = 80\n\n    # spec has shape [channel, n_mels, time], where channel is mono, stereo etc\n    spec = torchaudio.transforms.MelSpectrogram(sr, n_fft=n_fft, hop_length=hop_len, n_mels=n_mels)(sig)\n\n    # Convert to decibels\n    spec = torchaudio.transforms.AmplitudeToDB(top_db=top_db)(spec)\n    return (spec)\n\n  @staticmethod\n  def spectro_augment(spec, max_mask_pct=0.1, n_freq_masks=1, n_time_masks=1):\n    _, n_mels, n_steps = spec.shape\n    mask_value = spec.mean()\n    aug_spec = spec\n\n    freq_mask_param = max_mask_pct * n_mels\n    for _ in range(n_freq_masks):\n      aug_spec = torchaudio.transforms.FrequencyMasking(freq_mask_param)(aug_spec, mask_value)\n\n    time_mask_param = max_mask_pct * n_steps\n    for _ in range(n_time_masks):\n      aug_spec = torchaudio.transforms.TimeMasking(time_mask_param)(aug_spec, mask_value)\n\n    return aug_spec","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.513389Z","iopub.execute_input":"2023-03-16T23:17:58.513744Z","iopub.status.idle":"2023-03-16T23:17:58.534777Z","shell.execute_reply.started":"2023-03-16T23:17:58.513710Z","shell.execute_reply":"2023-03-16T23:17:58.533160Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def preprocessing(aud):\n    duration = 8000\n    sr = 32000\n    channel = 3\n    shift_pct = 0.4\n    reaud = AudioUtil.resample(aud, sr)\n    rechan = AudioUtil.rechannel(reaud, channel)\n    dur_aud = AudioUtil.pad_trunc(rechan, duration)\n    shift_aud = AudioUtil.time_shift(dur_aud, shift_pct)\n    sgram = AudioUtil.spectro_gram(shift_aud, n_mels=64, n_fft=1024, hop_len=None)\n    aug_sgram = AudioUtil.spectro_augment(sgram, max_mask_pct=0.1, n_freq_masks=2, n_time_masks=2)\n    aug_sgram_m, aug_sgram_s = aug_sgram.mean(), aug_sgram.std()\n    aug_sgram = (aug_sgram - aug_sgram_m) / aug_sgram_s\n    return aug_sgram","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.537073Z","iopub.execute_input":"2023-03-16T23:17:58.537449Z","iopub.status.idle":"2023-03-16T23:17:58.549457Z","shell.execute_reply.started":"2023-03-16T23:17:58.537413Z","shell.execute_reply":"2023-03-16T23:17:58.548319Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_samples = list(glob.glob(\"/kaggle/input/birdclef-2023/test_soundscapes/*.ogg\"))\ntest_samples","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.551416Z","iopub.execute_input":"2023-03-16T23:17:58.551860Z","iopub.status.idle":"2023-03-16T23:17:58.573505Z","shell.execute_reply.started":"2023-03-16T23:17:58.551812Z","shell.execute_reply":"2023-03-16T23:17:58.572314Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocessing(torchaudio.load(test_samples[0])).shape","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:58.575293Z","iopub.execute_input":"2023-03-16T23:17:58.576127Z","iopub.status.idle":"2023-03-16T23:17:59.806351Z","shell.execute_reply.started":"2023-03-16T23:17:58.576078Z","shell.execute_reply":"2023-03-16T23:17:59.804983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"meta_df = pd.read_csv('/kaggle/input/birdclef-2023/train_metadata.csv')\nprint('data shape:',meta_df.shape)\nmeta_df.head(2)","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:59.809054Z","iopub.execute_input":"2023-03-16T23:17:59.810237Z","iopub.status.idle":"2023-03-16T23:17:59.974609Z","shell.execute_reply.started":"2023-03-16T23:17:59.810178Z","shell.execute_reply":"2023-03-16T23:17:59.973136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"le = LabelEncoder().fit(meta_df['primary_label'])\ncompetition_classes = le.classes_","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:59.975962Z","iopub.execute_input":"2023-03-16T23:17:59.976807Z","iopub.status.idle":"2023-03-16T23:17:59.987589Z","shell.execute_reply.started":"2023-03-16T23:17:59.976770Z","shell.execute_reply":"2023-03-16T23:17:59.986099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"forced_defaults = 0\ncompetition_class_map = []\nfor c in competition_classes:\n    try:\n        i = classes.index(c)\n        competition_class_map.append(i)\n    except:\n        competition_class_map.append(0)\n        forced_defaults += 1","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:17:59.989524Z","iopub.execute_input":"2023-03-16T23:17:59.990108Z","iopub.status.idle":"2023-03-16T23:18:00.001947Z","shell.execute_reply.started":"2023-03-16T23:17:59.990051Z","shell.execute_reply":"2023-03-16T23:18:00.000371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub = pd.read_csv(\"/kaggle/input/birdclef-2023/sample_submission.csv\")\nsample_sub[competition_classes] = sample_sub[competition_classes].astype(np.float32)\nsample_sub.head()","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:00.003698Z","iopub.execute_input":"2023-03-16T23:18:00.004242Z","iopub.status.idle":"2023-03-16T23:18:00.114205Z","shell.execute_reply.started":"2023-03-16T23:18:00.004193Z","shell.execute_reply":"2023-03-16T23:18:00.112954Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for idx, col in enumerate(sample_sub.drop(columns = ['row_id'], axis = 1).columns):\n    if col != competition_classes[idx]:\n        print('Not fit class!')\nprint('If dont have any log, all fit')","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:00.117198Z","iopub.execute_input":"2023-03-16T23:18:00.117693Z","iopub.status.idle":"2023-03-16T23:18:00.129718Z","shell.execute_reply.started":"2023-03-16T23:18:00.117636Z","shell.execute_reply":"2023-03-16T23:18:00.128480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inference 📖","metadata":{}},{"cell_type":"code","source":"import glob\nmodel_file_list = glob.glob(\"/kaggle/input/bird-train-a-121-20230309095332/*\")\nmodel_file_list","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:00.135126Z","iopub.execute_input":"2023-03-16T23:18:00.136136Z","iopub.status.idle":"2023-03-16T23:18:00.154451Z","shell.execute_reply.started":"2023-03-16T23:18:00.136086Z","shell.execute_reply":"2023-03-16T23:18:00.153407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_file_list = [\n '/kaggle/input/bird-train-a-121-20230309095332/model_fold3_epoch9.pth',\n '/kaggle/input/bird-train-a-121-20230309095332/model_fold2_epoch9.pth',\n#  '/kaggle/input/bird-train-a-121-20230309095332/model_fold4_epoch9.pth',\n#  '/kaggle/input/bird-train-a-121-20230309095332/model_fold0_epoch9.pth',\n#  '/kaggle/input/bird-train-a-121-20230309095332/model_fold1_epoch9.pth',\n]\nmodel_file_list","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:00.155595Z","iopub.execute_input":"2023-03-16T23:18:00.156381Z","iopub.status.idle":"2023-03-16T23:18:00.165643Z","shell.execute_reply.started":"2023-03-16T23:18:00.156335Z","shell.execute_reply":"2023-03-16T23:18:00.164399Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model_list = []\nfor _model_path in model_file_list:\n    model = timm.create_model(\"tf_efficientnetv2_s\", \n                  pretrained=False, \n                  num_classes=264)\n    model.load_state_dict(torch.load(_model_path, map_location=torch.device('cpu')))\n    model_list.append(model)","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:00.167260Z","iopub.execute_input":"2023-03-16T23:18:00.167728Z","iopub.status.idle":"2023-03-16T23:18:03.811241Z","shell.execute_reply.started":"2023-03-16T23:18:00.167680Z","shell.execute_reply":"2023-03-16T23:18:03.809932Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Prediction Models ","metadata":{}},{"cell_type":"code","source":"def predict_for_sample(filename, sample_submission):\n    file_id = filename.split(\".ogg\")[0].split(\"/\")[-1]\n    lstFile = list(sample_submission[sample_submission.row_id.str.contains( file_id + \"_\")].row_id.unique())\n    data, rat = torchaudio.load(filename)\n    for file in lstFile:\n        end = int(file.split('_')[-1])\n        start = end - 5\n        chunk = (data[:, start*rat:end*rat - 1], rat)\n        samples = preprocessing(chunk).unsqueeze(0)\n        \n        \"\"\" Iter Inf Fold \"\"\"\n        proba_list = []\n        for _model in model_list:\n            device = torch.device(\"cuda:0\" if torch.cuda.is_available() else \"cpu\")\n            myModel = _model.to(device)\n            myModel = myModel.eval()\n            probabilities = myModel(samples)\n            probabilities = torch.nn.functional.softmax(probabilities).detach().numpy()\n            proba_list.append(probabilities)\n        \n        \"\"\" Merge \"\"\"\n        probabilities = [sum(column)/len(model_file_list) for column in zip(*proba_list)]\n        sample_submission.loc[sample_submission.row_id == file, competition_classes] = probabilities","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:03.813355Z","iopub.execute_input":"2023-03-16T23:18:03.813732Z","iopub.status.idle":"2023-03-16T23:18:03.826386Z","shell.execute_reply.started":"2023-03-16T23:18:03.813696Z","shell.execute_reply":"2023-03-16T23:18:03.824654Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Submission 📮","metadata":{}},{"cell_type":"code","source":"for sample_filename in test_samples:\n    predict_for_sample(sample_filename, sample_sub)\nsample_sub","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:03.827967Z","iopub.execute_input":"2023-03-16T23:18:03.828457Z","iopub.status.idle":"2023-03-16T23:18:05.579688Z","shell.execute_reply.started":"2023-03-16T23:18:03.828407Z","shell.execute_reply":"2023-03-16T23:18:05.578335Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub.to_csv(\"submission.csv\", index=False)\n","metadata":{"execution":{"iopub.status.busy":"2023-03-16T23:18:05.581807Z","iopub.execute_input":"2023-03-16T23:18:05.582305Z","iopub.status.idle":"2023-03-16T23:18:05.596450Z","shell.execute_reply.started":"2023-03-16T23:18:05.582254Z","shell.execute_reply":"2023-03-16T23:18:05.595009Z"},"trusted":true},"execution_count":null,"outputs":[]}]}