{"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":70203,"databundleVersionId":8068726,"sourceType":"competition"},{"sourceId":8033468,"sourceType":"datasetVersion","datasetId":4735360}],"dockerImageVersionId":30683,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Dense, Dropout, GlobalAveragePooling2D\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.applications import MobileNetV2\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nfrom sklearn.utils import class_weight\nimport numpy as np\nfrom collections import defaultdict\nimport os\nimport pandas as pd\n\n\ndef find_duplicate_filenames(root_dir):\n    files_dict = defaultdict(list)\n    for subdir, dirs, files in os.walk(root_dir):\n        for file in files:\n            file_path = os.path.join(subdir, file)\n            files_dict[file].append(file_path)\n    duplicates = {file: paths for file, paths in files_dict.items() if len(paths) > 1}\n    return duplicates\n\n# Path to the directory with training images\nroot_directory = '/kaggle/input/birdclef-2024-mel-spectrograms/train_images/'\n\n# Identifying duplicates\nduplicates_by_name = find_duplicate_filenames(root_directory)\n\n# Create a set of paths to exclude\nexclude_paths = {path for paths in duplicates_by_name.values() for path in paths}\n\n# Collect all valid image paths and their labels\nvalid_files = []\nlabels = []\nfor subdir, dirs, files in os.walk(root_directory):\n    for file in files:\n        file_path = os.path.join(subdir, file)\n        if file_path not in exclude_paths:\n            valid_files.append(file_path)\n            labels.append(subdir.split('/')[-1])  # assuming folder names are class labels\n\n# Create DataFrame for the image paths and labels\ndata = pd.DataFrame({'filename': valid_files, 'class': labels})\n\ndata = data[data['filename'].str.contains('.png')]\n\n\n# # Setup the ImageDataGenerator for training\n# train_datagen = ImageDataGenerator(\n#     preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input,\n#     validation_split=0.2  # Using 20% of the data for validation\n# )\n\n# # Setup train and validation generators\n# train_generator = train_datagen.flow_from_directory(\n#     'train_images/',  # this is the target directory\n#     target_size=(224, 224),  # all images will be resized to 224x224\n#     batch_size=32,\n#     class_mode='categorical',\n#     color_mode = 'rgb',  # this means that labels are one-hot encoded\n#     subset='training'  # set as training data\n# )\n\n# validation_generator = train_datagen.flow_from_directory(\n#     'train_images/',  # same directory as training data\n#     target_size=(224, 224),\n#     batch_size=32,\n#     class_mode='categorical',\n#     color_mode = 'rgb',\n#     subset='validation'  # set as validation data\n# )\n\ntrain_data, valid_data = train_test_split(\n    data,\n    test_size = 0.2,\n    random_state = 42,\n    stratify = data['class']\n    \n)\n\nprint(len(train_data['class'].unique()))\nprint(len(valid_data['class'].unique()))\n\n# ImageDataGenerator with preprocessing\ntrain_datagen = ImageDataGenerator(\n    preprocessing_function=tf.keras.applications.mobilenet_v2.preprocess_input,\n    #rescale=1./255.,\n    width_shift_range=0.5,\n    #height_shift_range=0.2,\n    horizontal_flip=False,\n    vertical_flip=False\n)\n\n# Setup train and validation generators\ntrain_generator = train_datagen.flow_from_dataframe(\n    dataframe=train_data,\n    x_col='filename',\n    y_col='class',\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='categorical',\n    color_mode='rgb'\n)\n\nvalidation_generator = train_datagen.flow_from_dataframe(\n    dataframe=valid_data,\n    x_col='filename',\n    y_col='class',\n    target_size=(224, 224),\n    batch_size=32,\n    class_mode='categorical',\n    color_mode='rgb'\n)\n\n\n\n# Build the model\nbase_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(224, 224, 3))  # Load pre-trained MobileNetV2\n\nx = base_model.output\nx = GlobalAveragePooling2D()(x)\nx = Dense(4096, activation='relu')(x)\n\nx = Dropout(0.5)(x)\n\nx = Dense(2048,activation='relu')(x)\nx = Dropout(0.5)(x)\n\nx = Dense(1024,activation='relu')(x)\nx = Dropout(0.5)(x)\npredictions = Dense(182, activation='softmax')(x)  # assuming there are 182 classes\n\nmodel = Model(inputs=base_model.input, outputs=predictions)\nfor layers in base_model.layers[:-1]:\n    layers.trainable = False\n\nclass_weights = class_weight.compute_class_weight(\n                                        class_weight = \"balanced\",\n                                        classes = np.unique(train_generator.classes),\n                                        y = train_generator.classes                                                  \n                                    )\nclass_weights = dict(zip(np.unique(train_generator.classes), class_weights))\n\n\n# Compile the model with these settings\nmodel.compile(optimizer=Adam(learning_rate=0.0003),\n                loss='categorical_crossentropy',\n                metrics=['accuracy'])\n\n\n\n# Define the checkpoint to save the best model based on validation accuracy\ncheckpoint = ModelCheckpoint(\n    'best_model.keras',  # Save with iteration number\n    monitor='accuracy',\n    save_best_only=True,\n    mode='max',\n    verbose=1\n)\n\n# Train the model\nhistory = model.fit(\n    train_generator,\n    epochs=150,  # Set the number of epochs for training\n    validation_data=validation_generator,\n    callbacks=[checkpoint],\n    class_weight = class_weights  # Include the checkpoint in the callbacks\n)\n\n# Optional: Plotting the training results for each iteration\nplt.figure(figsize=(10, 5))\nplt.plot(history.history['accuracy'], label='Train Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend()\nplt.show()\n\nplt.figure(figsize=(10, 5))\nplt.plot(history.history['loss'], label='Train Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend()\nplt.show()\n\n# Saving the final model configuration\n#model.save('final_mobile_net_v2_model.h5')\nprint(\"Model training completed and final model saved.\")\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-04-17T04:37:15.276320Z","iopub.execute_input":"2024-04-17T04:37:15.277421Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}