{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# tensorflow for tpu-vm\n!pip install -q /lib/wheels/tensorflow-2.9.1-cp38-cp38-linux_x86_64.whl\n\n# tensorflow utilities\n!pip install -q tensorflow-addons==0.18.0\n!pip install -q tensorflow-probability==0.17.0\n!pip install -q tensorflow-io==0.26.0\n\n# other utilies\n!pip install -q opencv-python-headless librosa wandb scikit-learn","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-03-14T05:44:14.834204Z","iopub.execute_input":"2023-03-14T05:44:14.834989Z","iopub.status.idle":"2023-03-14T05:45:36.689671Z","shell.execute_reply.started":"2023-03-14T05:44:14.834957Z","shell.execute_reply":"2023-03-14T05:45:36.688434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# efficientnet with filter stride reduction (FSR)\n!pip install -qU git+https://github.com/awsaf49/efficientnet-spec","metadata":{"papermill":{"duration":31.227648,"end_time":"2022-03-08T03:17:54.356004","exception":false,"start_time":"2022-03-08T03:17:23.128356","status":"completed"},"tags":[],"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-03-14T05:45:36.691904Z","iopub.execute_input":"2023-03-14T05:45:36.692304Z","iopub.status.idle":"2023-03-14T05:45:55.547083Z","shell.execute_reply.started":"2023-03-14T05:45:36.692267Z","shell.execute_reply":"2023-03-14T05:45:55.545874Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport pandas as pd\npd.options.mode.chained_assignment = None # avoids assignment warning\nimport numpy as np\nimport random\nfrom glob import glob\nfrom tqdm import tqdm\ntqdm.pandas()  # enable progress bars in pandas operations\nimport gc\n\nimport librosa\nimport sklearn\nimport json\n\n# Import for visualization\nimport matplotlib as mpl\nimport matplotlib.pyplot as plt\nimport librosa.display as lid\nimport IPython.display as ipd\n\n# Import tensorflow\nimport tensorflow as tf\n# Set logging level to avoid unnecessary messages\ntf.get_logger().setLevel('ERROR')\n# Set autograph verbosity to avoid unnecessary messages\ntf.autograph.set_verbosity(0)\n# Enable xla for speed up\ntf.config.optimizer.set_jit(True)\n\n# Import required tensorflow modules\nimport tensorflow_io as tfio\nimport tensorflow_addons as tfa\nimport tensorflow_probability as tfp\nimport tensorflow.keras.backend as K\n\n# Import KaggleDatasets for accessing Kaggle datasets\nfrom kaggle_datasets import KaggleDatasets","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","papermill":{"duration":2.632068,"end_time":"2022-03-08T03:18:14.585094","exception":false,"start_time":"2022-03-08T03:18:11.953026","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:45:55.552595Z","iopub.execute_input":"2023-03-14T05:45:55.552932Z","iopub.status.idle":"2023-03-14T05:46:12.171907Z","shell.execute_reply.started":"2023-03-14T05:45:55.552895Z","shell.execute_reply":"2023-03-14T05:46:12.170983Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('np:', np.__version__)\nprint('pd:', pd.__version__)\nprint('sklearn:', sklearn.__version__)\nprint('librosa:', librosa.__version__)\nprint('tf:', tf.__version__)\nprint('tfp:', tfp.__version__)\nprint('tfa:', tfa.__version__)\nprint('tfio:', tfio.__version__)","metadata":{"papermill":{"duration":0.155095,"end_time":"2022-03-08T03:18:14.939054","exception":false,"start_time":"2022-03-08T03:18:14.783959","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:12.173193Z","iopub.execute_input":"2023-03-14T05:46:12.173710Z","iopub.status.idle":"2023-03-14T05:46:12.180383Z","shell.execute_reply.started":"2023-03-14T05:46:12.173679Z","shell.execute_reply":"2023-03-14T05:46:12.179650Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    # Debugging\n    debug = False\n    \n    # Plot training history\n    training_plot = True\n    \n    # Weights and Biases logging\n    wandb = True\n    competition   = 'birdclef-2023' \n    _wandb_kernel = 'awsaf49'\n    \n    # Experiment name and comment\n    exp_name = 'baseline-v2'\n    comment = 'EfficientNetB2|FSR|t=10s|128x384|up_thr=50|cv_filter'\n    \n    # Notebook link\n    notebook_link = 'https://www.kaggle.com/awsaf49/birdclef23-effnet-fsr-cutmixup-train/edit'\n    \n    # Verbosity level\n    verbose = 0\n    \n    # Device and random seed\n    device = 'TPU-VM'\n    seed = 42\n    \n    # Input image size and batch size\n    img_size = [128, 384]\n    batch_size = 32\n    upsample_thr = 50 # min sample of each class (upsample)\n    cv_filter = True # always keeps low sample data in train\n    \n    # Inference batch size, test time augmentation, and drop remainder\n    infer_bs = 2\n    tta = 1\n    drop_remainder = True\n    \n    # Number of epochs, model name, and number of folds\n    epochs = 25\n    model_name = 'EfficientNetB2'\n    fsr = True # reduce stride of stem block\n    num_fold = 5\n    \n    # Selected folds for training and evaluation\n    selected_folds = [0]\n\n    # Pretraining, neck features, and final activation function\n    pretrain = 'imagenet'\n    neck_features = 0\n    final_act = 'softmax'\n    \n    # Learning rate, optimizer, and scheduler\n    lr = 1e-3\n    scheduler = 'cos'\n    optimizer = 'Adam' # AdamW, Adam\n    \n    # Loss function and label smoothing\n    loss = 'CCE' # BCE, CCE\n    label_smoothing = 0.05 # label smoothing\n    \n    # Audio duration, sample rate, and length\n    duration = 10 # second\n    sample_rate = 32000\n    audio_len = duration*sample_rate\n    \n    # STFT parameters\n    nfft = 2028\n    window = 2048\n    hop_length = audio_len // (img_size[1] - 1)\n    fmin = 20\n    fmax = 16000\n    normalize = True\n    \n    # Data augmentation parameters\n    augment=True\n    \n    # Spec augment\n    spec_augment_prob = 0.80\n    \n    mixup_prob = 0.65\n    mixup_alpha = 0.5\n    \n    cutmix_prob = 0.0\n    cutmix_alpha = 0.5\n    \n    mask_prob = 0.65\n    freq_mask = 20\n    time_mask = 30\n\n\n    # Audio Augmentation Settings\n    audio_augment_prob = 0.5\n    \n    timeshift_prob = 0.0\n    \n    gn_prob = 0.35\n\n    # Data Preprocessing Settings\n    class_names = sorted(os.listdir('/kaggle/input/birdclef-2023/train_audio/'))\n    num_classes = len(class_names)\n    class_labels = list(range(num_classes))\n    label2name = dict(zip(class_labels, class_names))\n    name2label = {v:k for k,v in label2name.items()}\n\n    # Training Settings\n    target_col = ['target']\n    tab_cols = ['filename']\n    monitor = 'auc'","metadata":{"papermill":{"duration":0.156464,"end_time":"2022-03-08T03:18:18.322809","exception":false,"start_time":"2022-03-08T03:18:18.166345","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:12.181811Z","iopub.execute_input":"2023-03-14T05:46:12.182108Z","iopub.status.idle":"2023-03-14T05:46:12.229940Z","shell.execute_reply.started":"2023-03-14T05:46:12.182074Z","shell.execute_reply":"2023-03-14T05:46:12.229220Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def seeding(SEED):\n    np.random.seed(SEED)\n    random.seed(SEED)\n    os.environ['PYTHONHASHSEED'] = str(SEED)\n#     os.environ['TF_CUDNN_DETERMINISTIC'] = str(SEED)\n    tf.random.set_seed(SEED)\n    print('seeding done!!!')\nseeding(CFG.seed)","metadata":{"papermill":{"duration":0.153451,"end_time":"2022-03-08T03:18:18.685056","exception":false,"start_time":"2022-03-08T03:18:18.531605","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:12.230913Z","iopub.execute_input":"2023-03-14T05:46:12.231178Z","iopub.status.idle":"2023-03-14T05:46:12.236956Z","shell.execute_reply.started":"2023-03-14T05:46:12.231154Z","shell.execute_reply":"2023-03-14T05:46:12.236125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import wandb library for logging and tracking experiments\nimport wandb\n\n# Try to get the API key from Kaggle secrets\ntry:\n    from kaggle_secrets import UserSecretsClient\n    user_secrets = UserSecretsClient()\n    api_key = user_secrets.get_secret(\"WANDB\")\n    # Login to wandb with the API key\n    wandb.login(key=api_key)\n    # Set anonymous mode to None\n    anonymous = None\nexcept:\n    # If Kaggle secrets are not available, set anonymous mode to 'must'\n    anonymous = 'must'\n    # Login to wandb anonymously and relogin if needed\n    wandb.login(anonymous=anonymous, relogin=True)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:46:12.237924Z","iopub.execute_input":"2023-03-14T05:46:12.238191Z","iopub.status.idle":"2023-03-14T05:46:13.666848Z","shell.execute_reply.started":"2023-03-14T05:46:12.238166Z","shell.execute_reply":"2023-03-14T05:46:13.665847Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_device():\n    \"Detect and intializes GPU/TPU automatically\"\n    # Check TPU category\n    tpu = 'local' if CFG.device=='TPU-VM' else None\n    try:\n        # Connect to TPU\n        tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect(tpu=tpu) \n        # Set TPU strategy\n        strategy = tf.distribute.TPUStrategy(tpu)\n        print(f'> Running on {CFG.device} ', tpu.master(), end=' | ')\n        print('Num of TPUs: ', strategy.num_replicas_in_sync)\n        device=CFG.device\n    except:\n        # If TPU is not available, detect GPUs\n        gpus = tf.config.list_logical_devices('GPU')\n        ngpu = len(gpus)\n         # Check number of GPUs\n        if ngpu:\n            # Set GPU strategy\n            strategy = tf.distribute.MirroredStrategy(gpus) # single-GPU or multi-GPU\n            # Print GPU details\n            print(\"> Running on GPU\", end=' | ')\n            print(\"Num of GPUs: \", ngpu)\n            device='GPU'\n        else:\n            # If no GPUs are available, use CPU\n            print(\"> Running on CPU\")\n            strategy = tf.distribute.get_strategy()\n            device='CPU'\n    return strategy, device, tpu","metadata":{"_kg_hide-input":true,"papermill":{"duration":7.941725,"end_time":"2022-03-08T03:18:26.826553","exception":false,"start_time":"2022-03-08T03:18:18.884828","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:13.668155Z","iopub.execute_input":"2023-03-14T05:46:13.668453Z","iopub.status.idle":"2023-03-14T05:46:13.677707Z","shell.execute_reply.started":"2023-03-14T05:46:13.668422Z","shell.execute_reply":"2023-03-14T05:46:13.676934Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Initialize GPU/TPU/TPU-VM\nstrategy, CFG.device, tpu = get_device()\nCFG.replicas = strategy.num_replicas_in_sync","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:46:13.681063Z","iopub.execute_input":"2023-03-14T05:46:13.681328Z","iopub.status.idle":"2023-03-14T05:46:23.692605Z","shell.execute_reply.started":"2023-03-14T05:46:13.681303Z","shell.execute_reply":"2023-03-14T05:46:23.691299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BASE_PATH = '/kaggle/input/birdclef-2023'\n\nif CFG.device==\"TPU\":\n    from kaggle_datasets import KaggleDatasets\n    GCS_PATH = KaggleDatasets().get_gcs_path(BASE_PATH.split('/')[-1])\nelse:\n    GCS_PATH = BASE_PATH","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:46:23.693915Z","iopub.execute_input":"2023-03-14T05:46:23.694197Z","iopub.status.idle":"2023-03-14T05:46:23.699523Z","shell.execute_reply.started":"2023-03-14T05:46:23.694170Z","shell.execute_reply":"2023-03-14T05:46:23.698675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = pd.read_csv(f'{BASE_PATH}/train_metadata.csv')\ndf['filepath'] = GCS_PATH + '/train_audio/' + df.filename\ndf['target'] = df.primary_label.map(CFG.name2label)\ndf.head(2)","metadata":{"papermill":{"duration":0.241649,"end_time":"2022-03-08T03:18:27.408813","exception":false,"start_time":"2022-03-08T03:18:27.167164","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:23.700658Z","iopub.execute_input":"2023-03-14T05:46:23.700998Z","iopub.status.idle":"2023-03-14T05:46:23.852339Z","shell.execute_reply.started":"2023-03-14T05:46:23.700974Z","shell.execute_reply":"2023-03-14T05:46:23.851350Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.describe()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T06:30:01.936276Z","iopub.execute_input":"2023-03-14T06:30:01.936777Z","iopub.status.idle":"2023-03-14T06:30:01.974325Z","shell.execute_reply.started":"2023-03-14T06:30:01.936736Z","shell.execute_reply":"2023-03-14T06:30:01.972879Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.tail()","metadata":{"execution":{"iopub.status.busy":"2023-03-14T06:30:11.895637Z","iopub.execute_input":"2023-03-14T06:30:11.896437Z","iopub.status.idle":"2023-03-14T06:30:11.924141Z","shell.execute_reply.started":"2023-03-14T06:30:11.896395Z","shell.execute_reply":"2023-03-14T06:30:11.922597Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.hist","metadata":{"execution":{"iopub.status.busy":"2023-03-14T06:30:21.620089Z","iopub.execute_input":"2023-03-14T06:30:21.620515Z","iopub.status.idle":"2023-03-14T06:30:21.639578Z","shell.execute_reply.started":"2023-03-14T06:30:21.620482Z","shell.execute_reply":"2023-03-14T06:30:21.638059Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.io.gfile.exists(df.filepath.iloc[0])","metadata":{"papermill":{"duration":0.244976,"end_time":"2022-03-08T03:18:33.994955","exception":false,"start_time":"2022-03-08T03:18:33.749979","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:23.853624Z","iopub.execute_input":"2023-03-14T05:46:23.853919Z","iopub.status.idle":"2023-03-14T05:46:23.861566Z","shell.execute_reply.started":"2023-03-14T05:46:23.853894Z","shell.execute_reply":"2023-03-14T05:46:23.860632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2\n\ndef load_audio(filepath):\n    audio, sr = librosa.load(filepath)\n    return audio, sr\n\ndef show_image(filename):\n    img = cv2.imread(f'/kaggle/input/birdclef23-image-dataset/{filename}.jpg')\n    img = img[...,::-1] # bgr => rgb\n    plt.figure(figsize=(6, 6))\n    plt.imshow(img)\n    plt.axis('OFF')\n    plt.show()\n    return img\n\ndef get_spectrogram(audio):\n    spec = librosa.feature.melspectrogram(y=audio, sr=CFG.sample_rate, \n                                   n_mels=CFG.img_size[0],\n                                   n_fft=CFG.nfft,\n                                   hop_length=CFG.hop_length,\n                                   fmax=CFG.fmax,\n                                   fmin=CFG.fmin,\n                                   )\n    spec = librosa.power_to_db(spec, ref=np.max)\n    return spec\n\ndef display_audio(row):\n    # Caption for viz\n    caption = f'Id: {row.filename} | Name: {row.common_name} | Sci.Name: {row.scientific_name} | Rating: {row.rating}'\n    # Read audio file\n    audio, sr = load_audio(row.filepath)\n    # Keep fixed length audio\n    audio = audio[:CFG.audio_len]\n    # Spectrogram from audio\n    spec = get_spectrogram(audio)\n    # Display audio\n    print(\"# Audio:\")\n    display(ipd.Audio(audio, rate=CFG.sample_rate))\n    print(\"# Image:\")\n    show_image(row.common_name)\n    print('# Visualization:')\n    fig, ax = plt.subplots(2, 1, figsize=(12, 2*3), sharex=True, tight_layout=True)\n    fig.suptitle(caption)\n    # Waveplot\n    lid.waveshow(audio,\n                 sr=CFG.sample_rate,\n                 ax=ax[0])\n    # Specplot\n    lid.specshow(spec, \n                 sr = CFG.sample_rate, \n                 hop_length = CFG.hop_length,\n                 n_fft=CFG.nfft,\n                 fmin=CFG.fmin,\n                 fmax=CFG.fmax,\n                 x_axis = 'time', \n                 y_axis = 'mel',\n                 cmap = 'coolwarm',\n                 ax=ax[1])\n    ax[0].set_xlabel('');\n    fig.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:23.862675Z","iopub.execute_input":"2023-03-14T05:46:23.862949Z","iopub.status.idle":"2023-03-14T05:46:24.787217Z","shell.execute_reply.started":"2023-03-14T05:46:23.862924Z","shell.execute_reply":"2023-03-14T05:46:24.786043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"stat = df.primary_label.value_counts().index.tolist()\nclass_names = stat[:3] + stat[-3:] # popular + not popular","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:46:24.788567Z","iopub.execute_input":"2023-03-14T05:46:24.788906Z","iopub.status.idle":"2023-03-14T05:46:24.796026Z","shell.execute_reply.started":"2023-03-14T05:46:24.788865Z","shell.execute_reply":"2023-03-14T05:46:24.795046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[0]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:24.797298Z","iopub.execute_input":"2023-03-14T05:46:24.797847Z","iopub.status.idle":"2023-03-14T05:46:38.147987Z","shell.execute_reply.started":"2023-03-14T05:46:24.797819Z","shell.execute_reply":"2023-03-14T05:46:38.146758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[1]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:38.149535Z","iopub.execute_input":"2023-03-14T05:46:38.150386Z","iopub.status.idle":"2023-03-14T05:46:39.816539Z","shell.execute_reply.started":"2023-03-14T05:46:38.150355Z","shell.execute_reply":"2023-03-14T05:46:39.815608Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[2]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:39.817795Z","iopub.execute_input":"2023-03-14T05:46:39.818142Z","iopub.status.idle":"2023-03-14T05:46:41.390457Z","shell.execute_reply.started":"2023-03-14T05:46:39.818107Z","shell.execute_reply":"2023-03-14T05:46:41.389128Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[-3]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:46:41.391805Z","iopub.execute_input":"2023-03-14T05:46:41.392115Z","iopub.status.idle":"2023-03-14T05:46:43.173463Z","shell.execute_reply.started":"2023-03-14T05:46:41.392086Z","shell.execute_reply":"2023-03-14T05:46:43.172533Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[-2]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:43.174636Z","iopub.execute_input":"2023-03-14T05:46:43.174921Z","iopub.status.idle":"2023-03-14T05:46:45.086435Z","shell.execute_reply.started":"2023-03-14T05:46:43.174895Z","shell.execute_reply":"2023-03-14T05:46:45.085423Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_name = class_names[-1]\nprint(f'# Category: {class_name}')\nclass_df = df.query(\"primary_label==@class_name\")\nprint(f'# Num Samples: {len(class_df)}')\nrow = class_df.sample(1).squeeze()\n\n# Display audio\ndisplay_audio(row)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:45.087807Z","iopub.execute_input":"2023-03-14T05:46:45.088156Z","iopub.status.idle":"2023-03-14T05:46:46.870738Z","shell.execute_reply.started":"2023-03-14T05:46:45.088123Z","shell.execute_reply":"2023-03-14T05:46:46.869651Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import required packages\nfrom sklearn.model_selection import StratifiedKFold\n\n# Initialize the StratifiedKFold object with 5 splits and shuffle the data\nskf = StratifiedKFold(n_splits=5, shuffle=True, random_state=CFG.seed)\n\n# Reset the index of the dataframe\ndf = df.reset_index(drop=True)\n\n# Create a new column in the dataframe to store the fold number for each row\ndf[\"fold\"] = -1\n\n# Iterate over the folds and assign the corresponding fold number to each row in the dataframe\nfor fold, (train_idx, val_idx) in enumerate(skf.split(df, df['primary_label'])):\n    df.loc[val_idx, 'fold'] = fold","metadata":{"papermill":{"duration":0.386301,"end_time":"2022-03-08T03:18:35.325064","exception":false,"start_time":"2022-03-08T03:18:34.938763","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:46.871975Z","iopub.execute_input":"2023-03-14T05:46:46.872270Z","iopub.status.idle":"2023-03-14T05:46:46.973282Z","shell.execute_reply.started":"2023-03-14T05:46:46.872243Z","shell.execute_reply":"2023-03-14T05:46:46.972243Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.groupby(['fold','primary_label']).size()","metadata":{"papermill":{"duration":0.173215,"end_time":"2022-03-08T03:18:36.347671","exception":false,"start_time":"2022-03-08T03:18:36.174456","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:46.974528Z","iopub.execute_input":"2023-03-14T05:46:46.974945Z","iopub.status.idle":"2023-03-14T05:46:46.989862Z","shell.execute_reply.started":"2023-03-14T05:46:46.974914Z","shell.execute_reply":"2023-03-14T05:46:46.988760Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def filter_data(df, thr=5):\n    # Count the number of samples for each class\n    counts = df.primary_label.value_counts()\n\n    # Condition that selects classes with less than `thr` samples\n    cond = df.primary_label.isin(counts[counts<thr].index.tolist())\n\n    # Add a new column to select samples for cross validation\n    df['cv'] = True\n\n    # Set cv = False for those class where there is samples less than thr\n    df.loc[cond, 'cv'] = False\n\n    # Return the filtered dataframe\n    return df\n    \ndef upsample_data(df, thr=20):\n    # get the class distribution\n    class_dist = df['primary_label'].value_counts()\n\n    # identify the classes that have less than the threshold number of samples\n    down_classes = class_dist[class_dist < thr].index.tolist()\n\n    # create an empty list to store the upsampled dataframes\n    up_dfs = []\n\n    # loop through the undersampled classes and upsample them\n    for c in down_classes:\n        # get the dataframe for the current class\n        class_df = df.query(\"primary_label==@c\")\n        # find number of samples to add\n        num_up = thr - class_df.shape[0]\n        # upsample the dataframe\n        class_df = class_df.sample(n=num_up, replace=True, random_state=CFG.seed)\n        # append the upsampled dataframe to the list\n        up_dfs.append(class_df)\n\n    # concatenate the upsampled dataframes and the original dataframe\n    up_df = pd.concat([df] + up_dfs, axis=0, ignore_index=True)\n    \n    return up_df","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:46.991162Z","iopub.execute_input":"2023-03-14T05:46:46.991460Z","iopub.status.idle":"2023-03-14T05:46:47.002175Z","shell.execute_reply.started":"2023-03-14T05:46:46.991431Z","shell.execute_reply":"2023-03-14T05:46:47.001136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Filter data\nf_df = filter_data(df, thr=5)\nf_df.cv.value_counts().plot.bar(legend=True)\nplt.yscale(\"log\")\nplt.title(\"Cross Validation samples\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:47.003382Z","iopub.execute_input":"2023-03-14T05:46:47.003732Z","iopub.status.idle":"2023-03-14T05:46:47.552563Z","shell.execute_reply.started":"2023-03-14T05:46:47.003700Z","shell.execute_reply":"2023-03-14T05:46:47.551448Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Upsample data\nup_df = upsample_data(df, thr=50)\nprint(f'Before Upsample Size: {len(df)}')\nprint(f'After Upsample Size: {len(up_df)}')\n\n# Show effect of upsample\nfig, ax = plt.subplots(1, 1, figsize=(12, 6))\nup_df.primary_label.value_counts()[:].plot.bar(ax=ax, color='green', label='w/ upsample')\ndf.primary_label.value_counts()[:].plot.bar(ax=ax, color='red', label='w/o upsample')\nplt.xticks([])\nplt.axhline(y=50, color='k', linestyle='--', label='threshold')\nplt.legend()\nplt.title(\"Effect of Upsample\")\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:47.553850Z","iopub.execute_input":"2023-03-14T05:46:47.554132Z","iopub.status.idle":"2023-03-14T05:46:49.666801Z","shell.execute_reply.started":"2023-03-14T05:46:47.554106Z","shell.execute_reply":"2023-03-14T05:46:49.665721Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Generates random integer\ndef random_int(shape=[], minval=0, maxval=1):\n    return tf.random.uniform(shape=shape, minval=minval, maxval=maxval, dtype=tf.int32)\n\n\n# Generats random float\ndef random_float(shape=[], minval=0.0, maxval=1.0):\n    rnd = tf.random.uniform(shape=shape, minval=minval, maxval=maxval, dtype=tf.float32)\n    return rnd","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.668127Z","iopub.execute_input":"2023-03-14T05:46:49.668484Z","iopub.status.idle":"2023-03-14T05:46:49.675092Z","shell.execute_reply.started":"2023-03-14T05:46:49.668453Z","shell.execute_reply":"2023-03-14T05:46:49.674165Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Import required packages\nimport tensorflow as tf\n\n# Define a function to crop or pad audio data to a target length\n@tf.function\ndef CropOrPad(audio, target_len, pad_mode='constant'):\n    # Get the length of the input audio\n    audio_len = tf.shape(audio)[0]\n    # If the length of the input audio is smaller than the target length, randomly pad the audio\n    if audio_len < target_len:\n        # Calculate the offset between the input audio and the target length\n        diff_len = (target_len - audio_len)\n        # Select a random location for padding\n        pad1 = random_int([], minval=0, maxval=diff_len)\n        # Calculate the second padding value\n        pad2 = diff_len - pad1\n        pad_len = [pad1, pad2]\n        # Apply padding to the audio data\n        audio = tf.pad(audio, paddings=[pad_len], mode=pad_mode)\n    # If the length of the input audio is larger than the target length, crop the audio\n    elif audio_len > target_len:\n        # Calculate the difference in length between the input audio and the target length\n        diff_len = (audio_len - target_len)\n        # Select a random location for cropping\n        idx = tf.random.uniform([], 0, diff_len, dtype=tf.int32)\n        # Crop the audio data\n        audio = audio[idx: (idx + target_len)]\n    # Reshape the audio data to the target length\n    audio = tf.reshape(audio, [target_len])\n    # Return the cropped or padded audio data\n    return audio\n\n\n# Randomly shift audio -> any sound at <t> time may get shifted to <t+shift> time\n@tf.function\ndef TimeShift(audio, prob=0.5):\n    # Randomly apply time shift with probability `prob`\n    if random_float() < prob:\n        # Calculate random shift value\n        shift = random_int(shape=[], minval=0, maxval=tf.shape(audio)[0])\n        # Randomly set the shift to be negative with 50% probability\n        if random_float() < 0.5:\n            shift = -shift\n        # Roll the audio signal by the shift value\n        audio = tf.roll(audio, shift, axis=0)\n    return audio\n\n# Apply random noise to audio data\n@tf.function\ndef GaussianNoise(audio, std=[0.0025, 0.025], prob=0.5):\n    # Select a random value of standard deviation for Gaussian noise within the given range\n    std = random_float([], std[0], std[1])\n    # Randomly apply Gaussian noise with probability `prob`\n    if random_float() < prob:\n        # Add random Gaussian noise to the audio signal\n        GN = tf.keras.layers.GaussianNoise(stddev=std)\n        audio = GN(audio, training=True) # training=False don't apply noise to data\n    return audio\n\n# Applies augmentation to Audio Signal\ndef AudioAug(audio):\n    # Apply time shift and Gaussian noise to the audio signal\n    audio = TimeShift(audio, prob=CFG.timeshift_prob)\n    audio = GaussianNoise(audio, prob=CFG.gn_prob)\n    return audio\n\n# Standardize the audio\n@tf.function\ndef Normalize(data, min_max=True):\n    # Compute the mean and standard deviation of the data\n    MEAN = tf.math.reduce_mean(data)\n    STD = tf.math.reduce_std(data)\n    # Standardize the data\n    data = tf.math.divide_no_nan(data - MEAN, STD)\n    # Normalize to [0, 1]\n    if min_max:\n        MIN = tf.math.reduce_min(data)\n        MAX = tf.math.reduce_max(data)\n        data = tf.math.divide_no_nan(data - MIN, MAX - MIN)\n    return data","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.681044Z","iopub.execute_input":"2023-03-14T05:46:49.681310Z","iopub.status.idle":"2023-03-14T05:46:49.699119Z","shell.execute_reply.started":"2023-03-14T05:46:49.681285Z","shell.execute_reply":"2023-03-14T05:46:49.698104Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Convert spectrogram (H,W) to image (H,W,3)\n@tf.function\ndef Spec2Img(spec, num_channels=3):\n    # If the original image has 1 channel, convert it to a 3 channel image by repeating the same image across channel axis\n    if num_channels > 1:\n        img = tf.tile(spec[..., tf.newaxis], [1, 1, num_channels])\n    else:\n        img = spec[..., tf.newaxis]\n    return img\n\n# Convert img (H,W,3) to image (H,W)\n@tf.function\ndef Img2Spec(img):\n    # Extract the first channel of the image\n    return img[..., 0]\n\n\n# Randomly mask data in time and freq axis\n@tf.function\ndef TimeFreqMask(spec, time_mask, freq_mask, prob=0.5):\n    if random_float() < prob:\n        # Apply frequency masking to the spectrogram\n        spec = tfio.audio.freq_mask(spec, param=freq_mask)\n        # Apply time masking to the spectrogram\n        spec = tfio.audio.time_mask(spec, param=time_mask)\n    return spec\n\n\n# Applies augmentation to Spectrogram\ndef SpecAug(spec):\n    # Convert the spectrogram to a 2D matrix and transpose it to get the shape [time, mel]\n    spec = tf.transpose(Img2Spec(spec), perm=[1, 0])\n    # Apply time and frequency masking to the spectrogram\n    spec = TimeFreqMask(spec, time_mask=CFG.time_mask, freq_mask=CFG.freq_mask, prob=0.5)\n    # Transpose the spectrogram back to the original shape [mel, time] and convert it to an image\n    spec = tf.transpose(spec, perm=[1, 0])\n    spec = Spec2Img(spec)\n    return spec\n\n# Compute MixUp Augmentation for Spectrogram\ndef MixUp(alpha=0.2, prob=0.5):\n    \"\"\"Apply Spectrogram-MixUp augmentaiton. Apply Mixup to one batch and its shifted version\"\"\"\n    @tf.function\n    def apply(specs, labels, alpha=alpha, prob=prob):\n        if random_float() > prob:\n            return specs, labels\n\n        spec_shape = tf.shape(specs)\n        label_shape = tf.shape(labels)\n\n        # Select lambda from beta distribution\n        beta = tfp.distributions.Beta(alpha, alpha)\n        lam = beta.sample(1)[0]\n        \n        # It's faster to roll the batch by one instead of shuffling it to create image pairs\n        specs = lam * specs + (1 - lam) * tf.roll(specs, shift=1, axis=0) # mixup = [1, 2, 3]*lam + [3, 1, 2]*(1 - lam)\n        labels = lam * labels + (1 - lam) * tf.roll(labels, shift=1, axis=0)\n\n        specs = tf.reshape(specs, spec_shape)\n        labels = tf.reshape(labels, label_shape)\n        return specs, labels\n    return apply\n\n\ndef CutMix(alpha, prob=0.5):\n    \"\"\"Apply Spectrogram-CutMix augmentaiton which only cuts patch across time axis unlike \n       typical Computer-Vision CutMix. Applies CutMix to one batch and its shifted version.\n    \"\"\"\n    @tf.function\n    def apply(specs, labels, alpha=alpha, prob=prob):\n        if random_float() > prob:\n            return specs, labels\n        spec_shape = tf.shape(specs)\n        label_shape = tf.shape(labels)\n        W = tf.cast(spec_shape[1], tf.int32)  # [batch, time, freq, channel]\n\n        # Lambda from beta distribution\n        beta = tfp.distributions.Beta(alpha, alpha)\n        lam = beta.sample(1)[0]\n        \n        # It's faster to roll the batch by one instead of shuffling it to create image pairs\n        specs_rolled = tf.roll(specs, shift=1, axis=0) # specs->[1, 2, 3], specs_rolled->[3, 1, 2]\n        labels_rolled = tf.roll(labels, shift=1, axis=0)\n\n        # Select random patch size\n        r_x = random_int([], minval=0, maxval=W)\n        r = 0.5 * tf.math.sqrt(1.0 - lam)\n        r_w_half = tf.cast(r * tf.cast(W, tf.float32), tf.int32)\n\n        # Select random location in time axis\n        x1 = tf.cast(tf.clip_by_value(r_x - r_w_half, 0, W), tf.int32)\n        x2 = tf.cast(tf.clip_by_value(r_x + r_w_half, 0, W), tf.int32)\n\n        # outer-pad patch -> [0, 0, x, x, 0, 0]\n        patch1 = specs[:, x1:x2, :, :]  # [batch, time, freq, channel]\n        patch1 = tf.pad(\n            patch1, [[0, 0], [x1, W - x2], [0, 0], [0, 0]])  # outer-pad\n\n        # inner-pad-patch -> [y, y, 0, 0, y, y]\n        patch2 = specs_rolled[:, x1:x2, :, :]  # [batch, mel, time, channel]\n        patch2 = tf.pad(\n            patch2, [[0, 0], [x1, W - x2], [0, 0], [0, 0]])  # outer-pad\n        patch2 = specs_rolled - patch2  # inner-pad-patch = img - outer-pad-patch\n        \n        # patch1 -> [0, 0, x, x, 0, 0], patch2 -> [y, y, 0, 0, y, y]\n        # cutmix = (patch1 + patch2) -> [y, y, x, x, y, y]\n        specs = patch1 + patch2  # cutmix img\n\n        # Compute lambda = [1 - (patch_area/image_area)]\n        lam = tf.cast((1.0 - (x2 - x1) / (W)),tf.float32)  # no H term as (y1 - y2) = H\n        labels = lam * labels + (1.0 - lam) * labels_rolled  # cutmix label\n\n        specs = tf.reshape(specs, spec_shape)\n        labels = tf.reshape(labels, label_shape)\n\n        return specs, labels\n    return apply","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.700695Z","iopub.execute_input":"2023-03-14T05:46:49.700956Z","iopub.status.idle":"2023-03-14T05:46:49.727103Z","shell.execute_reply.started":"2023-03-14T05:46:49.700932Z","shell.execute_reply":"2023-03-14T05:46:49.726253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Compute Spectrogram from audio\n@tf.function\ndef Audio2Spec(audio, spec_shape=[128, 384], sr=32000, nfft=2048, window=2048, fmin=500, fmax=14000):\n    \"\"\"\n    Computes a Mel-scaled spectrogram from audio using TensorFlow and TensorFlow-IO.\n    \"\"\"\n    # Get the desired height and width of the spectrogram\n    spec_height = spec_shape[0]\n    spec_width = spec_shape[1]\n    \n    # Get the length of the audio and calculate the hop length for the STFT\n    audio_len = tf.shape(audio)[0]\n    hop_length = tf.cast((audio_len // (spec_width - 1)), tf.int32) # sample rate * duration / spec width - 1 == 627\n    \n    # Compute the spectrogram and the Mel-scaled spectrogram using TensorFlow-IO\n    spec = tfio.audio.spectrogram(audio, nfft=nfft, window=window, stride=hop_length)\n    mel_spec = tfio.audio.melscale(spec, rate=sr, mels=spec_height, fmin=fmin, fmax=fmax)\n    \n    # Convert the Mel-scaled spectrogram to decibels and transpose it to keep it (mel, time)\n    db_mel_spec = tfio.audio.dbscale(mel_spec, top_db=80)\n    db_mel_spec = tf.transpose(db_mel_spec, perm=[1, 0])\n    \n    # If the spectrogram is larger than the desired shape, crop it\n    if tf.shape(db_mel_spec)[1] > spec_width:\n        db_mel_spec = db_mel_spec[:, :spec_width]\n    \n    # Reshape the spectrogram to the desired shape and return it\n    db_mel_spec = tf.reshape(db_mel_spec, spec_shape)\n    return db_mel_spec\n","metadata":{"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.728248Z","iopub.execute_input":"2023-03-14T05:46:49.728555Z","iopub.status.idle":"2023-03-14T05:46:49.742854Z","shell.execute_reply.started":"2023-03-14T05:46:49.728528Z","shell.execute_reply":"2023-03-14T05:46:49.742037Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Decodes Audio\ndef audio_decoder(with_labels=True, dim=CFG.audio_len, CFG=CFG):\n    def get_audio(filepath):\n        file_bytes = tf.io.read_file(filepath)\n        audio = tfio.audio.decode_vorbis(file_bytes) # decode .ogg file for .wave replace `decode_wav`\n        audio = tf.cast(audio, tf.float32)\n        audio = tf.squeeze(audio, axis=-1)\n        if CFG.normalize:\n            audio = Normalize(audio)\n        return audio\n\n    def get_target(target):          \n        target = tf.reshape(target, [1])\n        target = tf.cast(tf.one_hot(target, len(CFG.class_labels)), tf.float32) \n        target = tf.reshape(target, [len(CFG.class_labels)])\n        return target\n\n    def decode(path):\n        audio = get_audio(path)\n        audio = CropOrPad(audio, dim) # crop or pad audio to keep a fixed length\n        audio = tf.reshape(audio, [dim])\n        return audio\n    \n    def decode_with_labels(path, label):\n        label = get_target(label)\n        return decode(path), label\n    \n    return decode_with_labels if with_labels else decode\n\n# Decodes Spectrogram\ndef spec_decoder(with_labels=True, dim=CFG.img_size, CFG=CFG):\n    def decode(audio):\n        # Compute Spectrogram\n        spec = Audio2Spec(audio, spec_shape=dim, sr=CFG.sample_rate, \n                          nfft=CFG.nfft, window=CFG.window, fmin=CFG.fmin,fmax=CFG.fmax)\n        # Spectrogram (H, W) to Image (H, W, C)\n        spec = Spec2Img(spec, num_channels=3) \n        spec = tf.reshape(spec, [*dim, 3])\n        return spec\n    \n    def decode_with_labels(path, label):\n        return decode(path), label\n    \n    return decode_with_labels if with_labels else decode","metadata":{"papermill":{"duration":0.251237,"end_time":"2022-03-08T03:18:49.079346","exception":false,"start_time":"2022-03-08T03:18:48.828109","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.743965Z","iopub.execute_input":"2023-03-14T05:46:49.744241Z","iopub.status.idle":"2023-03-14T05:46:49.759827Z","shell.execute_reply.started":"2023-03-14T05:46:49.744217Z","shell.execute_reply":"2023-03-14T05:46:49.758869Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Applies augmentation to audio\ndef audio_augmenter(with_labels=True, dim=CFG.audio_len, CFG=CFG):\n    def augment(audio, dim=dim):\n        if random_float() <= CFG.audio_augment_prob:\n            audio = AudioAug(audio)\n        audio = tf.reshape(audio, [dim])\n        return audio\n    \n    def augment_with_labels(audio, label):    \n        return augment(audio), label\n    \n    return augment_with_labels if with_labels else augment\n\n# Applies augentation to spectrogram\ndef spec_augmenter(with_labels=True, dim=CFG.img_size, CFG=CFG):\n    def augment(spec, dim=dim): \n        if random_float() <= CFG.spec_augment_prob:\n            spec = SpecAug(spec)\n        spec = tf.reshape(spec, [*dim, 3])\n        return spec\n    \n    def augment_with_labels(spec, label):    \n        return augment(spec), label\n    \n    return augment_with_labels if with_labels else augment","metadata":{"papermill":{"duration":0.250484,"end_time":"2022-03-08T03:18:49.79513","exception":false,"start_time":"2022-03-08T03:18:49.544646","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.761015Z","iopub.execute_input":"2023-03-14T05:46:49.761276Z","iopub.status.idle":"2023-03-14T05:46:49.773928Z","shell.execute_reply.started":"2023-03-14T05:46:49.761252Z","shell.execute_reply":"2023-03-14T05:46:49.773096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_dataset(paths, labels=None, batch_size=32, target_size=[128, 256], \n                  audio_decode_fn=None, audio_augment_fn=None, \n                  spec_decode_fn=None, spec_augment_fn=None,\n                  cache=True, cache_dir=\"\",drop_remainder=False,\n                  augment=True, repeat=True, shuffle=1024):\n    \"\"\"\n    Creates a TensorFlow dataset from the given paths and labels.\n    \n    Args:\n        paths (list): A list of file paths to the audio files.\n        labels (list): A list of corresponding labels for the audio files.\n        batch_size (int): Batch size for the created dataset.\n        target_size (list): A list of target image size for the spectrograms.\n        audio_decode_fn (function): A function to decode the audio file.\n        audio_augment_fn (function): A function to augment the audio file.\n        spec_decode_fn (function): A function to decode the spectrogram.\n        spec_augment_fn (function): A function to augment the spectrogram.\n        cache (bool): Whether to cache the dataset or not.\n        cache_dir (str): Directory path to cache the dataset.\n        drop_remainder (bool): Whether to drop the last batch if it is smaller than batch_size.\n        augment (bool): Whether to augment the dataset or not.\n        repeat (bool): Whether to repeat the dataset or not.\n        shuffle (int): Number of elements from the dataset to buffer for shuffling.\n        \n    Returns:\n        ds (tf.data.Dataset): A TensorFlow dataset.\n    \"\"\"\n    # Create cache directory if cache is enabled\n    if cache_dir != \"\" and cache is True:\n        os.makedirs(cache_dir, exist_ok=True)\n    # Set default audio decode function if not provided\n    if audio_decode_fn is None:\n        audio_decode_fn = audio_decoder(\n            labels is not None, dim=CFG.audio_len, CFG=CFG)\n    # Set default audio augmentation function if not provided\n    if audio_augment_fn is None:\n        audio_augment_fn = audio_augmenter(\n            labels is not None, dim=CFG.audio_len, CFG=CFG)\n    # Set default spectrogram decode function if not provided\n    if spec_decode_fn is None:\n        spec_decode_fn = spec_decoder(\n            labels is not None, dim=CFG.img_size, CFG=CFG)\n    # Set default spectrogram augmentation function if not provided\n    if spec_augment_fn is None:\n        spec_augment_fn = spec_augmenter(\n            labels is not None, dim=CFG.img_size, CFG=CFG)\n    # Set TensorFlow AUTOTUNE option\n    AUTO = tf.data.experimental.AUTOTUNE\n    \n    # Create slices based on whether labels are provided\n    slices = paths if labels is None else (paths, labels)\n    # Create TensorFlow dataset from slices\n    ds = tf.data.Dataset.from_tensor_slices(slices)\n    # Map audio decode function to dataset\n    ds = ds.map(audio_decode_fn, num_parallel_calls=AUTO)\n    # Cache dataset in memory if cache is enabled\n    ds = ds.cache(cache_dir) if cache else ds\n    # Repeat dataset indefinitely if repeat is enabled\n    ds = ds.repeat() if repeat else ds\n    # Create TensorFlow dataset options\n    opt = tf.data.Options()\n    # Shuffle dataset if shuffle is enabled\n    if shuffle: \n        ds = ds.shuffle(shuffle, seed=CFG.seed)\n        opt.experimental_deterministic = False\n    if CFG.device=='GPU':\n        # If the device is a GPU, turn off auto-sharding to avoid performance issues\n        opt.experimental_distribute.auto_shard_policy = tf.data.experimental.AutoShardPolicy.OFF\n    # Set the options for the dataset\n    ds = ds.with_options(opt)\n    # Apply audio augmentation to the dataset if augment is True\n    ds = ds.map(audio_augment_fn, num_parallel_calls=AUTO) if augment else ds\n    # Decode the spectrograms for the dataset\n    ds = ds.map(spec_decode_fn, num_parallel_calls=AUTO)\n    # Apply spectrogram augmentation to the dataset if augment is True\n    ds = ds.map(spec_augment_fn, num_parallel_calls=AUTO) if augment else ds\n    # Batch the dataset with the specified batch size\n    ds = ds.batch(batch_size, drop_remainder=drop_remainder)\n    # MixUp: apply MixUp regularization to the dataset if specified\n    if CFG.mixup_prob and augment and labels is not None:\n        ds = ds.map(MixUp(alpha=CFG.mixup_alpha,prob=CFG.mixup_prob),num_parallel_calls=AUTO)\n    # CutMix: apply CutMix regularization to the dataset if specified\n    if CFG.cutmix_prob and augment and labels is not None:\n        ds = ds.map(CutMix(alpha=CFG.cutmix_alpha,prob=CFG.cutmix_prob),num_parallel_calls=AUTO)\n    # Prefetch the next batch of data to improve performance\n    ds = ds.prefetch(AUTO)\n    return ds","metadata":{"papermill":{"duration":0.240881,"end_time":"2022-03-08T03:18:50.489717","exception":false,"start_time":"2022-03-08T03:18:50.248836","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:46:49.775085Z","iopub.execute_input":"2023-03-14T05:46:49.775345Z","iopub.status.idle":"2023-03-14T05:46:49.793491Z","shell.execute_reply.started":"2023-03-14T05:46:49.775322Z","shell.execute_reply":"2023-03-14T05:46:49.792679Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_batch(batch, row=3, col=3):\n    \"\"\"Plot one batch data\"\"\"\n    if isinstance(batch, tuple) or isinstance(batch, list):\n        imgs, tars = batch\n    else:\n        imgs = batch\n        tars = None\n    plt.figure(figsize=(col*5, row*3))\n    for idx in range(row*col):\n        ax = plt.subplot(row, col, idx+1)\n        lid.specshow(imgs[idx][...,0].numpy(), \n                     sr = CFG.sample_rate, \n                     hop_length = CFG.hop_length,\n                     fmin=CFG.fmin,\n                     fmax=CFG.fmax,\n                     x_axis = 'time', \n                     y_axis = 'mel',\n                     cmap = 'coolwarm')\n        if tars is not None:\n            label = tars[idx].numpy().argmax()\n            name = CFG.label2name[label]\n            plt.title(name)\n    plt.tight_layout()\n    plt.show()\n    \n    \ndef plot_history(history):\n    \"\"\"Plot trainign history, credit: @cdeotte\"\"\"\n    epochs = len(history.history['auc'])\n    plt.figure(figsize=(15,5))\n    plt.plot(np.arange(epochs),history.history['auc'],'-o',label='Train AUC',color='#ff7f0e')\n    plt.plot(np.arange(epochs),history.history['val_auc'],'-o',label='Val AUC',color='#1f77b4')\n    x = np.argmax( history.history['val_auc'] ); y = np.max( history.history['val_auc'] )\n    xdist = plt.xlim()[1] - plt.xlim()[0]; ydist = plt.ylim()[1] - plt.ylim()[0]\n    plt.scatter(x,y,s=200,color='#1f77b4'); plt.text(x-0.03*xdist,y-0.13*ydist,'max auc\\n%.2f'%y,size=14)\n    plt.ylabel('AUC (PR)',size=14); plt.xlabel('Epoch',size=14)\n    plt.legend(loc=2)\n    plt2 = plt.gca().twinx()\n    plt2.plot(np.arange(epochs),history.history['loss'],'-o',label='Train Loss',color='#2ca02c')\n    plt2.plot(np.arange(epochs),history.history['val_loss'],'-o',label='Val Loss',color='#d62728')\n    x = np.argmin( history.history['val_loss'] ); y = np.min( history.history['val_loss'] )\n    ydist = plt.ylim()[1] - plt.ylim()[0]\n    plt.scatter(x,y,s=200,color='#d62728'); plt.text(x-0.03*xdist,y+0.05*ydist,'min loss',size=14)\n    plt.ylabel('Loss',size=14)\n    plt.title('Fold %i - Training Plot'%(fold+1),size=18)\n    plt.legend(loc=3)\n    plt.show()  ","metadata":{"papermill":{"duration":0.328513,"end_time":"2022-03-08T03:19:59.512224","exception":false,"start_time":"2022-03-08T03:19:59.183711","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.794545Z","iopub.execute_input":"2023-03-14T05:46:49.794806Z","iopub.status.idle":"2023-03-14T05:46:49.813703Z","shell.execute_reply.started":"2023-03-14T05:46:49.794783Z","shell.execute_reply":"2023-03-14T05:46:49.812807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = build_dataset(df.filepath.tolist(), df.target.tolist(), augment=False, cache=False)\nds = ds.take(100)\nimgs, labels = next(iter(ds))\nplot_batch((imgs, labels))","metadata":{"papermill":{"duration":3.299334,"end_time":"2022-03-08T03:20:02.987986","exception":false,"start_time":"2022-03-08T03:19:59.688652","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:49.814764Z","iopub.execute_input":"2023-03-14T05:46:49.815029Z","iopub.status.idle":"2023-03-14T05:46:58.494987Z","shell.execute_reply.started":"2023-03-14T05:46:49.815005Z","shell.execute_reply":"2023-03-14T05:46:58.493776Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"ds = build_dataset(df.filepath.tolist(), df.target.tolist(), augment=True, cache=False)\nds = ds.take(100)\nimgs, labels = next(iter(ds))\nplot_batch((imgs, labels))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:46:58.496415Z","iopub.execute_input":"2023-03-14T05:46:58.496745Z","iopub.status.idle":"2023-03-14T05:47:07.684896Z","shell.execute_reply.started":"2023-03-14T05:46:58.496716Z","shell.execute_reply":"2023-03-14T05:47:07.683653Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import sklearn.metrics\n\ndef get_metrics():\n#     acc = tf.keras.metrics.BinaryAccuracy(name='acc')\n    auc = tf.keras.metrics.AUC(curve='PR', name='auc', multi_label=False) # auc on prcision-recall curve\n    acc = tf.keras.metrics.CategoricalAccuracy(name='acc')\n    return [acc, auc]\n\ndef padded_cmap(y_true, y_pred, padding_factor=5):\n    num_classes = y_true.shape[1]\n    pad_rows = np.array([[1]*num_classes]*padding_factor)\n    y_true = np.concatenate([y_true, pad_rows])\n    y_pred = np.concatenate([y_pred, pad_rows])\n    score = sklearn.metrics.average_precision_score(y_true, y_pred, average='macro',)\n    return score\n\ndef get_loss():\n    if CFG.loss==\"CCE\":\n        loss = tf.keras.losses.CategoricalCrossentropy(label_smoothing=CFG.label_smoothing)\n    elif CFG.loss==\"BCE\":\n        loss = tf.keras.losses.BinaryCrossentropy(label_smoothing=CFG.label_smoothing)\n    else:\n        raise ValueError(\"Loss not found\")\n    return loss\n    \ndef get_optimizer():\n    if CFG.optimizer == \"Adam\":\n        opt = tf.keras.optimizers.Adam(learning_rate=CFG.lr)\n    else:\n        raise ValueError(\"Optmizer not found\")\n    return opt","metadata":{"papermill":{"duration":0.28125,"end_time":"2022-03-08T03:20:04.498883","exception":false,"start_time":"2022-03-08T03:20:04.217633","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:47:07.686233Z","iopub.execute_input":"2023-03-14T05:47:07.686528Z","iopub.status.idle":"2023-03-14T05:47:07.697523Z","shell.execute_reply.started":"2023-03-14T05:47:07.686501Z","shell.execute_reply":"2023-03-14T05:47:07.696675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import efficientnet.tfkeras as efn\n\ndef build_model(CFG, compile_model=True):\n    \"\"\"\n    Builds and returns a model based on the specified configuration.\n    \"\"\"\n    # Set the image input shape\n    DIM = (None, None)\n    # Load the specified EfficientNet model\n    base = getattr(efn, CFG.model_name)(input_shape=(*DIM, 3),\n                                        include_top=False,\n                                        weights=CFG.pretrain,\n                                        fsr=CFG.fsr,\n                                        )\n    # Create an input layer for the model\n    inp = tf.keras.layers.Input(shape=(*DIM, 3))\n    # Pass the input through the base model\n    out = base(inp)\n    # Add a global average pooling layer\n    out = tf.keras.layers.GlobalAveragePooling2D()(out)\n    # Add an optional bottleneck layer\n    if CFG.neck_features:\n        out = tf.keras.layers.Dense(CFG.num_features, activation='selu')(out)\n    # Add a final dense layer for classification\n    out = tf.keras.layers.Dense(len(CFG.class_names), activation=CFG.final_act)(out)\n    # Create the TensorFlow model with the input and output layers\n    model = tf.keras.Model(inputs=inp, outputs=out)\n    if compile_model:\n        # Set the optimizer\n        opt = get_optimizer()\n        # Set the loss function\n        loss = get_loss()\n        # Set the evaluation metrics\n        metrics = get_metrics()\n        # Compile the model with the specified optimizer, loss function, and metrics\n        model.compile(optimizer=opt,\n                      loss=loss,\n                      metrics=metrics)\n    return model","metadata":{"papermill":{"duration":1.239321,"end_time":"2022-03-08T03:20:06.281118","exception":false,"start_time":"2022-03-08T03:20:05.041797","status":"completed"},"tags":[],"_kg_hide-input":false,"execution":{"iopub.status.busy":"2023-03-14T05:47:07.698633Z","iopub.execute_input":"2023-03-14T05:47:07.698896Z","iopub.status.idle":"2023-03-14T05:47:07.813937Z","shell.execute_reply.started":"2023-03-14T05:47:07.698873Z","shell.execute_reply":"2023-03-14T05:47:07.813048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(CFG)\nmodel.summary()","metadata":{"papermill":{"duration":37.756883,"end_time":"2022-03-08T03:20:44.226871","exception":false,"start_time":"2022-03-08T03:20:06.469988","status":"completed"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:47:07.815105Z","iopub.execute_input":"2023-03-14T05:47:07.815375Z","iopub.status.idle":"2023-03-14T05:47:12.069147Z","shell.execute_reply.started":"2023-03-14T05:47:07.815351Z","shell.execute_reply":"2023-03-14T05:47:12.067913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"out = model(imgs, training=False)\nprint(out.shape)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T05:47:12.070593Z","iopub.execute_input":"2023-03-14T05:47:12.070943Z","iopub.status.idle":"2023-03-14T05:47:15.253201Z","shell.execute_reply.started":"2023-03-14T05:47:12.070911Z","shell.execute_reply":"2023-03-14T05:47:15.252111Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import math\n\ndef get_lr_callback(batch_size=8, mode='cos', epochs=CFG.epochs, plot=False):\n    \"\"\"\n    Returns a learning rate scheduler callback for a given batch size, mode, and number of epochs.\n    \"\"\"\n    # Define the learning rate schedule.\n    lr_start   = 0.000005\n    lr_max     = 0.00000140 * batch_size\n    lr_min     = 0.000001\n    lr_ramp_ep = 5\n    lr_sus_ep  = 0\n    lr_decay   = 0.8\n   \n    # Function to update the lr\n    def lrfn(epoch):\n        if epoch < lr_ramp_ep:\n            lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n\n        elif epoch < lr_ramp_ep + lr_sus_ep:\n            lr = lr_max\n\n        elif CFG.scheduler == 'exp':\n            lr = (lr_max - lr_min) * lr_decay**(epoch - \\\n                  lr_ramp_ep - lr_sus_ep) + lr_min\n\n        elif CFG.scheduler == 'step':\n            lr = lr_max * lr_decay**((epoch - lr_ramp_ep - lr_sus_ep) // 2)\n\n        elif CFG.scheduler == 'cos':\n            decay_total_epochs = epochs - lr_ramp_ep - lr_sus_ep + 3\n            decay_epoch_index = epoch - lr_ramp_ep - lr_sus_ep\n            phase = math.pi * decay_epoch_index / decay_total_epochs\n            cosine_decay = 0.5 * (1 + math.cos(phase))\n            lr = (lr_max - lr_min) * cosine_decay + lr_min\n        return lr\n    \n    # Plot the lr curve\n    if plot:\n        plt.figure(figsize=(10,5))\n        plt.plot(np.arange(epochs), [lrfn(epoch) for epoch in np.arange(epochs)], marker='o')\n        plt.xlabel('epoch'); plt.ylabel('learnig rate')\n        plt.title('Learning Rate Scheduler')\n        plt.show()\n        \n    # Crate lr-callback to update lr during training\n    lr_callback = tf.keras.callbacks.LearningRateScheduler(lrfn, verbose=False)\n    return lr_callback","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.510014,"end_time":"2022-03-08T03:20:45.290695","exception":false,"start_time":"2022-03-08T03:20:44.780681","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:47:15.254436Z","iopub.execute_input":"2023-03-14T05:47:15.254832Z","iopub.status.idle":"2023-03-14T05:47:15.268321Z","shell.execute_reply.started":"2023-03-14T05:47:15.254804Z","shell.execute_reply":"2023-03-14T05:47:15.267451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_=get_lr_callback(CFG.batch_size*CFG.replicas, plot=True)","metadata":{"execution":{"iopub.status.busy":"2023-03-14T05:47:15.269359Z","iopub.execute_input":"2023-03-14T05:47:15.269908Z","iopub.status.idle":"2023-03-14T05:47:15.515157Z","shell.execute_reply.started":"2023-03-14T05:47:15.269879Z","shell.execute_reply":"2023-03-14T05:47:15.514260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import yaml\n\ndef wandb_init(fold):\n    \"\"\"\n    Initializes the W&B run by creating a config file and initializing a W&B run.\n    \"\"\"\n    # Create a dictionary of configuration parameters\n    config = {k:v for k,v in dict(vars(CFG)).items() if '__' not in k}\n    config.update({\"fold\":int(fold)}) # int is to convert numpy.int -> int\n    # Dump the configuration dictionary to a YAML file\n    yaml.dump(config, open(f'/kaggle/working/config fold-{fold}.yaml', 'w'),)\n    # Load the configuration dictionary from the YAML file\n    config = yaml.load(open(f'/kaggle/working/config fold-{fold}.yaml', 'r'), Loader=yaml.FullLoader)\n    # Initialize a W&B run with the given configuration parameters\n    run = wandb.init(project=\"birdclef-2023-public\",\n                     name=f\"fold-{fold}|dim-{CFG.img_size[1]}x{CFG.img_size[0]}|model-{CFG.model_name}\",\n                     config=config,\n                     group=CFG.comment,\n                     save_code=True,)\n    return run\n\n    \ndef log_wandb(valid_df):\n    \"\"\"Log and save validation results with missclassified examples as audio in W&B\"\"\"\n    # Query only the rows with miss predictions\n    save_df = valid_df.query(\"miss==True\")\n    # Map the predicted and target labels to their corresponding names\n    save_df.loc[:, 'pred_name'] = save_df.pred.map(CFG.label2name)\n    save_df.loc[:, 'target_name'] = save_df.target.map(CFG.label2name)\n    # Trim the dataframe for debugging purposes\n    if CFG.debug:\n        save_df = save_df.iloc[:CFG.replicas*CFG.batch_size*CFG.infer_bs]\n    # Get the columns to be included in the wandb table\n    noimg_cols = [*CFG.tab_cols, 'target', 'pred', 'target_name','pred_name']\n    # Retain only the necessary columns\n    save_df = save_df.loc[:, noimg_cols]\n\n    data = []\n    # Load audio files for each miss prediction\n    for idx, row in tqdm(save_df.iterrows(), total=len(save_df), desc='wandb ', position=0, leave=True):\n        filepath = '/kaggle/input/birdclef-2023/train_audio/'+row.filename\n        audio, sr = librosa.load(filepath, sr=None)\n        # Add the audio file to the data list along with the other relevant information\n        data+=[[*row.tolist(), wandb.Audio(audio, caption=row.filename, sample_rate=sr)]]\n    # Create a wandb table with the audio files and other relevant information\n    wandb_table = wandb.Table(data=data, columns=[*noimg_cols, 'audio'])\n    # Log the scores and wandb table to wandb\n    wandb.log({'best': scores,\n               'table': wandb_table,\n               })","metadata":{"_kg_hide-input":true,"papermill":{"duration":0.288344,"end_time":"2022-03-08T03:20:47.977099","exception":false,"start_time":"2022-03-08T03:20:47.688755","status":"completed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:47:15.516265Z","iopub.execute_input":"2023-03-14T05:47:15.516543Z","iopub.status.idle":"2023-03-14T05:47:15.530937Z","shell.execute_reply.started":"2023-03-14T05:47:15.516517Z","shell.execute_reply":"2023-03-14T05:47:15.530119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"oof_pred = []; oof_true = []; oof_val = []; oof_ids = []; oof_folds = [] \n\nfor fold in range(CFG.num_fold):\n    # Check if the fold is selected\n    if fold not in CFG.selected_folds:\n        continue\n    \n    # Initialize Weights and Biases\n    if CFG.wandb:\n        run = wandb_init(fold)\n        WandbCallback = wandb.keras.WandbCallback(save_model=False)\n    \n    # Compute batch size and number of samples to drop\n    infer_bs = (CFG.batch_size*CFG.infer_bs)\n    drop_remainder = CFG.drop_remainder\n    \n    # Split dataset with cv filter\n    if CFG.cv_filter:\n        train_df = df.query(\"fold!=@fold | ~cv\").reset_index(drop=True)\n        valid_df = df.query(\"fold==@fold & cv\").reset_index(drop=True)\n    else:\n        train_df = df.query(\"fold!=@fold\").reset_index(drop=True)\n        valid_df = df.query(\"fold==@fold\").reset_index(drop=True)\n    \n    # Upsample train data\n    train_df = upsample_data(train_df, thr=CFG.upsample_thr)\n\n    # Get file paths and labels\n    train_paths = train_df.filepath.values; train_labels = train_df.target.values\n    valid_paths = valid_df.filepath.values; valid_labels = valid_df.target.values\n\n    # Shuffle the file paths and labels\n    index = np.arange(len(train_paths))\n    np.random.shuffle(index)\n    train_paths  = train_paths[index]\n    train_labels = train_labels[index]\n    \n    # For debugging\n    if CFG.debug:\n        min_samples = CFG.batch_size*CFG.replicas*2\n        train_paths = train_paths[:min_samples]; train_labels = train_labels[:min_samples]\n        valid_paths = valid_paths[:min_samples]; valid_labels = valid_labels[:min_samples]\n\n    # Compute the number of training and validation samples\n    num_train = len(train_paths); num_valid = len(valid_paths)\n        \n    # Log the number of training and validation samples if Weights and Biases is being used\n    if CFG.wandb:\n        wandb.log({'num_train':num_train,\n                   'num_valid':num_valid})\n        \n    # Build the training and validation datasets\n    cache=True\n    train_ds = build_dataset(train_paths, train_labels, \n                             batch_size=CFG.batch_size*CFG.replicas, cache=cache, shuffle=True,\n                            drop_remainder=drop_remainder)\n    valid_ds = build_dataset(valid_paths, valid_labels,\n                             batch_size=CFG.batch_size*CFG.replicas, cache=cache, shuffle=False,\n                             augment=False, repeat=False, drop_remainder=drop_remainder)\n    \n    # Print information about the fold and training\n    print('#'*25); print('#### FOLD',fold+1)\n    print('#### Image Size: (%i, %i) | Model: %s | Batch Size: %i | Scheduler: %s'%\n          (*CFG.img_size, CFG.model_name, CFG.batch_size*CFG.replicas, CFG.scheduler))\n    print('#### Num Train: {:,} | Num Valid: {:,}'.format(len(train_paths), len(valid_paths)))\n    \n    # Clear the session and build the model\n    K.clear_session()\n    with strategy.scope():\n        model = build_model(CFG)\n        \n    print('#'*25) \n    \n    # Callbacks\n    sv = tf.keras.callbacks.ModelCheckpoint(\n        'fold-%i.h5'%fold, monitor='val_auc', verbose=0, save_best_only=True,\n        save_weights_only=False, mode='max', save_freq='epoch')\n    callbacks = [sv, get_lr_callback(CFG.batch_size*CFG.replicas)]\n    if CFG.wandb:\n        # wandb callback for logging metrics and media\n        callbacks.append(WandbCallback)\n\n    # Training\n    print('# Training')\n    history = model.fit(\n        train_ds, \n        epochs=2 if CFG.debug else CFG.epochs, \n        callbacks=callbacks, \n        steps_per_epoch=len(train_paths)/CFG.batch_size//CFG.replicas,\n        validation_data=valid_ds, \n        verbose=CFG.verbose,\n    )\n    \n    # Load best checkpoint\n    print('# Loading best model')\n    model.load_weights('fold-%i.h5'%fold)\n    \n    # Predict on the validation data for oof result\n    print('# Infering OOF')\n    valid_ds = build_dataset(valid_paths, labels=None, augment=CFG.tta>1, repeat=True, cache=False, \n                             shuffle=False, batch_size=infer_bs*CFG.replicas, \n                             drop_remainder=drop_remainder)\n    ct_valid = len(valid_paths); STEPS = CFG.tta * ct_valid/infer_bs/CFG.replicas\n    pred = model.predict(valid_ds,steps=STEPS,verbose=CFG.verbose)[:CFG.tta*ct_valid,] \n    pred = np.mean(pred.reshape((CFG.tta,ct_valid,-1)),axis=0)\n    oof_pred.append(pred)               \n\n    # Get ids and targets\n    oof_true.append(valid_df[CFG.target_col].values[:ct_valid])\n    oof_folds.append(np.ones_like(oof_true[-1],dtype='int8')*fold )\n    oof_ids.append(valid_paths)\n   \n    # Save valid data prediction\n    y_true = oof_true[-1].reshape(-1).astype('float32')\n    y_pred = oof_pred[-1].argmax(axis=-1)\n    valid_df.loc[:num_valid - 1, 'pred'] = y_pred\n    valid_df.loc[:num_valid - 1, 'miss'] = y_true != y_pred\n    valid_df.loc[:num_valid - 1, CFG.class_names] = oof_pred[-1].tolist()\n    valid_df.to_csv(f'fold_{fold:02d}.csv',index=False)\n    \n    # Log the metrics\n    scores = {}\n    cmAP = padded_cmap(tf.keras.utils.to_categorical(y_true), oof_pred[-1])\n    best_epoch = np.argmax(history.history['val_'+CFG.monitor], axis=-1) + 1\n    best_score = history.history['val_'+CFG.monitor][best_epoch - 1]\n    scores.update({'auc': best_score,\n                   'epoch': best_epoch,\n                   'cmAP': cmAP,})\n    oof_val.append(best_score)\n    print('\\n>>> FOLD %i OOF AUC = %.3f | Padded_cmAP = %.3f' % (fold, oof_val[-1], cmAP))\n    \n    # Show training plot\n    if CFG.training_plot:\n        plot_history(history)\n        \n    # Log metrics, media to wandb\n    if CFG.wandb:\n        print('# WandB')\n        log_wandb(valid_df)\n        wandb.run.finish()\n        display(ipd.IFrame(run.url, width=1080, height=720))","metadata":{"_kg_hide-input":true,"_kg_hide-output":false,"papermill":{"duration":3436.548849,"end_time":"2022-03-08T04:18:05.540592","exception":true,"start_time":"2022-03-08T03:20:48.991743","status":"failed"},"tags":[],"execution":{"iopub.status.busy":"2023-03-14T05:47:15.532204Z","iopub.execute_input":"2023-03-14T05:47:15.532511Z","iopub.status.idle":"2023-03-14T06:29:17.943557Z","shell.execute_reply.started":"2023-03-14T05:47:15.532483Z","shell.execute_reply":"2023-03-14T06:29:17.942372Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_id(row):\n    row['filename'] = row['filepath'].split('/',5)[-1]\n    return row","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T06:29:17.944956Z","iopub.execute_input":"2023-03-14T06:29:17.945247Z","iopub.status.idle":"2023-03-14T06:29:17.950463Z","shell.execute_reply.started":"2023-03-14T06:29:17.945219Z","shell.execute_reply":"2023-03-14T06:29:17.949532Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# OOF Data\ny_pred = np.concatenate(oof_pred); y_true = np.concatenate(oof_true);\nids = np.concatenate(oof_ids); folds = np.concatenate(oof_folds)\n\n# Overall cmAP\ncmAP = padded_cmap(tf.keras.utils.to_categorical(y_true), y_pred)\n\n# Overall AUC in PR curve\nm = tf.keras.metrics.AUC(curve='PR')\nm.update_state(tf.keras.utils.to_categorical(y_true), y_pred)\nauc = m.result().numpy()\n\nprint('>>> Overall cmAP: ', cmAP)\nprint('>>> Overall AUC(PR): ', auc)","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T06:29:17.951813Z","iopub.execute_input":"2023-03-14T06:29:17.952113Z","iopub.status.idle":"2023-03-14T06:29:18.435412Z","shell.execute_reply.started":"2023-03-14T06:29:17.952085Z","shell.execute_reply":"2023-03-14T06:29:18.434102Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Save OOF data to disk\ncolumns = ['filepath', 'fold', 'true', 'pred', *CFG.class_names]\ndf_oof = pd.DataFrame(np.concatenate([ids[:,None], folds, y_true,\n                                      np.argmax(y_pred,axis=1)[:,None], y_pred], axis=1), columns=columns)\ndf_oof['class_name'] = df_oof.true.map(CFG.label2name)\ndf_oof['miss'] = df_oof.true!=df_oof.pred\ntqdm.pandas(desc='id ')\ndf_oof = df_oof.progress_apply(get_id,axis=1)\ndf_oof.to_csv('oof.csv',index=False)\ndisplay(df_oof.head(2))","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T06:29:18.436809Z","iopub.execute_input":"2023-03-14T06:29:18.437132Z","iopub.status.idle":"2023-03-14T06:29:23.222319Z","shell.execute_reply.started":"2023-03-14T06:29:18.437096Z","shell.execute_reply":"2023-03-14T06:29:23.220687Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print('Miss Total:')\ndisplay(df_oof.query(\"miss==True\").shape[0])\n\nprint()\nprint('Miss Distribution Top10:')\ndisplay(df_oof.query(\"miss==True\").class_name.value_counts()[:10])","metadata":{"papermill":{"duration":null,"end_time":null,"exception":null,"start_time":null,"status":"pending"},"tags":[],"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T06:29:23.224099Z","iopub.execute_input":"2023-03-14T06:29:23.224438Z","iopub.status.idle":"2023-03-14T06:29:23.298741Z","shell.execute_reply.started":"2023-03-14T06:29:23.224409Z","shell.execute_reply":"2023-03-14T06:29:23.297234Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import shutil\ntry:\n    !rm -rf ./wandb\nexcept:\n    pass","metadata":{"_kg_hide-output":true,"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-03-14T06:29:23.299976Z","iopub.execute_input":"2023-03-14T06:29:23.300273Z","iopub.status.idle":"2023-03-14T06:29:26.546574Z","shell.execute_reply.started":"2023-03-14T06:29:23.300244Z","shell.execute_reply":"2023-03-14T06:29:26.544732Z"},"trusted":true},"execution_count":null,"outputs":[]}]}