{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":25954,"databundleVersionId":2091745,"sourceType":"competition"},{"sourceId":33246,"databundleVersionId":3221581,"sourceType":"competition"},{"sourceId":44224,"databundleVersionId":5188730,"sourceType":"competition"},{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":1487019,"sourceType":"datasetVersion","datasetId":726237},{"sourceId":1487116,"sourceType":"datasetVersion","datasetId":726312}],"dockerImageVersionId":30684,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install git+https://github.com/awsaf49/tensorflow_extra.git@9a7f80d4c1073ab3fc4820fef01105bff43a45a6 --no-deps","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-05-04T07:55:29.610433Z","iopub.execute_input":"2024-05-04T07:55:29.610818Z","iopub.status.idle":"2024-05-04T07:55:35.466024Z","shell.execute_reply.started":"2024-05-04T07:55:29.610788Z","shell.execute_reply":"2024-05-04T07:55:35.464769Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip freeze | grep tensorflow","metadata":{"execution":{"iopub.status.busy":"2024-05-02T12:41:12.933440Z","iopub.execute_input":"2024-05-02T12:41:12.933768Z","iopub.status.idle":"2024-05-02T12:41:18.766021Z","shell.execute_reply.started":"2024-05-02T12:41:12.933740Z","shell.execute_reply":"2024-05-02T12:41:18.765055Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"code","source":"!pip install -qU git+https://github.com/awsaf49/efficientnet-spec","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:54:42.949473Z","iopub.execute_input":"2024-05-04T07:54:42.949867Z","iopub.status.idle":"2024-05-04T07:55:00.058524Z","shell.execute_reply.started":"2024-05-04T07:54:42.949834Z","shell.execute_reply":"2024-05-04T07:55:00.057352Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow\ntensorflow.__version__","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:00.060273Z","iopub.execute_input":"2024-05-04T07:55:00.060669Z","iopub.status.idle":"2024-05-04T07:55:14.786893Z","shell.execute_reply.started":"2024-05-04T07:55:00.060634Z","shell.execute_reply":"2024-05-04T07:55:14.786041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### TODO\n1. index the dataframe\n2. Train the model\n3. Experiment with learning rate\n","metadata":{}},{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nfrom tqdm import tqdm\ntqdm.pandas() \nimport matplotlib as mpl\ncmap = mpl.colormaps.get_cmap('coolwarm')\nimport matplotlib.pyplot as plt\nimport librosa.display as lid\nimport IPython.display as ipd\nfrom multiprocessing import Pool\nimport tensorflow as tf\nimport tensorflow_extra as tfe\nimport tensorflow_io as tfio\nimport tensorflow.keras.backend as K\nimport efficientnet.tfkeras as efn\nimport os\nfrom IPython.display import Audio\nimport librosa\n","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:39.988480Z","iopub.execute_input":"2024-05-04T07:55:39.988896Z","iopub.status.idle":"2024-05-04T07:55:42.563365Z","shell.execute_reply.started":"2024-05-04T07:55:39.988862Z","shell.execute_reply":"2024-05-04T07:55:42.562395Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class CFG:\n    device = 'CPU'\n    seed = 42\n    \n    # Input image size and batch size\n    img_size = [128, 512]\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    # 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 = 1024\n    window = 1024\n    hop_length = 128\n    fmin = 20\n    fmax = 16000\n    normalize = True\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 = 'EfficientNetB1'\n    fsr = False # 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    # Data augmentation parameters\n    augment=True\n    \n    # Time Freq masking\n    freq_mask_prob=0.50\n    num_freq_masks=1\n    freq_mask_param=10\n    time_mask_prob=0.50\n    num_time_masks=2\n    time_mask_param=25\n\n    # Audio Augmentation Settings\n    audio_augment_prob = 0.5\n    \n    mixup_prob = 0.65\n    mixup_alpha = 0.5\n    \n    cutmix_prob = 0.65\n    cutmix_alpha = 2.5\n    \n    timeshift_prob = 0.0\n    \n    gn_prob = 0.35\n\n    # Class Labels for BirdCLEF 23\n    class_names = sorted(set(os.listdir('/kaggle/input/birdclef-2023/train_audio/')+\n                            os.listdir('/kaggle/input/birdclef-2024/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    # Class Labels for BirdCLEF 21 & 22\n    class_names2 = sorted(set(os.listdir('/kaggle/input/birdclef-2021/train_short_audio/')\n                       +os.listdir('/kaggle/input/birdclef-2022/train_audio/') + \n                        os.listdir('/kaggle/input/xeno-canto-bird-recordings-extended-a-m/A-M')+\n                        os.listdir('/kaggle/input/xeno-canto-bird-recordings-extended-n-z/N-Z')))\n    num_classes2 = len(class_names2)\n    class_labels2 = list(range(num_classes2))\n    label2name2 = dict(zip(class_labels2, class_names2))\n    name2label2 = {v:k for k,v in label2name2.items()}\n    \n    # Training Settings\n    target_col = ['target']\n    tab_cols = ['filename']\n    monitor = 'auc'\n    debug = True\n    verbose = 0","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:44.649248Z","iopub.execute_input":"2024-05-04T07:55:44.649941Z","iopub.status.idle":"2024-05-04T07:55:44.968517Z","shell.execute_reply.started":"2024-05-04T07:55:44.649909Z","shell.execute_reply":"2024-05-04T07:55:44.967643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.keras.utils.set_random_seed(CFG.seed)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:45.022526Z","iopub.execute_input":"2024-05-04T07:55:45.023516Z","iopub.status.idle":"2024-05-04T07:55:45.029823Z","shell.execute_reply.started":"2024-05-04T07:55:45.023472Z","shell.execute_reply":"2024-05-04T07:55:45.028558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_xeno():\n    base1 = \"/kaggle/input/xeno-canto-bird-recordings-extended-a-m/\"\n    \n    base2 = \"/kaggle/input/xeno-canto-bird-recordings-extended-n-z/\"\n    xeno_am = pd.read_csv(\"/kaggle/input/xeno-canto-bird-recordings-extended-a-m/train_extended.csv\")\n    xeno_am['filepath'] = xeno_am['ebird_code'].map(lambda x : ((base1 + \"A-M/\") if x[0] <= 'm' else (base2 + \"N-Z/\")) + x) + \"/\" + xeno_am['filename']\n    xeno_nz = pd.read_csv(\"/kaggle/input/xeno-canto-bird-recordings-extended-n-z/train_extended.csv\")\n    xeno_nz['filepath'] = xeno_nz['ebird_code'].map(lambda x : ((base1 + \"A-M/\") if x[0] <= 'm' else (base2 + \"N-Z/\")) + x) + \"/\" + xeno_nz['filename']\n    df_xc = pd.concat([xeno_am, xeno_nz], axis=0, ignore_index=True) \n    df_xc['primary_label'] = df_xc['ebird_code']\n    df_xc['scientific_name'] = df_xc['sci_name']\n    df_xc['common_name'] = df_xc['species']\n    df_xc = df_xc.drop(['ebird_code', 'sci_name', 'species'], axis=1)\n    df_xc['dataset'] = 'xeno'\n    df_xc['target'] = df_xc.primary_label.map(CFG.name2label2).astype('int32')\n    return df_xc","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:45.383734Z","iopub.execute_input":"2024-05-04T07:55:45.384100Z","iopub.status.idle":"2024-05-04T07:55:45.391532Z","shell.execute_reply.started":"2024-05-04T07:55:45.384071Z","shell.execute_reply":"2024-05-04T07:55:45.390647Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_clef21():\n    base = '/kaggle/input/birdclef-2021'\n    df_21 = pd.read_csv(f'{base}/train_metadata.csv')\n    df_21['filepath'] = base + '/train_short_audio/' + df_21.primary_label + '/' + df_21.filename\n    df_21['target'] = df_21.primary_label.map(CFG.name2label2).astype('int32')\n    df_21['dataset'] = 'clef21'\n    return df_21","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:45.825903Z","iopub.execute_input":"2024-05-04T07:55:45.826514Z","iopub.status.idle":"2024-05-04T07:55:45.831790Z","shell.execute_reply.started":"2024-05-04T07:55:45.826483Z","shell.execute_reply":"2024-05-04T07:55:45.830683Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_clef22():\n    base = \"/kaggle/input/birdclef-2022\"\n    df_22 = pd.read_csv(f'{base}/train_metadata.csv')\n    df_22['filepath'] = base + '/train_audio/' + df_22['filename']\n    df_22['filename'] = df_22['filename'].map(lambda x: x.split('/')[-1])\n    df_22['target'] = df_22.primary_label.map(CFG.name2label2).astype('int32')\n    df_22['dataset'] = 'clef22'\n    \n    return df_22\n    ","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:46.237802Z","iopub.execute_input":"2024-05-04T07:55:46.238155Z","iopub.status.idle":"2024-05-04T07:55:46.244204Z","shell.execute_reply.started":"2024-05-04T07:55:46.238127Z","shell.execute_reply":"2024-05-04T07:55:46.242975Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_clef23():\n    base = \"/kaggle/input/birdclef-2023\"\n    df_23 = pd.read_csv(f'{base}/train_metadata.csv')\n    df_23['filepath'] = base + '/train_audio/' + df_23['filename']\n    df_23['filename'] = df_23['filename'].map(lambda x: x.split('/')[-1])\n    df_23['dataset'] = 'clef23'\n    df_23['target'] = df_23.primary_label.map(CFG.name2label).astype('int32')\n    return df_23","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:46.440786Z","iopub.execute_input":"2024-05-04T07:55:46.441147Z","iopub.status.idle":"2024-05-04T07:55:46.448483Z","shell.execute_reply.started":"2024-05-04T07:55:46.441118Z","shell.execute_reply":"2024-05-04T07:55:46.447013Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_clef24():\n    base = \"/kaggle/input/birdclef-2024\"\n    df_24 = pd.read_csv(f'{base}/train_metadata.csv')\n    df_24['filepath'] = base + '/train_audio/' + df_24.filename\n    df_24['filename'] = df_24['filename'].map(lambda x: x.split('/')[-1])\n    df_24['target'] = df_24.primary_label.map(CFG.name2label).astype('int32')\n    df_24['dataset'] = 'clef24'\n    return df_24","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:46.632388Z","iopub.execute_input":"2024-05-04T07:55:46.632781Z","iopub.status.idle":"2024-05-04T07:55:46.638819Z","shell.execute_reply.started":"2024-05-04T07:55:46.632753Z","shell.execute_reply":"2024-05-04T07:55:46.637757Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def loader(f):\n    return f()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:46.810027Z","iopub.execute_input":"2024-05-04T07:55:46.810978Z","iopub.status.idle":"2024-05-04T07:55:46.815778Z","shell.execute_reply.started":"2024-05-04T07:55:46.810938Z","shell.execute_reply":"2024-05-04T07:55:46.814552Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def load_datasets_in_parallel(num_processes):\n    loaders = [load_xeno, load_clef21, load_clef22, load_clef23, load_clef24]\n    with Pool(num_processes) as pool:\n        datasets = pool.map(loader, loaders)\n    return pd.concat(datasets, ignore_index=True)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:47.005216Z","iopub.execute_input":"2024-05-04T07:55:47.005845Z","iopub.status.idle":"2024-05-04T07:55:47.011771Z","shell.execute_reply.started":"2024-05-04T07:55:47.005800Z","shell.execute_reply":"2024-05-04T07:55:47.010463Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df = load_datasets_in_parallel(5)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:47.150182Z","iopub.execute_input":"2024-05-04T07:55:47.150920Z","iopub.status.idle":"2024-05-04T07:55:49.019809Z","shell.execute_reply.started":"2024-05-04T07:55:47.150876Z","shell.execute_reply":"2024-05-04T07:55:49.018479Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:49.021899Z","iopub.execute_input":"2024-05-04T07:55:49.022233Z","iopub.status.idle":"2024-05-04T07:55:49.493136Z","shell.execute_reply.started":"2024-05-04T07:55:49.022201Z","shell.execute_reply":"2024-05-04T07:55:49.492130Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_pre = df","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:49.494470Z","iopub.execute_input":"2024-05-04T07:55:49.494799Z","iopub.status.idle":"2024-05-04T07:55:49.499292Z","shell.execute_reply.started":"2024-05-04T07:55:49.494771Z","shell.execute_reply":"2024-05-04T07:55:49.498260Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# for development\ndf.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:49.501314Z","iopub.execute_input":"2024-05-04T07:55:49.501635Z","iopub.status.idle":"2024-05-04T07:55:49.532895Z","shell.execute_reply.started":"2024-05-04T07:55:49.501608Z","shell.execute_reply":"2024-05-04T07:55:49.531829Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df.info()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:49.537860Z","iopub.execute_input":"2024-05-04T07:55:49.538253Z","iopub.status.idle":"2024-05-04T07:55:49.742606Z","shell.execute_reply.started":"2024-05-04T07:55:49.538220Z","shell.execute_reply":"2024-05-04T07:55:49.741460Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"librosa.__version__","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:49.888794Z","iopub.execute_input":"2024-05-04T07:55:49.889163Z","iopub.status.idle":"2024-05-04T07:55:49.895827Z","shell.execute_reply.started":"2024-05-04T07:55:49.889134Z","shell.execute_reply":"2024-05-04T07:55:49.894715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def librosa_load(filepath:str):\n    return librosa.load(filepath)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:50.305518Z","iopub.execute_input":"2024-05-04T07:55:50.305899Z","iopub.status.idle":"2024-05-04T07:55:50.310608Z","shell.execute_reply.started":"2024-05-04T07:55:50.305867Z","shell.execute_reply":"2024-05-04T07:55:50.309703Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(df_pre.iloc[0])","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:50.723143Z","iopub.execute_input":"2024-05-04T07:55:50.723536Z","iopub.status.idle":"2024-05-04T07:55:50.730373Z","shell.execute_reply.started":"2024-05-04T07:55:50.723499Z","shell.execute_reply":"2024-05-04T07:55:50.729239Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"audio, rate = librosa_load(df_pre.iloc[1]['filepath'])","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:55:51.131216Z","iopub.execute_input":"2024-05-04T07:55:51.131648Z","iopub.status.idle":"2024-05-04T07:56:03.978781Z","shell.execute_reply.started":"2024-05-04T07:55:51.131618Z","shell.execute_reply":"2024-05-04T07:56:03.977549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"audio.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:03.980667Z","iopub.execute_input":"2024-05-04T07:56:03.981428Z","iopub.status.idle":"2024-05-04T07:56:03.987462Z","shell.execute_reply.started":"2024-05-04T07:56:03.981396Z","shell.execute_reply":"2024-05-04T07:56:03.986584Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Audio(data = audio, rate = rate)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:03.988876Z","iopub.execute_input":"2024-05-04T07:56:03.989597Z","iopub.status.idle":"2024-05-04T07:56:04.028378Z","shell.execute_reply.started":"2024-05-04T07:56:03.989557Z","shell.execute_reply":"2024-05-04T07:56:04.026830Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_spectrogram(audio):\n    spec = librosa.feature.melspectrogram(y=audio, \n                                   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=1.0)\n    return spec\n\ndef display_audio(row):\n    # Caption for viz\n    caption = f'Id: {row.filename} | Name: {row.primary_label} | Sci.Name: {row.scientific_name} | Rating: {row.rating}'\n    # Read audio file\n    audio, sr = librosa_load(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('# 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                color= cmap(0.1))\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":{"execution":{"iopub.status.busy":"2024-05-04T07:56:04.030744Z","iopub.execute_input":"2024-05-04T07:56:04.031706Z","iopub.status.idle":"2024-05-04T07:56:04.041442Z","shell.execute_reply.started":"2024-05-04T07:56:04.031669Z","shell.execute_reply":"2024-05-04T07:56:04.040434Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"spec = get_spectrogram(audio)\nprint(spec.shape)\nlid.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')","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:04.042699Z","iopub.execute_input":"2024-05-04T07:56:04.043219Z","iopub.status.idle":"2024-05-04T07:56:06.851027Z","shell.execute_reply.started":"2024-05-04T07:56:04.043189Z","shell.execute_reply":"2024-05-04T07:56:06.850077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Example\ndisplay_audio(df_pre.iloc[0])","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:06.852463Z","iopub.execute_input":"2024-05-04T07:56:06.853093Z","iopub.status.idle":"2024-05-04T07:56:08.593835Z","shell.execute_reply.started":"2024-05-04T07:56:06.853060Z","shell.execute_reply":"2024-05-04T07:56:08.592573Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display_audio(df_pre.iloc[1])","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:08.595455Z","iopub.execute_input":"2024-05-04T07:56:08.595850Z","iopub.status.idle":"2024-05-04T07:56:10.270823Z","shell.execute_reply.started":"2024-05-04T07:56:08.595816Z","shell.execute_reply":"2024-05-04T07:56:10.269559Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Spliting","metadata":{}},{"cell_type":"code","source":"from sklearn.model_selection import StratifiedKFold\n\nskf = StratifiedKFold(n_splits=CFG.num_fold, shuffle=True, random_state=CFG.seed)\n\ndf_pre = df_pre.reset_index(drop=True)\ndf_pre['fold'] = -1\nfor fold, (train_idx, val_idx) in enumerate(skf.split(df_pre, df_pre['primary_label'])):\n    df_pre.loc[val_idx, 'fold'] = fold","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:10.272267Z","iopub.execute_input":"2024-05-04T07:56:10.272689Z","iopub.status.idle":"2024-05-04T07:56:11.035968Z","shell.execute_reply.started":"2024-05-04T07:56:10.272653Z","shell.execute_reply":"2024-05-04T07:56:11.034789Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"df_pre.head()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:11.037254Z","iopub.execute_input":"2024-05-04T07:56:11.037576Z","iopub.status.idle":"2024-05-04T07:56:11.064262Z","shell.execute_reply.started":"2024-05-04T07:56:11.037549Z","shell.execute_reply":"2024-05-04T07:56:11.063105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Filter & Upsample Data\n\nFilter: As there is even only one sample for some classes we need to make sure they are in the train data using filtering. We can do this by always keeping them in the train data and do cross-validtion on the rest of the data.\n\nUpsample: Even in the filtered data there are some minority classes with very few samples. To amend the class imbalance we can try upsampling those classes. Following function will simply upsample the train data for minory class which has very few samples. This can potentially mitigate the classic \"Long Tail\" problem.\n\nDownsample: Ensure maximum sample of a class.","metadata":{}},{"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\n\ndef downsample_data(df, thr=500):\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    up_classes = class_dist[class_dist > thr].index.tolist()\n\n    # create an empty list to store the upsampled dataframes\n    down_dfs = []\n\n    # loop through the undersampled classes and upsample them\n    for c in up_classes:\n        # get the dataframe for the current class\n        class_df = df.query(\"primary_label==@c\")\n        # Remove that class data\n        df = df.query(\"primary_label!=@c\")\n        # upsample the dataframe\n        class_df = class_df.sample(n=thr, replace=False, random_state=CFG.seed)\n        # append the upsampled dataframe to the list\n        down_dfs.append(class_df)\n\n    # concatenate the upsampled dataframes and the original dataframe\n    down_df = pd.concat([df] + down_dfs, axis=0, ignore_index=True)\n    \n    return down_df","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:11.067823Z","iopub.execute_input":"2024-05-04T07:56:11.068174Z","iopub.status.idle":"2024-05-04T07:56:11.079701Z","shell.execute_reply.started":"2024-05-04T07:56:11.068145Z","shell.execute_reply":"2024-05-04T07:56:11.078534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Filter data\nf_df_pre = filter_data(df_pre, thr=5)\n\nplt.figure(figsize=(10, 4))\nax1 = plt.subplot(1, 2, 1)\nf_df_pre.cv.value_counts().plot.bar(legend=True, color=cmap(0.1))\nplt.yscale(\"log\")\nplt.title(\"df_pre\")","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:11.081096Z","iopub.execute_input":"2024-05-04T07:56:11.081572Z","iopub.status.idle":"2024-05-04T07:56:11.729953Z","shell.execute_reply.started":"2024-05-04T07:56:11.081538Z","shell.execute_reply":"2024-05-04T07:56:11.728535Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Upsample data\nup_thr = 100\ndn_df = downsample_data(df_pre, thr=400)\nup_df = upsample_data(dn_df, thr=up_thr)\nprint(\"# Pretraing Dataset\")\nprint(f'> Original: {len(df_pre)}')\nprint(f'> After Upsample: {len(up_df)}')\nprint(f'> After Downsample: {len(dn_df)}')\n\n# Show effect of upsample\nplt.figure(figsize=(12*2, 6))\n\nax1 = plt.subplot(1, 2, 1)\ndf_pre.primary_label.value_counts()[:].plot.bar(color='blue', label='original')\nup_df.primary_label.value_counts()[:].plot.bar(color='green', label='w/ upsample')\ndn_df.primary_label.value_counts()[:].plot.bar(color='red', label='w/ dowsample')\nplt.xticks([])\nplt.axhline(y=up_thr, color='g', linestyle='--', label='up threshold')\nplt.axhline(y=400, color='r', linestyle='--', label='down threshold')\nplt.legend()\nplt.title(\"Upsample for Pre-Training\")\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:11.731344Z","iopub.execute_input":"2024-05-04T07:56:11.731664Z","iopub.status.idle":"2024-05-04T07:56:34.150183Z","shell.execute_reply.started":"2024-05-04T07:56:11.731638Z","shell.execute_reply":"2024-05-04T07:56:34.149077Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"g = tf.random.Generator.from_seed(CFG.seed)\n\ndef random_int(shape=[], minval=0, maxval=1):\n    return g.uniform(shape=shape, minval=minval, maxval=maxval, dtype=tf.int32)\n\ndef random_float(shape=[], minval=0.0, maxval=1.0):\n  # Use the generator to create a random uniform tensor\n  random_tensor = g.uniform(shape=shape, minval=minval, maxval=maxval)\n  return random_tensor\n\n# Generats random float\n# def 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":{"execution":{"iopub.status.busy":"2024-05-04T07:56:34.151557Z","iopub.execute_input":"2024-05-04T07:56:34.151901Z","iopub.status.idle":"2024-05-04T07:56:34.209619Z","shell.execute_reply.started":"2024-05-04T07:56:34.151872Z","shell.execute_reply":"2024-05-04T07:56:34.208419Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"f = random_float([], 0.005, 0.05)\nf","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:34.210894Z","iopub.execute_input":"2024-05-04T07:56:34.211208Z","iopub.status.idle":"2024-05-04T07:56:34.239033Z","shell.execute_reply.started":"2024-05-04T07:56:34.211182Z","shell.execute_reply":"2024-05-04T07:56:34.238004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"@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    \nclass CustomGaussianNoise(tf.keras.layers.Layer):\n    def __init__(self, stddev, **kwargs):\n        super(CustomGaussianNoise, self).__init__(**kwargs)\n        self.stddev = stddev\n\n    def call(self, inputs, training=None):\n        if training:\n            noise = tf.random.normal(tf.shape(inputs), stddev=self.stddev)\n            return inputs + noise\n        return inputs\n\n@tf.function\ndef GaussianNoise(audio, std=tf.Variable([0.0025, 0.025]), prob=0.5):\n    stddev = random_float([], std[0], std[1])\n    if tf.random.uniform([]) < prob:\n        GN_layer = CustomGaussianNoise(stddev)\n        audio = GN_layer(audio, training=True)\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    print(CFG.gn_prob, type(CFG.gn_prob))\n    audio = GaussianNoise(audio, prob=CFG.gn_prob)\n    return audio\n\nmixup_layer = tfe.layers.MixUp(alpha=CFG.mixup_alpha, prob=CFG.mixup_prob)\ncutmix_layer = tfe.layers.CutMix(alpha=CFG.cutmix_alpha, prob=CFG.cutmix_prob)\n\ndef CutMixUp(audios, labels):\n    audios, labels = mixup_layer(audios, labels, training=True)\n    audios, labels = cutmix_layer(audios, labels, training=True)\n    return audios, labels","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:34.240459Z","iopub.execute_input":"2024-05-04T07:56:34.241095Z","iopub.status.idle":"2024-05-04T07:56:34.266680Z","shell.execute_reply.started":"2024-05-04T07:56:34.241056Z","shell.execute_reply":"2024-05-04T07:56:34.265451Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"spec = get_spectrogram(audio)\naudio = GaussianNoise(audio, prob=0.3).numpy()\nspec_gauss = get_spectrogram(audio)\n# Display audio\nprint(\"# Audio:\")\ndisplay(ipd.Audio(audio, rate=CFG.sample_rate))\nprint('# Visualization:')\nfig, ax = plt.subplots(2, 1, figsize=(12, 2*3), sharex=True, tight_layout=True)\n\n# Specplot\nlid.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[0])\n\n# Specplot Gauss\nlid.specshow(spec_gauss, \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\nax[0].set_xlabel('');\nfig.show()","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:56:34.268207Z","iopub.execute_input":"2024-05-04T07:56:34.268801Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Decodes Audio\ndef audio_decoder(with_labels=True, dim=CFG.audio_len, \n                  take_first=False, num_classes=264, CFG=CFG):\n    def get_audio(filepath):\n        ftype = filepath[1]\n        filepath = filepath[0]\n        file_bytes = tf.io.read_file(filepath)\n        if ftype:\n            audio = tfio.audio.decode_vorbis(file_bytes) # decode .ogg file\n        else:\n            audio = tfio.audio.decode_mp3(file_bytes) # decode .mp3 file\n        audio = tf.cast(audio, tf.float32)\n        if tf.shape(audio)[1]>1: # stereo -> mono\n            audio = audio[...,0:1]\n        audio = tf.squeeze(audio, axis=-1)\n        return audio\n    \n    def crop_or_pad(audio, target_len, pad_mode='constant', take_first=True):\n        audio_len = tf.shape(audio)[0]\n        diff_len = abs(target_len - audio_len)\n        if audio_len < target_len:\n            pad1 = tf.random.uniform([], maxval=diff_len, dtype=tf.int32)\n            pad2 = diff_len - pad1\n            audio = tf.pad(audio, paddings=[[pad1, pad2]], mode=pad_mode)\n        elif audio_len > target_len:\n            if take_first:\n                audio = audio[:target_len]\n            else:\n                idx = tf.random.uniform([], maxval=diff_len, dtype=tf.int32)\n                audio = audio[idx: (idx + target_len)]\n        return tf.reshape(audio, [target_len])\n\n    def get_target(target):          \n        target = tf.reshape(target, [1])\n        target = tf.cast(tf.one_hot(target, num_classes), tf.float32) \n        target = tf.reshape(target, [num_classes])\n        return target\n    \n    def decode(path):\n        audio = get_audio(path)\n        audio = crop_or_pad(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","metadata":{"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","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def plot_batch(batch, row=3, col=3, label2name=None,):\n    \"\"\"Plot one batch data\"\"\"\n    if isinstance(batch, tuple) or isinstance(batch, list):\n        audios, tars = batch\n    else:\n        audios = 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        plt.plot(audios[idx].numpy(), color=cmap(0.1))\n        if tars is not None:\n            label = tars[idx].numpy().argmax()\n            name = 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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_dataset(paths, ftype, labels=None, batch_size=32, target_size=[128, 256], \n                  audio_decode_fn=None, audio_augment_fn=None,\n                  take_first=False, num_classes=264,\n                  cache=True, cache_dir=\"/kaggle/working/cache\",drop_remainder=False,\n                  augment=True, repeat=False, 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        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(labels is not None,\n                                        dim=CFG.audio_len, \n                                        take_first=take_first,\n                                        num_classes=num_classes,\n                                        CFG=CFG)\n    # Set default audio augmentation function if not provided\n    if audio_augment_fn is None:\n        audio_augment_fn = audio_augmenter(labels is not None, \n                                           dim=CFG.audio_len, CFG=CFG)\n        \n    # Set TensorFlow AUTOTUNE option\n    AUTO = tf.data.AUTOTUNE\n    # Create slices based on whether labels are provided\n    slices = ((paths, ftype),) if labels is None else ((paths, ftype), 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\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    # Batch the dataset with the specified batch size\n    ds = ds.batch(batch_size, drop_remainder=drop_remainder)\n    # Apply MixUp & CutMix regularization to the dataset\n    if augment and labels is not None:\n        ds = ds.map(CutMixUp,num_parallel_calls=AUTO)\n    # Prefetch the next batch of data to improve performance\n    ds = ds.prefetch(AUTO)\n    return ds","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_df = df_pre.query(\"dataset=='clef21'\").sample(50)\nds = build_dataset(check_df.filepath.tolist(),\n                   check_df.filepath.str.contains('.ogg').tolist(),\n                   check_df.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=False)\nds = ds.take(32)\naudios, labels = next(iter(ds))\nplot_batch((audios, labels), label2name=CFG.label2name2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_df = df_pre.query(\"dataset=='xeno'\").sample(50)\nds = build_dataset(check_df.filepath.tolist(),\n                   check_df.filepath.str.contains('.ogg').tolist(),\n                   check_df.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=False)\nds = ds.take(32)\naudios, labels = next(iter(ds))\nplot_batch((audios, labels), label2name=CFG.label2name2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_df = df_pre.query(\"dataset=='clef22'\").sample(50)\nds = build_dataset(check_df.filepath.tolist(),\n                   check_df.filepath.str.contains('.ogg').tolist(),\n                   check_df.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=False)\nds = ds.take(32)\naudios, labels = next(iter(ds))\nplot_batch((audios, labels), label2name=CFG.label2name2)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_df = df_pre.query(\"dataset=='clef23'\").sample(50)\nds = build_dataset(check_df.filepath.tolist(),\n                   check_df.filepath.str.contains('.ogg').tolist(),\n                   check_df.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=False)\nds = ds.take(32)\naudios, labels = next(iter(ds))\nplot_batch((audios, labels), label2name=CFG.label2name)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"check_df = df_pre.query(\"dataset=='clef24'\").sample(50)\nds = build_dataset(check_df.filepath.tolist(),\n                   check_df.filepath.str.contains('.ogg').tolist(),\n                   check_df.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=False)\nds = ds.take(32)\naudios, labels = next(iter(ds))\nplot_batch((audios, labels), label2name=CFG.label2name)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"melspec_layer = tfe.layers.MelSpectrogram(n_fft=CFG.nfft, \n                                          hop_length=CFG.hop_length, \n                                          sr=CFG.sample_rate, \n                                          ref=1.0,\n                                          fmin=500,\n                                          fmax=15000,\n                                          out_channels=None)\nspecs = melspec_layer(audios)\n# print(specs[0, ..., 0])\n# print(specs[0, ..., 1])\n# print(specs[0, ..., 2])\nfig, ax = plt.subplots(2, 1, sharex=True, figsize=(12, 5))\nlid.waveshow(audios[0].numpy(), sr=CFG.sample_rate, ax=ax[0], axis=None)\nprint(specs.shape)\nlid.specshow(specs[0].numpy(), \n             n_fft=CFG.nfft, \n             hop_length=CFG.hop_length, \n             sr=CFG.sample_rate,\n             x_axis='time',\n             y_axis='mel',\n             cmap='coolwarm',\n              ax=ax[1])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"display(ipd.Audio(audios[0].numpy(), rate=CFG.sample_rate))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TimeFrequencyMasking(tf.keras.layers.Layer):\n\n    def __init__(self, freq_mask_prob=CFG.freq_mask_prob, num_freq_masks=CFG.num_freq_masks,\n                 freq_mask_param=CFG.freq_mask_param, time_mask_prob=CFG.time_mask_prob, \n                 num_time_masks=CFG.num_time_masks, time_mask_param=CFG.time_mask_param):\n        super(TimeFrequencyMasking, self).__init__()\n        self.freq_mask_prob=freq_mask_prob\n        self.num_freq_masks=num_freq_masks\n        self.freq_mask_param=freq_mask_param\n        self.time_mask_prob=time_mask_prob\n        self.num_time_masks=num_time_masks\n        self.time_mask_param=time_mask_param\n\n    @tf.function\n    def time_frequency_masking_tf(self, spec):\n        out = spec\n        for _ in range(self.num_freq_masks):\n            if random_float() < self.freq_mask_prob: out = tfio.audio.freq_mask(out, param=self.freq_mask_param)\n        \n        for _ in range(self.num_time_masks):\n            if random_float() < self.time_mask_prob: out = tfio.audio.time_mask(out, param=self.time_mask_param)\n        return out\n    \n    @tf.function\n    def call(self, batch_spectrogram):\n        batch_masked_spectrogram = tf.map_fn(self.time_frequency_masking_tf, batch_spectrogram)\n        return tf.convert_to_tensor(batch_masked_spectrogram)\n\n    def get_config(self):\n        config = super().get_config()\n        config.update({\n            'freq_mask_param': self.freq_mask_param,\n            'time_mask_param': self.time_mask_param,\n            'num_freq_masks' : self.num_freq_masks,\n            'num_time_masks' : self.num_time_masks,\n            'freq_mask_prob' : self.freq_mask_prob,\n            'time_mask_prob' : self.time_mask_prob,\n        })\n        return config\n\n    def __repr__(self):\n        return f\"{self.__class__.__name__}(F={self.freq_mask_param}, T={self.time_mask_param})\"\n","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(df_pre.iloc[0]['filepath'], df_pre.iloc[0]['filepath'][-3:] == \"ogg\"),(df_pre.iloc[1]['filepath'], df_pre.iloc[1]['filepath'][-3:] == \"ogg\")","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"audio_decoder_fn = audio_decoder(with_labels=False)\n\naudio1 = audio_decoder_fn((df_pre.iloc[0]['filepath'], df_pre.iloc[0]['filepath'][-3:] == \"ogg\"))\nspec = get_spectrogram(audio1.numpy())\nspec_tensor1 = tf.convert_to_tensor(spec)\n\n\naudio2 = audio_decoder_fn((df_pre.iloc[1]['filepath'], df_pre.iloc[1]['filepath'][-3:] == \"ogg\"))\nspec = get_spectrogram(audio2.numpy())\nspec_tensor2 = tf.convert_to_tensor(spec)\n\nbatch_spec_tensor = tf.stack([spec_tensor1, spec_tensor2])\nbatch_spec_tensor.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"masked_batch_spec_tensor = TimeFrequencyMasking().call(batch_spec_tensor)\nmasked_batch_spec_tensor.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(2, 1, sharex=True, figsize=(12, 5))\n\nlid.specshow(batch_spec_tensor[0].numpy(), \n             n_fft=CFG.nfft, \n             hop_length=CFG.hop_length, \n             sr=CFG.sample_rate,\n             x_axis='time',\n             y_axis='mel',\n             cmap='coolwarm',\n              ax=ax[0])\n\n\nlid.specshow(masked_batch_spec_tensor[0].numpy(), \n             n_fft=CFG.nfft, \n             hop_length=CFG.hop_length, \n             sr=CFG.sample_rate,\n             x_axis='time',\n             y_axis='mel',\n             cmap='coolwarm',\n              ax=ax[1])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fig, ax = plt.subplots(2, 1, sharex=True, figsize=(12, 5))\n\nlid.specshow(batch_spec_tensor[1].numpy(), \n             n_fft=CFG.nfft, \n             hop_length=CFG.hop_length, \n             sr=CFG.sample_rate,\n             x_axis='time',\n             y_axis='mel',\n             cmap='coolwarm',\n              ax=ax[0])\n\n\nlid.specshow(masked_batch_spec_tensor[1].numpy(), \n             n_fft=CFG.nfft, \n             hop_length=CFG.hop_length, \n             sr=CFG.sample_rate,\n             x_axis='time',\n             y_axis='mel',\n             cmap='coolwarm',\n              ax=ax[1])\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"norm_layer = tfe.layers.ZScoreMinMax()\nnormalized_batch_tensor = norm_layer(masked_batch_spec_tensor)\n\nplt.figure(figsize=(8,3))\nplt.hist(masked_batch_spec_tensor.numpy().ravel(), alpha=0.8, color=cmap(0.1))\nplt.hist(normalized_batch_tensor.numpy().ravel(), alpha=0.8, color=cmap(0.9))\nplt.legend([\"w/o normalize\", \"w/ normalize\"])\nplt.semilogx()\nplt.title(\"Effect of Normalization\")\nplt.xlabel(\"Pixel Value\")\nplt.ylabel(\"Count\")\nplt.show()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class TensorToImg(tf.keras.layers.Layer):\n    \n    def __init__(self, out_channels = 3):\n        super(TensorToImg, self).__init__()\n        self.out_channels = out_channels\n\n    @tf.function\n    def call(self, input):\n        specs = input[..., tf.newaxis]\n        if self.out_channels > 1:\n            multiples = tf.concat(\n                [\n                    tf.ones(tf.rank(specs) - 1, dtype=tf.int32),\n                    tf.constant([self.out_channels], dtype=tf.int32),\n                ],\n                axis=0,\n            )\n            specs = tf.tile(specs, multiples)\n        return specs\n\n\n    def get_config(self):\n        config = super().get_config()\n        config.update({\n            'out_channels': self.out_channels,\n        })\n        return config\n\n    def __repr__(self):\n        return f\"{self.__class__.__name__}(Channels={self.out_channels})\"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"batch_chan = TensorToImg().call(normalized_batch_tensor)\nbatch_chan.shape","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import cv2","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"resize_batch = tf.image.resize(batch_chan, [380, 380])\nplt.imshow(cv2.cvtColor(resize_batch[1].numpy(), cv2.COLOR_BGR2RGB))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"E4_imgsize = [380, 380]","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class ImageReshape(tf.keras.layers.Layer):\n    def __init__(self, height=E4_imgsize[0], width=E4_imgsize[1]):\n        super(ImageReshape, self).__init__()\n        self.height = height\n        self.width = width\n        \n    @tf.function\n    def call(self, input):\n        input = tf.image.resize(input, [self.height, self.width])\n        return input\n    \n    def get_config(self):\n        config = super().get_config()\n        config.update({\n            'height': self.height,\n            'width': self.width\n        })\n        return config\n\n    def __repr__(self):\n        return f\"{self.__class__.__name__}(Height={self.height})(Width={self.width})\"\n        ","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.applications import EfficientNetB4","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def build_model(CFG, model_name=None, num_classes=264, compile_model=True):\n    \"\"\"\n    Builds and returns a model based on the specified configuration.\n    \"\"\"\n    # Create an input layer for the model\n    inp = tf.keras.layers.Input(shape=(CFG.audio_len, ))\n    # Spectrogram\n    out = tfe.layers.MelSpectrogram(n_mels=CFG.img_size[0],\n                                    n_fft=CFG.nfft,\n                                    hop_length=CFG.hop_length, \n                                    sr=CFG.sample_rate,\n                                    ref=1.0,\n                                    out_channels=None)(inp)\n    # Normalize\n    out = tfe.layers.ZScoreMinMax()(out)\n    # TimeFreqMask\n    out = TimeFrequencyMasking()(out)\n    out = TensorToImg()(out)\n    out = ImageReshape(E4_imgsize[0], E4_imgsize[1])(out)\n    base = EfficientNetB4(include_top=False, input_tensor=out, weights=\"imagenet\")\n#     base = getattr(efn, model_name)(input_shape=(None, None, 3),\n#                                             include_top=False,\n#                                             weights=CFG.pretrain,\n#                                            fsr=CFG.fsr)\n#     for layer in base.layers[:13]:\n#         layer.trainable = False\n\n#     out = base(out)\n    out = tf.keras.layers.GlobalAveragePooling2D()(base.layers[20].output)\n    out = tf.keras.layers.Dense(num_classes, activation='softmax')(out)\n    model = tf.keras.models.Model(inputs=inp, outputs=out)\n    \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, loss=loss, metrics=metrics)\n    return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = build_model(CFG, model_name=CFG.model_name)\nmodel.summary()","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"strategy, CFG.device, tpu = get_device()\nCFG.replicas = strategy.num_replicas_in_sync\nCFG.replicas, CFG.device","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"audios = tf.random.uniform((2, CFG.audio_len))\nwith strategy.scope():\n    out = model(audios, training=False)\nprint(out.shape)","metadata":{"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":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"_=get_lr_callback(CFG.batch_size*CFG.replicas, plot=True)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CFG.debug = False","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Configurations\nnum_classes = CFG.num_classes2\ndf = df_pre.copy()\nfold = 1\n\n# Compute batch size and number of samples to drop\ninfer_bs = (CFG.batch_size*CFG.infer_bs)\ndrop_remainder = CFG.drop_remainder\n\n# Split dataset with cv filter\nif CFG.cv_filter:\n    df = filter_data(df, thr=5)\n    train_df = df.query(\"fold!=@fold | ~cv\").reset_index(drop=True)\n    valid_df = df.query(\"fold==@fold & cv\").reset_index(drop=True)\nelse:\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\ntrain_df = upsample_data(train_df, thr=50)\ntrain_df = downsample_data(train_df, thr=500)\n\nprint(train_df.shape)\n# Get file paths and labels\ntrain_paths = train_df.filepath.values; train_labels = train_df.target.values\nvalid_paths = valid_df.filepath.values; valid_labels = valid_df.target.values\n\n# Shuffle the file paths and labels\nindex = np.arange(len(train_paths))\nnp.random.shuffle(index)\ntrain_paths  = train_paths[index]\ntrain_labels = train_labels[index]\nprint(\"2\", train_paths.shape)\n\n# For debugging\nif 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# Ogg or Mp3\ntrain_ftype = list(map(lambda x: '.ogg' in x, train_paths))\nvalid_ftype = list(map(lambda x: '.ogg' in x, valid_paths))\n\n# Compute the number of training and validation samples\nnum_train = len(train_paths); num_valid = len(valid_paths)\nprint(\"3\", num_train)\n# Build the training and validation datasets\ncache=False\ntrain_ds = build_dataset(train_paths, train_ftype, train_labels, \n                         batch_size=CFG.batch_size*CFG.replicas, cache=cache, shuffle=True, repeat=True,\n                        drop_remainder=drop_remainder, num_classes=num_classes)\nvalid_ds = build_dataset(valid_paths, valid_ftype, valid_labels,\n                         batch_size=CFG.batch_size*CFG.replicas, cache=True, shuffle=False,\n                         augment=False, repeat=False, drop_remainder=drop_remainder,\n                         take_first=True, num_classes=num_classes)\n\n# Print information about the fold and training\nprint('#'*25); print('#### Pre-Training')\nprint('#### 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))\nprint('#### Num Train: {:,} | Num Valid: {:,}'.format(len(train_paths), len(valid_paths)))\n\n# Clear the session and build the model\nK.clear_session()\nwith strategy.scope():\n    model = build_model(CFG, model_name=CFG.model_name, num_classes=num_classes)\n\nprint('#'*25) \n\n# Checkpoint Callback\nckpt_cb = tf.keras.callbacks.ModelCheckpoint(\n    'birdclef_pretrained_ckpt.keras', monitor='val_auc', verbose=0, save_best_only=True,\n    save_weights_only=False, mode='max', save_freq='epoch')\n# LR Scheduler Callback\nlr_cb = get_lr_callback(CFG.batch_size*CFG.replicas)\ncallbacks = [ckpt_cb, lr_cb]\n\n\n","metadata":{"execution":{"iopub.status.idle":"2024-05-04T07:58:01.856631Z","shell.execute_reply.started":"2024-05-04T07:57:46.713668Z","shell.execute_reply":"2024-05-04T07:58:01.855708Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df2 = train_df.sample(40000)\n\nds = build_dataset(train_df2.filepath.tolist(),\n                   train_df2.filepath.str.contains('.ogg').tolist(),\n                   train_df2.target.tolist(), \n                   num_classes=CFG.num_classes2,\n                   augment=True, cache=True)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T07:59:19.157225Z","iopub.execute_input":"2024-05-04T07:59:19.157717Z","iopub.status.idle":"2024-05-04T07:59:19.870556Z","shell.execute_reply.started":"2024-05-04T07:59:19.157683Z","shell.execute_reply":"2024-05-04T07:59:19.869161Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:03:08.055901Z","iopub.execute_input":"2024-05-04T08:03:08.056559Z","iopub.status.idle":"2024-05-04T08:05:46.165865Z","shell.execute_reply.started":"2024-05-04T08:03:08.056500Z","shell.execute_reply":"2024-05-04T08:05:46.163916Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_paths.shape, train_df.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:50.923806Z","iopub.execute_input":"2024-05-04T08:06:50.924239Z","iopub.status.idle":"2024-05-04T08:06:50.931574Z","shell.execute_reply.started":"2024-05-04T08:06:50.924210Z","shell.execute_reply":"2024-05-04T08:06:50.930570Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CFG.debug","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:51.091383Z","iopub.execute_input":"2024-05-04T08:06:51.091811Z","iopub.status.idle":"2024-05-04T08:06:51.099134Z","shell.execute_reply.started":"2024-05-04T08:06:51.091778Z","shell.execute_reply":"2024-05-04T08:06:51.097682Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df.filepath.values.shape","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:51.251638Z","iopub.execute_input":"2024-05-04T08:06:51.252061Z","iopub.status.idle":"2024-05-04T08:06:51.259587Z","shell.execute_reply.started":"2024-05-04T08:06:51.252030Z","shell.execute_reply":"2024-05-04T08:06:51.258204Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_paths)/CFG.batch_size//CFG.replicas","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:51.536925Z","iopub.execute_input":"2024-05-04T08:06:51.537350Z","iopub.status.idle":"2024-05-04T08:06:51.544484Z","shell.execute_reply.started":"2024-05-04T08:06:51.537303Z","shell.execute_reply":"2024-05-04T08:06:51.543145Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(train_paths)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:51.905232Z","iopub.execute_input":"2024-05-04T08:06:51.905942Z","iopub.status.idle":"2024-05-04T08:06:51.911630Z","shell.execute_reply.started":"2024-05-04T08:06:51.905903Z","shell.execute_reply":"2024-05-04T08:06:51.910742Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"CFG.batch_size, len(train_paths)","metadata":{"execution":{"iopub.status.busy":"2024-05-04T08:06:52.622561Z","iopub.execute_input":"2024-05-04T08:06:52.623069Z","iopub.status.idle":"2024-05-04T08:06:52.632076Z","shell.execute_reply.started":"2024-05-04T08:06:52.623014Z","shell.execute_reply":"2024-05-04T08:06:52.630495Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Show training plot\n# Training\nCFG.debug = False\nhistory = model.fit(\n    train_ds, \n    epochs=2 if CFG.debug else CFG.epochs, \n    callbacks=callbacks, \n    steps_per_epoch=int(len(train_paths)/CFG.batch_size//CFG.replicas),\n    validation_data=valid_ds, \n    verbose=1,\n)\n\nplot_history(history)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}