{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.4"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":7327,"databundleVersionId":861871,"sourceType":"competition"}],"dockerImageVersionId":30746,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Developed a deep learning model to classify dog breeds from images by leveraging pre-trained Convolutional Neural Networks (CNN) models. The project utilized state-of-the-art architectures, including InceptionV3, Xception, and MobileNetV2, to achieve high accuracy in identifying over 100 different dog breeds.","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport tensorflow as tf\nfrom keras.layers import Dense, Conv2D, Flatten\nfrom tensorflow.keras import datasets, layers, models\nfrom tensorflow.math import confusion_matrix\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.callbacks import ModelCheckpoint\nimport os\nimport cv2\nimport warnings\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\nfrom kerastuner.tuners import RandomSearch\nimport matplotlib.pyplot as plt\nwarnings.filterwarnings('ignore')\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install keras-tuner","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Paths\ntrain_dir = '.../dog-breed-identification/train'\ntest_dir = '.../dog-breed-identification/test'\nval_csv = '.../dog-breed-identification/labels.csv'","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train = pd.read_csv(val_csv)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_features(model_name, data_preprocessor, input_size, data):\n    input_layer = Input(input_size)\n    preprocessor = Lambda(data_preprocessor)(input_layer)\n    base_model = model_name(weights='imagenet', include_top=False,\n                            input_shape=input_size)(preprocessor)\n    avg = GlobalAveragePooling2D()(base_model)\n    feature_extractor = Model(inputs = input_layer, outputs = avg)\n    feature_maps = feature_extractor.predict(data, batch_size=64, verbose=1)\n    print('Feature maps shape: ', feature_maps.shape)\n    return feature_maps","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"dog_breeds = sorted(list(set(train['breed'])))\nn_classes = len(dog_breeds)\nprint(n_classes)\ndog_breeds[:5]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_to_num = dict(zip(dog_breeds, range(n_classes)))","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def images_to_array(data_dir, labels_dataframe, img_size = (224,224,3)):\n    images_names = labels_dataframe['id']\n    images_labels = labels_dataframe['breed']\n    data_size = len(images_names)\n    X = np.zeros([data_size, img_size[0], img_size[1], img_size[2]], dtype=np.uint8)\n    y = np.zeros([data_size,1], dtype=np.uint8)\n    \n    for i in tqdm(range(data_size)):\n        image_name = images_names[i]\n        img_dir = os.path.join(data_dir, image_name+'.jpg')\n        img_pixels = load_img(img_dir, target_size=img_size)\n        X[i] = img_pixels\n        \n        image_breed = images_labels[i]\n        y[i] = class_to_num[image_breed]\n    \n    y = to_categorical(y)\n    \n    ind = np.random.permutation(data_size)\n    X = X[ind]\n    y = y[ind]\n    print('Output Data Size: ', X.shape)\n    print('Output Label Size: ', y.shape)\n    return X, y","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import load_img\nfrom tqdm import tqdm\nfrom keras.utils import to_categorical\n\n\nimg_size = (224,224, 3)\nX, y = images_to_array(train_dir, train, img_size)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.models import Model\nfrom keras.layers import BatchNormalization, Dense, GlobalAveragePooling2D, Lambda, Dropout, InputLayer, Input\nfrom keras.applications.inception_v3 import InceptionV3, preprocess_input\n\ninception_preprocessor = preprocess_input\ninception_features = get_features(InceptionV3,\n                                  inception_preprocessor,\n                                  img_size, X)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.applications.xception import Xception, preprocess_input\nxception_preprocessor = preprocess_input\nxception_features = get_features(Xception,\n                                 xception_preprocessor,\n                                 img_size, X)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input\nmobilenet_v2_preprocessor = preprocess_input\nmobilenet_v2_features = get_features(MobileNetV2,\n                                   mobilenet_v2_preprocessor,\n                                   img_size, X)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"del X","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"final_features = np.concatenate([inception_features,\n                                 xception_features,\n                                 mobilenet_v2_features], axis=-1)\nprint('Final feature maps shape', final_features.shape)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_temp, y_train, y_temp = train_test_split(final_features, y, test_size=0.2, random_state=42)\nX_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp, test_size=0.5, random_state=42)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"X_train = X_train / 255.0\nX_val = X_val / 255.0\nX_test = X_test / 255.0","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.callbacks import EarlyStopping\nEarlyStop_callback = EarlyStopping(monitor='val_loss', patience=15, restore_best_weights=True)\nmy_callback=[EarlyStop_callback]","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input\nfrom keras.layers import InputLayer, Flatten, Dense, Dropout\nfrom keras.models import Sequential\nfrom sklearn.model_selection import train_test_split\nfrom keras.callbacks import EarlyStopping\nimport numpy as np\n\n# Adjust Dropout Rate based on HPO results\ndropout_rate = 0.3  # increase from 0.2\n\n# Adjust Learning Rate based on HPO results\nlearning_rate = 0.001  # reduce it slightly from 0.00527\n\n# Model Definition with increased Dropout\nmodel = Sequential([\n    InputLayer(X_train.shape[1:]),  \n    Flatten(),\n    Dense(128, activation='relu'),\n    Dropout(dropout_rate),  # Increased dropout\n    Dense(n_classes, activation='softmax')  \n])\n\n# Compile the model with a reduced learning rate\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),\n              loss='categorical_crossentropy',\n              metrics=['accuracy'])\n\n# Use EarlyStopping to prevent overfitting\nEarlyStop_callback = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)\n\n# Train the model\nhistory = model.fit(X_train, y_train,\n                    batch_size=128,\n                    epochs=50,\n                    validation_data=(X_val, y_val), \n                    callbacks=[EarlyStop_callback])\n\n# Review the model summary\nmodel.summary()\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history['accuracy'], label='accuracy')\nplt.plot(history.history['val_accuracy'], label='val_accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend(loc='lower right')\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.plot(history.history['loss'], label='loss')\nplt.plot(history.history['val_loss'], label='val_loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend(loc='upper right')\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input\nfrom keras.layers import InputLayer, Flatten, Dense, Dropout\nfrom keras.models import Sequential\nfrom sklearn.model_selection import train_test_split\nfrom keras.callbacks import EarlyStopping\nimport numpy as np\n\n# Adjust Dropout Rate based on HPO results\ndropout_rate = 0.3  # increase from 0.2\n\n# Adjust Learning Rate based on HPO results\nlearning_rate = 0.001  # reduce it slightly from 0.00527\n\n# Model Definition with increased Dropout\nmodel = Sequential([\n    InputLayer(X_train.shape[1:]),  # assuming X_train is already defined\n    Flatten(),\n    Dense(128, activation='relu'),\n    Dropout(dropout_rate),  # Increased dropout\n    Dense(n_classes, activation='softmax')  # assuming n_classes is already defined\n])\n\n# Compile the model with a reduced learning rate\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=learning_rate),\n              loss='categorical_crossentropy',\n              metrics=['accuracy'])\n\n# Use EarlyStopping to prevent overfitting\nEarlyStop_callback = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)\n\n# Train the model\nhistory = model.fit(X_train, y_train,\n                    batch_size=128,\n                    epochs=50,\n                    validation_data=(X_val, y_val),  # assuming X_val and y_val are already defined\n                    callbacks=[EarlyStop_callback])\n\n# Review the model summary\nmodel.summary()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.callbacks import ModelCheckpoint\n\n# Define the checkpoint callback to save the model at each epoch\ncheckpoint_callback = ModelCheckpoint(\n    filepath='model_epoch_{epoch:02d}_val_acc_{val_accuracy:.2f}.keras',  # Use .keras extension\n    save_best_only=False,  # Set to False to save the model at each epoch, not just the best one\n    save_weights_only=False,  # Save the entire model, not just weights\n    monitor='val_accuracy',  # You can also monitor 'val_loss'\n    mode='max',  # 'max' for accuracy, 'min' for loss\n    verbose=1\n)\n\n# Train the model with the checkpoint callback\nhistory = model.fit(X_train, y_train,\n                    batch_size=128,\n                    epochs=50,\n                    validation_data=(X_val, y_val),\n                    callbacks=[EarlyStop_callback, checkpoint_callback])\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\n# List all the saved model files in the current directory\nmodel_files = [f for f in os.listdir() if f.endswith('.keras')]\n\n# Initialize variables to track the best model\nbest_accuracy = 0\nbest_model = None\n\n# Loop through each file and extract the validation accuracy\nfor model_file in model_files:\n    # Extract validation accuracy from the filename\n    try:\n        val_acc = float(model_file.split('_val_acc_')[1].split('.keras')[0])\n        if val_acc > best_accuracy:\n            best_accuracy = val_acc\n            best_model = model_file\n    except Exception as e:\n        print(f\"Error processing file {model_file}: {e}\")\n\n# Output the best model\nprint(f\"Best model: {best_model} with validation accuracy: {best_accuracy}\")\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os\n\n# List all the saved model files in the current directory\nmodel_files = [f for f in os.listdir() if f.endswith('.keras')]\n\n# Initialize variables to track the best model\nbest_accuracy = 0\nbest_model = None\n\n# Loop through each file and extract the validation accuracy\nfor model_file in model_files:\n    try:\n        # Attempt to extract validation accuracy from the filename\n        if 'val_acc' in model_file:\n            val_acc = float(model_file.split('_val_acc_')[1].split('.keras')[0])\n            if val_acc > best_accuracy:\n                best_accuracy = val_acc\n                best_model = model_file\n    except Exception as e:\n        print(f\"Error processing file {model_file}: {e}\")\n\n# Output the best model\nprint(f\"Best model: {best_model} with validation accuracy: {best_accuracy}\")\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.models import load_model\n\n# Load the best model\nbest_model = load_model('model_epoch_16_val_acc_0.83.keras')  # Replace with the actual filename","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Assuming X_test and y_test are your test datasets\ntest_loss, test_accuracy = best_model.evaluate(X_test, y_test)\n\nprint(f\"Test Accuracy: {test_accuracy:.4f}\")\nprint(f\"Test Loss: {test_loss:.4f}\")","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = best_model.predict(X_test)\n\n# If you want to see the predicted classes\npredicted_classes = np.argmax(predictions, axis=1)\n\n# If y_test is in categorical format (one-hot encoded), convert it to class labels\ntrue_classes = np.argmax(y_test, axis=1)\n\n# Evaluate the predictions, for example using a confusion matrix\nfrom sklearn.metrics import confusion_matrix, classification_report\n\nprint(confusion_matrix(true_classes, predicted_classes))\nprint(classification_report(true_classes, predicted_classes))\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(X_test.shape)  # This will show the shape of the test data","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay\n\n# Assuming true_classes and predicted_classes are defined\ncm = confusion_matrix(true_classes, predicted_classes)\ndisp = ConfusionMatrixDisplay(confusion_matrix=cm)\ndisp.plot(cmap='Blues')\nplt.show()\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import classification_report\n\nreport = classification_report(true_classes, predicted_classes)\nprint(report)","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import roc_curve, auc\nfrom sklearn.preprocessing import label_binarize\n\n# Binarize the true classes and predictions if they are not already\ny_true_bin = label_binarize(true_classes, classes=np.arange(n_classes))\ny_pred_bin = label_binarize(predicted_classes, classes=np.arange(n_classes))\n\n# Compute ROC curve and ROC area for each class\nfpr = dict()\ntpr = dict()\nroc_auc = dict()\nfor i in range(n_classes):\n    fpr[i], tpr[i], _ = roc_curve(y_true_bin[:, i], predictions[:, i])\n    roc_auc[i] = auc(fpr[i], tpr[i])\n\n# Plot all ROC curves\nplt.figure()\nfor i in range(n_classes):\n    plt.plot(fpr[i], tpr[i], label=f\"Class {i} (area = {roc_auc[i]:.2f})\")\nplt.plot([0, 1], [0, 1], 'k--')  # Diagonal line for reference\nplt.xlim([0.0, 1.0])\nplt.ylim([0.0, 1.0])\nplt.xlabel('False Positive Rate')\nplt.ylabel('True Positive Rate')\nplt.title('Receiver Operating Characteristic')\nplt.legend(loc=\"lower right\")\nplt.show()","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import precision_recall_curve, average_precision_score\nfrom sklearn.preprocessing import label_binarize\n\n# Binarize the true classes and predictions if they are not already\ny_true_bin = label_binarize(true_classes, classes=np.arange(n_classes))\ny_pred_bin = label_binarize(predicted_classes, classes=np.arange(n_classes))\n\nprecision = dict()\nrecall = dict()\navg_precision = dict()\n\nfor i in range(n_classes):\n    precision[i], recall[i], _ = precision_recall_curve(y_true_bin[:, i], predictions[:, i])\n    avg_precision[i] = average_precision_score(y_true_bin[:, i], predictions[:, i])\n\n# Plot Precision-Recall curve for each class\nplt.figure()\nfor i in range(n_classes):\n    plt.plot(recall[i], precision[i], label=f'Class {i} (AP = {avg_precision[i]:.2f})')\nplt.xlabel('Recall')\nplt.ylabel('Precision')\nplt.title('Precision-Recall curve')\nplt.legend(loc=\"best\")\nplt.show()\n","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from sklearn.metrics import log_loss\n\nloss = log_loss(true_classes, predictions)\nprint(f'Log Loss: {loss:.4f}')","metadata":{},"execution_count":null,"outputs":[]}]}