{"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":"# Summary of this notebook\n\nI'm affraid that this notebook has become so long.\nHere I summarize what we are gonna do.\n\n1. Import & Configration\n\nHere we import libraries and set some configurations as usual.\n\n2. Make Candidate\n\nHere we define functions which extract bird candidates for lightgbm stage training. \nThe output of melspectrogram multiclass classifier is used for that.\n\n3. Add features\n\nHere we define functions which make features for lightgbm stage training.\n\n4. Calculate birdcall probabilities (397dims per clip) from melspectrograms\n\nHere we define functions which calculate birdcall probabilities from melspectrograms.\nThey are used for training_soundscapes audios in this notebook.\nSpeaking of train_short_audio, we have already prepare birdcall probabilities data in csv format.\n(Check '../input/metadata-probability-v0525-2100')\n\n5. Training (Lightgbm)\n\nHere we define functions which train lightgbm models.\n\n6. Optimize Threshold\n\nHere we define functions which optimize the thresholds.\n\n7. Make Submission\n\nHere we define functions which make submission for Kaggle BirdCLEF 2021 Competition.\n\n8. Main\n\nHere we run the functions we have defined.\nTo take a quick look this notebook, this part is good place to start.\n\n# input & output of this notebook\n\n[input]\n\nbirdclef-2021 (original data)\n\nmelspectrogram multiclassifier models (Ⅰ)\n\nhttps://www.kaggle.com/namakemono/birdclef-groupby-author-05221040-728258\n\nhttps://www.kaggle.com/kami634/clefmodel\n\ntrain_short_audio birdcall probabilities calculated by melspectrogram multiclassifier models (Ⅰ)\n\nhttps://www.kaggle.com/namakemono/metadata-probability-v0525-2100\n\nresnest library\n\nhttps://www.kaggle.com/ttahara/resnest50-fast-package\n\nsklearn library (To use StratifiedGroupKfold, we have to install scikit-learn 1.0.dev0)\n\nhttps://www.kaggle.com/namakemono/scikit-learn-10dev0\n\n[output]\n\nsubmission.csv","metadata":{"papermill":{"duration":0.02392,"end_time":"2021-06-03T14:28:53.64268","exception":false,"start_time":"2021-06-03T14:28:53.61876","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# Import & Configuration","metadata":{"papermill":{"duration":0.022238,"end_time":"2021-06-03T14:28:53.6874","exception":false,"start_time":"2021-06-03T14:28:53.665162","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# !cp -r \"../input/scikit-learn-10dev0/\" ./\n# !pip install \"/kaggle/working/scikit-learn-10dev0/scikit_learn-1.0.dev0-cp37-cp37m-manylinux2010_x86_64.whl\"\n# !rm -r '/kaggle/working/resnest'\n!cp -r \"../input/resnest50-fast-package/resnest-0.0.6b20200701/resnest\" ./\n!pip install -q \"/kaggle/working/resnest\"\n# !pip install -U scikit-learn\n# !pip install resnest\n# !pip install -q \"../input/resnest-package/resnest-0.0.6b20200701/resnest\"","metadata":{"papermill":{"duration":19.268619,"end_time":"2021-06-03T14:29:12.979037","exception":false,"start_time":"2021-06-03T14:28:53.710418","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:49:33.253798Z","iopub.execute_input":"2023-07-28T19:49:33.254255Z","iopub.status.idle":"2023-07-28T19:50:08.475243Z","shell.execute_reply.started":"2023-07-28T19:49:33.254216Z","shell.execute_reply":"2023-07-28T19:50:08.474059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !pip install resampy\n# import resampy","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:08.477633Z","iopub.execute_input":"2023-07-28T19:50:08.477984Z","iopub.status.idle":"2023-07-28T19:50:08.482218Z","shell.execute_reply.started":"2023-07-28T19:50:08.477947Z","shell.execute_reply":"2023-07-28T19:50:08.481362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import warnings\nwarnings.filterwarnings('ignore')","metadata":{"papermill":{"duration":0.030206,"end_time":"2021-06-03T14:29:13.034071","exception":false,"start_time":"2021-06-03T14:29:13.003865","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:08.483392Z","iopub.execute_input":"2023-07-28T19:50:08.483688Z","iopub.status.idle":"2023-07-28T19:50:08.494252Z","shell.execute_reply.started":"2023-07-28T19:50:08.483658Z","shell.execute_reply":"2023-07-28T19:50:08.493391Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import gc","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:08.497112Z","iopub.execute_input":"2023-07-28T19:50:08.497480Z","iopub.status.idle":"2023-07-28T19:50:08.503664Z","shell.execute_reply.started":"2023-07-28T19:50:08.497451Z","shell.execute_reply":"2023-07-28T19:50:08.502795Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nfrom pathlib import Path\n\nimport re\nimport time\n\nimport pickle\nfrom typing import List\nfrom tqdm.notebook import tqdm\n\n# sound\nimport librosa as lb\nimport soundfile as sf\n\n# pytorch\nimport torch\nfrom torch import nn\nfrom  torch.utils.data import Dataset, DataLoader\nfrom resnest.torch import resnest50\n\nimport tensorflow as tf\n\nfrom sklearn.model_selection import StratifiedGroupKFold\nfrom sklearn.metrics import accuracy_score, f1_score, recall_score, precision_score\nimport xgboost as xgb\nimport pickle\nfrom catboost import CatBoostClassifier\nfrom catboost import Pool\nfrom imblearn.over_sampling import RandomOverSampler\nimport lightgbm as lgb\nimport random\n\nimport glob","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":10.323138,"end_time":"2021-06-03T14:29:23.380753","exception":false,"start_time":"2021-06-03T14:29:13.057615","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:08.505267Z","iopub.execute_input":"2023-07-28T19:50:08.505595Z","iopub.status.idle":"2023-07-28T19:50:21.759101Z","shell.execute_reply.started":"2023-07-28T19:50:08.505568Z","shell.execute_reply":"2023-07-28T19:50:21.757280Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BIRD_LIST = sorted(os.listdir('../input/birdclef-2021/train_short_audio'))\nBIRD2IDX = {bird:idx for idx, bird in enumerate(BIRD_LIST)}\nBIRD2IDX['nocall'] = -1\nIDX2BIRD = {idx:bird for bird, idx in BIRD2IDX.items()}","metadata":{"papermill":{"duration":0.078401,"end_time":"2021-06-03T14:29:23.484177","exception":false,"start_time":"2021-06-03T14:29:23.405776","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:21.760743Z","iopub.execute_input":"2023-07-28T19:50:21.761967Z","iopub.status.idle":"2023-07-28T19:50:21.835912Z","shell.execute_reply.started":"2023-07-28T19:50:21.761927Z","shell.execute_reply":"2023-07-28T19:50:21.835057Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# IDX2BIRD","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:21.837605Z","iopub.execute_input":"2023-07-28T19:50:21.837860Z","iopub.status.idle":"2023-07-28T19:50:21.841869Z","shell.execute_reply.started":"2023-07-28T19:50:21.837838Z","shell.execute_reply":"2023-07-28T19:50:21.841015Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"csv_list = glob.glob('/kaggle/input/augmented-editconfig-csv/*')\n\n# 10 frame version\nfilepath_list = [\n#      \"../input/metadata-probability-v0525-2100/birdclef_resnest50_fold1_epoch_34_f1_val_04757_20210524185455.csv\"\n    csv_list[6]\n]\nprob_df = pd.concat([pd.read_csv(_) for _ in filepath_list])\nprob_df","metadata":{"papermill":{"duration":9.211879,"end_time":"2021-06-03T14:29:32.720537","exception":false,"start_time":"2021-06-03T14:29:23.508658","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:21.843298Z","iopub.execute_input":"2023-07-28T19:50:21.843914Z","iopub.status.idle":"2023-07-28T19:50:25.442233Z","shell.execute_reply.started":"2023-07-28T19:50:21.843881Z","shell.execute_reply":"2023-07-28T19:50:25.441251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"csv_list","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:25.443620Z","iopub.execute_input":"2023-07-28T19:50:25.444035Z","iopub.status.idle":"2023-07-28T19:50:25.450488Z","shell.execute_reply.started":"2023-07-28T19:50:25.444004Z","shell.execute_reply":"2023-07-28T19:50:25.449522Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TrainingConfig:\n    def __init__(self):\n        self.nocall_threshold:float=0.5\n        self.num_kfolds:int = 5\n        self.num_spieces:int = 397\n        self.num_candidates:int = 5\n        self.max_distance:int = 15 # 20\n        self.sampling_strategy:float = None # 1.0\n        self.random_state:int=777\n        self.num_prob:int = 6\n        self.use_to_birds=True\n        self.weights_filepath_dict = {\n            'lgbm':[f\"./lgbm_{kfold_index}.pkl\" for kfold_index in range(self.num_kfolds)],\n        }\n        \ntraining_config = TrainingConfig()","metadata":{"papermill":{"duration":0.033456,"end_time":"2021-06-03T14:29:32.779213","exception":false,"start_time":"2021-06-03T14:29:32.745757","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.456066Z","iopub.execute_input":"2023-07-28T19:50:25.456552Z","iopub.status.idle":"2023-07-28T19:50:25.465127Z","shell.execute_reply.started":"2023-07-28T19:50:25.456528Z","shell.execute_reply":"2023-07-28T19:50:25.464208Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config:\n    def __init__(self):\n        self.num_kfolds:int = training_config.num_kfolds\n        self.num_spieces:int = training_config.num_spieces\n        self.num_candidates:int = training_config.num_candidates\n        self.max_distance:int = training_config.max_distance\n        self.nocall_threshold:float = training_config.nocall_threshold\n        self.num_prob:int = training_config.num_prob\n        # check F1 score without 3rd stage(table competition) \n        self.check_baseline:bool = True\n        # List of file paths of the models which are used when determining if the bird is acceptable.\n        self.weights_filepath_dict = training_config.weights_filepath_dict\n        # Weights for the models to predict the probability of each bird singing for each frame.\n        self.checkpoint_paths = [ \n            Path(\"../input/clefmodel/birdclef_resnest50_fold0_epoch_27_f1_val_05179_20210520120053.pth\"), # id36\n            Path(\"../input/clefmodel/birdclef_resnest50_fold0_epoch_13_f1_val_03502_20210522050604.pth\"), # id51\n            Path(\"../input/birdclef-groupby-author-05221040-728258/birdclef_resnest50_fold0_epoch_33_f1_val_03859_20210524151554.pth\"), # id58\n            Path(\"../input/birdclef-groupby-author-05221040-728258/birdclef_resnest50_fold1_epoch_34_f1_val_04757_20210524185455.pth\"), # id59\n            Path(\"../input/birdclef-groupby-author-05221040-728258/birdclef_resnest50_fold2_epoch_34_f1_val_05027_20210524223209.pth\"), # id60\n            Path(\"../input/birdclef-groupby-author-05221040-728258/birdclef_resnest50_fold3_epoch_20_f1_val_04299_20210525010703.pth\"), # id61\n            Path(\"../input/birdclef-groupby-author-05221040-728258/birdclef_resnest50_fold4_epoch_34_f1_val_05140_20210525074929.pth\"), # id62\n            Path(\"../input/clefmodel/resnest50_sr32000_d7_miixup-5.0_2ndlw-0.6_grouped-by-auther/birdclef_resnest50_fold0_epoch_78_f1_val_03658_20210528221629.pth\"), # id97\n            Path(\"../input/clefmodel/resnest50_sr32000_d7_miixup-5.0_2ndlw-0.6_grouped-by-auther/birdclef_resnest50_fold0_epoch_84_f1_val_03689_20210528225810.pth\"), # id97\n            Path(\"../input/clefmodel/resnest50_sr32000_d7_miixup-5.0_2ndlw-0.6_grouped-by-auther/birdclef_resnest50_fold1_epoch_27_f1_val_03942_20210529062427.pth\"), # id98\n        ]\n        # call probability of each bird for each sample used for candidate extraction (cache)\n        self.pred_filepath_list = [\n            self.get_prob_filepath_from_checkpoint(path) for path in self.checkpoint_paths\n        ]\n        \n    def get_prob_filepath_from_checkpoint(self, checkpoint_path:Path) -> str:\n        filename = f\"train_soundscape_labels_probabilitiy_%s.csv\" % checkpoint_path.stem\n        return filename\n\nconfig = Config()","metadata":{"papermill":{"duration":0.034411,"end_time":"2021-06-03T14:29:32.837976","exception":false,"start_time":"2021-06-03T14:29:32.803565","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.466674Z","iopub.execute_input":"2023-07-28T19:50:25.466997Z","iopub.status.idle":"2023-07-28T19:50:25.477944Z","shell.execute_reply.started":"2023-07-28T19:50:25.466967Z","shell.execute_reply":"2023-07-28T19:50:25.477131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make Candidate\nhelper functions for making candidates","metadata":{"papermill":{"duration":0.023979,"end_time":"2021-06-03T14:29:32.886126","exception":false,"start_time":"2021-06-03T14:29:32.862147","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def get_locations():\n    return [{\n        \"site\": \"COL\",\n        \"latitude\": 5.57,\n        \"longitude\": -75.85\n    }, {\n        \"site\": \"COR\",\n        \"latitude\": 10.12,\n        \"longitude\": -84.51\n    }, {\n        \"site\": \"SNE\",\n        \"latitude\": 38.49,\n        \"longitude\": -119.95\n    }, {\n        \"site\": \"SSW\",\n        \"latitude\": 42.47,\n        \"longitude\": -76.45\n    }]\n\n\ndef to_site(row, max_distance:int):\n    best = max_distance\n    answer = \"Other\"\n    for location in get_locations():\n        x = (row[\"latitude\"] - location[\"latitude\"])\n        y = (row[\"longitude\"] - location[\"longitude\"])\n        dist = (x**2 + y**2) ** 0.5\n        if dist < best:\n            best = dist\n            answer = location[\"site\"]\n    return answer\n\n\ndef to_latitude(site:str) -> str:\n    for location in get_locations():\n        if site == location[\"site\"]:\n            return location[\"latitude\"]\n    return -10000\n\n\ndef to_longitude(site:str) -> str:\n    for location in get_locations():\n        if site == location[\"site\"]:\n            return location[\"longitude\"]\n    return -10000\n\n\ndef to_birds(row, th:float) -> str:\n    if row[\"call_prob\"] < th:\n        return \"nocall\"\n    res = [row[\"primary_label\"]] + eval(row[\"secondary_labels\"])\n    return \" \".join(res)","metadata":{"papermill":{"duration":0.036791,"end_time":"2021-06-03T14:29:32.947315","exception":false,"start_time":"2021-06-03T14:29:32.910524","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.479460Z","iopub.execute_input":"2023-07-28T19:50:25.479821Z","iopub.status.idle":"2023-07-28T19:50:25.492373Z","shell.execute_reply.started":"2023-07-28T19:50:25.479790Z","shell.execute_reply":"2023-07-28T19:50:25.491327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"making candidates main func","metadata":{"papermill":{"duration":0.024216,"end_time":"2021-06-03T14:29:32.996454","exception":false,"start_time":"2021-06-03T14:29:32.972238","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def make_candidates(\n    prob_df:pd.DataFrame,\n    num_spieces:int,\n    num_candidates:int,\n    max_distance:int,\n    num_prob:int=6, # number of frames to be allocated for front and rear (if 3, then 3 for front, 3 for rear)\n    nocall_threshold:float=0.5,\n):\n    if \"author\" in prob_df.columns: # meta data (train_short_audio)\n        prob_df[\"birds\"] = prob_df.apply(\n            lambda row: to_birds(row, th=nocall_threshold),\n            axis=1\n        )\n        print(\"Candidate nocall ratio: %.4f\" % (prob_df[\"birds\"] == \"nocall\").mean())\n        prob_df[\"audio_id\"] = prob_df[\"filename\"].apply(\n            lambda _: int(_.replace(\"XC\", \"\").replace(\".ogg\", \"\"))\n        )\n        prob_df[\"row_id\"] = prob_df.apply(\n            lambda row: \"%s_%s_%s\" % (row[\"audio_id\"], row['site'], row[\"seconds\"]),\n            axis=1\n        )\n        prob_df[\"year\"] = prob_df[\"date\"].apply(lambda _: int(_.split(\"-\")[0]))\n        prob_df[\"month\"] = prob_df[\"date\"].apply(lambda _: int(_.split(\"-\")[1]))\n        prob_df[\"site\"] = prob_df.apply(\n            lambda row: to_site(row, max_distance),\n            axis=1\n        )\n    else:\n        prob_df[\"year\"] = prob_df[\"date\"].apply(lambda _: int(str(_)[:4]))\n        prob_df[\"month\"] = prob_df[\"date\"].apply(lambda _: int(str(_)[4:6]))\n        prob_df[\"latitude\"] = prob_df[\"site\"].apply(to_latitude)\n        prob_df[\"longitude\"] = prob_df[\"site\"].apply(to_longitude)\n        prob_df[\"row_id\"] = prob_df.apply(\n            lambda row: \"%s_%s_%s\" % (row[\"audio_id\"], row['site'], row[\"seconds\"]),\n            axis=1\n        )\n        \n    sum_prob_list = prob_df[BIRD_LIST].sum(axis=1).tolist()\n    mean_prob_list = prob_df[BIRD_LIST].mean(axis=1).tolist()\n    std_prob_list = prob_df[BIRD_LIST].std(axis=1).tolist()\n    max_prob_list = prob_df[BIRD_LIST].max(axis=1).tolist()\n    min_prob_list = prob_df[BIRD_LIST].min(axis=1).tolist()\n    skew_prob_list = prob_df[BIRD_LIST].skew(axis=1).tolist()\n    kurt_prob_list = prob_df[BIRD_LIST].kurt(axis=1).tolist()\n    \n    X = prob_df[BIRD_LIST].values\n    bird_ids_list = np.argsort(-X)[:,:num_candidates]\n    row_ids = prob_df[\"row_id\"].tolist()\n    rows = [i//num_candidates for i in range(len(bird_ids_list.flatten()))]\n    cols = bird_ids_list.flatten()\n    # What number?\n    ranks = [i%num_candidates for i in range(len(rows))]\n    probs_list = X[rows, cols]\n    D = {\n        \"row_id\": [row_ids[i] for i in rows],\n        \"rank\": ranks,\n        \"bird_id\": bird_ids_list.flatten(),\n        \"prob\": probs_list.flatten(),\n        \"sum_prob\": [sum_prob_list[i//num_candidates] for i in range(num_candidates*len(mean_prob_list))],\n        \"mean_prob\": [mean_prob_list[i//num_candidates] for i in range(num_candidates*len(mean_prob_list))],\n        \"std_prob\": [std_prob_list[i//num_candidates] for i in range(num_candidates*len(std_prob_list))],\n        \"max_prob\": [max_prob_list[i//num_candidates] for i in range(num_candidates*len(max_prob_list))],\n        \"min_prob\": [min_prob_list[i//num_candidates] for i in range(num_candidates*len(min_prob_list))],\n        \"skew_prob\": [skew_prob_list[i//num_candidates] for i in range(num_candidates*len(skew_prob_list))],\n        \"kurt_prob\": [kurt_prob_list[i//num_candidates] for i in range(num_candidates*len(kurt_prob_list))],\n    }\n    audio_ids = prob_df[\"audio_id\"].values[rows]\n    for diff in range(-num_prob, num_prob+1):\n        if diff == 0:\n            continue\n        neighbor_audio_ids = prob_df[\"audio_id\"].shift(diff).values[rows]\n        Y = prob_df[BIRD_LIST].shift(diff).values\n        c = f\"next{abs(diff)}_prob\" if diff < 0 else f\"prev{diff}_prob\"\n        c = c.replace(\"1_prob\", \"_prob\") # Fix next1_prob to next_prob\n        v = Y[rows, cols].flatten()\n        v[audio_ids != neighbor_audio_ids] = np.nan\n        D[c] = v\n\n    candidate_df = pd.DataFrame(D)\n    columns = [\n        \"row_id\",\n        \"site\",\n        \"year\",\n        \"month\",\n        \"audio_id\",\n        \"seconds\",\n        \"birds\",\n    ]\n    candidate_df = pd.merge(\n        candidate_df,\n        prob_df[columns],\n        how=\"left\",\n        on=\"row_id\"\n    )\n    candidate_df[\"target\"] = candidate_df.apply(\n        lambda row: IDX2BIRD[row[\"bird_id\"]] in set(str(row[\"birds\"]).split()),\n        axis=1\n    )\n    candidate_df[\"label\"] = candidate_df[\"bird_id\"].map(IDX2BIRD)\n    return candidate_df","metadata":{"papermill":{"duration":0.049883,"end_time":"2021-06-03T14:29:33.070891","exception":false,"start_time":"2021-06-03T14:29:33.021008","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.493633Z","iopub.execute_input":"2023-07-28T19:50:25.494122Z","iopub.status.idle":"2023-07-28T19:50:25.519115Z","shell.execute_reply.started":"2023-07-28T19:50:25.494091Z","shell.execute_reply":"2023-07-28T19:50:25.517994Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Add Features\nhelper functions for adding features","metadata":{"papermill":{"duration":0.024856,"end_time":"2021-06-03T14:29:33.120328","exception":false,"start_time":"2021-06-03T14:29:33.095472","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def load_metadata():\n    meta_df = pd.read_csv(\"../input/birdclef-2021/train_metadata.csv\")\n    meta_df[\"id\"] = meta_df.index + 1\n    meta_df[\"year\"] = meta_df[\"date\"].apply(lambda _: _.split(\"-\")[0]).astype(int)\n    meta_df[\"month\"] = meta_df[\"date\"].apply(lambda _: _.split(\"-\")[1]).astype(int)\n    return meta_df\n\n\ndef to_zscore(row):\n    x = row[\"prob\"]\n    mu = row[\"prob_avg_in_same_audio\"]\n    sigma = row[\"prob_var_in_same_audio\"] ** 0.5\n    if sigma < 1e-6:\n        return 0\n    else:\n        return (x - mu) / sigma\n\n\ndef add_same_audio_features(\n    candidate_df:pd.DataFrame,\n    df:pd.DataFrame\n):\n    # Average probability per bird in the same audio\n    _gdf = df.groupby([\"audio_id\"], as_index=False).mean()[[\"audio_id\"] + BIRD_LIST]\n    _df = pd.melt(\n        _gdf,\n        id_vars=[\"audio_id\"]\n    ).rename(columns={\n        \"variable\": \"label\",\n        \"value\": \"prob_avg_in_same_audio\"\n    })\n    candidate_df = pd.merge(candidate_df, _df, how=\"left\", on=[\"audio_id\", \"label\"])\n    # Maximum value for each bird in the same audio\n    _gdf = df.groupby([\"audio_id\"], as_index=False).max()[[\"audio_id\"] + BIRD_LIST]\n    _df = pd.melt(\n        _gdf,\n        id_vars=[\"audio_id\"]\n    ).rename(columns={\n        \"variable\": \"label\",\n        \"value\": \"prob_max_in_same_audio\"\n    })\n    candidate_df = pd.merge(candidate_df, _df, how=\"left\", on=[\"audio_id\", \"label\"])\n    # Variance of each bird in the same audio\n    _gdf = df.groupby([\"audio_id\"], as_index=False).var()[[\"audio_id\"] + BIRD_LIST]\n    _df = pd.melt(\n        _gdf,\n        id_vars=[\"audio_id\"]\n    ).rename(columns={\n        \"variable\": \"label\",\n        \"value\": \"prob_var_in_same_audio\"\n    })\n    candidate_df = pd.merge(candidate_df, _df, how=\"left\", on=[\"audio_id\", \"label\"])\n    candidate_df[\"zscore_in_same_audio\"] = candidate_df.apply(to_zscore, axis=1)\n    return candidate_df","metadata":{"papermill":{"duration":0.039197,"end_time":"2021-06-03T14:29:33.18412","exception":false,"start_time":"2021-06-03T14:29:33.144923","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.520567Z","iopub.execute_input":"2023-07-28T19:50:25.520921Z","iopub.status.idle":"2023-07-28T19:50:25.536124Z","shell.execute_reply.started":"2023-07-28T19:50:25.520890Z","shell.execute_reply":"2023-07-28T19:50:25.534849Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"making candidates main func","metadata":{}},{"cell_type":"code","source":"def add_features(\n    candidate_df:pd.DataFrame,\n    df:pd.DataFrame,\n    max_distance:int,\n):\n    meta_df = load_metadata()\n    # latitude & longitude\n    if not \"latitude\" in candidate_df.columns:\n        candidate_df[\"latitude\"] = candidate_df[\"site\"].apply(to_latitude)\n    if not \"longitude\" in candidate_df.columns:\n        candidate_df[\"longitude\"] = candidate_df[\"site\"].apply(to_longitude)\n    # Number of Appearances\n    candidate_df[\"num_appear\"] = candidate_df[\"label\"].map(\n        meta_df[\"primary_label\"].value_counts()\n    )\n    meta_df[\"site\"] = meta_df.apply(\n        lambda row: to_site(\n            row,\n            max_distance=max_distance\n        ),\n        axis=1\n    )\n\n    # Number of occurrences by region\n    _df = meta_df.groupby(\n        [\"primary_label\", \"site\"],\n        as_index=False\n    )[\"id\"].count().rename(\n        columns={\n            \"primary_label\": \"label\",\n            \"id\": \"site_num_appear\"\n        }\n    )\n    candidate_df = pd.merge(\n        candidate_df,\n        _df,\n        how=\"left\",\n        on=[\"label\", \"site\"]\n    )\n    candidate_df[\"site_appear_ratio\"] = candidate_df[\"site_num_appear\"] / candidate_df[\"num_appear\"]\n    # Seasonal statistics\n    _df = meta_df.groupby(\n        [\"primary_label\", \"month\"],\n        as_index=False\n    )[\"id\"].count().rename(\n        columns={\n            \"primary_label\": \"label\",\n            \"id\": \"month_num_appear\"\n        }\n    )\n    candidate_df = pd.merge(candidate_df, _df, how=\"left\", on=[\"label\", \"month\"])\n    candidate_df[\"month_appear_ratio\"] = candidate_df[\"month_num_appear\"] / candidate_df[\"num_appear\"]\n\n    candidate_df = add_same_audio_features(candidate_df, df)\n\n    # Correction of probability (all down)\n    candidate_df[\"prob / num_appear\"] = candidate_df[\"prob\"] / (candidate_df[\"num_appear\"].fillna(0) + 1)\n    candidate_df[\"prob / site_num_appear\"] = candidate_df[\"prob\"] / (candidate_df[\"site_num_appear\"].fillna(0) + 1)\n    candidate_df[\"prob * site_appear_ratio\"] = candidate_df[\"prob\"] * (candidate_df[\"site_appear_ratio\"].fillna(0) + 0.001)\n\n    # Amount of change from the previous and following frames\n    candidate_df[\"prob_avg\"] = candidate_df[[\"prev_prob\", \"prob\", \"next_prob\"]].mean(axis=1)\n    candidate_df[\"prob_diff\"] = candidate_df[\"prob\"] - candidate_df[\"prob_avg\"]\n    candidate_df[\"prob - prob_max_in_same_audio\"] = candidate_df[\"prob\"] - candidate_df[\"prob_max_in_same_audio\"]\n\n    # Average of back and forward frames\n\n    return candidate_df","metadata":{"papermill":{"duration":0.039005,"end_time":"2021-06-03T14:29:33.247442","exception":false,"start_time":"2021-06-03T14:29:33.208437","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.537659Z","iopub.execute_input":"2023-07-28T19:50:25.538002Z","iopub.status.idle":"2023-07-28T19:50:25.552487Z","shell.execute_reply.started":"2023-07-28T19:50:25.537971Z","shell.execute_reply":"2023-07-28T19:50:25.551467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Calculate birdcall probabilities (397dims per clip) from melspectrograms\nhelper functions for calculating birdcall probabilities","metadata":{"papermill":{"duration":0.024251,"end_time":"2021-06-03T14:29:33.296327","exception":false,"start_time":"2021-06-03T14:29:33.272076","status":"completed"},"tags":[]}},{"cell_type":"code","source":"DEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\nprint(\"DEVICE:\", DEVICE)\n\n\nclass MelSpecComputer:\n    def __init__(self, sr, n_mels, fmin, fmax, **kwargs):\n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax\n        kwargs[\"n_fft\"] = kwargs.get(\"n_fft\", self.sr//10)\n        kwargs[\"hop_length\"] = kwargs.get(\"hop_length\", self.sr//(10*4))\n        self.kwargs = kwargs\n\n    def __call__(self, y):\n\n        melspec = lb.feature.melspectrogram(\n            y=y, sr=self.sr, n_mels=self.n_mels, fmin=self.fmin, fmax=self.fmax, **self.kwargs,\n        )\n\n        melspec = lb.power_to_db(melspec).astype(np.float32)\n        return melspec\n\n    \ndef mono_to_color(X, eps=1e-6, mean=None, std=None):\n    mean = mean or X.mean()\n    std = std or X.std()\n    X = (X - mean) / (std + eps)\n\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\n\ndef crop_or_pad(y, length):\n    if len(y) < length:\n        y = np.concatenate([y, length - np.zeros(len(y))])\n    elif len(y) > length:\n        y = y[:length]\n    return y\n\n\nclass BirdCLEFDataset(Dataset):\n    def __init__(self, data, sr=32_000, n_mels=128, fmin=0, fmax=None, duration=5, step=None, res_type=\"kaiser_fast\", resample=True):\n\n        self.data = data\n\n        self.sr = sr\n        self.n_mels = n_mels\n        self.fmin = fmin\n        self.fmax = fmax or self.sr//2\n\n        self.duration = duration\n        self.audio_length = self.duration*self.sr\n        self.step = step or self.audio_length\n\n        self.res_type = res_type\n        self.resample = resample\n\n        self.mel_spec_computer = MelSpecComputer(\n            sr=self.sr,\n            n_mels=self.n_mels,\n            fmin=self.fmin,\n            fmax=self.fmax\n        )\n        self.npy_save_root = Path(\"./data\")\n        \n        os.makedirs(self.npy_save_root, exist_ok=True)\n\n    def __len__(self):\n        return len(self.data)\n\n    @staticmethod\n    def normalize(image):\n        image = image.astype(\"float32\", copy=False) / 255.0\n        image = np.stack([image, image, image])\n        return image\n\n    def audio_to_image(self, audio):\n        melspec = self.mel_spec_computer(audio)\n        image = mono_to_color(melspec)\n        image = self.normalize(image)\n        return image\n\n    def read_file(self, filepath):\n#         print(\"path: \", filepath)\n        filename = filepath.stem\n        npy_path = self.npy_save_root / f\"{filename}.npy\"\n        \n        if not os.path.exists(npy_path):\n            audio, orig_sr = sf.read(filepath, dtype=\"float32\")\n\n            if self.resample and orig_sr != self.sr:\n                print(\"LB: \", audio, orig_sr, self.sr, self.res_type)\n                audio = lb.resample(y=audio, orig_sr = orig_sr, target_sr = self.sr,res_type =  self.res_type)\n\n            audios = []\n            for i in range(self.audio_length, len(audio) + self.step, self.step):\n#                 print(\"in loop: \", i)\n                start = max(0, i - self.audio_length)\n                end = start + self.audio_length\n                audios.append(audio[start:end])\n\n#             print(\"done loop\")\n            if len(audios[-1]) < self.audio_length:\n                audios = audios[:-1]\n\n#             print(\"adding to images\")\n#             print(\"audios size: \", len(audios))\n#             images = [self.audio_to_image(audio) for audio in audios]\n\n            images = []\n            for audio in audios:\n                x = self.audio_to_image(audio)\n#                 print(len(x))\n                images.append(x)\n            \n#             print(\"len: \", len(images))\n            images = np.stack(images)\n            \n#             print(\"saving images\")\n            np.save(str(npy_path), images)\n        return np.load(npy_path)\n\n    def __getitem__(self, idx):\n        return self.read_file(self.data.loc[idx, \"filepath\"])\n\n    \ndef load_net(checkpoint_path, num_classes=397):\n    net = resnest50(pretrained=False)\n    net.fc = nn.Linear(net.fc.in_features, num_classes)\n    dummy_device = torch.device(\"cpu\")\n    d = torch.load(checkpoint_path, map_location=dummy_device)\n    for key in list(d.keys()):\n        d[key.replace(\"model.\", \"\")] = d.pop(key)\n    net.load_state_dict(d)\n    net = net.to(DEVICE)\n    net = net.eval()\n    return net\n\n\n@torch.no_grad()\ndef get_thresh_preds(out, thresh=None):\n    thresh = thresh or THRESH\n    o = (-out).argsort(1)\n    npreds = (out > thresh).sum(1)\n    preds = []\n    for oo, npred in zip(o, npreds):\n        preds.append(oo[:npred].cpu().numpy().tolist())\n    return preds\n\n\ndef predict(nets, test_data, names=True):\n    preds = []\n    with torch.no_grad():\n        for idx in  tqdm(list(range(len(test_data)))):\n            xb = torch.from_numpy(test_data[idx]).to(DEVICE)\n            pred = 0.\n            for net in nets:\n                o = net(xb)\n                o = torch.sigmoid(o)\n                pred += o\n            pred /= len(nets)\n            if names:\n                pred = BIRD_LIST(get_thresh_preds(pred))\n\n            preds.append(pred)\n    return preds","metadata":{"papermill":{"duration":0.119816,"end_time":"2021-06-03T14:29:33.440692","exception":false,"start_time":"2021-06-03T14:29:33.320876","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.554448Z","iopub.execute_input":"2023-07-28T19:50:25.555038Z","iopub.status.idle":"2023-07-28T19:50:25.614603Z","shell.execute_reply.started":"2023-07-28T19:50:25.555008Z","shell.execute_reply":"2023-07-28T19:50:25.613655Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"calculating birdcall probabilities main func","metadata":{"papermill":{"duration":0.037678,"end_time":"2021-06-03T14:29:33.521001","exception":false,"start_time":"2021-06-03T14:29:33.483323","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def get_prob_df(config, audio_paths):\n    gc.collect()\n#     print('getting prob df for ', audio_paths)\n    data = pd.DataFrame(\n         [(path.stem, *path.stem.split(\"_\"), path) for path in Path(audio_paths).glob(\"*.ogg\")],\n        columns = [\"filename\", \"id\", \"site\", \"date\", \"filepath\"]\n    )\n    test_data = BirdCLEFDataset(data=data)\n#     print(\"get_prob_df, data: \", data)\n\n    for checkpoint_path in config.checkpoint_paths:\n        prob_filepath = config.get_prob_filepath_from_checkpoint(checkpoint_path)\n        if (not os.path.exists(prob_filepath)) or (TARGET_PATH is None):  # Always calculate when no cash is available or when submitting.\n#         if (True):  # Always calculate when no cash is available or when submitting.\n            nets = [load_net(checkpoint_path.as_posix())]\n            pred_probas = predict(nets, test_data, names=False)\n#             print(prob_filepath, 'probas: ', pred_probas)\n            if TARGET_PATH: # local                \n                df = pd.read_csv(TARGET_PATH, usecols=[\"row_id\", \"birds\"])\n            else: # when it is submission\n                if str(audio_paths)==\"../input/birdclef-2021/train_soundscapes\":\n                    print(audio_paths)\n                    df = pd.read_csv(Path(\"../input/birdclef-2021/train_soundscape_labels.csv\"), usecols=[\"row_id\", \"birds\"])\n                else:\n                    print(SAMPLE_SUB_PATH)\n                    df = pd.read_csv(SAMPLE_SUB_PATH, usecols=[\"row_id\", \"birds\"])\n#             print(\"get_prob_df, df: \",df)\n            df[\"audio_id\"] = df[\"row_id\"].apply(lambda _: int(_.split(\"_\")[0]))\n            df[\"site\"] = df[\"row_id\"].apply(lambda _: _.split(\"_\")[1])\n            df[\"seconds\"] = df[\"row_id\"].apply(lambda _: int(_.split(\"_\")[2]))\n            assert len(data) == len(pred_probas)\n            n = len(data)\n#             print(\"get_prob_df, n: \",n)\n            audio_id_to_date = {}\n            audio_id_to_site = {}\n            for filepath in audio_paths.glob(\"*.ogg\"):\n                audio_id, site, date = os.path.basename(filepath).replace(\".ogg\", \"\").split(\"_\")\n                audio_id = int(audio_id)\n                audio_id_to_date[audio_id] = date\n                audio_id_to_site[audio_id] = site\n            dfs = []\n            for i in range(n):\n                row = data.iloc[i]\n                audio_id = int(row[\"id\"])\n                pred = pred_probas[i]\n                _df = pd.DataFrame(pred.to(\"cpu\").numpy())\n                _df.columns = [IDX2BIRD[j] for j in range(_df.shape[1])]\n                _df[\"audio_id\"] = audio_id\n                _df[\"date\"] = audio_id_to_date[audio_id]\n                _df[\"site\"] = audio_id_to_site[audio_id]\n#                 _df[\"seconds\"] = [(j+1)*5 for j in range(len(_df))]\n                _df[\"seconds\"] = [(j+1)*5 for j in range(120)]\n                dfs.append(_df)\n            prob_df = pd.concat(dfs)\n            prob_df = pd.merge(prob_df, df, how=\"left\", on=[\"site\", \"audio_id\", \"seconds\"])\n            print(f\"Save to {prob_filepath}\")\n            prob_df.to_csv(prob_filepath, index=False)\n\n    # Ensemble\n    prob_df = pd.read_csv(\n        config.get_prob_filepath_from_checkpoint(config.checkpoint_paths[0])\n    )\n    if len(config.checkpoint_paths) > 1:\n        columns = BIRD_LIST\n        for checkpoint_path in config.checkpoint_paths[1:]:\n            _df = pd.read_csv(\n                config.get_prob_filepath_from_checkpoint(checkpoint_path)\n            )\n            prob_df[columns] += _df[columns]\n        prob_df[columns] /= len(config.checkpoint_paths)\n\n    return prob_df","metadata":{"papermill":{"duration":0.044679,"end_time":"2021-06-03T14:29:33.590655","exception":false,"start_time":"2021-06-03T14:29:33.545976","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.616328Z","iopub.execute_input":"2023-07-28T19:50:25.616919Z","iopub.status.idle":"2023-07-28T19:50:25.635517Z","shell.execute_reply.started":"2023-07-28T19:50:25.616889Z","shell.execute_reply":"2023-07-28T19:50:25.634467Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Training (LightGBM)\nhelper function for training","metadata":{"papermill":{"duration":0.024599,"end_time":"2021-06-03T14:29:33.640248","exception":false,"start_time":"2021-06-03T14:29:33.615649","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def seed_everything(seed=1234):\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    tf.random.set_seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True","metadata":{"papermill":{"duration":0.033361,"end_time":"2021-06-03T14:29:33.698423","exception":false,"start_time":"2021-06-03T14:29:33.665062","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.637184Z","iopub.execute_input":"2023-07-28T19:50:25.637788Z","iopub.status.idle":"2023-07-28T19:50:25.647494Z","shell.execute_reply.started":"2023-07-28T19:50:25.637753Z","shell.execute_reply":"2023-07-28T19:50:25.646580Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"training main func","metadata":{"papermill":{"duration":0.024879,"end_time":"2021-06-03T14:29:33.748128","exception":false,"start_time":"2021-06-03T14:29:33.723249","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def train(\n    candidate_df:pd.DataFrame,\n    df:pd.DataFrame,\n    candidate_df_soundscapes:pd.DataFrame,\n    df_soundscapes:pd.DataFrame,\n    num_kfolds:int,\n    num_candidates:int,\n    verbose:bool=False,\n    sampling_strategy:float=1.0,\n    random_state:int=777,\n):\n    \n    seed_everything(random_state)\n    feature_names = get_feature_names()\n    if verbose:\n        print(\"features\", feature_names)\n        \n        \n    # short audio の  k fold\n    groups = candidate_df[\"audio_id\"]\n    kf = StratifiedGroupKFold(n_splits=num_kfolds) # When using lgbm_rank, it is necessary to use the data attached to each group, so don't shuffle them.\n    for kfold_index, (_, valid_index) in enumerate(kf.split(candidate_df[feature_names].values, candidate_df[\"target\"].values, groups)):\n        candidate_df.loc[valid_index, \"fold\"] = kfold_index\n                        \n    X = candidate_df[feature_names].values\n    y = candidate_df[\"target\"].values\n    oofa = np.zeros(len(candidate_df_soundscapes), dtype=np.float32)\n    \n    for kfold_index in range(num_kfolds):\n        print(f\"fold {kfold_index}\")\n        train_index = candidate_df[candidate_df[\"fold\"] != kfold_index].index\n        valid_index = candidate_df[candidate_df[\"fold\"] == kfold_index].index\n        X_train, y_train = X[train_index], y[train_index]\n        #X_valid, y_valid = X[valid_index], y[valid_index]\n        X_valid, y_valid = candidate_df_soundscapes[feature_names].values, candidate_df_soundscapes[\"target\"].values\n        \n        dtrain = lgb.Dataset(X_train, label=y_train)\n        dvalid = lgb.Dataset(X_valid, label=y_valid)\n        params = {\n            'objective': 'binary',\n            'metric': 'binary_logloss',\n            'device':'gpu',\n        }\n        model = lgb.train(\n            params,\n            dtrain,\n            valid_sets=dvalid,\n            num_boost_round=200,\n            early_stopping_rounds=20,\n            verbose_eval=20,\n        )\n        oofa += model.predict(X_valid.astype(np.float32))/num_kfolds\n        pickle.dump(model, open(f\"lgbm_{kfold_index}.pkl\", \"wb\"))\n        \n    def f(th):\n        _df = candidate_df_soundscapes[(oofa > th)]\n        if len(_df) == 0:\n            return 0\n        _gdf = _df.groupby(\n            [\"audio_id\", \"seconds\"],\n            as_index=False\n        )[\"label\"].apply(lambda _: \" \".join(_))\n        df2 = pd.merge(\n            df_soundscapes[[\"audio_id\", \"seconds\", \"birds\"]],\n            _gdf,\n            how=\"left\",\n            on=[\"audio_id\", \"seconds\"]\n        )\n        df2.loc[df2[\"label\"].isnull(), \"label\"] = \"nocall\"\n        return df2.apply(\n            lambda _: get_metrics(_[\"birds\"], _[\"label\"])[\"f1\"],\n            axis=1\n        ).mean()\n\n\n    print(\"-\"*30)\n    print(f\"#sound_scapes (len:{len(candidate_df_soundscapes)}) でのスコア\")\n    lb, ub = 0, 1\n    for k in range(30):\n        th1 = (2*lb + ub) / 3\n        th2 = (lb + 2*ub) / 3\n        if f(th1) < f(th2):\n            lb = th1\n        else:\n            ub = th2\n    th = (lb + ub) / 2\n    print(\"best th: %.4f\" % th)\n    print(\"best F1: %.4f\" % f(th))\n    if verbose:\n        y_soundscapes =  candidate_df_soundscapes[\"target\"].values\n        oof = (oofa > th).astype(int)\n        print(\"[details] Call or No call classirication\")\n        print(\"binary F1: %.4f\" % f1_score(y_soundscapes, oof))\n        print(\"gt positive ratio: %.4f\" % np.mean(y_soundscapes))\n        print(\"oof positive ratio: %.4f\" % np.mean(oof))\n        print(\"Accuracy: %.4f\" % accuracy_score(y_soundscapes, oof))\n        print(\"Recall: %.4f\" % recall_score(y_soundscapes, oof))\n        print(\"Precision: %.4f\" % precision_score(y_soundscapes, oof))\n    print(\"-\"*30)\n    print()","metadata":{"papermill":{"duration":0.046046,"end_time":"2021-06-03T14:29:33.819545","exception":false,"start_time":"2021-06-03T14:29:33.773499","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.649070Z","iopub.execute_input":"2023-07-28T19:50:25.649451Z","iopub.status.idle":"2023-07-28T19:50:25.669327Z","shell.execute_reply.started":"2023-07-28T19:50:25.649399Z","shell.execute_reply":"2023-07-28T19:50:25.668184Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Optimize Threshold","metadata":{"papermill":{"duration":0.024325,"end_time":"2021-06-03T14:29:33.86862","exception":false,"start_time":"2021-06-03T14:29:33.844295","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"helper functions for optimizing threshold","metadata":{"papermill":{"duration":0.024112,"end_time":"2021-06-03T14:29:33.917545","exception":false,"start_time":"2021-06-03T14:29:33.893433","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def get_feature_names() -> List[str]:\n    return [\n        \"year\",\n        \"month\",\n        \"sum_prob\",\n        \"mean_prob\",\n        #\"std_prob\",\n        \"max_prob\",\n        #\"min_prob\",\n        #\"skew_prob\",\n        #\"kurt_prob\",\n        \"prev6_prob\",\n        \"prev5_prob\",\n        \"prev4_prob\",\n        \"prev3_prob\",\n        \"prev2_prob\",\n        \"prev_prob\",\n        \"prob\",\n        \"next_prob\",\n        \"next2_prob\",\n        \"next3_prob\",\n        \"next4_prob\",\n        \"next5_prob\",\n        \"next6_prob\",\n        \"rank\",\n        \"latitude\",\n        \"longitude\",\n        \"bird_id\", # +0.013700\n        \"seconds\", # -0.0050\n        \"num_appear\",\n        \"site_num_appear\",\n        \"site_appear_ratio\",\n        # \"prob / num_appear\", # -0.005\n        # \"prob / site_num_appear\", # -0.0102\n        # \"prob * site_appear_ratio\", # -0.0049\n        # \"prob_avg\", # -0.0155\n        \"prob_diff\", # 0.0082\n        # \"prob_avg_in_same_audio\", # -0.0256\n        # \"prob_max_in_same_audio\", # -0.0142\n        # \"prob_var_in_same_audio\", # -0.0304\n        # \"prob - prob_max_in_same_audio\", # -0.0069\n        # \"zscore_in_same_audio\", # -0.0110\n        # \"month_num_appear\", # 0.0164\n    ]\n\n\ndef get_metrics(s_true, s_pred):\n    s_true = set(s_true.split())\n    s_pred = set(s_pred.split())\n    n, n_true, n_pred = len(s_true.intersection(s_pred)), len(s_true), len(s_pred)\n    prec = n/n_pred\n    rec = n/n_true\n    f1 = 2*prec*rec/(prec + rec) if prec + rec else 0\n    return {\n        \"f1\": f1,\n        \"prec\": prec,\n        \"rec\": rec,\n        \"n_true\": n_true,\n        \"n_pred\": n_pred,\n        \"n\": n\n    }","metadata":{"papermill":{"duration":0.035858,"end_time":"2021-06-03T14:29:33.978091","exception":false,"start_time":"2021-06-03T14:29:33.942233","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.670882Z","iopub.execute_input":"2023-07-28T19:50:25.671221Z","iopub.status.idle":"2023-07-28T19:50:25.684047Z","shell.execute_reply.started":"2023-07-28T19:50:25.671168Z","shell.execute_reply":"2023-07-28T19:50:25.683050Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"optimizing threshold main func","metadata":{"papermill":{"duration":0.02412,"end_time":"2021-06-03T14:29:34.026936","exception":false,"start_time":"2021-06-03T14:29:34.002816","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def optimize(\n    candidate_df:pd.DataFrame,\n    prob_df:pd.DataFrame,\n    num_kfolds:int,\n    weights_filepath_dict:dict,\n):\n    feature_names = get_feature_names()\n    X = candidate_df[feature_names].values\n    y_preda_list = []\n    for mode in weights_filepath_dict.keys():\n        fold_y_preda_list = []\n        for kfold_index in range(num_kfolds):\n            clf = pickle.load(open(weights_filepath_dict[mode][kfold_index], \"rb\"))\n            if mode=='lgbm':\n                y_preda = clf.predict(X.astype(np.float32), num_iteration=clf.best_iteration)\n            elif mode=='lgbm_rank':\n                y_preda = clf.predict(X.astype(np.float32), num_iteration=clf.best_iteration)\n            else:\n                y_preda = clf.predict_proba(X)[:,1]\n            fold_y_preda_list.append(y_preda)\n        mean_preda = np.mean(fold_y_preda_list, axis=0)\n        if mode=='lgbm_rank': # scaling\n            mean_preda = 1/(1 + np.exp(-mean_preda))\n        y_preda_list.append(mean_preda)\n    y_preda = np.mean(y_preda_list, axis=0)\n    candidate_df[\"y_preda\"] = y_preda\n    \n    def f(th):\n        _df = candidate_df[y_preda > th]\n        if len(_df) == 0:\n            return 0\n        _gdf = _df.groupby(\n            [\"audio_id\", \"seconds\"],\n            as_index=False\n        )[\"label\"].apply(\n            lambda _: \" \".join(_)\n        ).rename(columns={\n            \"label\": \"predictions\"\n        })\n        submission_df = pd.merge(\n            prob_df[[\"row_id\", \"audio_id\", \"seconds\", \"birds\"]],\n            _gdf,\n            how=\"left\",\n            on=[\"audio_id\", \"seconds\"]\n        )\n        submission_df.loc[submission_df[\"predictions\"].isnull(), \"predictions\"] = \"nocall\"\n#         print(f\"sub_df in f({th}): {submission_df}\")\n        return submission_df.apply(\n            lambda row: get_metrics(str(row[\"birds\"]), str(row[\"predictions\"]))[\"f1\"],\n            axis=1\n        ).mean()\n    \n    lb, ub = 0, 1\n    for k in range(30):\n        th1 = (lb * 2 + ub) / 3\n        th2 = (lb + ub * 2) / 3\n        if f(th1) < f(th2):\n            lb = th1\n        else:\n            ub = th2\n    th = (lb + ub) / 2\n    print(\"-\" * 30)\n    print(\"📌best threshold: %f\" % th)\n    print(\"best F1: %f\" % f(th))\n    \n    # nocall injection\n    _df = candidate_df[y_preda > th]\n    if len(_df) == 0:\n        return 0\n    _gdf = _df.groupby(\n            [\"audio_id\", \"seconds\"],\n            as_index=False\n    )[\"label\"].apply(\n        lambda _: \" \".join(_)\n    ).rename(columns={\n        \"label\": \"predictions\"\n    })\n    submission_df = pd.merge(\n            prob_df[[\"row_id\", \"audio_id\", \"seconds\", \"birds\"]],\n            _gdf,\n            how=\"left\",\n            on=[\"audio_id\", \"seconds\"]\n        )\n    submission_df.loc[submission_df[\"predictions\"].isnull(), \"predictions\"] = \"nocall\"\n\n    \n    _gdf2 = _df.groupby(\n            [\"audio_id\", \"seconds\"],\n            as_index=False\n    )[\"y_preda\"].sum()\n    submission_df = pd.merge(\n            submission_df,\n            _gdf2,\n            how=\"left\",\n            on=[\"audio_id\", \"seconds\"]\n        )\n    def f_nocall(nocall_th):\n        submission_df_with_nocall = submission_df.copy()\n        submission_df_with_nocall.loc[(submission_df_with_nocall[\"y_preda\"]<nocall_th) \n                                      & (submission_df_with_nocall[\"predictions\"]!=\"nocall\"), \"predictions\"] += \" nocall\"\n        return submission_df_with_nocall.apply(\n            lambda row: get_metrics(str(row[\"birds\"]), str(row[\"predictions\"]))[\"f1\"],\n\n            axis=1\n        ).mean()\n    lb, ub = 0, 1\n    for k in range(30):\n        th1 = (lb * 2 + ub) / 3\n        th2 = (lb + ub * 2) / 3\n        if f_nocall(th1) < f_nocall(th2):\n            lb = th1\n        else:\n            ub = th2\n    nocall_th = (lb + ub) / 2\n    print(\"-\" * 30)\n    print(\"## nocall injection\")\n    print(\"📌best nocall threshold: %f\" % nocall_th)\n    print(\"best F1: %f\" % f_nocall(nocall_th))\n    \n    return th, nocall_th","metadata":{"papermill":{"duration":0.047718,"end_time":"2021-06-03T14:29:34.098972","exception":false,"start_time":"2021-06-03T14:29:34.051254","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:50:25.685637Z","iopub.execute_input":"2023-07-28T19:50:25.686170Z","iopub.status.idle":"2023-07-28T19:50:25.709017Z","shell.execute_reply.started":"2023-07-28T19:50:25.686140Z","shell.execute_reply":"2023-07-28T19:50:25.707842Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Fine tuning","metadata":{}},{"cell_type":"markdown","source":"## Prep","metadata":{}},{"cell_type":"code","source":"!pip show pandas | grep Version","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:25.710603Z","iopub.execute_input":"2023-07-28T19:50:25.710994Z","iopub.status.idle":"2023-07-28T19:50:36.140919Z","shell.execute_reply.started":"2023-07-28T19:50:25.710965Z","shell.execute_reply":"2023-07-28T19:50:36.139622Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from  ast import literal_eval\nimport re, time, json\nimport joblib\nfrom torch import nn, optim\nfrom sklearn.metrics import label_ranking_average_precision_score","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:36.142396Z","iopub.execute_input":"2023-07-28T19:50:36.142802Z","iopub.status.idle":"2023-07-28T19:50:36.154673Z","shell.execute_reply.started":"2023-07-28T19:50:36.142756Z","shell.execute_reply":"2023-07-28T19:50:36.153764Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport librosa as lb\nimport librosa.display as lbd\nimport soundfile as sf\nfrom  soundfile import SoundFile\nimport pandas as pd\nfrom  IPython.display import Audio\nfrom pathlib import Path\n\nimport torch\nfrom torch import nn, optim\nfrom  torch.utils.data import Dataset, DataLoader\n\nfrom resnest.torch import resnest50\n\nfrom matplotlib import pyplot as plt\nimport timm\nimport os, random, gc\nimport re, time, json\nfrom  ast import literal_eval\n\n\nfrom IPython.display import Audio\nfrom sklearn.metrics import label_ranking_average_precision_score\n\nfrom tqdm.notebook import tqdm\nimport joblib\nimport glob\n\n# from efficientnet_pytorch import EfficientNet\n# import pretrainedmodels\n# import resnest.torch as resnest_torch\n\n!pip install ../input/scikit-learn-10dev0/scikit_learn-1.0.dev0-cp37-cp37m-manylinux2010_x86_64.whl\nfrom sklearn.model_selection import StratifiedGroupKFold","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:36.156838Z","iopub.execute_input":"2023-07-28T19:50:36.158540Z","iopub.status.idle":"2023-07-28T19:50:59.315191Z","shell.execute_reply.started":"2023-07-28T19:50:36.158509Z","shell.execute_reply":"2023-07-28T19:50:59.313974Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"INPUT = Path('../input/')","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.317950Z","iopub.execute_input":"2023-07-28T19:50:59.318703Z","iopub.status.idle":"2023-07-28T19:50:59.323979Z","shell.execute_reply.started":"2023-07-28T19:50:59.318651Z","shell.execute_reply":"2023-07-28T19:50:59.322697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seed_everything(seed=42):\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_everything()","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.326638Z","iopub.execute_input":"2023-07-28T19:50:59.326984Z","iopub.status.idle":"2023-07-28T19:50:59.345561Z","shell.execute_reply.started":"2023-07-28T19:50:59.326954Z","shell.execute_reply":"2023-07-28T19:50:59.344623Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"NUM_CLASSES = 397\nSR = 32_000\nDURATION = 7\n\nMAX_READ_SAMPLES = 10 # Each record will have 10 melspecs at most, you can increase this on Colab with High Memory Enabled","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.347434Z","iopub.execute_input":"2023-07-28T19:50:59.347710Z","iopub.status.idle":"2023-07-28T19:50:59.354466Z","shell.execute_reply.started":"2023-07-28T19:50:59.347687Z","shell.execute_reply":"2023-07-28T19:50:59.353380Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MODEL_NAMES = [ \n            Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_26_f1_val_03882_20230719114118.pth\"), # id36\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_12_f1_val_04764_20230718204621.pth\"), # id51\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_32_f1_val_03974_20230719122845.pth\"), # id58\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold1_epoch_33_f1_val_04708_20230719124126.pth\"), # id59\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold2_epoch_33_f1_val_05269_20230719171944.pth\"), # id60\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold3_epoch_19_f1_val_04804_20230719152822.pth\"), # id61\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold4_epoch_33_f1_val_04921_20230719201223.pth\"), # id62\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_77_f1_val_03789_20230720042312.pth\"), # id97\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_49_f1_val_03852_20230722230730.pth\"), # id97\n#             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold1_epoch_26_f1_val_04692_20230720220745.pth\"), # id98\n#             AUGMENTED_MODELS[0]\n        ]","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.363422Z","iopub.execute_input":"2023-07-28T19:50:59.364251Z","iopub.status.idle":"2023-07-28T19:50:59.370473Z","shell.execute_reply.started":"2023-07-28T19:50:59.364220Z","shell.execute_reply":"2023-07-28T19:50:59.369537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config2:\n    def __init__(self, debug:bool):\n        self.debug = debug\n        \n#         self.epochs = 1 if self.debug else 100 # 50\n        self.epochs = 27\n\n        self.max_distance = None # choose from [10, 20, None]\n        if self.max_distance is not None:\n            self.sites = [\"SSW\"] # choose multiples from [\"COL\", \"COR\", \"SNE\", \"SSW\"]\n        else:\n            self.sites = None\n        self.max_duration = None # choose from [15, 30, 60, None]\n        self.min_rating = None # choose from [3, 4, None], best: 3?\n        self.max_spieces = None # choose from [100, 200, 300, None], best: 300?\n        self.confidence_ub = 0.995 # Probability of birdsong occurrence, default: 0.995, choose from [0.5, 0.7, 0.9, 0.995]\n        self.use_high_confidence_only = False # Whether to use only frames that are likely to be ringing (False performed better).\n        self.use_mixup = True\n        self.mixup_alpha = 0.5 # 5.0\n        self.secondary_labels_weight = 0.6 #0.6 > 0.8 > 0.3 for better performance\n        self.grouped_by_author = False\n        self.folds = [0,]\n\n        self.use_weight = False\n        self.use_valid2020 = False\n        self.use_ff1010 = False\n\n        self.suffix = f\"_sr{SR}_d{DURATION}\"\n        if self.max_spieces:\n            self.suffix += f\"_spices-{self.max_spieces}\"\n        if self.min_rating:\n            self.suffix += f\"_rating-{self.min_rating}\"\n        if self.use_high_confidence_only:\n            self.suffix += f\"_high-confidence-only\"\n        if self.use_mixup:\n            self.suffix += f\"_miixup-{self.mixup_alpha}\"\n        if self.secondary_labels_weight:\n            self.suffix += f\"_2ndlw-{self.secondary_labels_weight}\"\n        if self.use_weight:\n            self.suffix += f\"_weight\"\n        if self.use_valid2020:\n            self.suffix += f\"_valid2020\"\n        if self.use_ff1010:\n            self.suffix += f\"_ff1010\"\n        if self.grouped_by_author:\n            self.suffix += f\"_grouped-by-auther\"\n\n    def to_dict(self):\n        return {\n            \"debug\": self.debug,\n            \"epochs\": self.epochs,\n            \"max_distance\": self.max_distance,\n            \"sites\": self.sites,\n            \"max_duration\": self.max_duration,\n            \"min_rating\": self.min_rating,\n            \"max_spieces\": self.max_spieces,\n            \"confidence_ub\": self.confidence_ub,\n            \"use_high_confidence_only\": self.use_high_confidence_only,\n            \"use_mixup\": self.use_mixup,\n            \"mixup_alpha\": self.mixup_alpha,\n            \"secondary_labels_weight\": self.secondary_labels_weight,\n            \"suffix\": self.suffix,\n            \"grouped_by_author\": self.grouped_by_author\n        }\n\nconfig2 = Config2(debug=False)\nfrom pprint import pprint\npprint(config2.to_dict())","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.371884Z","iopub.execute_input":"2023-07-28T19:50:59.372403Z","iopub.status.idle":"2023-07-28T19:50:59.388186Z","shell.execute_reply.started":"2023-07-28T19:50:59.372372Z","shell.execute_reply":"2023-07-28T19:50:59.387126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"MEL_PATHS = sorted(INPUT.glob(\"birdclef2021augmentedaudio-melspec-p?/rich_train_metadata.csv\"))\nTRAIN_LABEL_PATHS = sorted(INPUT.glob(\"birdclef2021augmentedaudio-melspec-p?/LABEL_IDS.json\"))\n# /kaggle/input/birdclef2021augmentedaudio-melspec-p1\n# MEL_PATHS = sorted(INPUT.glob(\"kkiller-birdclef-mels-computer-d7-part?/rich_train_metadata.csv\"))\n# TRAIN_LABEL_PATHS = sorted(INPUT.glob(\"kkiller-birdclef-mels-computer-d7-part?/LABEL_IDS.json\"))\n\nMODEL_ROOT = Path(\".\")\n\nMEL_PATHS","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.389670Z","iopub.execute_input":"2023-07-28T19:50:59.390017Z","iopub.status.idle":"2023-07-28T19:50:59.421584Z","shell.execute_reply.started":"2023-07-28T19:50:59.389987Z","shell.execute_reply":"2023-07-28T19:50:59.420745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"TRAIN_BATCH_SIZE = 64\nTRAIN_NUM_WORKERS = 2\n\nVAL_BATCH_SIZE = 64\nVAL_NUM_WORKERS = 2\n\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\nprint(\"Device:\", DEVICE)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.424420Z","iopub.execute_input":"2023-07-28T19:50:59.424679Z","iopub.status.idle":"2023-07-28T19:50:59.431407Z","shell.execute_reply.started":"2023-07-28T19:50:59.424651Z","shell.execute_reply":"2023-07-28T19:50:59.430396Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_df(mel_paths=MEL_PATHS, train_label_paths=TRAIN_LABEL_PATHS):\n  df = None\n  LABEL_IDS = {}\n    \n  for file_path in mel_paths:\n    temp = pd.read_csv(str(file_path), index_col=1)\n    temp[\"impath\"] = temp.apply(lambda row: file_path.parent/\"audio_images/{}/{}.npy\".format(row.primary_label, row.filename), axis=1) \n#     print('temp: ', temp)\n#     temp = temp.reset_index(drop=True)\n#     print('temp: ', temp.shape, temp)\n#     temp = temp.drop('index', axis=1)\n    df = temp if df is None else df.append(temp)\n    \n  df[\"secondary_labels\"] = df[\"secondary_labels\"].apply(literal_eval)\n\n  for file_path in train_label_paths:\n    with open(str(file_path)) as f:\n      LABEL_IDS.update(json.load(f))\n\n  return LABEL_IDS, df","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.432845Z","iopub.execute_input":"2023-07-28T19:50:59.433508Z","iopub.status.idle":"2023-07-28T19:50:59.441490Z","shell.execute_reply.started":"2023-07-28T19:50:59.433457Z","shell.execute_reply":"2023-07-28T19:50:59.440477Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from typing import List\ndef get_locations() -> List[dict]:\n    return [{\n        \"site\": \"COL\",\n        \"latitude\": 5.57,\n        \"longitude\": -75.85\n    }, {\n        \"site\": \"COR\",\n        \"latitude\": 10.12,\n        \"longitude\": -84.51\n    }, {\n        \"site\": \"SNE\",\n        \"latitude\": 38.49,\n        \"longitude\": -119.95\n    }, {\n        \"site\": \"SSW\",\n        \"latitude\": 42.47,\n        \"longitude\": -76.45\n    }]\n\ndef is_in_site(row, sites, max_distance):\n    for location in get_locations():\n        if location[\"site\"] in sites:\n            x = (row[\"latitude\"] - location[\"latitude\"])\n            y = (row[\"longitude\"] - location[\"longitude\"])\n            r = (x**2 + y**2) ** 0.5\n            if r < max_distance:\n                return True\n    return False","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.443002Z","iopub.execute_input":"2023-07-28T19:50:59.443351Z","iopub.status.idle":"2023-07-28T19:50:59.454089Z","shell.execute_reply.started":"2023-07-28T19:50:59.443305Z","shell.execute_reply":"2023-07-28T19:50:59.453217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"LABEL_IDS, df = get_df()\n# df = df.reset_index(drop=True)\n# print('df: ', df.shape, df, df.columns)\n\n\n# print(len(df))\n# print(df)\n# df.reset_index(drop=True, inplace=True)\n\nif config2.grouped_by_author:\n    kf = StratifiedGroupKFold(n_splits=5)\n    x = df[[\"latitude\", \"longitude\"]].values\n    y = df[\"label_id\"].values\n    groups = df[\"author\"].values\n    df = df.reset_index(drop=True) # add this line\n    df[\"fold\"] = -1\n    for kfold_index, (train_index, valid_index) in enumerate(kf.split(x, y, groups)):\n        print(valid_index)\n        print(df)\n        df.loc[valid_index, \"fold\"] = kfold_index\n\nif config2.debug:\n    df = df.head(100)\n\nprint(\"before:%d\" % len(df))\n# Within a certain distance of the target area\nif config2.max_distance is not None:\n    df = df[df.apply(lambda row: is_in_site(row, config2.sites, config2.max_distance), axis=1)]\n# Number of Species\nif config2.max_spieces is not None:\n    s = df[\"primary_label\"].value_counts().head(config2.max_spieces)\n    df = df[df[\"primary_label\"].isin(s.index)]\nif config2.min_rating is not None:\n    df = df[df[\"rating\"] >= config2.min_rating]\nif config2.max_duration is not None:\n    df = df[df[\"duration\"] < config2.max_duration]\ndf = df.reset_index(drop=True)\nprint(\"after:%d\" % len(df))\n\nprint(df.shape)\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:50:59.455585Z","iopub.execute_input":"2023-07-28T19:50:59.456175Z","iopub.status.idle":"2023-07-28T19:51:03.317936Z","shell.execute_reply.started":"2023-07-28T19:50:59.456144Z","shell.execute_reply":"2023-07-28T19:51:03.316922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import glob\nnocall_paths = glob.glob(\"/kaggle/input/augmented-train-short-audio-nocall-fold0to4/*.csv\")\nprobs_list = []\nfor nocall_path in nocall_paths:\n    nocall_df = pd.read_csv(nocall_path)\n    probs = nocall_df[\"nocalldetection\"].apply(\n        lambda _: list(\n            map(\n                float,\n                _.split()\n            )\n        )\n    )\n    probs_list.append(probs)\nprobs = []\nfor di in range(len(nocall_df)):\n    one_row = []\n    for ni in range(len(nocall_paths)):\n        one_row.append(probs_list[ni][di])\n    probs.append(np.mean(one_row,axis=0).tolist())\n\naudio_prob_store = dict(zip(nocall_df[\"filename\"].tolist(), probs))","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:03.319575Z","iopub.execute_input":"2023-07-28T19:51:03.320259Z","iopub.status.idle":"2023-07-28T19:51:10.264979Z","shell.execute_reply.started":"2023-07-28T19:51:03.320224Z","shell.execute_reply":"2023-07-28T19:51:10.264012Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if config2.use_valid2020:\n    clef_2020_df = pd.read_csv(\"../input/birdclef2020-validation-audio-and-ground-truth-d5/rich_metadata.csv\", index_col=0)\n    clef_2020_df[\"fold\"] = clef_2020_df[\"file_fold\"]%5\n    clef_2020_df[\"impath\"] = \"../input/birdclef2020-validation-audio-and-ground-truth-d5/\" + clef_2020_df[\"primary_label\"] + \"/\" + clef_2020_df[\"filename\"] + \".npy\"\n    clef_2020_df[\"label_id\"] = -1\n    clef_2020_df = clef_2020_df[clef_2020_df[\"primary_label\"]==\"nocall\"]\n    clef_2020_df[\"secondary_labels\"] = [[] for i in range(len(clef_2020_df))]\n\n    # Update prob with nocall detector\n    probs = [[0] for i in range(len(clef_2020_df))]\n    prob_dict = dict(zip(clef_2020_df[\"filename\"].tolist(), probs))\n    audio_prob_store.update(prob_dict)\n#     df = df.reset_index(drop=True)\n#     clef_2020_df = clef_2020_df.reset_index(drop=True)\n\n    df = pd.concat([clef_2020_df, df]).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:10.266549Z","iopub.execute_input":"2023-07-28T19:51:10.266901Z","iopub.status.idle":"2023-07-28T19:51:10.275066Z","shell.execute_reply.started":"2023-07-28T19:51:10.266868Z","shell.execute_reply":"2023-07-28T19:51:10.274123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:10.276518Z","iopub.execute_input":"2023-07-28T19:51:10.277180Z","iopub.status.idle":"2023-07-28T19:51:10.355124Z","shell.execute_reply.started":"2023-07-28T19:51:10.277139Z","shell.execute_reply":"2023-07-28T19:51:10.354238Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"if config2.use_ff1010:\n    #!unzip -q /content/drive/MyDrive/git/kaggle-birdclef-2021/working/preprocessed/ff1010bird_duration7.zip -d {INPUT}/ff1010bird_duration7\n\n    ff1010_df = pd.read_csv(\"../input/ff1010bird-duration7-1/rich_metadata.csv\", index_col=0)\n    ff1010_df[\"impath\"] = \"../input/ff1010bird-duration7-1/\" + ff1010_df[\"primary_label\"] + \"/\" + ff1010_df[\"filename\"] + \".npy\"\n    ff1010_df = ff1010_df[ff1010_df[\"primary_label\"]==\"nocall\"] #nocall のみを使う\n    ff1010_df[\"label_id\"] = -1\n    ff1010_df[\"fold\"] = ff1010_df.index % 5\n    ff1010_df[\"secondary_labels\"] = [[] for i in range(len(ff1010_df))]\n\n    # Update prob with nocall detector\n    probs = [[0] for i in range(len(ff1010_df))]\n    prob_dict = dict(zip(ff1010_df[\"filename\"].tolist(), probs))\n    audio_prob_store.update(prob_dict)\n    \n#     df = df.reset_index(drop=True)\n#     ff1010_df = ff1010_df.reset_index(drop=True)\n\n    df = pd.concat([ff1010_df, df]).reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:10.356615Z","iopub.execute_input":"2023-07-28T19:51:10.357627Z","iopub.status.idle":"2023-07-28T19:51:10.365504Z","shell.execute_reply.started":"2023-07-28T19:51:10.357593Z","shell.execute_reply":"2023-07-28T19:51:10.364519Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:10.367091Z","iopub.execute_input":"2023-07-28T19:51:10.367478Z","iopub.status.idle":"2023-07-28T19:51:10.445415Z","shell.execute_reply.started":"2023-07-28T19:51:10.367443Z","shell.execute_reply":"2023-07-28T19:51:10.444525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_data(df):\n    def load_row(row):\n        # impath = TRAIN_IMAGES_ROOT/f\"{row.primary_label}/{row.filename}.npy\"\n        return row.filename, np.load(str(row.impath))[:MAX_READ_SAMPLES]\n    pool = joblib.Parallel(4)\n    mapper = joblib.delayed(load_row)\n    tasks = [mapper(row) for row in df.itertuples(False)]\n    res = pool(tqdm(tasks))\n    res = dict(res)\n    return res\n\n# We cache the train set to reduce training time\n\naudio_image_store = load_data(df)\nlen(audio_image_store)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:51:10.446757Z","iopub.execute_input":"2023-07-28T19:51:10.447348Z","iopub.status.idle":"2023-07-28T19:52:35.991379Z","shell.execute_reply.started":"2023-07-28T19:51:10.447302Z","shell.execute_reply":"2023-07-28T19:52:35.990372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_w = 281\n\ndef pad_image(image, image_w=image_w):\n    h = image.shape[0]\n    w = image.shape[1]\n    if w < image_w:\n        start = np.random.choice((image_w-w))\n        ret = np.zeros((h, image_w))\n        ret[:, start:start+w] = image\n        return ret\n    return image\n\nclass BirdClefDataset(Dataset):\n\n    def __init__(\n        self,\n        audio_image_store,\n        audio_prob_store,\n        meta,\n        sr=SR,\n        is_train=True,\n        num_classes=NUM_CLASSES,\n        duration=DURATION,\n    ):        \n        self.audio_image_store = audio_image_store\n        self.audio_prob_store = audio_prob_store\n        self.meta = meta.copy().reset_index(drop=True)\n        self.sr = sr\n        self.is_train = is_train\n        self.num_classes = num_classes\n        self.duration = duration\n        self.audio_length = self.duration*self.sr\n        self.eps = 0.0025\n    \n    @staticmethod\n    def normalize(image):\n        image = image.astype(\"float32\", copy=False) / 255.0\n        image = np.stack([image, image, image])\n        return image\n\n    def __len__(self):\n        return len(self.meta)\n    \n    def mixup_data(self, image, noize, alpha=0.5):\n        if alpha > 0.:\n            lam = np.random.beta(alpha, alpha)\n        else:\n            lam = 1.\n        lam /= 2 # leave it at half maximum.\n        mixed_x = (1 - lam) * image + lam * noize\n        return mixed_x\n\n    def __getitem__(self, idx):\n        row = self.meta.iloc[idx]\n        images = self.audio_image_store[row.filename]\n        probs = self.audio_prob_store[row.filename]\n\n        i = np.random.choice(len(images))\n        image = images[i]\n\n        if image.shape[1] < self.audio_length:\n            image = pad_image(image, image_w)\n\n        \n        image = self.normalize(image)\n        prob = probs[i]\n        t = np.zeros(self.num_classes, dtype=np.float32) + self.eps # Label smoothing\n        t[row.label_id] = max(min(prob, config2.confidence_ub), self.eps) # clipping\n        for secondary_label in row.secondary_labels:\n            # Set a lower value than the primary label\n            if secondary_label in LABEL_IDS:\n                t[LABEL_IDS[secondary_label]] = max(self.eps, prob * 0.6)\n\n        \n        return image, t","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:35.993757Z","iopub.execute_input":"2023-07-28T19:52:35.994137Z","iopub.status.idle":"2023-07-28T19:52:36.011299Z","shell.execute_reply.started":"2023-07-28T19:52:35.994096Z","shell.execute_reply":"2023-07-28T19:52:36.010443Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Fine tune main","metadata":{}},{"cell_type":"code","source":"def mixup_data(x, y, alpha=0.5, use_cuda=True):\n    x = x.to(DEVICE)\n    y = y.to(DEVICE)\n    if alpha > 0.:\n        lam = np.random.beta(alpha, alpha)\n    else:\n        lam = 1.\n    batch_size = x.size()[0]\n    if use_cuda:\n        index = torch.randperm(batch_size).cuda()\n    else:\n        index = torch.randperm(batch_size)\n\n    mixed_x = lam * x + (1 - lam) * x[index,:]\n    mixed_y = lam * y + (1 - lam) * y[index]\n    #mixed_y = torch.maximum(y, y[index])\n    return mixed_x, mixed_y, lam\n\n# def mixup_data(x, y, alpha, use_cuda):\n#     if alpha > 0:\n#         lam = np.random.beta(alpha, alpha)\n#     else:\n#         lam = 1\n#     batch_size = x.size()[0]\n#     if use_cuda:\n#         index = torch.randperm(batch_size).to(x.device)\n#     else:\n#         index = torch.randperm(batch_size)\n#     mixed_x = lam * x + (1 - lam) * x[index, :]\n#     mixed_y = lam * y + (1 - lam) * y[index]\n#     return mixed_x, mixed_y, lam","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.014708Z","iopub.execute_input":"2023-07-28T19:52:36.014997Z","iopub.status.idle":"2023-07-28T19:52:36.026835Z","shell.execute_reply.started":"2023-07-28T19:52:36.014972Z","shell.execute_reply":"2023-07-28T19:52:36.025906Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_step( xb, yb, net, criterion, optimizer, scheduler=None):\n  if config2.use_mixup:\n      xb, yb, lam = mixup_data(xb,yb, alpha=config2.mixup_alpha)\n  xb, yb = xb.to(DEVICE), yb.to(DEVICE)\n        \n  optimizer.zero_grad()\n  o = net(xb)\n  loss = criterion(o, yb)\n  loss.backward()\n  optimizer.step()\n  \n  with torch.no_grad():\n      l = loss.item()\n\n      o = o.sigmoid()\n      yb = (yb > 0.5 )*1.0\n      lrap = label_ranking_average_precision_score(yb.cpu().numpy(), o.cpu().numpy())\n\n      o = (o > 0.5)*1.0\n\n      prec = (o*yb).sum()/(1e-6 + o.sum())\n      rec = (o*yb).sum()/(1e-6 + yb.sum())\n      f1 = 2*prec*rec/(1e-6+prec+rec)\n\n  if  scheduler is not None:\n    scheduler.step()\n\n  return l, lrap, f1.item(), rec.item(), prec.item()","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.030087Z","iopub.execute_input":"2023-07-28T19:52:36.030375Z","iopub.status.idle":"2023-07-28T19:52:36.039844Z","shell.execute_reply.started":"2023-07-28T19:52:36.030327Z","shell.execute_reply":"2023-07-28T19:52:36.038870Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@torch.no_grad()\ndef evaluate(net, criterion, val_laoder):\n    net.eval()\n\n    os, y = [], []\n    val_laoder = tqdm(val_laoder, leave = False, total=len(val_laoder))\n\n    for icount, (xb, yb) in  enumerate(val_laoder):\n\n        y.append(yb.to(DEVICE))\n\n        xb = xb.to(DEVICE)\n        o = net(xb)\n\n        os.append(o)\n\n    y = torch.cat(y)\n    o = torch.cat(os)\n\n    l = criterion(o, y).item()\n    \n    o = o.sigmoid()\n    y = (y > 0.5)*1.0\n\n    lrap = label_ranking_average_precision_score(y.cpu().numpy(), o.cpu().numpy())\n\n    o = (o > 0.5)*1.0\n\n    prec = ((o*y).sum()/(1e-6 + o.sum())).item()\n    rec = ((o*y).sum()/(1e-6 + y.sum())).item()\n    f1 = 2*prec*rec/(1e-6+prec+rec)\n\n    return l, lrap, f1, rec, prec, \n    ","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.041277Z","iopub.execute_input":"2023-07-28T19:52:36.041888Z","iopub.status.idle":"2023-07-28T19:52:36.053425Z","shell.execute_reply.started":"2023-07-28T19:52:36.041857Z","shell.execute_reply":"2023-07-28T19:52:36.052565Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_epoch(net, criterion, optimizer, scheduler, train_laoder, val_laoder):\n  net.train()\n  l, lrap, prec, rec, f1, icount = 0.,0.,0.,0., 0., 0\n  train_laoder = tqdm(train_laoder, leave = False)\n  epoch_bar = train_laoder\n  \n  for (xb, yb) in  epoch_bar:\n      # epoch_bar.set_description(\"----|----|----|----|---->\")\n      _l, _lrap, _f1, _rec, _prec = one_step(xb, yb, net, criterion, optimizer)\n      l += _l\n      lrap += _lrap\n      f1 += _f1\n      rec += _rec\n      prec += _prec\n\n      icount += 1\n        \n      if hasattr(epoch_bar, \"set_postfix\") and not icount%10:\n          epoch_bar.set_postfix(\n            loss=\"{:.6f}\".format(l/icount),\n            lrap=\"{:.3f}\".format(lrap/icount),\n            prec=\"{:.3f}\".format(prec/icount),\n            rec=\"{:.3f}\".format(rec/icount),\n            f1=\"{:.3f}\".format(f1/icount),\n          )\n  \n  scheduler.step()\n\n  l /= icount\n  lrap /= icount\n  f1 /= icount\n  rec /= icount\n  prec /= icount\n  \n  l_val, lrap_val, f1_val, rec_val, prec_val = evaluate(net, criterion, val_laoder)\n  \n  return (l, l_val), (lrap, lrap_val), (f1, f1_val), (rec, rec_val), (prec, prec_val)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.056057Z","iopub.execute_input":"2023-07-28T19:52:36.056762Z","iopub.status.idle":"2023-07-28T19:52:36.066785Z","shell.execute_reply.started":"2023-07-28T19:52:36.056738Z","shell.execute_reply":"2023-07-28T19:52:36.065950Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class AutoSave:\n  def __init__(self, top_k=50, metric=\"f1\", mode=\"min\", root=None, name=\"ckpt\"):\n    self.top_k = top_k\n    self.logs = []\n    self.metric = metric\n    self.mode = mode\n#     self.root = Path(root or MODEL_ROOT)\n    self.root = Path(MODEL_ROOT)\n    assert self.root.exists()\n    self.name = name\n\n    self.top_models = []\n    self.top_metrics = []\n\n  def log(self, model, metrics):\n    metric = metrics[self.metric]\n    rank = self.rank(metric)\n\n    self.top_metrics.insert(rank+1, metric)\n    if len(self.top_metrics) > self.top_k:\n      self.top_metrics.pop(0)\n\n    self.logs.append(metrics)\n    self.save(model, metric, rank, metrics[\"epoch\"])\n\n\n  def save(self, model, metric, rank, epoch):\n    t = time.strftime(\"%Y%m%d%H%M%S\")\n    name = \"{}_epoch_{:02d}_{}_{:.04f}_{}\".format(self.name, epoch, self.metric, metric, t)\n    name = re.sub(r\"[^\\w_-]\", \"\", name) + \".pth\"\n    path = self.root.joinpath(name)\n\n    old_model = None\n    self.top_models.insert(rank+1, name)\n    if len(self.top_models) > self.top_k:\n      old_model = self.root.joinpath(self.top_models[0])\n      self.top_models.pop(0)      \n\n    torch.save(model.state_dict(), path.as_posix())\n\n    if old_model is not None:\n      old_model.unlink()\n\n    self.to_json()\n\n\n  def rank(self, val):\n    r = -1\n    for top_val in self.top_metrics:\n      if val <= top_val:\n        return r\n      r += 1\n\n    return r\n  \n  def to_json(self):\n    # t = time.strftime(\"%Y%m%d%H%M%S\")\n    name = \"{}_logs\".format(self.name)\n    name = re.sub(r\"[^\\w_-]\", \"\", name) + \".json\"\n    path = self.root.joinpath(name)\n\n    with path.open(\"w\") as f:\n      json.dump(self.logs, f, indent=2)\n","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.067977Z","iopub.execute_input":"2023-07-28T19:52:36.068372Z","iopub.status.idle":"2023-07-28T19:52:36.083381Z","shell.execute_reply.started":"2023-07-28T19:52:36.068327Z","shell.execute_reply":"2023-07-28T19:52:36.082325Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def one_fold(model_path, model_name, fold, train_set, val_set, epochs=20, save=True, save_root=None):\n\n  save_root = Path(save_root) or MODEL_ROOT\n\n  saver = AutoSave(root=save_root, name=f\"birdclef_{model_name}_fold{fold}\", metric=\"f1_val\")\n\n  net = load_net(model_path).to(DEVICE)\n\n  #criterion = nn.BCEWithLogitsLoss()\n  weight = None\n  if config2.use_weight:\n      label_inv = (1/df[\"label_id\"].value_counts().sort_index()).values\n      label_inv_mean = label_inv.mean()\n      weight = label_inv*(1/label_inv_mean)  # Inverse proportion such that the mean is 1\n      weight = torch.tensor(weight).to(DEVICE)\n  criterion = nn.BCEWithLogitsLoss(weight=weight)\n  \n  lr =  8e-4\n  optimizer = optim.Adam(net.parameters(), lr=lr)\n  scheduler = optim.lr_scheduler.CosineAnnealingLR(optimizer, eta_min=1e-5, T_max=epochs)\n\n  train_data = BirdClefDataset(\n      audio_image_store,\n      audio_prob_store,\n      meta=df.iloc[train_set].reset_index(drop=True),\n      sr=SR,\n      duration=DURATION,\n      is_train=True\n    )\n  train_laoder = DataLoader(train_data, batch_size=TRAIN_BATCH_SIZE, num_workers=TRAIN_NUM_WORKERS, shuffle=True, pin_memory=True)\n\n  val_data = BirdClefDataset(\n      audio_image_store,\n      audio_prob_store,\n      meta=df.iloc[val_set].reset_index(drop=True),\n      sr=SR,\n      duration=DURATION,\n      is_train=False)\n  val_laoder = DataLoader(val_data, batch_size=VAL_BATCH_SIZE, num_workers=VAL_NUM_WORKERS, shuffle=False)\n\n  epochs_bar = tqdm(list(range(epochs)), leave=False)\n  for epoch  in epochs_bar:\n    epochs_bar.set_description(f\"--> [EPOCH {epoch:02d}]\")\n    net.train()\n\n    (l, l_val), (lrap, lrap_val), (f1, f1_val), (rec, rec_val), (prec, prec_val) = one_epoch(\n        net=net,\n        criterion=criterion,\n        optimizer=optimizer,\n        scheduler=scheduler,\n        train_laoder=train_laoder,\n        val_laoder=val_laoder,\n      )\n\n    epochs_bar.set_postfix(\n        loss=\"({:.6f}, {:.6f})\".format(l, l_val),\n        prec=\"({:.3f}, {:.3f})\".format(prec, prec_val),\n        rec=\"({:.3f}, {:.3f})\".format(rec, rec_val),\n        f1=\"({:.3f}, {:.3f})\".format(f1, f1_val),\n        lrap=\"({:.3f}, {:.3f})\".format(lrap, lrap_val),\n    )\n\n    print(\n        \"[{epoch:02d}] loss: {loss} lrap: {lrap} f1: {f1} rec: {rec} prec: {prec}\".format(\n            epoch=epoch,\n            loss=\"({:.6f}, {:.6f})\".format(l, l_val),\n            prec=\"({:.3f}, {:.3f})\".format(prec, prec_val),\n            rec=\"({:.3f}, {:.3f})\".format(rec, rec_val),\n            f1=\"({:.3f}, {:.3f})\".format(f1, f1_val),\n            lrap=\"({:.3f}, {:.3f})\".format(lrap, lrap_val),\n        )\n    )\n\n    if save:\n      metrics = {\n          \"loss\": l, \"lrap\": lrap, \"f1\": f1, \"rec\": rec, \"prec\": prec,\n          \"loss_val\": l_val, \"lrap_val\": lrap_val, \"f1_val\": f1_val, \"rec_val\": rec_val, \"prec_val\": prec_val,\n          \"epoch\": epoch,\n      }\n\n      saver.log(net, metrics)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.084983Z","iopub.execute_input":"2023-07-28T19:52:36.085401Z","iopub.status.idle":"2023-07-28T19:52:36.103176Z","shell.execute_reply.started":"2023-07-28T19:52:36.085366Z","shell.execute_reply":"2023-07-28T19:52:36.102219Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def finetune(model_path, epochs=20, save=True, n_splits=5, seed=177, save_root=None, suffix=\"\", folds=None):\n    gc.collect()\n    torch.cuda.empty_cache()\n    model_name = os.path.basename(model_path)\n\n    save_root = save_root or MODEL_ROOT/f\"{model_name}{suffix}\"\n    save_root.mkdir(exist_ok=True, parents=True)\n  \n    print(len(df))\n    print(df)\n    fold_bar = tqdm(df.reset_index().groupby(\"fold\").index.apply(list).items(), total=df.fold.max()+1)\n  \n    for fold, val_set in fold_bar:\n        if folds and not fold in folds:\n            continue\n      \n        print(f\"\\n############################### [FOLD {fold}]\")\n        fold_bar.set_description(f\"[FOLD {fold}]\")\n        train_set = np.setdiff1d(df.index, val_set)\n        print(len(val_set))\n        \n        one_fold(model_path, model_name, fold=fold, train_set=train_set , val_set=val_set , epochs=epochs, save=save, save_root=save_root)\n    \n        gc.collect()\n        torch.cuda.empty_cache()","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.104677Z","iopub.execute_input":"2023-07-28T19:52:36.105167Z","iopub.status.idle":"2023-07-28T19:52:36.116806Z","shell.execute_reply.started":"2023-07-28T19:52:36.105122Z","shell.execute_reply":"2023-07-28T19:52:36.115889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# MODEL_NAMES = [ \n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_26_f1_val_03882_20230719114118.pth\"), # id36\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_12_f1_val_04764_20230718204621.pth\"), # id51\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_32_f1_val_03974_20230719122845.pth\"), # id58\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold1_epoch_33_f1_val_04708_20230719124126.pth\"), # id59\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold2_epoch_33_f1_val_05269_20230719171944.pth\"), # id60\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold3_epoch_19_f1_val_04804_20230719152822.pth\"), # id61\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold4_epoch_33_f1_val_04921_20230719201223.pth\"), # id62\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_77_f1_val_03789_20230720042312.pth\"), # id97\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold0_epoch_49_f1_val_03852_20230722230730.pth\"), # id97\n# #             Path(\"/kaggle/input/augmentedclassifiermodel-res50/birdclef_resnest50_fold1_epoch_26_f1_val_04692_20230720220745.pth\"), # id98\n# #             AUGMENTED_MODELS[0]\n#         ]","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.118423Z","iopub.execute_input":"2023-07-28T19:52:36.119200Z","iopub.status.idle":"2023-07-28T19:52:36.127301Z","shell.execute_reply.started":"2023-07-28T19:52:36.119098Z","shell.execute_reply":"2023-07-28T19:52:36.126407Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for model_name in MODEL_NAMES:\n    print(\"\\n\\n###########################################\", model_name)\n    finetune(model_name, epochs=config2.epochs, suffix=config2.suffix, folds=config2.folds)","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:52:36.128634Z","iopub.execute_input":"2023-07-28T19:52:36.129189Z","iopub.status.idle":"2023-07-28T19:55:09.069780Z","shell.execute_reply.started":"2023-07-28T19:52:36.129160Z","shell.execute_reply":"2023-07-28T19:55:09.068064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# config.checkpoint_paths = [ \n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold0_epoch_33_f1_val_03859_20210524151554pth_fold0_epoch_00_f1_val_04528_20230620112351.pth\"), # id36\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold2_epoch_34_f1_val_05027_20210524223209pth_fold0_epoch_00_f1_val_04151_20230620112401.pth\"), # id51\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold0_epoch_78_f1_val_03658_20210528221629pth_fold0_epoch_00_f1_val_04727_20230620112414.pth\"), # id58\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold4_epoch_34_f1_val_05140_20210525074929pth_fold0_epoch_00_f1_val_04444_20230620112409.pth\"), # id59\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold0_epoch_13_f1_val_03502_20210522050604pth_fold0_epoch_00_f1_val_03265_20230620112347.pth\"), # id60\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold1_epoch_34_f1_val_04757_20210524185455pth_fold0_epoch_00_f1_val_04528_20230620112356.pth\"), # id61\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold0_epoch_84_f1_val_03689_20210528225810pth_fold0_epoch_00_f1_val_03265_20230620112419.pth\"), # id62\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold3_epoch_20_f1_val_04299_20210525010703pth_fold0_epoch_00_f1_val_04528_20230620112405.pth\"), # id97\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold1_epoch_27_f1_val_03942_20210529062427pth_fold0_epoch_00_f1_val_04444_20230620112424.pth\"), # id97\n#             Path(\"/kaggle/working/birdclef_birdclef_resnest50_fold0_epoch_27_f1_val_05179_20210520120053pth_fold0_epoch_00_f1_val_04815_20230620112342.pth\"), # id98\n#         ]\ntemp = glob.glob('/kaggle/working/*.pth')\nconfig.checkpoint_paths = [Path(x) for x in temp]\nconfig.checkpoint_paths","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.071431Z","iopub.status.idle":"2023-07-28T19:55:09.072751Z","shell.execute_reply.started":"2023-07-28T19:55:09.072482Z","shell.execute_reply":"2023-07-28T19:55:09.072512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# def train_model(model, dataset, num_epochs, batch_size, learning_rate):\n#     # Set the device\n#     device = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n#     # Create data loader\n#     data_loader = DataLoader(dataset, batch_size=batch_size, shuffle=True)\n\n#     # Move model to the device\n#     model = model.to(device)\n\n#     # Define loss function and optimizer\n#     criterion = nn.CrossEntropyLoss()\n#     optimizer = optim.Adam(model.parameters(), lr=learning_rate)\n\n#     # Start training loop\n#     for epoch in range(num_epochs):\n#         model.train()\n#         running_loss = 0.0\n        \n#         for images in data_loader:\n#             images = images.to(device)\n#             labels = images[\"label\"].to(device)  # Adjust this line to match the label format in your dataset\n            \n#             optimizer.zero_grad()\n            \n#             outputs = model(images)\n#             loss = criterion(outputs, labels)\n            \n#             loss.backward()\n#             optimizer.step()\n            \n#             running_loss += loss.item()\n        \n#         epoch_loss = running_loss / len(data_loader)\n#         print(f\"Epoch [{epoch+1}/{num_epochs}], Loss: {epoch_loss:.4f}\")\n\n#     print(\"Training finished.\")","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.074104Z","iopub.status.idle":"2023-07-28T19:55:09.074812Z","shell.execute_reply.started":"2023-07-28T19:55:09.074553Z","shell.execute_reply":"2023-07-28T19:55:09.074576Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# model = models.resnest50(pretrained=False)\n# model.fc = nn.Linear(model.fc.in_features, num_classes)\n\n# dataset = BirdCLEFDataset(data)  # Replace 'data' with your actual dataset\n\n# num_epochs = 10\n# batch_size = 16\n# learning_rate = 0.001\n\n# train_model(model, dataset, num_epochs, batch_size, learning_rate)\n\n\n# for model_path in \n","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.076097Z","iopub.status.idle":"2023-07-28T19:55:09.076802Z","shell.execute_reply.started":"2023-07-28T19:55:09.076546Z","shell.execute_reply":"2023-07-28T19:55:09.076569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for checkpoint_path in config.checkpoint_paths:\n#     prob_filepath = config.get_prob_filepath_from_checkpoint(checkpoint_path)\n#     if (not os.path.exists(prob_filepath)) or (TARGET_PATH is None):  # Always calculate when no cash is available or when submitting.\n# #         if (True):  # Always calculate when no cash is available or when submitting.\n#         nets = [load_net(checkpoint_path.as_posix())]\n#         model = nets[0]\n        \n#         model.fc = nn.Linear(model.fc.in_features, num_classes)\n\n#         dataset = BirdCLEFDataset(data)  # Replace 'data' with your actual dataset\n\n#         num_epochs = 10\n#         batch_size = 16\n#         learning_rate = 0.001\n\n#         train_model(model, dataset, num_epochs, batch_size, learning_rate)\n        \n#         print(len(nets))\n# #         print(nets, 'cho anh hai ne')","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.078049Z","iopub.status.idle":"2023-07-28T19:55:09.078744Z","shell.execute_reply.started":"2023-07-28T19:55:09.078492Z","shell.execute_reply":"2023-07-28T19:55:09.078514Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Make Submission\nhelper functions for making submission","metadata":{"papermill":{"duration":0.024158,"end_time":"2021-06-03T14:29:34.14762","exception":false,"start_time":"2021-06-03T14:29:34.123462","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"make_submission main func","metadata":{"papermill":{"duration":0.024182,"end_time":"2021-06-03T14:29:34.256677","exception":false,"start_time":"2021-06-03T14:29:34.232495","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# Main","metadata":{"papermill":{"duration":0.024431,"end_time":"2021-06-03T14:29:34.372753","exception":false,"start_time":"2021-06-03T14:29:34.348322","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# candidate_df","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.079991Z","iopub.status.idle":"2023-07-28T19:55:09.080684Z","shell.execute_reply.started":"2023-07-28T19:55:09.080434Z","shell.execute_reply":"2023-07-28T19:55:09.080457Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# best_th, best_nocall_th","metadata":{"execution":{"iopub.status.busy":"2023-07-28T19:55:09.081948Z","iopub.status.idle":"2023-07-28T19:55:09.082627Z","shell.execute_reply.started":"2023-07-28T19:55:09.082386Z","shell.execute_reply":"2023-07-28T19:55:09.082410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# !cp '/kaggle/input/birdclef-2021/sample_submission.csv' ./","metadata":{"papermill":{"duration":0.042051,"end_time":"2021-06-03T14:33:49.394309","exception":false,"start_time":"2021-06-03T14:33:49.352258","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-07-28T19:55:09.083878Z","iopub.status.idle":"2023-07-28T19:55:09.084594Z","shell.execute_reply.started":"2023-07-28T19:55:09.084328Z","shell.execute_reply":"2023-07-28T19:55:09.084378Z"},"trusted":true},"execution_count":null,"outputs":[]}]}