{"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":"gpu","dataSources":[{"sourceId":70203,"databundleVersionId":8068726,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# import librosa\n# import os\n# import numpy as np\n# import matplotlib.pyplot as plt\n# from PIL import Image\n# from pkg_resources import parse_version\n# import gc\n\n# # Check PIL version for ANTIALIAS method\n# if parse_version(Image.__version__) >= parse_version('10.0.0'):\n#     antialias_method = Image.LANCZOS\n# else:\n#     antialias_method = Image.ANTIALIAS\n\n# base_folder = '/kaggle/input/birdclef-2024/train_audio'\n# output_folder = '/kaggle/working/'\n\n# c = 0\n# folders_to_parse = 15\n\n# # Create the main directory for new train images if it does not exist\n# if not os.path.exists(output_folder):\n#     os.makedirs(output_folder)\n\n# for dir_name in os.listdir(base_folder):\n#     print(f\"Processing directory: {dir_name}\")\n#     dir_path = os.path.join(base_folder, dir_name)\n#     output_dir_path = os.path.join(output_folder, dir_name)\n    \n#     # Create a sub-directory in train_images_v1 for each directory in train_audio\n#     if not os.path.exists(output_dir_path):\n#         os.makedirs(output_dir_path)\n    \n#     for file_name in os.listdir(dir_path):\n#         file_path = os.path.join(dir_path, file_name)\n        \n#         # Load audio file\n#         audio, sr = librosa.load(file_path)\n#         ## Get first 5 seconds of the audio\n#         audio = audio[:sr*5]\n#         n_fft = 2048  # Length of the FFT window\n#         hop_length = 512  # Number of samples between successive frames\n#         n_mels = 128  # Number of Mel bands\n#         fmin = 1000  # Min frequency (Hz)\n#         fmax = 9000  # Max frequency (Hz)\n\n#         # Convert to Mel Spectrogram\n#         S = librosa.feature.melspectrogram(y=audio, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels, fmin=fmin, fmax=fmax)\n#         ms = librosa.feature.melspectrogram(y=audio, sr=sr)\n#         log_ms = librosa.power_to_db(ms, ref=np.max)\n        \n#         # Normalize log_ms to be between 0 and 1\n#         log_ms_normalized = (log_ms - log_ms.min()) / (log_ms.max() - log_ms.min())\n        \n#         # Use librosa to plot the Mel Spectrogram directly\n#         plt.figure(figsize=(10, 4))\n#         librosa.display.specshow(log_ms_normalized, sr=sr, x_axis='time', y_axis='mel')\n#         plt.axis('off')  # Don't display axes (or white edges)\n        \n#         image_name = f\"{file_name.replace('.ogg', '')}.png\"\n#         path_to_save = os.path.join(output_dir_path, image_name)\n#         plt.savefig(path_to_save, bbox_inches='tight', pad_inches=0)\n#         plt.close()  # Close the plot to free up memory\n        \n#         # Clear variables to free up memory\n#         del audio, S, ms, log_ms, log_ms_normalized\n#         gc.collect()  # Run garbage collector\n\n# print(\"Processing complete.\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import librosa\nimport os\nimport numpy as np\nimport cv2\nfrom pkg_resources import parse_version\nimport gc\n\nbase_folder = '/kaggle/input/birdclef-2024/train_audio'\noutput_folder = '/kaggle/working/'\n\n\n\n# Create the main directory for new train images if it does not exist\nif not os.path.exists(output_folder):\n    os.makedirs(output_folder)\n\nfor dir_name in os.listdir(base_folder):\n    print(f\"Processing directory: {dir_name}\")\n    dir_path = os.path.join(base_folder, dir_name)\n    output_dir_path = os.path.join(output_folder, dir_name)\n    \n    # Create a sub-directory in train_images_v1 for each directory in train_audio\n    if not os.path.exists(output_dir_path):\n        os.makedirs(output_dir_path)\n    \n    for file_name in os.listdir(dir_path):\n        file_path = os.path.join(dir_path, file_name)\n        \n        # Load audio file\n        audio, sr = librosa.load(file_path)\n        \n        audio = audio[:sr*5]  # Take a 5-second chunk of audio\n        n_fft = 2048  # Length of the FFT window\n        hop_length = 512  # Number of samples between successive frames\n        n_mels = 128  # Number of Mel bands\n        fmin = 1000  # Min frequency (Hz)\n        fmax = 9000  # Max frequency (Hz)\n\n        # Convert to Mel Spectrogram\n        S = librosa.feature.melspectrogram(y=audio, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels, fmin=fmin, fmax=fmax)\n        ms = librosa.feature.melspectrogram(y=audio, sr=sr)\n        log_ms = librosa.power_to_db(ms, ref=np.max)\n        \n        # Normalize log_ms to be between 0 and 1\n        log_ms_normalized = (log_ms - log_ms.min()) / (log_ms.max() - log_ms.min())\n        \n        # Convert log_ms_normalized to 8-bit unsigned integer format\n        log_ms_normalized_uint8 = (log_ms_normalized * 255).astype(np.uint8)\n        \n        # Convert single-channel image to three-channel RGB image\n        log_ms_rgb = cv2.cvtColor(log_ms_normalized_uint8, cv2.COLOR_GRAY2RGB)\n        \n        # Save the image using cv2\n        image_name = f\"{file_name.replace('.ogg', '')}.png\"\n        path_to_save = os.path.join(output_dir_path, image_name)\n        cv2.imwrite(path_to_save, log_ms_rgb)\n        \n        # Clear variables to free up memory\n        del audio, S, ms, log_ms, log_ms_normalized, log_ms_normalized_uint8, log_ms_rgb\n        gc.collect()  # Run garbage collector\n\nprint(\"Processing complete.\")\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport keras\nimport matplotlib.pyplot as plt\n\nimport tensorflow as tf\n\nfrom keras import layers\n\n# TF imports related to tf.data preprocessing\nfrom tensorflow import clip_by_value\nfrom tensorflow import data as tf_data\nfrom tensorflow import image as tf_image\nfrom tensorflow import random as tf_random\n\nkeras.utils.set_random_seed(42)\n\n\n\ndirectory = \"/kaggle/working/\"\n\nIMG_SIZE = 224\n# Load the dataset from the directory\ndataset = tf.keras.preprocessing.image_dataset_from_directory(\n    directory,\n    labels ='inferred',\n    label_mode='categorical',\n    image_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=1,\n    shuffle=True,\n    seed=123,\n    validation_split=0.2,\n    color_mode = 'rgb',\n    subset=\"both\",  # Use 'training' or 'validation' as needed\n)\n\n# Get class names\nimport pickle\n\n# Assuming dataset[1].class_names contains the class names\nclass_names = dataset[1].class_names\n\n# Define the path to save the file\nsave_path = '/kaggle/working/class_names.pkl'\n\n# Save the class names to a file using pickle\nwith open(save_path, 'wb') as f:\n    pickle.dump(class_names, f)\n\nprint(f\"Class names saved to {save_path}\")\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"AUTO = tf_data.AUTOTUNE\nBATCH_SIZE = 16\n\ntrain_ds = dataset[0]  ## For training\n# def preprocess_image(image, label):\n#     image = tf_image.convert_image_dtype(image, \"float32\") / 255.0\n#     return image, label\n\nimport tensorflow as tf\n\ndef preprocess_image(image, label):\n    image = tf.image.convert_image_dtype(image, dtype=tf.float16) / 255.0\n    return image, label\n\n\ntrain_ds = (\n    train_ds\n    .batch(BATCH_SIZE)\n    .shuffle(1024)\n    .map(preprocess_image, num_parallel_calls=AUTO)\n)\n\n\n\ntest_ds = dataset[1]\n\n\n\ntest_ds = (\n    test_ds.map(preprocess_image, num_parallel_calls=AUTO)\n    .batch(BATCH_SIZE)\n    .prefetch(AUTO)\n)\n\n\n\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import keras_cv\n\n\nrand_augment = keras_cv.layers.RandAugment(\n    value_range=(0, 1),\n    augmentations_per_image=3,\n    magnitude=0.3,\n    magnitude_stddev=0.2,\n    rate=1.0,\n)\n\n\ndef apply_rand_augment(image,label):\n    image = rand_augment(image)\n    return image,label\n\n\ncut_mix = keras_cv.layers.CutMix()\nmix_up = keras_cv.layers.MixUp()\n\n\n\ndef cut_mix_and_mix_up(image, label):\n    # Convert tuple to dictionary\n    samples_dict = {'images': image, 'labels': label}\n    \n    # Apply CutMix\n    mixed_samples = cut_mix(samples_dict)\n    \n    # Apply MixUp\n    mixed_samples = mix_up(mixed_samples)\n    \n    # Convert dictionary back to tuple\n    return (mixed_samples['images'], mixed_samples['labels'])\n\n\n\n\ndef preprocess(image, label):\n    # Squeeze the unnecessary dimension out\n    image = tf.squeeze(image, axis=[1])\n    label = tf.squeeze(label,axis=[1])# Squeeze out the second dimension which is 1\n    return image, label\n\n# Apply the preprocessing function to training and testing datasets\ntrain_ds = train_ds.map(preprocess)\ntest_ds = test_ds.map(preprocess) # Assu\n\n#train_ds = train_ds.map(apply_rand_augment, num_parallel_calls=tf.data.AUTOTUNE)\n\ntrain_ds_cmu = train_ds.map(cut_mix_and_mix_up, num_parallel_calls=tf.data.AUTOTUNE)\n\ndef convert_to_float16(image, label):\n    image = tf.cast(image, tf.float16)\n    return image, label\n\n# Apply the conversion to the second dataset\ntrain_ds_cmu = train_ds_cmu.map(convert_to_float16)\n\n\ntrain_ds = train_ds.concatenate(train_ds_cmu)\n\ntest_ds = test_ds.map(convert_to_float16)\n\n\ntrain_ds = train_ds.shuffle(100)\n\ntrain_ds = train_ds.take(1500)\n\n\n\n\n\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D, Input\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.applications.mobilenet_v2 import preprocess_input\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nimport keras\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import backend as K\nfrom tensorflow.keras import mixed_precision\n\n# Enable mixed precision\npolicy = mixed_precision.Policy('mixed_float16')\nmixed_precision.set_global_policy(policy)\nK.clear_session()\n\n# Assuming the rest of your code sets up the dataset and model\nbatch_size = 32  # Adjust batch size if needed\nAUTOTUNE = tf.data.AUTOTUNE\n\n# Setup your data pipeline\ntrain_ds = train_ds.cache().prefetch(buffer_size=AUTOTUNE)\ntest_ds = test_ds.cache().prefetch(buffer_size=AUTOTUNE)\n\n# Define the model architecture\ninputs = Input(shape=(224, 224, 3))\nbase_model = MobileNetV2(weights='imagenet', include_top=False, input_tensor=inputs)  # Load pre-trained MobileNetV2\nx = GlobalAveragePooling2D()(base_model.output)\n#x = Dropout(0.2)(x)\nx = Dense(256, activation='relu')(x)\n#x = Dropout(0.2)(x)\noutputs = Dense(182, activation='softmax')(x)\n\n# Make all layers in the base model trainable\nfor layer in base_model.layers:\n    layer.trainable = True\n\n# Create the model\nmodel = Model(inputs=inputs, outputs=outputs)\n\n# Define a learning rate scheduler\nimport math\n\ndef get_lr_callback(batch_size=16, mode='cos', epochs=50, plot=False):\n    lr_start, lr_max, lr_min = 5e-5, 8e-6 * batch_size, 1e-5\n    lr_ramp_ep, lr_sus_ep, lr_decay = 3, 0, 0.75\n\n    def lrfn(epoch):  # Learning rate update function\n        if epoch < lr_ramp_ep:\n            lr = (lr_max - lr_start) / lr_ramp_ep * epoch + lr_start\n        elif epoch < lr_ramp_ep + lr_sus_ep:\n            lr = lr_max\n        elif mode == 'exp':\n            lr = (lr_max - lr_min) * lr_decay**(epoch - lr_ramp_ep - lr_sus_ep) + lr_min\n        elif mode == 'step':\n            lr = lr_max * lr_decay**((epoch - lr_ramp_ep - lr_sus_ep) // 2)\n        elif mode == '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            lr = (lr_max - lr_min) * 0.5 * (1 + math.cos(phase)) + lr_min\n        return lr\n\n    if plot:  # Plot lr curve if plot is True\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('lr')\n        plt.title('LR Scheduler')\n        plt.show()\n\n    return keras.callbacks.LearningRateScheduler(lrfn, verbose=False)  # Create lr callback\n\nlr_cb = get_lr_callback(epochs=50, plot=True)\nmodel.compile(optimizer=Adam(learning_rate=0.001),\n              loss=keras.losses.CategoricalCrossentropy(label_smoothing=0.02),\n              metrics=['accuracy'])\n\n\n# Define callbacks\ncheckpoint = ModelCheckpoint(\n    'best_model.keras',  # The saved directory will be named 'best_model'\n    monitor='val_accuracy',\n    save_best_only=True,\n    save_weights_only=False,\n    mode='max',\n    verbose=1)\n\nckpt_cb = keras.callbacks.ModelCheckpoint(\n    \"best_model.weights.h5\",\n    monitor='val_auc',\n    save_best_only=True,\n    save_weights_only=True,\n    mode='max')\n\n# Train the model\nhistory = model.fit(\n    train_ds,\n    validation_data=test_ds,\n    epochs=50,  # Adjust this according to your needs\n    callbacks=[lr_cb, checkpoint]\n)\n\nprint(\"Model trained and saved successfully.\")\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\nimport glob\nimport librosa\nimport numpy as np\nimport cv2\nimport tensorflow as tf\nimport pandas as pd\nimport pickle\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense, Dropout, GlobalAveragePooling2D, Input\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.models import Model\n\n# Define the model (assumed structure based on typical CNN for spectrograms)\ndef create_model(input_shape, num_classes):\n    inputs = Input(shape=(224, 224, 3))\n    base_model = MobileNetV2(weights='imagenet', include_top=False, input_tensor=inputs)  # Load pre-trained MobileNetV2\n    x = GlobalAveragePooling2D()(base_model.output)\n    x = Dense(256, activation='relu')(x)\n    outputs = Dense(num_classes, activation='softmax')(x)\n    model = Model(inputs=inputs, outputs=outputs)\n    return model\n\n# Load the model weights\ninput_shape = (224, 224, 3)\nnum_classes = 182\nmodel = create_model(input_shape, num_classes)\nmodel.load_weights('/kaggle/working/best_model.keras')\n\n# Function to preprocess audio to spectrogram using librosa and cv2\ndef preprocess_audio_to_spectrogram(audio_path, img_size=224):\n    audio, sr = librosa.load(audio_path)\n    audio = audio[:sr*5]  # Take a 5-second chunk of audio\n    n_fft = 2048  # Length of the FFT window\n    hop_length = 512  # Number of samples between successive frames\n    n_mels = 128  # Number of Mel bands\n    fmin = 1000  # Min frequency (Hz)\n    fmax = 9000  # Max frequency (Hz)\n\n    # Convert to Mel Spectrogram\n    ms = librosa.feature.melspectrogram(y=audio, sr=sr, n_fft=n_fft, hop_length=hop_length, n_mels=n_mels, fmin=fmin, fmax=fmax)\n    log_ms = librosa.power_to_db(ms, ref=np.max)\n    \n    # Normalize log_ms to be between 0 and 1\n    log_ms_normalized = (log_ms - log_ms.min()) / (log_ms.max() - log_ms.min())\n    \n    # Convert log_ms_normalized to 8-bit unsigned integer format\n    log_ms_normalized_uint8 = (log_ms_normalized * 255).astype(np.uint8)\n    \n    # Convert single-channel image to three-channel RGB image\n    log_ms_rgb = cv2.cvtColor(log_ms_normalized_uint8, cv2.COLOR_GRAY2RGB)\n    \n    # Resize to the target image size for the model\n    log_ms_rgb_resized = cv2.resize(log_ms_rgb, (img_size, img_size))\n    \n    # Normalize the image array\n    log_ms_rgb_resized = log_ms_rgb_resized / 255.0\n    \n    return log_ms_rgb_resized\n\n# Load class names from the pkl file\nwith open('/kaggle/working/class_names.pkl', 'rb') as f:\n    class_names = pickle.load(f)\n\n# Step 1: Read .ogg files from the test folder\ntest_folder = '/kaggle/input/birdclef-2024/unlabeled_soundscapes'\nogg_files = glob.glob(os.path.join(test_folder, '*.ogg'))\n\n# Step 2: Use the trained model to make predictions directly\npredictions = {}\nfor ogg_file in ogg_files:\n    spectrogram = preprocess_audio_to_spectrogram(ogg_file)\n    spectrogram = np.expand_dims(spectrogram, axis=0)  # Create batch axis\n    prediction = model.predict(spectrogram)\n    predictions[os.path.basename(ogg_file)] = prediction\n\n# Step 3: Create a CSV file with predictions\noutput_file = '/kaggle/working/submission.csv'\ncolumns = ['row_id'] + class_names\ndata = []\n\nfor filename, prediction in predictions.items():\n    row_id = f\"soundscape_{filename.replace('.ogg', '')}\"\n    row = [row_id] + prediction.tolist()[0]\n    data.append(row)\n\ndf = pd.DataFrame(data, columns=columns)\ndf.to_csv(output_file, index=False)\n\nprint(f'Predictions saved to {output_file}')\n","metadata":{},"execution_count":null,"outputs":[]}]}