{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":175156349,"sourceType":"kernelVersion"}],"dockerImageVersionId":30684,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"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)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\n#for dirname, _, filenames in os.walk('/kaggle/input'):\n#    for filename in filenames:\n#        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session\n\nfrom keras.models import Model,Sequential, load_model\nfrom keras.layers import Concatenate,Input, InputLayer, Dense, Dropout, Conv1D, Conv2D, MaxPooling1D, MaxPooling2D, Flatten, BatchNormalization\nfrom keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom keras.optimizers import Adam\nfrom keras.regularizers import l2\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-23T14:52:22.237825Z","iopub.execute_input":"2024-04-23T14:52:22.238400Z","iopub.status.idle":"2024-04-23T14:52:33.544515Z","shell.execute_reply.started":"2024-04-23T14:52:22.238371Z","shell.execute_reply":"2024-04-23T14:52:33.543701Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Sample Submission","metadata":{}},{"cell_type":"code","source":"#sample_submission = pd.read_csv('/kaggle/input/birdclef-2024/sample_submission.csv')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Saved Spectrograms","metadata":{}},{"cell_type":"code","source":"import pickle\n# Load Spectrogram PNG Bytes\nwith open('/kaggle/input/birdclef-2024-preprocess/X.pkl', 'rb') as file:\n    X = pickle.load(file)\n    \n# Load Labels\nwith open('/kaggle/input/birdclef-2024-preprocess/y.pkl', 'rb') as file:\n    y = pickle.load(file)","metadata":{"execution":{"iopub.status.busy":"2024-04-23T14:52:44.330056Z","iopub.execute_input":"2024-04-23T14:52:44.331320Z","iopub.status.idle":"2024-04-23T14:53:14.430100Z","shell.execute_reply.started":"2024-04-23T14:52:44.331277Z","shell.execute_reply":"2024-04-23T14:53:14.429004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Set Split for Train/Validation","metadata":{}},{"cell_type":"code","source":"j = 0\nfor i in X.keys():\n    print(i)\n    j += 1\n    if j > 10: break","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import random\n\n# create partition to hold train/test keys\n\n# set training set size, randomly sample\ntrain_size = round(0.75 * len(X))\ntrain_key = random.sample(sorted(X), train_size)\nprint(f'Training set size: {train_size}')\n\n# creating test set\ntest_size = len(X)-train_size\ntest_key = sorted(list(set(X).difference(train_key)))\n\nprint(f'Test set size: {test_size}')\n\n# create dictionary for keys\npartition = {\n        'train':  train_key,\n        'validation':  test_key}\n\nspecs = X","metadata":{"execution":{"iopub.status.busy":"2024-04-23T14:53:31.667685Z","iopub.execute_input":"2024-04-23T14:53:31.668327Z","iopub.status.idle":"2024-04-23T14:53:31.763236Z","shell.execute_reply.started":"2024-04-23T14:53:31.668298Z","shell.execute_reply":"2024-04-23T14:53:31.762265Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"unique_vals = sorted(list(set(value for value in y.values())))\n\n# Maps a class to corresponding integer label\nCLASS2LABEL = dict(zip(unique_vals, np.arange(len(unique_vals))))\n# Label to class mapping\nLABEL2CLASS = dict([(v,k) for k, v in CLASS2LABEL.items()])\n\nfor key in y:\n    y[key] = CLASS2LABEL[y[key]]","metadata":{"execution":{"iopub.status.busy":"2024-04-23T14:53:35.369399Z","iopub.execute_input":"2024-04-23T14:53:35.370199Z","iopub.status.idle":"2024-04-23T14:53:35.406437Z","shell.execute_reply.started":"2024-04-23T14:53:35.370169Z","shell.execute_reply":"2024-04-23T14:53:35.405567Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Keras DataGenerator","metadata":{}},{"cell_type":"code","source":"import keras\nimport imageio.v3 as imageio\n\nclass DataGenerator(keras.utils.Sequence):\n    'Generates data for Keras'\n    def __init__(self, list_IDs, labels, batch_size=32, dim=(128,626,1), n_channels=1,\n                 n_classes=182, shuffle=True):\n        'Initialization'\n        self.dim = dim\n        self.batch_size = batch_size\n        self.labels = labels\n        self.list_IDs = list_IDs\n        self.n_channels = n_channels\n        self.n_classes = n_classes\n        self.shuffle = shuffle\n        self.on_epoch_end()        \n        self.duration = 5000\n        self.sample_rate = 32000                \n        \n    def __len__(self):\n        'Denotes the number of batches per epoch'\n        return int(np.floor(len(self.list_IDs) / self.batch_size))\n\n    def __getitem__(self, index):\n        'Generate one batch of data'\n        # Generate indexes of the batch\n        indexes = self.indexes[index*self.batch_size:(index+1)*self.batch_size]\n\n        # Find list of IDs\n        list_IDs_temp = [self.list_IDs[k] for k in indexes]\n\n        # Generate data\n        X, y = self.__data_generation(list_IDs_temp)\n        \n        return X, y\n\n    def on_epoch_end(self):\n        'Updates indexes after each epoch'\n        self.indexes = np.arange(len(self.list_IDs))\n        if self.shuffle == True:\n            np.random.shuffle(self.indexes)\n\n    def __data_generation(self, list_IDs_temp):\n        'Generates data containing batch_size samples' # X : (n_samples, *dim, n_channels)\n        # Initialization\n        X = np.empty((self.batch_size, *self.dim), dtype=float)\n        y = np.empty((self.batch_size), dtype=int)\n\n        # Generate data\n        for i, ID in enumerate(list_IDs_temp):\n            # Store sample\n            #aud = AudioUtil.open('/kaggle/input/birdclef-2024/train_audio/' + ID)\n            #reaud = AudioUtil.resample(aud, self.sample_rate)\n            #dur_aud = AudioUtil.pad_trunc(reaud, self.duration)\n            #sgram = AudioUtil.spectro_gram(dur_aud, n_mels=128, n_fft=1024, hop_len=None)            \n            \n            # normalize spectrogram\n            #norm_sgram = AudioUtil.normalize_sgram(sgram)\n            \n            X[i,] = np.reshape(imageio.imread(specs[ID])/255,(128,626,1))\n\n            # Store class\n            y[i] = self.labels[ID]\n            \n        return X, keras.utils.to_categorical(y, num_classes=self.n_classes)","metadata":{"execution":{"iopub.status.busy":"2024-04-23T14:53:37.357863Z","iopub.execute_input":"2024-04-23T14:53:37.358186Z","iopub.status.idle":"2024-04-23T14:53:37.427953Z","shell.execute_reply.started":"2024-04-23T14:53:37.358163Z","shell.execute_reply":"2024-04-23T14:53:37.427169Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nparams = {'batch_size': 2,          \n          'shuffle': True}\n\ntraining_generator = DataGenerator(partition['train'], y, **params)\nj=0\nfor i in training_generator:\n    #print(i[0])\n    j+=1\n    if j > 1: break","metadata":{"execution":{"iopub.status.busy":"2024-04-23T14:53:46.725812Z","iopub.execute_input":"2024-04-23T14:53:46.726444Z","iopub.status.idle":"2024-04-23T14:53:46.756584Z","shell.execute_reply.started":"2024-04-23T14:53:46.726416Z","shell.execute_reply":"2024-04-23T14:53:46.755587Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#import tensorflow as tf\n#import keras\n\n#def shuffle_generator(input_data, input_label, seed, sample_rate=32000, duration=5000):\n#    idx = np.arange(len(input_data))\n#    np.random.default_rng(seed).shuffle(idx)\n#    for i in idx:\n        \n        # process the audio file\n#        path = input_data[i].decode('utf-8')\n#        aud = AudioUtil.open('/kaggle/input/birdclef-2024/train_audio/' + path)\n#        reaud = AudioUtil.resample(aud, sample_rate)\n#        dur_aud = AudioUtil.pad_trunc(reaud, duration)\n#        sgram = AudioUtil.spectro_gram(dur_aud, n_mels=128, n_fft=1024, hop_len=None)            \n            \n        # normalize spectrogram\n#        norm_sgram = AudioUtil.normalize_sgram(sgram)\n        \n#        yield norm_sgram, keras.utils.to_categorical(input_label[i], num_classes=182)\n\n#dataset = tf.data.Dataset.from_generator(\n#    shuffle_generator,\n#    args=[list(X_train), list(y_train), 42],\n#    output_signature=(\n#        tf.TensorSpec(shape=(128,626,1), dtype=tf.float16),\n#        tf.TensorSpec(shape=(182), dtype=tf.uint8)))\n\n#val_dataset = tf.data.Dataset.from_generator(\n#    shuffle_generator,\n#    args=[list(X_test), list(y_test), 42],\n#    output_signature=(\n#        tf.TensorSpec(shape=(128,626,1), dtype=tf.float16),\n#        tf.TensorSpec(shape=(182), dtype=tf.uint8)))","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Super Simple Model","metadata":{}},{"cell_type":"code","source":"# define baseline model\ndef baseline_model():\n    # create model\n    model = Sequential()\n    model.add(Input(shape=(128, 626, 1),name='Input_Layer'))\n    model.add(Conv2D(256,  kernel_size=(16,16), strides=(2,2), activation='relu', name='Conv_Layer_1'))    \n    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), name='MaxPool_Layer_1'))\n #   model.add(Dropout(0.4))\n    BatchNormalization()\n    model.add(Conv2D(128, kernel_size=(4,4), strides=(1,1), activation='relu', name='Conv_Layer_2')) \n    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), name='MaxPool_Layer_2'))\n#    model.add(Dropout(0.4))\n    BatchNormalization()\n    model.add(Conv2D(64, kernel_size=(2,2), strides=(1,1), activation='relu', name='Conv_Layer_3'))\n    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), name='MaxPool_Layer_3'))\n    model.add(Conv2D(32, kernel_size=(2,2), strides=(1,1), activation='relu', name='Conv_Layer_4'))\n    model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), name='MaxPool_Layer_4'))\n    BatchNormalization()\n    model.add(Flatten())\n    model.add(Dense(256, activation='relu', name = 'Fully_Connected_Layer_1'))\n  #  model.add(Dropout(0.4))\n    model.add(Dense(182, activation='softmax', name='Output_Layer'))\n \n    # compile model\n    model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate=0.025), metrics=['AUC'])\n    \n    return model","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Parameters\nparams = {'batch_size': 64,          \n          'shuffle': True}\n\n# Generators\ntraining_generator = DataGenerator(partition['train'], y, **params)\nvalidation_generator = DataGenerator(partition['validation'], y, **params)\n\nmodel = baseline_model()\n\n# simple early stopping\nes = EarlyStopping(monitor='val_loss', mode='min', verbose=1, patience=10)\n\n# keep best model\nmc = ModelCheckpoint('best_model.keras', monitor='val_loss', mode='min', verbose=1, save_best_only=True)\n\nlr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=10, min_lr=0.0001)\n\nmodel.fit(x=training_generator,\n          validation_data=validation_generator, epochs=20, verbose = 1, callbacks=[es, mc, lr])","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}