{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12053762%2F3c94ab343f0e44a43b6f3563a7116373%2FXUGEPVQJJMI6LBP3WAQRGYECEI.jpg?generation=1695786557088668&alt=media)","metadata":{}},{"cell_type":"markdown","source":"<div style=\"background-color: #87CEFA; padding: 20px; margin: 10px; border-radius: 10px; box-shadow: 5px 5px 5px #888888;\">\n  <h1 style=\"color: #000; font-size: 20px;\">Table of Contents</h1>\n  <ul style=\"list-style-type: disc; padding-left: 0; font-size: 16px;\">\n    <li style=\"margin-left: 15px;\"><a href=\"#section-1\" style=\"color: #000; text-decoration: none;\">1. Overview</a></li>\n    <li style=\"margin-left: 15px;\"><a href=\"#section-2\" style=\"color: #000; text-decoration: none;\">2. Import Libraries</a></li>\n    <li style=\"margin-left: 15px;\"><a href=\"#section-3\" style=\"color: #000; text-decoration: none;\">3. Preprocessing</a>\n        <br> \n      <ul style=\"list-style-type: circle; padding-left: 15px; font-size: 14px;\">\n        <li>3.1 Get the pathes</li>\n        <li>3.2 Load the Images with a generator and Data Augmentation</li>\n        <li>3.3 Display images</li>\n        <li>3.4 EarlyStopping</li>\n        <li>3.5 Reduction learning_rate</li>\n      </ul>\n    </li>\n      <li style=\"margin-left: 15px;\"><a href=\"#section-1\" style=\"color: #000; text-decoration: none;\">4. Exponential Decay</a></li>\n    <li style=\"margin-left: 15px;\"><a href=\"#section-4\" style=\"color: #000; text-decoration: none;\">5. Transfer Learning</a>\n      <ul style=\"list-style-type: circle; padding-left: 15px; font-size: 14px;\">\n        <li>5.1 Get the weights from DenseNet121</li>\n        <li>5.2 Freeze the layers of DenseNet121</li>\n      </ul>\n    </li>\n    <li style=\"margin-left: 15px;\"><a href=\"#section-5\" style=\"color: #000; text-decoration: none;\">6. Build the Model</a>\n      <ul style=\"list-style-type: circle; padding-left: 15px; font-size: 14px;\">\n        <li>6.1 Build the Model </li>\n        <li>6.2 Set the optimizer</li>\n        <li>6.3 Training the model </li>\n      </ul>\n    </li>\n      <li style=\"margin-left: 15px;\"><a href=\"#section-1\" style=\"color: #000; text-decoration: none;\">7. Evaluate the model</a>\n      <ul style=\"list-style-type: circle; padding-left: 15px; font-size: 14px;\">\n        <li>7.1 Evaluate the validationr</li>\n        <li>7.2 Accuracy graph</li>\n        <li>7.3 Loss graph</li>\n        <li>7.4 Confusion Matrix</li>\n        <li>7.5 Generate predictions for the test data</li>    \n      </ul>\n      </li>\n    <li style=\"margin-left: 15px;\"><a href=\"#section-6\" style=\"color: #000; text-decoration: none;\">8. Conclusion</a></li>\n  </ul>\n</div>\n","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Overview\n</h1>\n\n# 1. Overview\n\n\n\n\nIn this notebook we will make a **classifier** for **dogs-&-cats** datasets according to the following steps:\n\n- We will pre-process the data using **Generator** way, and we will explain why we used it\n- Then we will explain both ideas **Early_stopping** and **Reduction_learning_rate** and why we used them\n- After that, we explained in detail the importance of the idea of **Exponential Decay** and how to implement it\n- Then we chose **DeseNet-121-v2** to train the model on it and showed the difference between it and other transfer learning model\n- Finally, we built the neural network, trained it, and checked its accuracy","metadata":{}},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Import Libraries\n</h1>\n\n# 2. Import Libraries","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\n%matplotlib inline\nimport os\nimport cv2\nimport glob as gb\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.image as mpimg\nimport imagehash\nfrom PIL import Image\n\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\n\nfrom keras.utils.np_utils import to_categorical\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras.callbacks import ReduceLROnPlateau\nfrom keras.callbacks import EarlyStopping\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import confusion_matrix\n\nfrom keras.applications import DenseNet121","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-10-05T03:54:59.149002Z","iopub.execute_input":"2023-10-05T03:54:59.149364Z","iopub.status.idle":"2023-10-05T03:55:09.001053Z","shell.execute_reply.started":"2023-10-05T03:54:59.149333Z","shell.execute_reply":"2023-10-05T03:55:08.999978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Preprocessing\n</h1>\n\n# 3.Preprocessing","metadata":{}},{"cell_type":"markdown","source":"","metadata":{}},{"cell_type":"markdown","source":"### 3.1 Get the pathes","metadata":{}},{"cell_type":"code","source":"train_path = '../input/dogs-cats-images/dog vs cat/dataset/training_set'\ntest_path = '../input/dogs-cats-images/dog vs cat/dataset/test_set'","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:55:24.762992Z","iopub.execute_input":"2023-10-05T03:55:24.763619Z","iopub.status.idle":"2023-10-05T03:55:24.768515Z","shell.execute_reply.started":"2023-10-05T03:55:24.763587Z","shell.execute_reply":"2023-10-05T03:55:24.767489Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.2 Load the Images with a generator and Data Augmentation\n","metadata":{}},{"cell_type":"markdown","source":" ### Why you should use (flow_from_directory) for Visualize Images ?\n\n\n Using `flow_from_directory` in conjunction with `ImageDataGenerator` offers several advantages when working with image datasets in deep learning tasks. Here are some reasons why you might want to use `flow_from_directory`:\n\n1. **Directory Structure and Labels**: If your data is organized in a directory structure where each subdirectory corresponds to a class, `flow_from_directory` can automatically assign labels to images based on the directory names. This eliminates the need for you to manually assign labels to each image.\n\n2. **Data Augmentation**: `ImageDataGenerator` allows you to apply data augmentation techniques such as rotation, flipping, and scaling to your images on-the-fly while they are being loaded. This helps improve the generalization of your model and prevents overfitting.\n\n3. **Batch Loading**: Loading images in batches helps manage memory efficiently, **especially when working with large datasets that may not fit into memory**. `flow_from_directory`loads images in batches, allowing you to train your model with minimal memory usage.\n\n4. **Preprocessing**: `ImageDataGenerator` can apply preprocessing steps such as rescaling pixel values and standardizing input data on-the-fly. This ensures that your input data is properly preprocessed before being fed into the model.\n\n5. **Easy Integration with Keras Models**: The data generator returned by `flow_from_directory` can be directly used as input for Keras' `fit` and `evaluate` methods. This streamlines the training and evaluation process, making it easier to manage data loading and preprocessing.\n\n6. **Shuffling**: By setting the `shuffle` parameter to `True` in `flow_from_directory`, you can shuffle the order of images within each epoch, preventing the model from memorizing the order of training examples.\n\n7. **Efficient Coding**: Using `flow_from_directory` reduces the amount of manual coding required to load and preprocess images, freeing you to focus more on building and training your models.","metadata":{}},{"cell_type":"code","source":"# Data augmentation for training\ntrain_datagen = ImageDataGenerator(\n    rescale=1.0/255,                # Rescale pixel values to [0, 1]\n    rotation_range=20,              # Random rotation within 20 degrees\n    width_shift_range=0.2,          # Random horizontal shift by 20% of image width\n    height_shift_range=0.2,         # Random vertical shift by 20% of image height\n    horizontal_flip=True,           # Random horizontal flipping\n    fill_mode='nearest'             # Fill mode for new pixels after shifts/rotations\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:55:29.219146Z","iopub.execute_input":"2023-10-05T03:55:29.219504Z","iopub.status.idle":"2023-10-05T03:55:29.224788Z","shell.execute_reply.started":"2023-10-05T03:55:29.219477Z","shell.execute_reply":"2023-10-05T03:55:29.223698Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"size_images = 200\nbatch_size = 64","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:55:34.883494Z","iopub.execute_input":"2023-10-05T03:55:34.883819Z","iopub.status.idle":"2023-10-05T03:55:34.888101Z","shell.execute_reply.started":"2023-10-05T03:55:34.883795Z","shell.execute_reply":"2023-10-05T03:55:34.887046Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_generator = train_datagen.flow_from_directory(\n    train_path,                     # Path to the training data\n    target_size=(size_images, size_images),  # Resize images to this size\n    batch_size=batch_size,           # Number of images in each batch\n    seed=32,                         # Optional: Set a random seed for shuffling\n    shuffle=True,                    # Shuffle the data during training\n    class_mode='categorical'        # Mode for class labels (categorical for one-hot encoding)\n)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:55:41.646510Z","iopub.execute_input":"2023-10-05T03:55:41.646879Z","iopub.status.idle":"2023-10-05T03:55:46.140182Z","shell.execute_reply.started":"2023-10-05T03:55:41.646853Z","shell.execute_reply":"2023-10-05T03:55:46.139217Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the class labels\nclass_labels = list(train_generator.class_indices.keys())\n\n# Calculate the count of images per class\nclass_counts = {label: 0 for label in class_labels}\n\nfor i in range(len(train_generator)):\n    batch_data, batch_labels = train_generator[i]\n    for j in range(len(batch_data)):\n        class_idx = int(batch_labels[j].argmax())\n        class_label = class_labels[class_idx]\n        class_counts[class_label] += 1\n\n# Define unique colors for each class\nclass_colors = plt.cm.tab20(np.linspace(0, 1, len(class_labels)))\n\n# Create a bar chart with different colors for each class\nplt.figure(figsize=(9, 5))\nbars = plt.bar(class_counts.keys(), class_counts.values(), color=class_colors)\nplt.xlabel('Class')\nplt.ylabel('Count')\nplt.title('Number of Images per Class')\nplt.xticks(rotation=45)\n\n# Add a legend for class colors\nlegend_labels = [plt.Line2D([0], [0], color=class_colors[i], lw=4, label=class_labels[i]) for i in range(len(class_labels))]\nplt.legend(handles=legend_labels, title=\"Classes\")\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:55:57.111051Z","iopub.execute_input":"2023-10-05T03:55:57.111444Z","iopub.status.idle":"2023-10-05T03:57:35.722338Z","shell.execute_reply.started":"2023-10-05T03:55:57.111418Z","shell.execute_reply":"2023-10-05T03:57:35.721390Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# data augmentation for testing\ntest_datagen = ImageDataGenerator(rescale=1.0/255)  # Rescale pixel values to [0, 1]","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:57:44.295854Z","iopub.execute_input":"2023-10-05T03:57:44.296192Z","iopub.status.idle":"2023-10-05T03:57:44.301060Z","shell.execute_reply.started":"2023-10-05T03:57:44.296169Z","shell.execute_reply":"2023-10-05T03:57:44.299914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a generator for testing data\ntest_generator = test_datagen.flow_from_directory(\n    test_path,\n    target_size=(size_images, size_images),\n    batch_size = batch_size,\n    class_mode='categorical')","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:57:55.044759Z","iopub.execute_input":"2023-10-05T03:57:55.045109Z","iopub.status.idle":"2023-10-05T03:57:55.130142Z","shell.execute_reply.started":"2023-10-05T03:57:55.045081Z","shell.execute_reply":"2023-10-05T03:57:55.129268Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Get the class labels\nclass_labels = list(test_generator.class_indices.keys())\n\n# Calculate the count of images per class\nclass_counts = {label: 0 for label in class_labels}\n\nfor i in range(len(test_generator)):\n    batch_data, batch_labels = test_generator[i]\n    for j in range(len(batch_data)):\n        class_idx = int(batch_labels[j].argmax())\n        class_label = class_labels[class_idx]\n        class_counts[class_label] += 1\n\n# Define unique colors for each class\nclass_colors = plt.cm.tab20(np.linspace(0, 1, len(class_labels)))\n\n# Create a bar chart with different colors for each class\nplt.figure(figsize=(12, 6))\nbars = plt.bar(class_counts.keys(), class_counts.values(), color=class_colors)\nplt.xlabel('Class')\nplt.ylabel('Count')\nplt.title('Number of Images per Class')\nplt.xticks(rotation=45)\n\n# Add a legend for class colors\nlegend_labels = [plt.Line2D([0], [0], color=class_colors[i], lw=4, label=class_labels[i]) for i in range(len(class_labels))]\nplt.legend(handles=legend_labels, title=\"Classes\")\n\nplt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:57:59.422945Z","iopub.execute_input":"2023-10-05T03:57:59.423304Z","iopub.status.idle":"2023-10-05T03:58:10.759100Z","shell.execute_reply.started":"2023-10-05T03:57:59.423276Z","shell.execute_reply":"2023-10-05T03:58:10.758149Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.3 Display Images","metadata":{}},{"cell_type":"code","source":"def Show_Images(target_gen):\n    # Get a batch of images and labels\n    batch_images, batch_labels = next(target_gen)\n\n    # Get class labels\n    class_labels = list(target_gen.class_indices.keys())\n\n    # Display images with labels\n    plt.figure(figsize=(20, 20))\n    for n , i in enumerate(list(np.random.randint(0,len(batch_images),36))):\n        plt.subplot(6, 6, n + 1)\n        plt.imshow(batch_images[i])\n        plt.title(class_labels[np.argmax(batch_labels[i])])  # Display the class label\n        plt.axis('off')\n    plt.show()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:58:15.632523Z","iopub.execute_input":"2023-10-05T03:58:15.632883Z","iopub.status.idle":"2023-10-05T03:58:15.640255Z","shell.execute_reply.started":"2023-10-05T03:58:15.632856Z","shell.execute_reply":"2023-10-05T03:58:15.639005Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Show_Images(train_generator)","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T03:58:22.959153Z","iopub.execute_input":"2023-10-05T03:58:22.959525Z","iopub.status.idle":"2023-10-05T03:58:26.773455Z","shell.execute_reply.started":"2023-10-05T03:58:22.959497Z","shell.execute_reply":"2023-10-05T03:58:26.772324Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Show_Images(test_generator)","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.4 EarlyStopping\n***Early stopping*** works by monitoring the performance of the model on a validation set during training. The validation set is a set of data that is held out from the training data and is not used to train the model. The model's performance on the validation set is **used to determine if the model is overfitting.**\n\nIf the model's performance on the validation set starts to plateau or decrease, then the training is stopped early. **This prevents the model from continuing to fit the training data too closely**, which can lead to overfitting.\n\n💡 Here is a simple analogy to help you understand early stopping:\n\nImagine you are trying to learn how to play a new game. You start by playing the game against a computer opponent. As you play, you get better and better at the game. However, at some point, you start to plateau. You are not getting any better at the game, even though you are still playing against the same computer opponent.\n\n\n","metadata":{}},{"cell_type":"code","source":"early_stopping = EarlyStopping(\n    min_delta=0.001, # minimium amount of change to count as an improvement\n    patience=5, # how many epochs to wait before stopping\n    restore_best_weights=True,\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:58:41.148174Z","iopub.execute_input":"2023-10-05T03:58:41.148625Z","iopub.status.idle":"2023-10-05T03:58:41.153833Z","shell.execute_reply.started":"2023-10-05T03:58:41.148585Z","shell.execute_reply":"2023-10-05T03:58:41.152557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 3.5 Reduction learning_rate\n\nReduction of the learning rate means decreasing the step size (learning rate) during training to help a machine learning model converge more effectively and avoid convergence issues.","metadata":{}},{"cell_type":"code","source":"# Configure the learning rate reduction callback\nlearning_rate_reduce = ReduceLROnPlateau(\n    monitor='val_acc',   # Metric to monitor for changes (usually validation accuracy)\n    patience=5,          # Number of epochs with no improvement after which learning rate will be reduced\n    verbose=1,           # Verbosity mode (0: silent, 1: update messages)\n    factor=0.5,          # Factor by which the learning rate will be reduced (e.g., 0.5 means halving)\n    min_lr=0.00001       # Lower bound for the learning rate (it won't go below this value)\n)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:59:01.007505Z","iopub.execute_input":"2023-10-05T03:59:01.007846Z","iopub.status.idle":"2023-10-05T03:59:01.013086Z","shell.execute_reply.started":"2023-10-05T03:59:01.007820Z","shell.execute_reply":"2023-10-05T03:59:01.012133Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Exponential Decay\n</h1>\n\n# 4.Exponential Decay\n\n📕 ***ExponentialDecay*** is a learning rate schedule that reduces the learning rate exponentially over time. This is done by multiplying the learning rate by a factor of less than 1, such as 0.5 or 0.9, after a certain number of epochs or training steps.\n\n- The formula for exponential decay can be expressed as:\n\n##  ***New Value = Initial Value × Decay Rate ^(Step Count)***\n\n\n For example, if you start with an initial learning rate of `0.1` and use an exponential decay rate of `0.9`, the learning rate might evolve as follows:\n\n- After 1 step: \\(0.1 \\times 0.9^1 = 0.09\\)\n- After 2 steps: \\(0.1 \\times 0.9^2 = 0.081\\)\n- After 3 steps: \\(0.1 \\times 0.9^3 = 0.0729\\)\n- ...\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12053762%2F33e63b666e59d83dc3f11e46f4d04430%2F640px-Plot-exponential-decay.svg.png?generation=1695445033268258&alt=media)\n\n📘 `ExponentialDecay` is a common and effective learning rate schedule **for image classification**. It is often used in conjunction with other techniques, such as momentum and weight decay, **to improve the performance of deep learning models.**\n\n✔️ Here are some of the **benefits** of using `ExponentialDecay`:\n\n* It can help to **prevent overfitting** by reducing the learning rate over time.\n* It can help the model to converge **more quickly and smoothly.**\n* It can help to **improve the fine-tuning** performance of the model.\n\n❌ However, there are also some **potential drawbacks** to using` ExponentialDecay`:\n\n* It can be **difficult to choose the right initial learning rate and decay rate.**\n* It can be **slow to converge in the early stages of training.**\n\n💡 ***Overall***, `ExponentialDecay` is a powerful learning rate schedule that **can be used to improve the performance of deep learning models**. However, **it is important to carefully consider the benefits and drawbacks before using it.**","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras import optimizers\n\n# Create a learning rate schedule using Exponential Decay\nlearning_rate_schedule = keras.optimizers.schedules.ExponentialDecay(\n    initial_learning_rate=0.01,  # Initial learning rate for training\n    decay_steps=1000,            # Number of steps before decaying the learning rate\n    decay_rate=0.5,              # Rate at which the learning rate decreases\n)\n\n# learning_rate = initial_learning_rate * decay_rate ^ (global_step / decay_steps)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:59:12.767735Z","iopub.execute_input":"2023-10-05T03:59:12.768083Z","iopub.status.idle":"2023-10-05T03:59:12.773153Z","shell.execute_reply.started":"2023-10-05T03:59:12.768057Z","shell.execute_reply":"2023-10-05T03:59:12.772155Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from keras.callbacks import LearningRateScheduler\n\n# Create a Learning Rate Scheduler callback using a pre-defined schedule\nlr_callback = LearningRateScheduler(learning_rate_schedule)\ncallback=[ lr_callback , learning_rate_reduce ,early_stopping ]","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:59:16.642721Z","iopub.execute_input":"2023-10-05T03:59:16.643456Z","iopub.status.idle":"2023-10-05T03:59:16.648695Z","shell.execute_reply.started":"2023-10-05T03:59:16.643426Z","shell.execute_reply":"2023-10-05T03:59:16.647357Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Transfer Learning \n</h1>\n\n# 5.Transfer Learning \n\n#### We have chosen DeseNet-121v2 for training our model \n#### Here we have a definition and some reasons why we have chosen DeseNet-121v2\nDenseNet-121v2 is a specific variant of the DenseNet architecture, and when comparing it to other popular transfer learning models like ResNet, Inception, and VGG, here are three key differences:\n\n1. **Dense Connectivity**: DenseNet is characterized by dense connectivity between layers. In a DenseNet, each layer receives input from all previous layers. This is in contrast to models like ResNet, where layers are connected by skip connections, but not every layer is directly connected to every other layer. The dense connectivity in DenseNet promotes feature reuse and helps gradients flow more efficiently during training.\n\n2. **Parameter Efficiency**: DenseNet is more parameter-efficient compared to some other architectures like VGG or traditional deep networks. This is because of the shared feature maps and feature concatenation in each layer. The dense connectivity allows you to achieve similar or better performance with fewer parameters, which can be advantageous in scenarios with limited computational resources.\n\n3. **Gradient Flow**: DenseNet's architecture helps in maintaining a strong gradient flow during training. With each layer directly connected to every other layer, the gradients have a clear path to propagate through the network. This can lead to faster convergence during training and makes it easier to train very deep networks.\n\nThese differences make DenseNet-121v2 a unique and effective choice for various computer vision tasks, especially when you have limited data or computational resources. However, the choice of which transfer learning model to use ultimately depends on the specific requirements of your task and the trade-offs you are willing to make in terms of computational complexity and model size.","metadata":{}},{"cell_type":"markdown","source":"### 5.1 Get the weights from DenseNet121","metadata":{}},{"cell_type":"code","source":"base_model = DenseNet121(weights='imagenet', include_top=False, input_shape=(size_images, size_images, 3))","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2023-10-05T03:59:25.288451Z","iopub.execute_input":"2023-10-05T03:59:25.288786Z","iopub.status.idle":"2023-10-05T03:59:33.532116Z","shell.execute_reply.started":"2023-10-05T03:59:25.288759Z","shell.execute_reply":"2023-10-05T03:59:33.531114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 5.2 Freeze the layers of DenseNet121","metadata":{}},{"cell_type":"code","source":"# Freeze the layers of the base model\nfor layer in base_model.layers:\n    layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2023-10-05T03:59:42.517900Z","iopub.execute_input":"2023-10-05T03:59:42.518486Z","iopub.status.idle":"2023-10-05T03:59:42.533907Z","shell.execute_reply.started":"2023-10-05T03:59:42.518446Z","shell.execute_reply":"2023-10-05T03:59:42.532913Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Build the model\n</h1>\n\n# 6.Build the model","metadata":{}},{"cell_type":"code","source":"model = tf.keras.models.Sequential([\n    base_model,\n    \n    layers.Flatten(),\n    \n    layers.Dense(256,activation='relu'),\n    layers.Dense(128,activation='relu'),\n    layers.Dense(64,activation='relu'),\n    layers.Dropout(0.5),\n    layers.Dense(2,activation='softmax'),\n])\n\nmodel.summary()","metadata":{"_kg_hide-input":true,"execution":{"iopub.status.busy":"2023-10-05T04:00:38.894017Z","iopub.execute_input":"2023-10-05T04:00:38.894373Z","iopub.status.idle":"2023-10-05T04:00:39.887679Z","shell.execute_reply.started":"2023-10-05T04:00:38.894345Z","shell.execute_reply":"2023-10-05T04:00:39.886643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n","metadata":{"execution":{"iopub.status.busy":"2023-10-05T04:00:04.122408Z","iopub.execute_input":"2023-10-05T04:00:04.122762Z","iopub.status.idle":"2023-10-05T04:00:04.663442Z","shell.execute_reply.started":"2023-10-05T04:00:04.122737Z","shell.execute_reply":"2023-10-05T04:00:04.662096Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 6.1 Set the optimizer","metadata":{}},{"cell_type":"code","source":"optimizer = optimizers.Adam(learning_rate=learning_rate_schedule)","metadata":{"execution":{"iopub.status.busy":"2023-10-05T04:00:51.766111Z","iopub.execute_input":"2023-10-05T04:00:51.767259Z","iopub.status.idle":"2023-10-05T04:00:51.803079Z","shell.execute_reply.started":"2023-10-05T04:00:51.767210Z","shell.execute_reply":"2023-10-05T04:00:51.801635Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(optimizer=optimizer,\n             loss=\"categorical_crossentropy\",\n              metrics=['accuracy']\n             )","metadata":{"execution":{"iopub.status.busy":"2023-10-05T04:00:58.370266Z","iopub.execute_input":"2023-10-05T04:00:58.370648Z","iopub.status.idle":"2023-10-05T04:00:58.393401Z","shell.execute_reply.started":"2023-10-05T04:00:58.370623Z","shell.execute_reply":"2023-10-05T04:00:58.392099Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 6.2 Training the model","metadata":{}},{"cell_type":"code","source":"history = model.fit(\n    train_generator,\n    steps_per_epoch=train_generator.samples // batch_size,\n    epochs=5,\n    validation_data=test_generator,\n    validation_steps=test_generator.samples // batch_size,\n    callbacks=[callback]\n)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint\n\n# 定义一个回调函数，保存模型的权重\ncheckpoint = ModelCheckpoint('best_model_weights.h5', \n                             monitor='val_accuracy',  # 监控验证准确率\n                             save_best_only=True,     # 仅保存验证性能最佳的模型\n                             mode='max',              # 监控模式，根据验证准确率的最大值保存模型\n                             verbose=1)               # 显示保存信息\n\n# 在model.fit中使用回调函数\nhistory = model.fit(train_generator, \n                    epochs=5, \n                    callbacks=[checkpoint],    # 将回调函数添加到训练中\n                    validation_data=test_generator)\n","metadata":{"execution":{"iopub.status.busy":"2023-10-05T04:01:29.153438Z","iopub.execute_input":"2023-10-05T04:01:29.153950Z","iopub.status.idle":"2023-10-05T04:10:34.136412Z","shell.execute_reply.started":"2023-10-05T04:01:29.153914Z","shell.execute_reply":"2023-10-05T04:10:34.135452Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Evaluate the model\n</h1>\n\n# 7. Evaluate the model","metadata":{}},{"cell_type":"markdown","source":"### 7.1 Evaluate the validation","metadata":{}},{"cell_type":"code","source":"# Evaluate on test dataset\nscore = model.evaluate(test_generator, verbose=False)\nprint('Test loss:', score[0])\nprint('Test accuracy:', score[1])","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 7.2 Accuracy graph ","metadata":{}},{"cell_type":"code","source":"# Accuracy\nacc = history.history['accuracy']\nval_acc = history.history['val_accuracy']\nepochs = range(len(acc))\n\nplt.plot(epochs, acc, 'b', label='Training Accuracy')\nplt.plot(epochs, val_acc, 'r', label='Validation Accuracy')\nplt.title('Accuracy Graph')\nplt.legend()\nplt.figure()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 7.3 Loss graph ","metadata":{}},{"cell_type":"code","source":"# Loss\nloss = history.history['loss']\nval_loss = history.history['val_loss']\nplt.plot(epochs, loss, 'b', label='Training Loss')\nplt.plot(epochs, val_loss, 'r', label='Validation Loss')\nplt.title('Loss Graph')\nplt.legend()\nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 7.4 Confusion Matrix","metadata":{}},{"cell_type":"code","source":"# Confusion Matrix\nimport itertools\n\n# Make predictions on the test data\npredictions = model.predict(test_generator)\n\n# Convert probabilities to class labels\npredicted_labels = np.argmax(predictions, axis=1)\n\n# Get true labels from the test_generator\ntrue_labels = test_generator.classes\n\n# Calculate confusion matrix\ncm = confusion_matrix(true_labels, predicted_labels)\n\n# Define class names (assuming you have class_names defined)\nclass_names = test_generator.class_indices.keys()\n\n# Plot confusion matrix\ndef plot_confusion_matrix(cm, classes, normalize=False, title=\"Confusion Matrix\", cmap=plt.cm.Blues):\n    plt.imshow(cm, interpolation=\"nearest\", cmap=cmap)\n    plt.title(title)\n    plt.colorbar()\n    tick_marks = np.arange(len(classes))\n    plt.xticks(tick_marks, classes, rotation=45)\n    plt.yticks(tick_marks, classes)\n\n    if normalize:\n        cm = cm.astype(\"float\") / cm.sum(axis=1)[:, np.newaxis]\n\n    thresh = cm.max() / 2.0\n    for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])):\n        plt.text(j, i, cm[i, j], horizontalalignment=\"center\", color=\"white\" if cm[i, j] > thresh else \"black\")\n\n    plt.tight_layout()\n    plt.ylabel(\"True label\")\n    plt.xlabel(\"Predicted label\")\n\n# Plot non-normalized confusion matrix\nplt.figure(figsize=(8, 6))\nplot_confusion_matrix(cm, classes=class_names, title=\"Confusion Matrix\")\nplt.show()\n","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### 7.5 Generate predictions for the test data","metadata":{}},{"cell_type":"code","source":"# Generate predictions for the test data\npredictions = model.predict(test_generator)\n\n# Retrieve true labels from the generator (assuming class_mode is 'categorical')\ntrue_labels = test_generator.classes\n\n# Get the class labels\nclass_labels = list(test_generator.class_indices.keys())\n\n# Plot images with true and predicted labels\nfig, axes = plt.subplots(nrows=3, ncols=3, figsize=(10, 10))\nfor i in range(9):\n    plt.figure(figsize=(6, 6))\n    \n    # Plot the image\n    ax = axes[i // 3, i % 3]\n    image = test_generator[i][0][0]  # Change [0][0] depending on your generator setup\n    ax.imshow(image)\n    \n    # True label\n    true_label = class_labels[true_labels[i]]\n    \n    # Predicted label\n    predicted_label = class_labels[np.argmax(predictions[i])]\n    \n    ax.set_title(f'Predicted: {predicted_label}')\n    ax.axis('off')\n    \nplt.show()","metadata":{"_kg_hide-input":true,"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"section-1\"></a>\n<h1 style=\"background-color: #87CEFA; color: #000; text-align: center; border: 2px solid #000; border-radius: 10px; padding: 10px; box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.75); transform: rotateX(10deg);\">\n  Conclusion\n</h1>\n\n\n# 8. Conclusion\n#### I hope this code can help you, if you liked this notebook please  press up votes, thanks ❤\n","metadata":{}}]}