{"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":74752,"databundleVersionId":8237627,"sourceType":"competition"}],"dockerImageVersionId":30698,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nimport os\nimport shutil\nimport random\nimport cv2\nimport numpy as np\nfrom PIL import Image\nimport matplotlib.pyplot as plt\nimport pandas as pd\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import Input, Conv2D, MaxPooling2D, Flatten, Dense, GlobalAveragePooling2D, Dropout","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-05-01T07:59:31.073634Z","iopub.execute_input":"2024-05-01T07:59:31.074006Z","iopub.status.idle":"2024-05-01T07:59:43.433609Z","shell.execute_reply.started":"2024-05-01T07:59:31.073976Z","shell.execute_reply":"2024-05-01T07:59:43.432816Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Load Datasets\n! This Notebook is created based on my limited knowledge on machine learning so the way I'm managing datasets, creating and training models might be not the most efficient as I just started learning on this field :3","metadata":{}},{"cell_type":"code","source":"# Read CSV file\ncsv_path = '/kaggle/input/bird-genus-multi-class-image-classification/train.csv'  # Update with your CSV file path\ndf = pd.read_csv(csv_path)\n\n# Path to original image folder\nimage_folder = '/kaggle/input/bird-genus-multi-class-image-classification/images/train'  # Update with your image folder path\n\n# Path to new train folder\nnew_train_folder = '/kaggle/working/train'  # Destination train folder\n\n# Path to new validation folder\nnew_validation_folder = '/kaggle/working/validation'  # Destination validation folder\n\n# Create the new train and validation folders if they don't exist\nif not os.path.exists(new_train_folder):\n    os.makedirs(new_train_folder)\nif not os.path.exists(new_validation_folder):\n    os.makedirs(new_validation_folder)\n\n# Count the number of images in the original train folder\noriginal_image_count = len(os.listdir(image_folder))\n\n# Splitting data into train and validation sets\ntrain_df, validation_df = train_test_split(df, test_size=0.2, random_state=42, stratify=df['genus'])\n\n# Function to copy images to respective folders\ndef copy_images(df, destination_folder):\n    for index, row in df.iterrows():\n        filename = row['filename']\n        genus = row['genus']\n\n        # Create subfolder for each class if it doesn't exist\n        class_folder = os.path.join(destination_folder, genus)\n        if not os.path.exists(class_folder):\n            os.makedirs(class_folder)\n\n        # Copy image to its respective class folder\n        src = os.path.join(image_folder, filename)\n        dst = os.path.join(class_folder, filename)\n        shutil.copy(src, dst)\n\n# Copy images to train folder\ncopy_images(train_df, new_train_folder)\n\n# Copy images to validation folder\ncopy_images(validation_df, new_validation_folder)\n\n# Count the number of images in the new train and validation folders\nnew_train_image_count = sum(len(files) for _, _, files in os.walk(new_train_folder))\nnew_validation_image_count = sum(len(files) for _, _, files in os.walk(new_validation_folder))\n\nprint(\"Number of images in the original train folder:\", original_image_count)\nprint(\"Number of images in the new train folder:\", new_train_image_count)\nprint(\"Number of images in the new validation folder:\", new_validation_image_count)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T07:59:43.435575Z","iopub.execute_input":"2024-05-01T07:59:43.436120Z","iopub.status.idle":"2024-05-01T08:00:06.834308Z","shell.execute_reply.started":"2024-05-01T07:59:43.436094Z","shell.execute_reply":"2024-05-01T08:00:06.833409Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Visualisation ","metadata":{}},{"cell_type":"code","source":"train_folder = '/kaggle/working/train'\ncategories = os.listdir(train_folder)\ntrain_counts = []","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:06.835605Z","iopub.execute_input":"2024-05-01T08:00:06.836026Z","iopub.status.idle":"2024-05-01T08:00:06.840774Z","shell.execute_reply.started":"2024-05-01T08:00:06.835999Z","shell.execute_reply":"2024-05-01T08:00:06.839821Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_folder = '/kaggle/working/train'\nvalidation_folder = '/kaggle/working/validation'\n\ncategories = os.listdir(train_folder)\n\ntrain_counts = []\nvalidation_counts = []\n\nfor category in categories:\n    train_count = len(os.listdir(os.path.join(train_folder, category)))\n    train_counts.append(train_count)\n    validation_count = len(os.listdir(os.path.join(validation_folder, category)))\n    validation_counts.append(validation_count)\n\nplt.figure(figsize=(10, 6))\nplt.bar(categories, train_counts, color='blue', alpha=0.7, label='Train')\nplt.bar(categories, validation_counts, color='orange', alpha=0.7, label='Validation')\nplt.xlabel('Categories')\nplt.ylabel('Number of Images')\nplt.title('Training and Validation Data Distribution')\nplt.xticks(rotation=45, ha='right')\nplt.legend()\nplt.tight_layout()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:06.843424Z","iopub.execute_input":"2024-05-01T08:00:06.843952Z","iopub.status.idle":"2024-05-01T08:00:07.683922Z","shell.execute_reply.started":"2024-05-01T08:00:06.843920Z","shell.execute_reply":"2024-05-01T08:00:07.683049Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_folder = '/kaggle/working/train'\nvalidation_folder = '/kaggle/working/validation'\n\ndef display_images(folder):\n    classes = os.listdir(folder)\n    num_images_per_class = 5\n\n    for class_name in classes:\n        class_folder = os.path.join(folder, class_name)\n        images = os.listdir(class_folder)\n        num_images_to_display = min(num_images_per_class, len(images))\n        fig, axes = plt.subplots(1, num_images_to_display, figsize=(15, 2))\n        fig.suptitle(class_name)\n\n        for i in range(num_images_to_display):\n            image_path = os.path.join(class_folder, images[i])\n            image = Image.open(image_path)\n\n            axes[i].imshow(image)\n            axes[i].axis('off')\n\n        plt.show()\n\nprint(\"Training Data:\")\ndisplay_images(train_folder)\n\nprint(\"Validation Data:\")\ndisplay_images(validation_folder)\n","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:07.685125Z","iopub.execute_input":"2024-05-01T08:00:07.685480Z","iopub.status.idle":"2024-05-01T08:00:25.772858Z","shell.execute_reply.started":"2024-05-01T08:00:07.685448Z","shell.execute_reply":"2024-05-01T08:00:25.771957Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Train Set","metadata":{}},{"cell_type":"code","source":"train_generator = ImageDataGenerator(rescale= 1./255,\n                                    zoom_range = 0.2,\n                                    rotation_range = 7,\n                                    horizontal_flip = True)\ntrain_dataset = train_generator.flow_from_directory('/kaggle/working/train',\n                                                   target_size= (244,244),\n                                                   class_mode = 'categorical',\n                                                   batch_size = 25,\n                                                   shuffle = True)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:25.774501Z","iopub.execute_input":"2024-05-01T08:00:25.775013Z","iopub.status.idle":"2024-05-01T08:00:25.904082Z","shell.execute_reply.started":"2024-05-01T08:00:25.774976Z","shell.execute_reply":"2024-05-01T08:00:25.903327Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_generator = ImageDataGenerator(rescale=1./255)\nvalidation_dataset = validation_generator.flow_from_directory('/kaggle/working/validation',\n                                                              target_size=(244, 244),\n                                                              class_mode='categorical',\n                                                              batch_size= 1,\n                                                              shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:25.905141Z","iopub.execute_input":"2024-05-01T08:00:25.905426Z","iopub.status.idle":"2024-05-01T08:00:25.948694Z","shell.execute_reply.started":"2024-05-01T08:00:25.905396Z","shell.execute_reply":"2024-05-01T08:00:25.948040Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset.class_indices","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:25.949581Z","iopub.execute_input":"2024-05-01T08:00:25.949810Z","iopub.status.idle":"2024-05-01T08:00:25.956157Z","shell.execute_reply.started":"2024-05-01T08:00:25.949790Z","shell.execute_reply":"2024-05-01T08:00:25.955315Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Pretrained Model","metadata":{}},{"cell_type":"code","source":"\n# Control GPU Placement\nwith tf.device('/gpu:0'):\n    # Check GPU availability\n    print(\"Num GPUs Available: \", len(tf.config.experimental.list_physical_devices('GPU')))\n    \n    # TensorFlow GPU Configurations\n    # Setting memory growth before initializing runtime\n    gpus = tf.config.experimental.list_physical_devices('GPU')\n    if gpus:\n        try:\n            for gpu in gpus:\n                tf.config.experimental.set_memory_growth(gpu, True)\n        except RuntimeError as e:\n            print(e)  # Memory growth must be set before GPUs have been initialized\n","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:25.957418Z","iopub.execute_input":"2024-05-01T08:00:25.958029Z","iopub.status.idle":"2024-05-01T08:00:26.237285Z","shell.execute_reply.started":"2024-05-01T08:00:25.958000Z","shell.execute_reply":"2024-05-01T08:00:26.235856Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = tf.keras.applications.InceptionResNetV2(\n    include_top=False,\n    weights=\"imagenet\",\n    input_tensor=Input(shape = (244, 244, 3)),\n    classifier_activation=\"softmax\",\n)\n","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:26.241777Z","iopub.execute_input":"2024-05-01T08:00:26.242149Z","iopub.status.idle":"2024-05-01T08:00:37.048293Z","shell.execute_reply.started":"2024-05-01T08:00:26.242123Z","shell.execute_reply":"2024-05-01T08:00:37.047483Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:37.049847Z","iopub.execute_input":"2024-05-01T08:00:37.050149Z","iopub.status.idle":"2024-05-01T08:00:38.092374Z","shell.execute_reply.started":"2024-05-01T08:00:37.050124Z","shell.execute_reply":"2024-05-01T08:00:38.091493Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"len(base_model.layers)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.093740Z","iopub.execute_input":"2024-05-01T08:00:38.094714Z","iopub.status.idle":"2024-05-01T08:00:38.102330Z","shell.execute_reply.started":"2024-05-01T08:00:38.094673Z","shell.execute_reply":"2024-05-01T08:00:38.101525Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fine_tuning_at = 740","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.103772Z","iopub.execute_input":"2024-05-01T08:00:38.104688Z","iopub.status.idle":"2024-05-01T08:00:38.806124Z","shell.execute_reply.started":"2024-05-01T08:00:38.104656Z","shell.execute_reply":"2024-05-01T08:00:38.804965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in base_model.layers[:fine_tuning_at]:\n  layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.807716Z","iopub.execute_input":"2024-05-01T08:00:38.809135Z","iopub.status.idle":"2024-05-01T08:00:38.870083Z","shell.execute_reply.started":"2024-05-01T08:00:38.809104Z","shell.execute_reply":"2024-05-01T08:00:38.869300Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"for layer in base_model.layers:\n  print(layer, layer.trainable)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.871132Z","iopub.execute_input":"2024-05-01T08:00:38.871406Z","iopub.status.idle":"2024-05-01T08:00:38.897823Z","shell.execute_reply.started":"2024-05-01T08:00:38.871382Z","shell.execute_reply":"2024-05-01T08:00:38.896960Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Custom Dense Layer","metadata":{}},{"cell_type":"code","source":"base_model.output","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.899035Z","iopub.execute_input":"2024-05-01T08:00:38.899292Z","iopub.status.idle":"2024-05-01T08:00:38.912041Z","shell.execute_reply.started":"2024-05-01T08:00:38.899271Z","shell.execute_reply":"2024-05-01T08:00:38.911217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"(1536+2)/2","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.913107Z","iopub.execute_input":"2024-05-01T08:00:38.913386Z","iopub.status.idle":"2024-05-01T08:00:38.922682Z","shell.execute_reply.started":"2024-05-01T08:00:38.913365Z","shell.execute_reply":"2024-05-01T08:00:38.921859Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"head_model = base_model.output\nhead_model = GlobalAveragePooling2D()(head_model)\nhead_model = Dense(units = 769, activation='relu')(head_model)\nhead_model = Dropout(rate = 0.2)(head_model)\nhead_model = Dense(units = 769, activation='relu')(head_model)\nhead_model = Dropout(rate = 0.2)(head_model)\nhead_model = Dense(27, activation='softmax')(head_model)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.923790Z","iopub.execute_input":"2024-05-01T08:00:38.924131Z","iopub.status.idle":"2024-05-01T08:00:38.962494Z","shell.execute_reply.started":"2024-05-01T08:00:38.924101Z","shell.execute_reply":"2024-05-01T08:00:38.961675Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"head_model","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.963645Z","iopub.execute_input":"2024-05-01T08:00:38.964192Z","iopub.status.idle":"2024-05-01T08:00:38.969319Z","shell.execute_reply.started":"2024-05-01T08:00:38.964163Z","shell.execute_reply":"2024-05-01T08:00:38.968517Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Building and Training Neural Network","metadata":{}},{"cell_type":"code","source":"base_model.input","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.970506Z","iopub.execute_input":"2024-05-01T08:00:38.970808Z","iopub.status.idle":"2024-05-01T08:00:38.979248Z","shell.execute_reply.started":"2024-05-01T08:00:38.970779Z","shell.execute_reply":"2024-05-01T08:00:38.978379Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"network = Model(inputs = base_model.input, outputs = head_model)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:38.980183Z","iopub.execute_input":"2024-05-01T08:00:38.980473Z","iopub.status.idle":"2024-05-01T08:00:39.104114Z","shell.execute_reply.started":"2024-05-01T08:00:38.980441Z","shell.execute_reply":"2024-05-01T08:00:39.103486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"network.summary()","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:39.104999Z","iopub.execute_input":"2024-05-01T08:00:39.105252Z","iopub.status.idle":"2024-05-01T08:00:40.317837Z","shell.execute_reply.started":"2024-05-01T08:00:39.105231Z","shell.execute_reply":"2024-05-01T08:00:40.316966Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"network.compile(optimizer= 'Adam', loss = 'categorical_crossentropy', metrics = ['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:00:40.319055Z","iopub.execute_input":"2024-05-01T08:00:40.319377Z","iopub.status.idle":"2024-05-01T08:00:40.339577Z","shell.execute_reply.started":"2024-05-01T08:00:40.319348Z","shell.execute_reply":"2024-05-01T08:00:40.338745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with tf.device('/gpu:0'):\n    history = network.fit(train_dataset,\n                          epochs=50,\n                          validation_data=validation_dataset)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:05:01.852264Z","iopub.execute_input":"2024-05-01T08:05:01.853299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"accuracy = history.history['accuracy']\nloss = history.history['loss']\nval_accuracy = history.history['val_accuracy']\nval_loss = history.history['val_loss']\nepochs = range(1, len(accuracy) + 1)\n\nplt.plot(epochs, accuracy, 'b', label='Training accuracy')\nplt.plot(epochs, val_accuracy, 'g', label='Validation accuracy')\nplt.title('Training and Validation accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.show()\n\nplt.plot(epochs, loss, 'r', label='Training loss')\nplt.plot(epochs, val_loss, 'm', label='Validation loss')\nplt.title('Training and Validation loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\nplt.show()\n","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:03:15.433596Z","iopub.execute_input":"2024-05-01T08:03:15.433889Z","iopub.status.idle":"2024-05-01T08:03:15.990724Z","shell.execute_reply.started":"2024-05-01T08:03:15.433864Z","shell.execute_reply":"2024-05-01T08:03:15.989828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = network.predict(validation_dataset)\npredictions","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:03:15.991821Z","iopub.execute_input":"2024-05-01T08:03:15.992173Z","iopub.status.idle":"2024-05-01T08:03:48.238404Z","shell.execute_reply.started":"2024-05-01T08:03:15.992143Z","shell.execute_reply":"2024-05-01T08:03:48.237480Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = np.argmax(predictions, axis = 1)\npredictions","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:03:48.239808Z","iopub.execute_input":"2024-05-01T08:03:48.240575Z","iopub.status.idle":"2024-05-01T08:03:48.249379Z","shell.execute_reply.started":"2024-05-01T08:03:48.240539Z","shell.execute_reply":"2024-05-01T08:03:48.248489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import accuracy_score\naccuracy_score(validation_dataset.classes, predictions)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:03:48.253756Z","iopub.execute_input":"2024-05-01T08:03:48.254042Z","iopub.status.idle":"2024-05-01T08:03:48.261409Z","shell.execute_reply.started":"2024-05-01T08:03:48.254019Z","shell.execute_reply":"2024-05-01T08:03:48.260449Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Creating Submission ","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.preprocessing import image\nfrom tqdm import tqdm\n\n\ncsv_file = '/kaggle/input/bird-genus-multi-class-image-classification/test.csv'\ndata = pd.read_csv(csv_file)\nimg_dir = '/kaggle/input/bird-genus-multi-class-image-classification/images/test'\npredictions = []\ntotal_images = len(data)\n\nfor index, row in tqdm(data.iterrows(), total=total_images, desc=\"Predicting\"):\n\n    img_path = os.path.join(img_dir, row['filename'])\n    img = image.load_img(img_path, target_size=(244,244))\n    img_array = image.img_to_array(img)\n    img_array = img_array / 255.0\n    img_array = img_array.reshape((1,) + img_array.shape)\n    prediction = network.predict(img_array)\n    predicted_class_index = prediction.argmax(axis=-1)[0]\n    predicted_class = list(train_dataset.class_indices.keys())[predicted_class_index]\n    predictions.append({'id': row['id'], 'genus': predicted_class})\n\n# Convert predictions to DataFrame and save to CSV\npredictions_df = pd.DataFrame(predictions)\npredictions_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-05-01T08:03:48.262521Z","iopub.execute_input":"2024-05-01T08:03:48.262794Z","iopub.status.idle":"2024-05-01T08:04:51.499604Z","shell.execute_reply.started":"2024-05-01T08:03:48.262770Z","shell.execute_reply":"2024-05-01T08:04:51.498736Z"},"trusted":true},"execution_count":null,"outputs":[]}]}