{"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 tensorflow as tf\nimport tensorflow_hub as hub\nimport tensorflow_io as tfio\n\nimport pandas as pd\nimport numpy as np\nimport librosa\nimport glob\nimport os\n\nimport csv\nimport io\nfrom tqdm.auto import tqdm\n\nfrom IPython.display import Audio","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-09T06:59:31.927849Z","iopub.execute_input":"2023-05-09T06:59:31.928497Z","iopub.status.idle":"2023-05-09T06:59:40.677608Z","shell.execute_reply.started":"2023-05-09T06:59:31.928465Z","shell.execute_reply":"2023-05-09T06:59:40.676489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = hub.load('https://kaggle.com/models/google/bird-vocalization-classifier/frameworks/tensorFlow2/variations/bird-vocalization-classifier/versions/2')\nlabels_path = hub.resolve('https://kaggle.com/models/google/bird-vocalization-classifier/frameworks/tensorFlow2/variations/bird-vocalization-classifier/versions/2') + \"/assets/label.csv\"","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:40.679982Z","iopub.execute_input":"2023-05-09T06:59:40.680796Z","iopub.status.idle":"2023-05-09T06:59:50.081751Z","shell.execute_reply.started":"2023-05-09T06:59:40.680743Z","shell.execute_reply":"2023-05-09T06:59:50.080705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Find the name of the class with the top score when mean-aggregated across frames.\ndef class_names_from_csv(class_map_csv_text):\n    \"\"\"Returns list of class names corresponding to score vector.\"\"\"\n    with open(labels_path) as csv_file:\n        csv_reader = csv.reader(csv_file, delimiter=',')\n        class_names = [mid for mid, desc in csv_reader]\n        return class_names[1:]\n\n## note that the bird classifier classifies a much larger set of birds than the\n## competition, so we need to load the model's set of class names or else our \n## indices will be off.\nclasses = class_names_from_csv(labels_path)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.083202Z","iopub.execute_input":"2023-05-09T06:59:50.08358Z","iopub.status.idle":"2023-05-09T06:59:50.100079Z","shell.execute_reply.started":"2023-05-09T06:59:50.083538Z","shell.execute_reply":"2023-05-09T06:59:50.098847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use on except pretraining dataset\ntrain_metadata = pd.read_csv(\"/kaggle/input/birdclef-2023/train_metadata.csv\")\n\n# Use on pretraining dataset\n#train_metadata = pd.read_csv(\"/kaggle/input/birdclef-2023-additional/pretrain_metadata_10fold.csv\")\n\n\ncompetition_classes = sorted(train_metadata.primary_label.unique())\n\nforced_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        print(c)\n        competition_class_map.append(0)\n        forced_defaults += 1\n        \n## this is the count of classes not supported by our pretrained model\n## you could choose to simply not predict these, set a default as above,\n## or create your own model using the pretrained model as a base.\nforced_defaults","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.102821Z","iopub.execute_input":"2023-05-09T06:59:50.103281Z","iopub.status.idle":"2023-05-09T06:59:50.256852Z","shell.execute_reply.started":"2023-05-09T06:59:50.103243Z","shell.execute_reply":"2023-05-09T06:59:50.25574Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_metadata","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.258472Z","iopub.execute_input":"2023-05-09T06:59:50.25881Z","iopub.status.idle":"2023-05-09T06:59:50.289362Z","shell.execute_reply.started":"2023-05-09T06:59:50.258774Z","shell.execute_reply":"2023-05-09T06:59:50.288237Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def frame_audio(\n      audio_array: np.ndarray,\n      window_size_s: float = 5.0,\n      hop_size_s: float = 5.0,\n      sample_rate = 32000,\n      ) -> np.ndarray:\n    \n    \"\"\"Helper function for framing audio for inference.\"\"\"\n    \"\"\" using tf.signal \"\"\"\n    if window_size_s is None or window_size_s < 0:\n        return audio_array[np.newaxis, :]\n    frame_length = int(window_size_s * sample_rate)\n    hop_length = int(hop_size_s * sample_rate)\n    framed_audio = tf.signal.frame(audio_array, frame_length, hop_length, pad_end=True)\n    return framed_audio\n\n\ndef ensure_sample_rate(waveform, original_sample_rate,\n                       desired_sample_rate=32000):\n    \"\"\"Resample waveform if required.\"\"\"\n    if original_sample_rate != desired_sample_rate:\n        waveform = tfio.audio.resample(waveform, original_sample_rate, desired_sample_rate)\n    return desired_sample_rate, waveform","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.290801Z","iopub.execute_input":"2023-05-09T06:59:50.291373Z","iopub.status.idle":"2023-05-09T06:59:50.299009Z","shell.execute_reply.started":"2023-05-09T06:59:50.291334Z","shell.execute_reply":"2023-05-09T06:59:50.297762Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def predict_for_sample(filename, sample_submission, index, frame_limit_secs=None):\n    \n    # Use on no-call dataset\n    #filename = f'/kaggle/input/birdclef2021-background-noise/ff1010bird_nocall/nocall/{filename}'\n    \n    # Use on additional xeno-canto(CC-BY-NC-SA)\n    #dirname = os.path.dirname(filename).split('/')[-1]\n    #basename = os.path.basename(filename)\n    #filename = f'/kaggle/input/birdclef-2023-additional/xeno-canto/{dirname}/{basename}'\n    \n    # Use on additional xeno-canto(and CC-BY-NC-ND)\n    #dirname = os.path.dirname(filename).split('/')[-1]\n    #basename = os.path.basename(filename)\n    #filename = f'/kaggle/input/birdclef-2023-additional/xeno-canto_nd/xeno-canto_nd/{dirname}/{basename}'\n\n    # Use on pretraining dataset\n    #filename = filename.replace('../', '/kaggle/')\n    \n    audio, sample_rate = librosa.load(filename, sr=32000, mono=True)\n    sample_rate, wav_data = ensure_sample_rate(audio, sample_rate)\n    \n    fixed_tm = frame_audio(wav_data)\n    \n    frame = 5\n    all_logits, all_embeddings = model.infer_tf(fixed_tm[:1])\n    for window in fixed_tm[1:]:\n        if frame_limit_secs and frame > frame_limit_secs:\n            continue\n        \n        logits, embeddings = model.infer_tf(window[np.newaxis, :])\n        all_logits = np.concatenate([all_logits, logits], axis=0)\n        frame += 5\n    \n    all_logits = np.mean(all_logits, axis=0)  # Averaged over all 5-sec clips\n    sample_submission.loc[index, competition_classes] = all_logits[competition_class_map]","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.300781Z","iopub.execute_input":"2023-05-09T06:59:50.301506Z","iopub.status.idle":"2023-05-09T06:59:50.315349Z","shell.execute_reply.started":"2023-05-09T06:59:50.301469Z","shell.execute_reply":"2023-05-09T06:59:50.314327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use on training dataset(2023)\ndata = pd.read_csv('/kaggle/input/birdclef-2023/train_metadata.csv')\n\n# Use on no-call dataset\n#data = pd.read_csv('/kaggle/input/birdclef-2023-additional/ff1010bird_metadata_v1.csv')\n\n# Use on additional xeno-canto(CC-BY-NC-SA)\n#data = pd.read_csv('/kaggle/input/birdclef-2023-additional/xeno-canto_audio_meta.csv')\n\n# Use on additional xeno-canto(CC-BY-NC-ND)\n#data = pd.read_csv('/kaggle/input/birdclef-2023-additional/xeno-canto_nd_audio_meta.csv')\n\n\n# Use on training dataset(2023)\ntest_samples = list('/kaggle/input/birdclef-2023/train_audio/' + data.filename)\n\n# Use on pretraining dataset\n#test_samples = list(train_metadata.filename)\n\n# Use on no-call dataset, additional xeno-canto(CC-BY-NC-SA), xeno-canto(CC-BY-NC-ND)\n#test_samples = list(data.filename)\n\nlen(test_samples)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.317263Z","iopub.execute_input":"2023-05-09T06:59:50.317697Z","iopub.status.idle":"2023-05-09T06:59:50.350145Z","shell.execute_reply.started":"2023-05-09T06:59:50.317661Z","shell.execute_reply":"2023-05-09T06:59:50.349263Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use on training dataset(2023), no-call dataset, xeno-canto(CC-BY-NC-SA), additional xeno-canto(CC-BY-NC-ND)\nsub = pd.read_csv(\"/kaggle/input/birdclef-2023/sample_submission.csv\")\n\n\n# Use on training dataset(2023), pretraining dataset\nsample_sub = train_metadata.copy()\n\n# Use on no-call dataset\n#sample_sub = pd.read_csv('/kaggle/input/birdclef-2023-additional/ff1010bird_metadata_v1.csv')\n\n# Use on additional xeno-canto(CC-BY-NC-SA)\n#sample_sub = pd.read_csv('/kaggle/input/birdclef-2023-additional/xeno-canto_audio_meta.csv')\n\n# Use on additional xeno-canto(CC-BY-NC-ND)\n#sample_sub = pd.read_csv('/kaggle/input/birdclef-2023-additional/xeno-canto_nd_audio_meta.csv')\n\n\n# Use on training dataset(2023), no-call dataset, additional xeno-canto(CC-BY-NC-SA), additional xeno-canto(CC-BY-NC-ND)\nfor c in sub.columns[1:]:\n    sample_sub[c] = 0\n\n# Use on pretraining dataset\n#for c in list(sample_sub.primary_label.unique()):\n#    sample_sub[c] = 0\n\n\nsample_sub[competition_classes] = sample_sub[competition_classes].astype(np.float32)\nsample_sub","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.353176Z","iopub.execute_input":"2023-05-09T06:59:50.353545Z","iopub.status.idle":"2023-05-09T06:59:50.697587Z","shell.execute_reply.started":"2023-05-09T06:59:50.353519Z","shell.execute_reply":"2023-05-09T06:59:50.695908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"frame_limit_secs = None\n\nfor index, sample_filename in enumerate(tqdm(test_samples)):\n    predict_for_sample(sample_filename, sample_sub, index, frame_limit_secs=frame_limit_secs)","metadata":{"execution":{"iopub.status.busy":"2023-05-09T06:59:50.701185Z","iopub.execute_input":"2023-05-09T06:59:50.702243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sample_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"columns_name = ['primary_label', 'filename']\n\n# Use on training dataset(2023), additional xeno-canto(and CC-BY-NC-SA), additional xeno-canto(and CC-BY-NC-ND)\nfor c in sub.columns[1:]:\n    columns_name.append(c)\n    \n# Use on pretraining dataset\n#for c in list(sample_sub.primary_label.unique()):\n#    columns_name.append(c)\n    \nsample_sub = sample_sub[columns_name]\nsample_sub","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Use on training dataset(2023)\nsample_sub.to_csv(\"train_meta_data_pseudo.csv\", index=False)\n\n# Use on no-call dataset\n#sample_sub.to_csv(\"ff1010bird_metadata_v1_pseudo.csv\", index=False)\n\n# Use on pretraining dataset\n#sample_sub.to_csv(\"pretrain_metadata_10fold_pseudo.csv\", index=False)\n\n# Use on additional xeno-canto(and CC-BY-NC-ND)\n#sample_sub.to_csv(\"xeno-canto_audio_meta_pseudo.csv\", index=False)\n\n# Use on additional xeno-canto(and CC-BY-NC-ND)\n#sample_sub.to_csv(\"xeno-canto_nd_audio_meta_pseudo.csv\", index=False)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}