{"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":"- Single model\n- No external data\n\n## Model\nResNet50 + Attention Block\n\n## Data Augmentation\n- mixup\n- spec augmentation\n- pitch & tempo augmentation\n- melspectrogram cropping \n\n## Secondary labels\nI only used secondary labels from data's duration < 40\n\n## Balancing data\nFor large data size classes, downsampling to 80 samples each class.(removing long duration samples)\n\nFor small data size classes, upsamling to 60 samples each class.(splitting long duration samples)\n\n## Inferece\nsegmentwise_output.\n\nPredicting 5 second periods with 2.5 seconds intervals. (Half overlapped each period)","metadata":{}},{"cell_type":"code","source":"# !pip install ../input/tensorflow-io0150/tensorflow_io-0.15.0-cp37-cp37m-manylinux2010_x86_64.whl","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:43:17.689848Z","iopub.execute_input":"2021-05-20T02:43:17.690322Z","iopub.status.idle":"2021-05-20T02:43:17.696989Z","shell.execute_reply.started":"2021-05-20T02:43:17.690224Z","shell.execute_reply":"2021-05-20T02:43:17.695456Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install -q tensorflow_io\n# tfp stable version won't work on TPU. https://github.com/tensorflow/tensorflow/issues/40584\n# !pip install -q tfp-nightly","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:43:17.699063Z","iopub.execute_input":"2021-05-20T02:43:17.699519Z","iopub.status.idle":"2021-05-20T02:44:24.053479Z","shell.execute_reply.started":"2021-05-20T02:43:17.699472Z","shell.execute_reply":"2021-05-20T02:44:24.052257Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# # There seems to be a problems in Kaggle TPU environment...\n# # hack to avoid errors\n# !pip install cloud-tpu-client\n\n# import tensorflow as tf\n# from cloud_tpu_client import Client\n# print(tf.__version__)\n\n# Client().configure_tpu_version(tf.__version__, restart_type='ifNeeded')","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:24.055567Z","iopub.execute_input":"2021-05-20T02:44:24.055888Z","iopub.status.idle":"2021-05-20T02:44:24.059326Z","shell.execute_reply.started":"2021-05-20T02:44:24.055846Z","shell.execute_reply":"2021-05-20T02:44:24.058600Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nimport tensorflow.keras.backend as K\nimport tensorflow.keras.layers as L\nimport tensorflow_addons as tfa\nimport tensorflow_io as tfio\nfrom keras.applications.resnet50 import ResNet50\nfrom keras.applications.resnet50 import preprocess_input\n# from keras.utils import to_categorical\nfrom tensorflow.keras.utils import to_categorical\nfrom kaggle_datasets import KaggleDatasets\nimport os\nimport numpy as np\nimport pandas as pd\nimport yaml\nfrom IPython.display import display, Audio\nfrom sklearn.model_selection import StratifiedKFold\n\nprint(tf.__version__)","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2021-05-20T02:44:24.060693Z","iopub.execute_input":"2021-05-20T02:44:24.060975Z","iopub.status.idle":"2021-05-20T02:44:27.734145Z","shell.execute_reply.started":"2021-05-20T02:44:24.060948Z","shell.execute_reply":"2021-05-20T02:44:27.732879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Detect hardware, return appropriate distribution strategy\ntry:\n    # TPU detection. No parameters necessary if TPU_NAME environment variable is\n    # set: this is always the case on Kaggle.\n    tpu = tf.distribute.cluster_resolver.TPUClusterResolver()\n    # print('Running on TPU ', tpu.master())\nexcept ValueError:\n    tpu = None\n\nif tpu:\n    tf.config.experimental_connect_to_cluster(tpu)\n    tf.tpu.experimental.initialize_tpu_system(tpu)\n    strategy = tf.distribute.TPUStrategy(tpu)\nelse:\n    # Default distribution strategy in Tensorflow. Works on CPU and single GPU.\n    strategy = tf.distribute.get_strategy()\n\n# print(\"REPLICAS: \", strategy.num_replicas_in_sync)\nAUTO = tf.data.experimental.AUTOTUNE\n\nBATCH_SIZE = 32 * strategy.num_replicas_in_sync","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","execution":{"iopub.status.busy":"2021-05-20T02:44:27.735462Z","iopub.execute_input":"2021-05-20T02:44:27.735742Z","iopub.status.idle":"2021-05-20T02:44:33.548069Z","shell.execute_reply.started":"2021-05-20T02:44:27.735716Z","shell.execute_reply":"2021-05-20T02:44:33.547002Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"SEED = 777\nos.environ['PYTHONHASHSEED'] = str(SEED)\nnp.random.seed(SEED)\ntf.random.set_seed(SEED)\n\nUSE_FOLD=2\nN_SPLIT=7\nSAMPLE_RATE=32000\nNUM_CLASSES = 264\nPERIOD = 5","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:33.549405Z","iopub.execute_input":"2021-05-20T02:44:33.549722Z","iopub.status.idle":"2021-05-20T02:44:33.555905Z","shell.execute_reply.started":"2021-05-20T02:44:33.549692Z","shell.execute_reply":"2021-05-20T02:44:33.554859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Load data","metadata":{}},{"cell_type":"code","source":"train = pd.read_csv('../input/birdsong-resampled-train-audio-00/train_mod.csv')","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:33.557339Z","iopub.execute_input":"2021-05-20T02:44:33.557931Z","iopub.status.idle":"2021-05-20T02:44:34.681589Z","shell.execute_reply.started":"2021-05-20T02:44:33.557895Z","shell.execute_reply":"2021-05-20T02:44:34.680120Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Process secondary labels","metadata":{}},{"cell_type":"code","source":"BIRD_CODE = {\n    'aldfly': 0, 'ameavo': 1, 'amebit': 2, 'amecro': 3, 'amegfi': 4,\n    'amekes': 5, 'amepip': 6, 'amered': 7, 'amerob': 8, 'amewig': 9,\n    'amewoo': 10, 'amtspa': 11, 'annhum': 12, 'astfly': 13, 'baisan': 14,\n    'baleag': 15, 'balori': 16, 'banswa': 17, 'barswa': 18, 'bawwar': 19,\n    'belkin1': 20, 'belspa2': 21, 'bewwre': 22, 'bkbcuc': 23, 'bkbmag1': 24,\n    'bkbwar': 25, 'bkcchi': 26, 'bkchum': 27, 'bkhgro': 28, 'bkpwar': 29,\n    'bktspa': 30, 'blkpho': 31, 'blugrb1': 32, 'blujay': 33, 'bnhcow': 34,\n    'boboli': 35, 'bongul': 36, 'brdowl': 37, 'brebla': 38, 'brespa': 39,\n    'brncre': 40, 'brnthr': 41, 'brthum': 42, 'brwhaw': 43, 'btbwar': 44,\n    'btnwar': 45, 'btywar': 46, 'buffle': 47, 'buggna': 48, 'buhvir': 49,\n    'bulori': 50, 'bushti': 51, 'buwtea': 52, 'buwwar': 53, 'cacwre': 54,\n    'calgul': 55, 'calqua': 56, 'camwar': 57, 'cangoo': 58, 'canwar': 59,\n    'canwre': 60, 'carwre': 61, 'casfin': 62, 'caster1': 63, 'casvir': 64,\n    'cedwax': 65, 'chispa': 66, 'chiswi': 67, 'chswar': 68, 'chukar': 69,\n    'clanut': 70, 'cliswa': 71, 'comgol': 72, 'comgra': 73, 'comloo': 74,\n    'commer': 75, 'comnig': 76, 'comrav': 77, 'comred': 78, 'comter': 79,\n    'comyel': 80, 'coohaw': 81, 'coshum': 82, 'cowscj1': 83, 'daejun': 84,\n    'doccor': 85, 'dowwoo': 86, 'dusfly': 87, 'eargre': 88, 'easblu': 89,\n    'easkin': 90, 'easmea': 91, 'easpho': 92, 'eastow': 93, 'eawpew': 94,\n    'eucdov': 95, 'eursta': 96, 'evegro': 97, 'fiespa': 98, 'fiscro': 99,\n    'foxspa': 100, 'gadwal': 101, 'gcrfin': 102, 'gnttow': 103, 'gnwtea': 104,\n    'gockin': 105, 'gocspa': 106, 'goleag': 107, 'grbher3': 108, 'grcfly': 109,\n    'greegr': 110, 'greroa': 111, 'greyel': 112, 'grhowl': 113, 'grnher': 114,\n    'grtgra': 115, 'grycat': 116, 'gryfly': 117, 'haiwoo': 118, 'hamfly': 119,\n    'hergul': 120, 'herthr': 121, 'hoomer': 122, 'hoowar': 123, 'horgre': 124,\n    'horlar': 125, 'houfin': 126, 'houspa': 127, 'houwre': 128, 'indbun': 129,\n    'juntit1': 130, 'killde': 131, 'labwoo': 132, 'larspa': 133, 'lazbun': 134,\n    'leabit': 135, 'leafly': 136, 'leasan': 137, 'lecthr': 138, 'lesgol': 139,\n    'lesnig': 140, 'lesyel': 141, 'lewwoo': 142, 'linspa': 143, 'lobcur': 144,\n    'lobdow': 145, 'logshr': 146, 'lotduc': 147, 'louwat': 148, 'macwar': 149,\n    'magwar': 150, 'mallar3': 151, 'marwre': 152, 'merlin': 153, 'moublu': 154,\n    'mouchi': 155, 'moudov': 156, 'norcar': 157, 'norfli': 158, 'norhar2': 159,\n    'normoc': 160, 'norpar': 161, 'norpin': 162, 'norsho': 163, 'norwat': 164,\n    'nrwswa': 165, 'nutwoo': 166, 'olsfly': 167, 'orcwar': 168, 'osprey': 169,\n    'ovenbi1': 170, 'palwar': 171, 'pasfly': 172, 'pecsan': 173, 'perfal': 174,\n    'phaino': 175, 'pibgre': 176, 'pilwoo': 177, 'pingro': 178, 'pinjay': 179,\n    'pinsis': 180, 'pinwar': 181, 'plsvir': 182, 'prawar': 183, 'purfin': 184,\n    'pygnut': 185, 'rebmer': 186, 'rebnut': 187, 'rebsap': 188, 'rebwoo': 189,\n    'redcro': 190, 'redhea': 191, 'reevir1': 192, 'renpha': 193, 'reshaw': 194,\n    'rethaw': 195, 'rewbla': 196, 'ribgul': 197, 'rinduc': 198, 'robgro': 199,\n    'rocpig': 200, 'rocwre': 201, 'rthhum': 202, 'ruckin': 203, 'rudduc': 204,\n    'rufgro': 205, 'rufhum': 206, 'rusbla': 207, 'sagspa1': 208, 'sagthr': 209,\n    'savspa': 210, 'saypho': 211, 'scatan': 212, 'scoori': 213, 'semplo': 214,\n    'semsan': 215, 'sheowl': 216, 'shshaw': 217, 'snobun': 218, 'snogoo': 219,\n    'solsan': 220, 'sonspa': 221, 'sora': 222, 'sposan': 223, 'spotow': 224,\n    'stejay': 225, 'swahaw': 226, 'swaspa': 227, 'swathr': 228, 'treswa': 229,\n    'truswa': 230, 'tuftit': 231, 'tunswa': 232, 'veery': 233, 'vesspa': 234,\n    'vigswa': 235, 'warvir': 236, 'wesblu': 237, 'wesgre': 238, 'weskin': 239,\n    'wesmea': 240, 'wessan': 241, 'westan': 242, 'wewpew': 243, 'whbnut': 244,\n    'whcspa': 245, 'whfibi': 246, 'whtspa': 247, 'whtswi': 248, 'wilfly': 249,\n    'wilsni1': 250, 'wiltur': 251, 'winwre3': 252, 'wlswar': 253, 'wooduc': 254,\n    'wooscj2': 255, 'woothr': 256, 'y00475': 257, 'yebfly': 258, 'yebsap': 259,\n    'yehbla': 260, 'yelwar': 261, 'yerwar': 262, 'yetvir': 263\n}\n\nINV_BIRD_CODE = {v: k for k, v in BIRD_CODE.items()}","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:34.684350Z","iopub.execute_input":"2021-05-20T02:44:34.684684Z","iopub.status.idle":"2021-05-20T02:44:34.713806Z","shell.execute_reply.started":"2021-05-20T02:44:34.684652Z","shell.execute_reply":"2021-05-20T02:44:34.712449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/hawkey/birdsong-multi-label-dataset\nimport re\nSPS_CODE = dict(zip(train.sci_name, train.ebird_code))\n# background\ndef get_sps_from_bg(s):\n    if type(s) != str: s = str(s)\n    return re.findall('\\((.*?)\\)', s)\n\n# secondary\ndef get_sps_from_sec(l):\n    return [re.split('_', s[1:-1])[0] for s in re.split(',\\s*', l[1:-1])]\n\ndef map_sps_to_code(l):\n    res = []\n    for s in l:\n        if s == '':\n            continue\n        elif s in SPS_CODE:\n            res.append(SPS_CODE[s])\n        else:\n            None\n            # there are species not included in the classification targets (thus no ebird_code)\n#             print(f\"{s} doesn't exist.\")\n    return res\n\ntrain['labels_bg'] = train['background'].apply(get_sps_from_bg).apply(map_sps_to_code)\ntrain['labels_sec'] = train['secondary_labels'].apply(get_sps_from_sec).apply(map_sps_to_code)\ntrain['secondary_codes'] = [list(set(a+b)) for a,b in zip(train['labels_sec'].values, train['labels_bg'].values)]","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:34.716567Z","iopub.execute_input":"2021-05-20T02:44:34.716970Z","iopub.status.idle":"2021-05-20T02:44:35.157148Z","shell.execute_reply.started":"2021-05-20T02:44:34.716934Z","shell.execute_reply":"2021-05-20T02:44:35.156017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# flitering secondary codes because secondary codes isn't reliable in long duration data. \nfilter_limit = 30\ntrain['secondary_codes'] = train['secondary_codes'].where(train['duration'] < filter_limit, '[]')\n\n# BIRD_CODE to number\ntrain.secondary_codes = train.secondary_codes.apply(lambda x: list(x for x in map(BIRD_CODE.get, x) if x is not None))","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:35.158576Z","iopub.execute_input":"2021-05-20T02:44:35.158895Z","iopub.status.idle":"2021-05-20T02:44:35.388005Z","shell.execute_reply.started":"2021-05-20T02:44:35.158862Z","shell.execute_reply":"2021-05-20T02:44:35.386722Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Dealing with Imbalanced Data","metadata":{}},{"cell_type":"code","source":"# downsampling to 80 samples per sepecies for large data. (removing longer samples)\n# \ndef downsampling(df):\n    main_data = pd.DataFrame()\n    for ebird_code in list(df.groupby('ebird_code').groups.keys()):\n        main_data = pd.concat([main_data, df[df['ebird_code'] == ebird_code].sort_values('duration')[:80]])\n    return main_data\n\n# upsampling data to 60 samples per sepecies for small data. (splitting \"duration > 40\" samples)\ndef upsampling(df):\n    def duplicate_long_data(df, ebird_code, dif):            \n        long_data = df[df['ebird_code'] == ebird_code].query('duration > 40').sort_values('duration', ascending=False)[:dif]\n        df = pd.concat([df, long_data])\n        return df\n    for i in range(5):\n        ebird_code_count = df.groupby('ebird_code').count().filename\n        for ebird_code in ebird_code_count.keys():\n                dif = 60 - ebird_code_count[ebird_code]\n                if dif > 0:\n                    df = duplicate_long_data(df, ebird_code, dif)\n                else:\n                    continue\n    return df","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:35.389259Z","iopub.execute_input":"2021-05-20T02:44:35.389551Z","iopub.status.idle":"2021-05-20T02:44:35.398620Z","shell.execute_reply.started":"2021-05-20T02:44:35.389523Z","shell.execute_reply":"2021-05-20T02:44:35.397259Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import re\n# birdsong-resampled-train-audio\nGCS_PATH0 = KaggleDatasets().get_gcs_path('birdsong-resampled-train-audio-00')\nGCS_PATH1 = KaggleDatasets().get_gcs_path('birdsong-resampled-train-audio-01')\nGCS_PATH2 = KaggleDatasets().get_gcs_path('birdsong-resampled-train-audio-02')\nGCS_PATH3 = KaggleDatasets().get_gcs_path('birdsong-resampled-train-audio-03')\nGCS_PATH4 = KaggleDatasets().get_gcs_path('birdsong-resampled-train-audio-04')\n\n\ntrain_all = train.copy()\ntrain_all['file_path'] = ''\n\ndef f(x):\n    fl = x[0]   \n    def get_gcp_path(fl): \n        if re.compile('[a-b]').fullmatch(fl):\n            return GCS_PATH0\n        elif re.compile('[c-f]').fullmatch(fl):\n            return GCS_PATH1\n        elif re.compile('[g-m]').fullmatch(fl):\n            return GCS_PATH2\n        elif re.compile('[n-r]').fullmatch(fl):\n            return GCS_PATH3\n        elif re.compile('[s-y]').fullmatch(fl):\n            return GCS_PATH4\n        else:\n            raise Exception('no matching code')\n    return get_gcp_path(fl) + '/' + x + '/'\ntrain_all['file_path'] = train_all['ebird_code'].map(f) +  train_all['resampled_filename']\n\ntrain_all = downsampling(train_all)\n\nskf = StratifiedKFold(n_splits=N_SPLIT, shuffle=True, random_state=1)\n\ntrain_all[\"fold\"] = -1\nfor fold_id, (train_index, val_index) in enumerate(skf.split(train_all, train_all[\"ebird_code\"])):\n    train_all.iloc[val_index, -1] = fold_id\n\nprint(len(train_all))\ntrain_all = upsampling(train_all)\nprint(len(train_all))\n\nuse_fold = USE_FOLD\ntrain_file_list = train_all.query(\"fold != @use_fold\")[[\"file_path\", \"ebird_code\", \"secondary_codes\"]]\nval_file_list = train_all.query(\"fold == @use_fold\")[[\"file_path\", \"ebird_code\", \"secondary_codes\"]]\n\nprint(\"[fold {}] train: {}, val: {}\".format(use_fold, len(train_file_list), len(val_file_list)))","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:35.400162Z","iopub.execute_input":"2021-05-20T02:44:35.400652Z","iopub.status.idle":"2021-05-20T02:44:51.740645Z","shell.execute_reply.started":"2021-05-20T02:44:35.400618Z","shell.execute_reply":"2021-05-20T02:44:51.739241Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_file_list.ebird_code = train_file_list.ebird_code.map(BIRD_CODE)\nval_file_list.ebird_code = val_file_list.ebird_code.map(BIRD_CODE)\n\ntrain_file_list.secondary_codes = [list(set(s + [p])) for s , p in zip(train_file_list.secondary_codes, train_file_list.ebird_code)]\nval_file_list.secondary_codes = [list(set(s + [p])) for s , p in zip(val_file_list.secondary_codes, val_file_list.ebird_code)]","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:51.742355Z","iopub.execute_input":"2021-05-20T02:44:51.742824Z","iopub.status.idle":"2021-05-20T02:44:51.795602Z","shell.execute_reply.started":"2021-05-20T02:44:51.742778Z","shell.execute_reply":"2021-05-20T02:44:51.793778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# hoge  = train_file_list.secondary_codes.apply(lambda x: sum(list(map(lambda x: to_categorical(x, NUM_CLASSES), x)))).tolist()","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:51.797300Z","iopub.execute_input":"2021-05-20T02:44:51.798025Z","iopub.status.idle":"2021-05-20T02:44:52.047565Z","shell.execute_reply.started":"2021-05-20T02:44:51.797980Z","shell.execute_reply":"2021-05-20T02:44:52.046703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import functools\nimport tensorflow_probability as tfp\n\ndef mixup(batch_size, alpha, images, labels):\n    \"\"\"Applies Mixup regularization to a batch of images and labels.\n    [1] Hongyi Zhang, Moustapha Cisse, Yann N. Dauphin, David Lopez-Paz\n      Mixup: Beyond Empirical Risk Minimization.\n      ICLR'18, https://arxiv.org/abs/1710.09412\n    Arguments:\n      batch_size: The input batch size for images and labels.\n      alpha: Float that controls the strength of Mixup regularization.\n      images: A batch of images of shape [batch_size, ...]\n      labels: A batch of labels of shape [batch_size, num_classes]\n    Returns:\n      A tuple of (images, labels) with the same dimensions as the input with\n      Mixup regularization applied.\n    \"\"\"\n    if  tf.random.uniform([]) < 0.5:\n        return images, (tf.zeros([batch_size, 1, NUM_CLASSES]),labels) \n    mix_weight = tfp.distributions.Beta(alpha, alpha).sample([batch_size, 1])\n    mix_weight = tf.maximum(mix_weight, 1. - mix_weight)\n    images_mix_weight = tf.reshape(mix_weight, [batch_size, 1, 1, 1])\n    # Mixup on a single batch is implemented by taking a weighted sum with the\n    # same batch in reverse.\n    images_mix = (\n        images * images_mix_weight + images[::-1] * (1. - images_mix_weight))\n    labels_mix = labels * mix_weight + labels[::-1] * (1. - mix_weight)\n    # return  images_mix, labels_mix #images, labels \n    return  images_mix, (tf.zeros([batch_size, 1, NUM_CLASSES]),labels_mix) #images, labels \n\ndef augment_freq_time_mask(spectrogram,\n                           frequency_masking_para=15,\n                           time_masking_para=15,\n                           frequency_mask_num=1,\n                           time_mask_num=1):\n    time_max = tf.shape(spectrogram)[1]\n    freq_max = tf.shape(spectrogram)[2]\n    # Frequency masking\n    for _ in range(frequency_mask_num):\n        f = tf.random.uniform(shape=(), minval=0, maxval=frequency_masking_para, dtype=tf.dtypes.int32)\n        f0 = tf.random.uniform(shape=(), minval=0, maxval=freq_max - f, dtype=tf.dtypes.int32)\n        value_ones_freq_prev = tf.ones(shape=[1, time_max, f0])\n        value_zeros_freq = tf.zeros(shape=[1, time_max, f])\n        value_ones_freq_next = tf.ones(shape=[1, time_max, freq_max-(f0+f)])\n        freq_mask = tf.concat([value_ones_freq_prev, value_zeros_freq, value_ones_freq_next], axis=2)\n        # mel_spectrogram[:, f0:f0 + f, :] = 0 #can't assign to tensor\n        # mel_spectrogram[:, f0:f0 + f, :] = value_zeros_freq #can't assign to tensor\n        spectrogram = spectrogram*freq_mask\n\n    # Time masking\n    for _ in range(time_mask_num):\n        t = tf.random.uniform(shape=(), minval=0, maxval=time_masking_para, dtype=tf.dtypes.int32)\n        t0 = tf.random.uniform(shape=(), minval=0, maxval=time_max - t, dtype=tf.dtypes.int32)\n        value_zeros_time_prev = tf.ones(shape=[1, t0, freq_max])\n        value_zeros_time = tf.zeros(shape=[1, t, freq_max])\n        value_zeros_time_next = tf.ones(shape=[1, time_max-(t0+t), freq_max])\n        time_mask = tf.concat([value_zeros_time_prev, value_zeros_time, value_zeros_time_next], axis=1)\n        # mel_spectrogram[:, :, t0:t0 + t] = 0 #can't assign to tensor\n        # mel_spectrogram[:, :, t0:t0 + t] = value_zeros_time #can't assign to tensor\n        spectrogram = spectrogram*time_mask\n\n    return spectrogram\n\ndef augment_pitch_and_tempo(spectrogram,\n                            max_tempo=1.2,\n                            max_pitch=1.1,\n                            min_pitch=0.95):\n    original_shape = tf.shape(spectrogram)\n    choosen_pitch = tf.random.uniform(shape=(), minval=min_pitch, maxval=max_pitch)\n    choosen_tempo = tf.random.uniform(shape=(), minval=1, maxval=max_tempo)\n    new_freq_size = tf.cast(tf.cast(original_shape[2], tf.float32)*choosen_pitch, tf.int32)\n    new_time_size = tf.cast(tf.cast(original_shape[1], tf.float32)/(choosen_tempo), tf.int32)\n    spectrogram_aug = tf.image.resize(tf.expand_dims(spectrogram, -1), [new_time_size, new_freq_size])\n    spectrogram_aug = tf.image.crop_to_bounding_box(spectrogram_aug, offset_height=0, offset_width=0, target_height=tf.shape(spectrogram_aug)[1], target_width=tf.minimum(original_shape[2], new_freq_size))\n    spectrogram_aug = tf.cond(choosen_pitch < 1,\n                              lambda: tf.image.pad_to_bounding_box(spectrogram_aug, offset_height=0, offset_width=0,\n                                                                   target_height=tf.shape(spectrogram_aug)[1], target_width=original_shape[2]),\n                              lambda: spectrogram_aug)\n    return spectrogram_aug[:, :, :, 0]\n\ndef augment_speed_up(spectrogram,\n                     speed_std=0.1):\n    original_shape = tf.shape(spectrogram)\n    choosen_speed = tf.math.abs(tf.random.normal(shape=(), stddev=speed_std)) # abs makes sure the augmention will only speed up\n    choosen_speed = 1 + choosen_speed\n    new_freq_size = tf.cast(tf.cast(original_shape[2], tf.float32), tf.int32)\n    new_time_size = tf.cast(tf.cast(original_shape[1], tf.float32)/(choosen_speed), tf.int32)\n    spectrogram_aug = tf.image.resize(tf.expand_dims(spectrogram, -1), [new_time_size, new_freq_size])\n    return spectrogram_aug[:, :, :, 0]\n\ndef augment_dropout(spectrogram,\n                    keep_prob=0.9):\n    return tf.nn.dropout(spectrogram, rate=1-keep_prob)\n\ndef transform_spectrogram(spectrogram,y):\n    spectrogram = tf.expand_dims(spectrogram, axis=0)\n    if  tf.random.uniform([]) > 0.7:\n        spectrogram = augment_freq_time_mask(spectrogram)\n    rand = tf.random.uniform([])\n    if  rand < 0.3:\n        spectrogram = augment_dropout(spectrogram, keep_prob=1-rand)\n    if  tf.random.uniform([]) < 0.2:\n        spectrogram = augment_pitch_and_tempo(spectrogram)\n    spectrogram = tf.squeeze(spectrogram, axis=0)\n    return spectrogram,y","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:52.049776Z","iopub.execute_input":"2021-05-20T02:44:52.050612Z","iopub.status.idle":"2021-05-20T02:44:52.900851Z","shell.execute_reply.started":"2021-05-20T02:44:52.050556Z","shell.execute_reply":"2021-05-20T02:44:52.899949Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def paths_and_labels_to_dataset(audio_paths, labels, sec_labels):\n    \"\"\"Constructs a dataset of audios and labels.\"\"\"\n    path_ds = tf.data.Dataset.from_tensor_slices(audio_paths)\n    audio_ds = path_ds.map(lambda x: path_to_audio(x), num_parallel_calls=AUTO)\n    label_ds = tf.data.Dataset.from_tensor_slices(to_categorical(labels))\n\n#     sec_labels_ds = tf.data.Dataset.from_tensor_slices(sec_labels.apply(lambda x: sum(list(map(lambda x: to_categorical(x, NUM_CLASSES), x)))).tolist())\n    # sec_labels = 1\n    label_ds = tf.data.Dataset.from_tensor_slices(sec_labels.apply(lambda x: sum(list(map(lambda x: to_categorical(x, NUM_CLASSES), x)))).tolist())\n    # sec_labels = 0.5\n    # label_ds = tf.data.Dataset.zip((label_ds, sec_labels_ds)).map(lambda p,s: tf.clip_by_value(p + s * 0.5, 0.0, 1.0) , num_parallel_calls=AUTO)\n    return tf.data.Dataset.zip((audio_ds, label_ds))\n\ndef path_to_audio(path):\n    \"\"\"Reads and decodes an audio file.\"\"\"\n    audio = tf.io.read_file(path)\n    audio, sample_rate = tf.audio.decode_wav(audio, 1)    \n    return audio\n\ndef split_audio(audio, y):\n    len_audio = len(audio)\n    effective_length = SAMPLE_RATE * PERIOD \n    if len_audio <= effective_length:\n        audio = tf.concat([audio, tf.expand_dims(tf.zeros([effective_length - len_audio]), 1)], axis=0)\n    else:\n        start = tf.random.uniform([1], maxval = len_audio - effective_length, dtype = tf.int32)[0]\n        audio = audio[start:start + effective_length]\n    return audio, y\n\n# def split_audio_val(audio, y):\n#     len_audio = len(audio)\n#     effective_length = SAMPLE_RATE * PERIOD \n#     if len_audio <= effective_length:\n#         audio = tf.concat([audio, tf.expand_dims(tf.zeros([effective_length - len_audio]), 1)], axis=0)\n#     else:\n#         # split down the middle\n#         # start = tf.math.floordiv(len_audio - effective_length, 2)\n#         start = 0\n#         audio = audio[start: start + effective_length]\n#     return audio, y\n\ndef audio_to_fft(audio, y):\n    # Since tf.signal.fft applies FFT on the innermost dimension,\n    # we need to squeeze the dimensions and then expand them again\n    # after FFT\n    audio = tf.squeeze(audio, axis=-1)\n    fft = tf.signal.fft(\n        tf.cast(tf.complex(real=audio, imag=tf.zeros_like(audio)), tf.complex64)\n    )\n    # print(audio.shape)\n    fft = tf.expand_dims(fft, axis=-1)\n\n    # Return the absolute value of the first half of the FFT\n    # which represents the positive frequencies\n    return tf.math.abs(fft[: (audio.shape[0] // 2), :]), y\n\ndef audio_to_mel_spectrogram(audio, y):\n    audio = tf.squeeze(audio, axis=-1)\n    spectrogram = tfio.audio.spectrogram(\n        audio, nfft=2048, window=2048, stride=320)\n\n    mel_spectrogram = tfio.audio.melscale(\n        spectrogram, rate=SAMPLE_RATE, mels=500, fmin=50, fmax=14000)\n    \n    dbscale_mel_spectrogram = tfio.audio.dbscale(\n        mel_spectrogram, top_db=80)\n\n    return dbscale_mel_spectrogram, y\n\ndef mono_to_color(audio, y):\n    eps=1e-6\n    X = audio\n    # Stack X as [X,X,X]\n    X = tf.stack([X, X, X], axis=-1)\n\n    # Standardize\n    mean = tf.math.reduce_mean(X)\n    X = X - mean\n    std = tf.math.reduce_std(X)\n    Xstd = X / (std + eps)\n    _min, _max = tf.math.reduce_min(Xstd), tf.math.reduce_max(Xstd)\n    norm_max = _max\n    norm_min = _min\n    if (_max - _min) > eps:\n        # Normalize to [0, 255]\n        V = Xstd\n        V = 255 * (V - norm_min) / (norm_max - norm_min)\n    else:\n        # Just zero\n        V = tf.zeros_like(Xstd)\n    img_size = 224\n    image = tf.image.resize(V, (img_size,img_size))\n\n    return preprocess_input(image), y\n","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:45:37.248668Z","iopub.execute_input":"2021-05-20T02:45:37.249077Z","iopub.status.idle":"2021-05-20T02:45:37.270416Z","shell.execute_reply.started":"2021-05-20T02:45:37.249046Z","shell.execute_reply":"2021-05-20T02:45:37.269177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for hoge in paths_and_labels_to_dataset(train_file_list['file_path'].values.tolist(), train_file_list['ebird_code'].values.tolist(), train_file_list['secondary_codes']).take(1):\n#     print(hoge)","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:45:37.620965Z","iopub.execute_input":"2021-05-20T02:45:37.621540Z","iopub.status.idle":"2021-05-20T02:45:37.626040Z","shell.execute_reply.started":"2021-05-20T02:45:37.621493Z","shell.execute_reply":"2021-05-20T02:45:37.624671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_ds = (\n    paths_and_labels_to_dataset(train_file_list['file_path'].values.tolist(), train_file_list['ebird_code'].values.tolist(), train_file_list['secondary_codes'])\n    .cache()\n    .map(split_audio, num_parallel_calls=AUTO)\n    .map(audio_to_mel_spectrogram, num_parallel_calls=AUTO)\n    .map(transform_spectrogram, num_parallel_calls=AUTO)\n    .map(mono_to_color, num_parallel_calls=AUTO)\n    .shuffle(1024)\n    .repeat()\n    .batch(BATCH_SIZE, drop_remainder=True)\n#     .map(functools.partial(mixup, BATCH_SIZE, 0.2), num_parallel_calls=AUTO)\n    .prefetch(AUTO)\n)\n\n\nvalid_ds = (\n    paths_and_labels_to_dataset(val_file_list['file_path'].values.tolist(), val_file_list['ebird_code'].values.tolist(), val_file_list['secondary_codes'])\n    .map(split_audio, num_parallel_calls=AUTO)\n    .map(audio_to_mel_spectrogram, num_parallel_calls=AUTO)\n    .map(mono_to_color, num_parallel_calls=AUTO)\n    .cache()\n    .batch(BATCH_SIZE, drop_remainder=True)\n    .prefetch(AUTO)\n)","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:47:04.435918Z","iopub.execute_input":"2021-05-20T02:47:04.436280Z","iopub.status.idle":"2021-05-20T02:47:08.385558Z","shell.execute_reply.started":"2021-05-20T02:47:04.436250Z","shell.execute_reply":"2021-05-20T02:47:08.384507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# https://www.kaggle.com/itsuki9180/birdcall-using-tpu-train\nfrom keras.callbacks import Callback\n\nclass F1Callback(Callback):\n    def __init__(self):\n        self.f1s = []\n\n    def on_epoch_end(self, epoch, logs):\n        eps = np.finfo(np.float32).eps\n        recall = logs[\"val_clipwise_output_true_positives\"] / (logs[\"val_clipwise_output_possible_positives\"] + eps)\n        precision = logs[\"val_clipwise_output_true_positives\"] / (logs[\"val_clipwise_output_predicted_positives\"] + eps)\n        f1 = 2*precision*recall / (precision+recall+eps)\n        print(\"f1_val (from log) =\", f1)\n        self.f1s.append(f1)\n\ndef true_positives(y_true, y_pred):\n    return K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))\n\ndef possible_positives(y_true, y_pred):\n    return K.sum(K.round(K.clip(y_true, 0, 1)))\n\ndef predicted_positives(y_true, y_pred):\n    return K.sum(K.round(K.clip(y_pred, 0, 1)))\n\ndef F1(y_true, y_pred):\n    TPFN = possible_positives(y_true, y_pred)\n    TPFP = predicted_positives(y_true, y_pred)\n    TP = true_positives(y_true, y_pred)\n    return  (TP * 2) / (TPFN + TPFP + K.epsilon())\n\nf1cb = F1Callback()\n","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:47:08.387286Z","iopub.execute_input":"2021-05-20T02:47:08.387598Z","iopub.status.idle":"2021-05-20T02:47:08.399479Z","shell.execute_reply.started":"2021-05-20T02:47:08.387570Z","shell.execute_reply":"2021-05-20T02:47:08.398277Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with strategy.scope():\n    base_model = ResNet50(include_top=False, weights='imagenet')\n    # for inference\n#     base_model = ResNet50(include_top=False, weights=None)\n    x = base_model.output\n\n    # https://gist.github.com/hengck23/6ebe1c75f8b3bcc953c0599ac76bad45\n    x = tf.reduce_mean(x, axis=2)\n    x1 = L.MaxPooling1D(pool_size=3, strides=1, padding='same')(x)\n    x2 = L.AveragePooling1D(pool_size=3, strides=1, padding='same')(x)\n    x = x1 + x2 \n    x = L.Dropout(0.5)(x)\n    x = L.Dense(1024, activation='relu')(x)\n    x = L.Dropout(0.5)(x)\n\n    norm_att = L.Conv1D(filters=NUM_CLASSES, kernel_size=1, padding='same')(x)\n    norm_att = tf.keras.activations.tanh(norm_att/10)*10\n    norm_att = tf.keras.activations.softmax(norm_att, axis=-2)\n    segmentwise_output = L.Conv1D(filters=NUM_CLASSES, kernel_size=1, padding='same', activation='sigmoid', name='segmentwise_output')(x)\n    clipwise_output = tf.math.reduce_sum(norm_att * segmentwise_output, axis=1)\n    clipwise_output = L.Lambda(lambda x: x, name=\"clipwise_output\")(clipwise_output)\n    output = [segmentwise_output, clipwise_output]\n\n    model = tf.keras.models.Model(inputs=base_model.input, outputs=output)\n    optimizer= tfa.optimizers.RectifiedAdam(\n        lr=1e-3,\n        total_steps=10000,\n        warmup_proportion=0.1,\n        min_lr=1e-8,\n    )\n\n    model.compile(optimizer, loss=[None, \"binary_crossentropy\"],loss_weights=[0,1], metrics=[[],[\"accuracy\", F1,true_positives,possible_positives,predicted_positives]])\n    model.summary()","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:47:08.401760Z","iopub.execute_input":"2021-05-20T02:47:08.402206Z","iopub.status.idle":"2021-05-20T02:47:20.993615Z","shell.execute_reply.started":"2021-05-20T02:47:08.402163Z","shell.execute_reply":"2021-05-20T02:47:20.989788Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"%%time\nes = tf.keras.callbacks.EarlyStopping(monitor='loss', verbose=1, patience=10)\nsv = tf.keras.callbacks.ModelCheckpoint('model.h5', monitor='val_loss', verbose=1, save_best_only=True, save_weights_only=True)\nreduce_lr = tf.keras.callbacks.ReduceLROnPlateau(monitor='loss', verbose=1, factor=0.5, patience=2, min_delta=0.0001, cooldown=1, min_lr=1e-7)\n\nSTEPS_PER_EPOCH = len(train_file_list) // BATCH_SIZE\nVALIDATION_STEP = len(val_file_list) // BATCH_SIZE\n\nhistory = model.fit(\n    train_ds,\n    epochs=100,\n    steps_per_epoch=STEPS_PER_EPOCH,\n    callbacks=[reduce_lr, es, sv, f1cb],\n    validation_data=valid_ds,\n    validation_steps = VALIDATION_STEP\n)","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:47:20.995720Z","iopub.execute_input":"2021-05-20T02:47:20.996196Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Inferece","metadata":{}},{"cell_type":"code","source":"# import tensorflow as tf\n# import tensorflow.keras.backend as K\n# import tensorflow.keras.layers as L\n# import tensorflow_io as tfio\n# from keras.applications.resnet50 import ResNet50\n# from keras.applications.resnet50 import preprocess_input, decode_predictions\n# import os\n# import numpy as np\n# import pandas as pd\n# import yaml\n# import librosa\n# from pathlib import Path\n\n# TEST_PATH = Path('../input/birdsong-recognition') if os.path.exists('../input/birdsong-recognition/test_audio') else Path('../input/birdcall-check')\n\n# TEST_AUDIO_PATH = TEST_PATH/'test_audio'\n# test = pd.read_csv(TEST_PATH/'test.csv')\n\n# model.load_weights('../input/birdcallweight/model.h5')","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.507859Z","iopub.status.idle":"2021-05-20T02:44:56.508341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def audio_to_mel_spectrogram(audio):\n#     spectrogram = tfio.experimental.audio.spectrogram(\n#         audio, nfft=2048, window=2048, stride=320)\n#     mel_spectrogram = tfio.experimental.audio.melscale(\n#         spectrogram, rate=SAMPLE_RATE, mels=500, fmin=50, fmax=14000)\n    \n#     dbscale_mel_spectrogram = tfio.experimental.audio.dbscale(\n#         mel_spectrogram, top_db=80)\n#     return dbscale_mel_spectrogram\n\n# def mono_to_color(audio):\n#     eps=1e-6\n#     X = audio\n#     X = tf.stack([X, X, X], axis=-1)\n\n#     mean = tf.math.reduce_mean(X)\n#     X = X - mean\n#     std = tf.math.reduce_std(X)\n#     Xstd = X / (std + eps)\n#     _min, _max = tf.math.reduce_min(Xstd), tf.math.reduce_max(Xstd)\n#     norm_max = _max\n#     norm_min = _min\n#     if (_max - _min) > eps:\n#         V = Xstd\n#         V = 255 * (V - norm_min) / (norm_max - norm_min)\n#     else:\n#         V = tf.zeros_like(Xstd)\n#     img_size = 224\n#     image = tf.image.resize(V, (img_size,img_size))\n#     return preprocess_input(image)","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.509572Z","iopub.status.idle":"2021-05-20T02:44:56.510048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def upsample(x):\n#     ratio = 72\n#     (time_steps, classes_num) = x.shape\n#     upsampled = np.repeat(x, ratio, axis=0)\n#     upsampled = upsampled[2:-2]\n#     return upsampled\n\n# def prediction_for_clip(test_df: pd.DataFrame,\n#                         clip: np.ndarray, \n#                         model: tf.keras.models.Model,\n#                         threshold=0.5):\n#     PERIOD = 5\n#     INTERVAL_RATE = 0.5\n#     OFFSET_LEGNTH = 0.01\n#     audios = []\n#     LENGTH_THRESHOLD = 0.1\n#     y = clip.astype(np.float32)\n#     len_y = len(y)\n#     start = 0\n#     end = PERIOD * SAMPLE_RATE\n#     while True:\n#         y_batch = y[start:end].astype(np.float32)\n#         if len(y_batch) != PERIOD * SAMPLE_RATE:\n#             y_pad = np.zeros(PERIOD * SAMPLE_RATE, dtype=np.float32)\n#             y_pad[:len(y_batch)] = y_batch\n#             audios.append(y_pad)\n#             break\n#         start = end - int(PERIOD * (1.0-INTERVAL_RATE) * SAMPLE_RATE)\n#         end = start + PERIOD * SAMPLE_RATE\n#         audios.append(y_batch)\n        \n#     array = np.asarray(audios)\n\n#     estimated_event_list = []\n#     global_time = 0.0\n#     site = test_df[\"site\"].values[0]\n#     audio_id = test_df[\"audio_id\"].values[0]\n#     for audio in array:\n#         melspec = audio_to_mel_spectrogram(audio)\n#         image = mono_to_color(melspec)\n#         image = tf.expand_dims(image, axis=0)\n\n#         framewise_outputs, _ = model.predict(image)\n#         framewise_outputs = upsample(framewise_outputs[0])\n        \n#         thresholded = framewise_outputs >= threshold\n#         for target_idx in range(thresholded.shape[1]):\n#             if thresholded[:, target_idx].mean() == 0:\n#                 pass\n#             else:\n#                 detected = np.argwhere(thresholded[:, target_idx]).reshape(-1)\n#                 head_idx = 0\n#                 tail_idx = 0\n#                 while True:\n#                     if (tail_idx + 1 == len(detected)) or (\n#                             detected[tail_idx + 1] - \n#                             detected[tail_idx] != 1):\n                                \n#                         onset = OFFSET_LEGNTH * detected[\n#                             head_idx] + global_time\n#                         offset = OFFSET_LEGNTH * detected[\n#                             tail_idx] + global_time\n#                         onset_idx = detected[head_idx]\n#                         offset_idx = detected[tail_idx]\n#                         max_confidence = framewise_outputs[\n#                             onset_idx:offset_idx, target_idx].max()\n#                         mean_confidence = framewise_outputs[\n#                             onset_idx:offset_idx, target_idx].mean()\n                                                    \n#                         estimated_event = {\n#                             \"site\": site,\n#                             \"audio_id\": audio_id,\n#                             \"ebird_code\": INV_BIRD_CODE[target_idx],\n#                             \"onset\": onset,\n#                             \"offset\": offset,\n#                             \"max_confidence\": max_confidence,\n#                             \"mean_confidence\": mean_confidence\n#                         }\n#                         if offset-onset > LENGTH_THRESHOLD or max_confidence > threshold * 1.5:\n#                             estimated_event_list.append(estimated_event)\n#                         else:\n#                             None\n# #                             print(estimated_event)\n#                         head_idx = tail_idx + 1\n#                         tail_idx = tail_idx + 1\n#                         if head_idx >= len(detected):\n#                             break\n#                     else:\n#                         tail_idx += 1\n#         global_time += PERIOD*INTERVAL_RATE\n        \n#     prediction_df = pd.DataFrame(estimated_event_list)\n#     return prediction_df","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.511042Z","iopub.status.idle":"2021-05-20T02:44:56.511476Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import warnings\n\n# warnings.filterwarnings(\"ignore\", category=UserWarning)\n# prediction_dfs = []\n\n\n# unique_audio_id = test.audio_id.unique()\n# for audio_id in unique_audio_id:\n#     print(audio_id)\n#     audio_path = TEST_AUDIO_PATH/f'{audio_id}.mp3'\n#     clip, _ = librosa.load(audio_path, sr=SAMPLE_RATE, mono=True, res_type=\"kaiser_fast\")\n#     test_df_for_audio_id = test.query(f\"audio_id == '{audio_id}'\").reset_index(drop=True)\n#     prediction_df = prediction_for_clip(test_df_for_audio_id,\n#                                           clip=clip,\n#                                           model=model,  \n#                                           threshold=0.85)\n#     prediction_dfs.append(prediction_df)\n                                        \n# prediction_df = pd.concat(prediction_dfs, axis=0, sort=False).reset_index(drop=True)\n# prediction_df","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.512478Z","iopub.status.idle":"2021-05-20T02:44:56.512926Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# labels = {}\n\n# for audio_id, sub_df in prediction_df.groupby(\"audio_id\"):\n#     events = sub_df[[\"ebird_code\", \"onset\", \"offset\", \"max_confidence\", \"site\"]].values\n#     n_events = len(events)\n#     removed_event = []\n    \n#     site = events[0][4]\n#     for i in range(n_events):\n#         if i in removed_event:\n#             continue\n#         event = events[i][0] \n#         onset = events[i][1] + 0.35\n#         offset = events[i][2] - 0.35\n#         if site in {\"site_1\", \"site_2\"}:\n#             start_section = int((onset // 5) * 5) + 5\n#             end_section = int((offset // 5) * 5) + 5\n#             cur_section = start_section\n\n#             row_id = f\"{site}_{audio_id}_{start_section}\"\n#             if labels.get(row_id) is not None:\n#                 labels[row_id].add(event)\n#             else:\n#                 labels[row_id] = set()\n#                 labels[row_id].add(event)\n\n#             while cur_section != end_section:\n#                 cur_section += 5\n#                 row_id = f\"{site}_{audio_id}_{cur_section}\"\n#                 if labels.get(row_id) is not None:\n#                     labels[row_id].add(event)\n#                 else:\n#                     labels[row_id] = set()\n#                     labels[row_id].add(event)\n#         else:\n#             row_id = f\"{site}_{audio_id}\"\n#             if labels.get(row_id) is not None:\n#                 labels[row_id].add(event)\n#             else:\n#                 labels[row_id] = set()\n#                 labels[row_id].add(event)\n\n# for key in labels:\n#     labels[key] = \" \".join(sorted(list(labels[key])))\n    \n    \n# row_ids = list(labels.keys())\n# birds = list(labels.values())\n# post_processed = pd.DataFrame({\n#     \"row_id\": row_ids,\n#     \"birds\": birds\n# })\n# post_processed.head()","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.514006Z","iopub.status.idle":"2021-05-20T02:44:56.514458Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# all_row_id = test[[\"row_id\"]]\n# submission = all_row_id.merge(post_processed, on=\"row_id\", how=\"left\")\n# submission = submission.fillna(\"nocall\")\n# submission.to_csv(\"submission.csv\", index=False)\n# submission.values","metadata":{"execution":{"iopub.status.busy":"2021-05-20T02:44:56.515989Z","iopub.status.idle":"2021-05-20T02:44:56.516433Z"},"trusted":true},"execution_count":null,"outputs":[]}]}