{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":8146763,"sourceType":"datasetVersion","datasetId":4817596},{"sourceId":8165959,"sourceType":"datasetVersion","datasetId":4831835},{"sourceId":8636158,"sourceType":"datasetVersion","datasetId":5160228}],"dockerImageVersionId":30684,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import glob\nimport os\nimport warnings\nimport time\nimport numpy as np\nimport pandas as pd\nimport librosa\nimport torch\nfrom torch.utils.data import Dataset\nfrom tqdm.auto import tqdm\nimport soundfile as sf\nfrom scipy import signal\n\nwarnings.filterwarnings(\"ignore\")","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-06-08T02:30:08.401285Z","iopub.execute_input":"2024-06-08T02:30:08.401708Z","iopub.status.idle":"2024-06-08T02:30:08.415748Z","shell.execute_reply.started":"2024-06-08T02:30:08.401674Z","shell.execute_reply":"2024-06-08T02:30:08.413785Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"try:\n    import onnxruntime\nexcept:\n    !pip install  onnxruntime==1.17.1 --no-index --find-links=/kaggle/input/birdclef2024-final-models/onnx_runtime_pkgs\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.421541Z","iopub.execute_input":"2024-06-08T02:30:08.422053Z","iopub.status.idle":"2024-06-08T02:30:08.430355Z","shell.execute_reply.started":"2024-06-08T02:30:08.422017Z","shell.execute_reply":"2024-06-08T02:30:08.428772Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"is_kaggle = True\nif is_kaggle:\n    data_root = '/kaggle/input/birdclef-2024/'\nelse:\n    data_root = '/home/hw/m2_disk/kaggle/BirdCLEF2024_lhw/data/birdclef-2024/'","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.432533Z","iopub.execute_input":"2024-06-08T02:30:08.433091Z","iopub.status.idle":"2024-06-08T02:30:08.446661Z","shell.execute_reply.started":"2024-06-08T02:30:08.433048Z","shell.execute_reply":"2024-06-08T02:30:08.444981Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    sample_rate = 32000\n    \nsample_submission = pd.read_csv(f'{data_root}sample_submission.csv')\n\n\nCFG.target_columns = sample_submission.columns[1:]\nCFG.n_classes = len(CFG.target_columns)\n\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.448215Z","iopub.execute_input":"2024-06-08T02:30:08.448678Z","iopub.status.idle":"2024-06-08T02:30:08.472651Z","shell.execute_reply.started":"2024-06-08T02:30:08.448644Z","shell.execute_reply":"2024-06-08T02:30:08.471307Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_audio_dir = f'{data_root}/test_soundscapes/'\nimport glob\ntest_paths = [test_audio_dir+f for f in sorted(os.listdir(test_audio_dir))]\nif len(test_paths)<=1:\n    test_audio_dir = f'{data_root}/unlabeled_soundscapes/'\n    test_paths = [test_audio_dir+f for f in sorted(os.listdir(test_audio_dir))][:10]\n    #test_paths = glob.glob('/kaggle/input/birdclef2024-final-models/*.wav')\n    \ntest_df = pd.DataFrame(test_paths, columns=['filepath'])\ntest_df['filename'] = test_df.filepath.map(lambda x: x.split('/')[-1].replace('.ogg',''))\ntest_df.head()","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.474478Z","iopub.execute_input":"2024-06-08T02:30:08.474983Z","iopub.status.idle":"2024-06-08T02:30:08.505846Z","shell.execute_reply.started":"2024-06-08T02:30:08.474929Z","shell.execute_reply":"2024-06-08T02:30:08.504387Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_audio(filepath, sr=32000):\n    audio, orig_sr = sf.read(filepath)\n    if sr != orig_sr:\n        audio = signal.resample(audio, int(len(audio) * sr / orig_sr))\n    audio = audio.astype(np.float32).ravel()\n    return audio\n\ndef make_frame(audio, duration=5, sr=32000):\n    frame_length = int(duration * sr)\n    frame_step = int(duration * sr)\n    chunks = [\n        audio[i:i+frame_length] \n        for i in range(0, len(audio), frame_step)\n    ]\n    for i in range(len(chunks)):\n        if len(chunks[i]) < frame_length:\n            padding = np.zeros(frame_length - len(chunks[i]))\n            chunks[i] = np.concatenate([chunks[i], padding])\n            \n    return np.array(chunks)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.507545Z","iopub.execute_input":"2024-06-08T02:30:08.507978Z","iopub.status.idle":"2024-06-08T02:30:08.520792Z","shell.execute_reply.started":"2024-06-08T02:30:08.507941Z","shell.execute_reply":"2024-06-08T02:30:08.519253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import onnxruntime as ort\n\nsess_options = ort.SessionOptions()\nsess_options.intra_op_num_threads = 1\n\nmodel_root = '/kaggle/input/my-birdclef2024-models-2/'\nmodels = []\nmodel_paths=[\n    '/kaggle/input/birdclef2024-final-models/fold_2_s1_tf_efficientnet_b2.ns_jft_in1k_6_to_10.onnx', # 1\n    '/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b2.ns_jft_in1k0605_v2_2.onnx', # new rank2\n    '/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b2.ns_jft_in1k_mixv2_0503_logit.onnx', # 2\n    '/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b1.ns_jft_in1k_pretrain_all_data_logit.onnx', # 3\n    #'/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b1.ns_jft_in1k_student_only.onnx', # 5\n    \n    '/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b1.ns_jft_in1k_0603.onnx', #best 0.67\n    '/kaggle/input/birdclef2024-final-models/fold_3_s1_tf_efficientnet_b0.ns_jft_in1k_pretrain_all_data_logit.onnx',# 4\n\n]\nfor p in model_paths:\n    print('load: ', p)\n    model = ort.InferenceSession(p, sess_options)\n    models.append(model)\n\nweights = np.array([0.25, 0.25, 0.15, 0.15, 0.1, 0.1])\nassert np.sum(weights)==1\nweights = weights.reshape(6, 1, 1)\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:08.523467Z","iopub.execute_input":"2024-06-08T02:30:08.523968Z","iopub.status.idle":"2024-06-08T02:30:11.343458Z","shell.execute_reply.started":"2024-06-08T02:30:08.523924Z","shell.execute_reply":"2024-06-08T02:30:11.341715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import librosa\ndef compute_melspec(y):\n    melspec = librosa.feature.melspectrogram(\n        y=y, sr=32000, n_mels=128, fmin=20, fmax=16000,\n        hop_length=512, n_fft=2048\n    )\n\n    melspec = librosa.power_to_db(melspec).astype(np.float32)\n    return melspec\n\ndef mono_to_color(X, eps=1e-6, mean=None, std=None):\n    \"\"\"\n    Converts a one channel array to a 3 channel one in [0, 255]\n    Arguments:\n        X {numpy array [H x W]} -- 2D array to convert\n    Keyword Arguments:\n        eps {float} -- To avoid dividing by 0 (default: {1e-6})\n        mean {None or np array} -- Mean for normalization (default: {None})\n        std {None or np array} -- Std for normalization (default: {None})\n    Returns:\n        numpy array [3 x H x W] -- RGB numpy array\n    \"\"\"\n    X = np.stack([X, X, X], axis=-1)\n\n    # Standardize\n    mean = mean or X.mean()\n    std = std or X.std()\n    X = (X - mean) / (std + eps)\n\n    # Normalize to [0, 255]\n    _min, _max = X.min(), X.max()\n\n    if (_max - _min) > eps:\n        V = np.clip(X, _min, _max)\n        V = 255 * (V - _min) / (_max - _min)\n        V = V.astype(np.uint8)\n    else:\n        V = np.zeros_like(X, dtype=np.uint8)\n\n    return V\n\ndef normalize(img, mean, std, max_pixel_value=255.0):\n    mean = np.array(mean, dtype=np.float32)\n    mean *= max_pixel_value\n\n    std = np.array(std, dtype=np.float32)\n    std *= max_pixel_value\n\n    denominator = np.reciprocal(std, dtype=np.float32)\n\n    img = img.astype(np.float32)\n    img -= mean\n    img *= denominator\n    return img\n\nimport concurrent.futures\n\ndef get_specs(y):\n    mean = (0.485, 0.456, 0.406)\n    std = (0.229, 0.224, 0.225)\n    image = compute_melspec(y)\n    image = mono_to_color(image)\n    image = normalize(image, mean, std)\n    return image\n","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:11.345139Z","iopub.execute_input":"2024-06-08T02:30:11.345721Z","iopub.status.idle":"2024-06-08T02:30:11.366842Z","shell.execute_reply.started":"2024-06-08T02:30:11.345673Z","shell.execute_reply":"2024-06-08T02:30:11.364564Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# tick = time.time()\n# ids = []\n# preds = np.empty(shape=(0, 182), dtype='float32')\n\n# for filepath in tqdm(test_df.filepath.tolist(), 'test '):\n#     filename = filepath.split('/')[-1].replace('.ogg','')\n#     audio = load_audio(filepath)\n#     chunks = make_frame(audio, duration=5)\n#     spec = get_specs(chunks).transpose(0, 3, 2, 1) \n#     ort_inputs = {models[0].get_inputs()[0].name: spec}\n\n    \n#     chunk_preds = []\n#     for i in range(0, len(models)):\n#         pred = models[i].run(None, ort_inputs)[0]\n#         chunk_preds.append(pred)\n\n#     chunk_preds = np.array(chunk_preds)\n#     chunk_preds = (chunk_preds * weights).sum(axis=0)\n#     chunk_preds = torch.sigmoid(torch.from_numpy(chunk_preds).float()).numpy()\n\n#     rec_ids = [f'{filename}_{(frame_id+1)*5}' for frame_id in range(len(chunk_preds))]\n#     ids += rec_ids\n#     preds = np.concatenate([preds, chunk_preds], axis=0)\n    \n\n# tock = time.time()","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:11.368682Z","iopub.execute_input":"2024-06-08T02:30:11.369111Z","iopub.status.idle":"2024-06-08T02:30:11.389210Z","shell.execute_reply.started":"2024-06-08T02:30:11.369075Z","shell.execute_reply":"2024-06-08T02:30:11.387177Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from concurrent.futures import ThreadPoolExecutor\n\ndef process_file(filepath):\n    filename = filepath.split('/')[-1].replace('.ogg','')\n    audio = load_audio(filepath)\n    chunks = make_frame(audio, duration=5)\n    spec = get_specs(chunks).transpose(0, 3, 2, 1) \n    ort_inputs = {models[0].get_inputs()[0].name: spec}\n\n    chunk_preds = []\n    for i in range(0, len(models)):\n        pred = models[i].run(None, ort_inputs)[0]\n        chunk_preds.append(pred)\n\n    chunk_preds = np.array(chunk_preds)\n    chunk_preds = (chunk_preds * weights).sum(axis=0)\n    chunk_preds = torch.sigmoid(torch.from_numpy(chunk_preds).float()).numpy()\n\n    rec_ids = [f'{filename}_{(frame_id+1)*5}' for frame_id in range(len(chunk_preds))]\n\n    return rec_ids, chunk_preds\n\n# Start stopwatch\ntick = time.time()\n\n# Initialize empty list to store ids\nids = []\n# Initialize empty array to store predictions\npreds = np.empty(shape=(0, 182), dtype='float32')\n\n# Create a ThreadPoolExecutor\nwith ThreadPoolExecutor(max_workers=5) as executor:\n    # Use the executor to map the function to the inputs\n    results = executor.map(process_file, test_df.filepath.tolist())\n\n# process the results\nfor rec_ids, chunk_preds in results:\n    ids += rec_ids\n    preds = np.concatenate([preds, chunk_preds], axis=0)\n\n# Stop stopwatch\ntock = time.time()","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:30:11.394902Z","iopub.execute_input":"2024-06-08T02:30:11.395546Z","iopub.status.idle":"2024-06-08T02:31:22.653076Z","shell.execute_reply.started":"2024-06-08T02:30:11.395492Z","shell.execute_reply":"2024-06-08T02:31:22.651832Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pred_df = pd.DataFrame(ids, columns=['row_id'])\npred_df.loc[:, CFG.target_columns] = preds\n#pred_df.to_csv('submission.csv',index=False)\npred_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:31:22.655149Z","iopub.execute_input":"2024-06-08T02:31:22.655732Z","iopub.status.idle":"2024-06-08T02:31:22.822240Z","shell.execute_reply.started":"2024-06-08T02:31:22.655687Z","shell.execute_reply":"2024-06-08T02:31:22.820697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"vc_df = pd.read_csv('/kaggle/input/birdclef2024-final-models/value_counts.csv')\nvc_d = {}\nfor i, row in vc_df.iterrows():\n    vc_d[row[0]] = row['primary_label']\nvc = []\nfor c in CFG.target_columns:\n    vc.append(vc_d[c])\nvc = np.array(vc)\nvc = np.clip(vc, 50, 500)","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:31:22.823791Z","iopub.execute_input":"2024-06-08T02:31:22.824136Z","iopub.status.idle":"2024-06-08T02:31:22.857644Z","shell.execute_reply.started":"2024-06-08T02:31:22.824108Z","shell.execute_reply":"2024-06-08T02:31:22.856455Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for k in range(182):\n    pred_df.iloc[:,1+k] -= pred_df.iloc[:,1+k].min()\n    pred_df.iloc[:,1+k] /= pred_df.iloc[:,1+k].max()\n\n# CONVERT PROBS TO ODDS, APPLY MULTIPLIER, CONVERT BACK TO PROBS\ndef scale(probs, factor):\n    probs = probs.copy()\n    idx = np.where(probs!=1)[0]\n    odds = factor * probs[idx] / (1-probs[idx])\n    probs[idx] =  odds/(1+odds)\n    return probs\n\nd2 = 10* vc / vc.sum()\n# TRAIN AND TEST MEANS\nd1 = pred_df.iloc[:,1:].mean().values\nfor k in range(182):\n    d = d1[k]/(1-d1[k])\n    s = (d2[k]/(1-d2[k]))/d \n    print(s)\n    pred_df.iloc[:,k+1] = scale(pred_df.iloc[:,k+1].values,s)\n\npred_df.to_csv('submission.csv',index=False)\npred_df.head(10)","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:33:30.891967Z","iopub.execute_input":"2024-06-08T02:33:30.892469Z","iopub.status.idle":"2024-06-08T02:33:31.429716Z","shell.execute_reply.started":"2024-06-08T02:33:30.892407Z","shell.execute_reply":"2024-06-08T02:33:31.426995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub_time = (tock-tick)*110 # ~1100 recording on the test data\nsub_time = time.gmtime(sub_time)\nsub_time = time.strftime(\"%H hr: %M min : %S sec\", sub_time)\nprint(f\">> Time for submission: ~ {sub_time}\")","metadata":{"execution":{"iopub.status.busy":"2024-06-08T02:31:23.388504Z","iopub.execute_input":"2024-06-08T02:31:23.388876Z","iopub.status.idle":"2024-06-08T02:31:23.398171Z","shell.execute_reply.started":"2024-06-08T02:31:23.388845Z","shell.execute_reply":"2024-06-08T02:31:23.396524Z"},"trusted":true},"execution_count":null,"outputs":[]}]}