{"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":"none","dataSources":[{"sourceId":21154,"databundleVersionId":1243559,"sourceType":"competition"}],"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"Download all important import","metadata":{}},{"cell_type":"markdown","source":"**Flower Classification using Transfer Learning**\nThere are millions of beautiful flowers bursting around every corner, & we've been constantly awed by the beauty & uniqueness of each flower. Classifying different flowers from one another is indeed a challenging task, as there's a plethora of flowers to classify & flowers can appear similar to each other. However, classifying different flower species will be advantageous in the fields such as the pharmaceutical industry, botany, agricultural, & trade activities, which is why we thought of performing this task.\n\nThe main aim of this project is to solve a Supervised Image Classification problem of classifying the flower types - rose, daisy, dandelion, sunflower, & tulip. In the end, we'll have a trained model, which can predict the class of the flower using the Convolutional Neural Networks (CNN).\n\nThe dataset consists of 5 classes of flower species - rose, daisy, dandelion, sunflower, & tulip, each having more than 800 images.\n\nThis project follows a basic workflow:\n\nExamine and understand data\n* Build an input pipeline\n* Build the model\n* Train the model\n* Test the model\nInitially, the following libraries were imported to use in the data conversion process:\n\nHere we are going to import necessary libraries:\nMatplotlib for data visualization\nNumpy to perform array and matrix operations.\nOs provides functions for interacting with the operating system.\nPIL Python Imaging Library which provides the python interpreter with image editing capabilities.\nTensorFlow provides a collection of workflows to develop and train models.\nkeras is used to make the implementation of neural networks easy.\nSequential the core idea of Sequential API is simply arranging the Keras layers in a sequential order.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport matplotlib.pyplot as plt\nimport os\nimport PIL\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.models import Sequential  # Corrected import\nfrom tensorflow.keras.layers import Dense, Flatten, Dropout  # Corrected import\nfrom tensorflow.keras.optimizers import Adam  # Corrected import\n","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:07.238186Z","iopub.execute_input":"2024-03-27T16:12:07.238595Z","iopub.status.idle":"2024-03-27T16:12:11.926184Z","shell.execute_reply.started":"2024-03-27T16:12:07.238552Z","shell.execute_reply":"2024-03-27T16:12:11.924735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# import pathlib\nfrom pathlib import Path\n\n# dataset_url = link of the dataset\ndataset_url = 'https://storage.googleapis.com/download.tensorflow.org/example_images/flower_photos.tgz'\ndata_dir = tf.keras.utils.get_file('flower_photos', origin=dataset_url, untar=True)\ndata_dir = Path(data_dir)\n     ","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:16.536365Z","iopub.execute_input":"2024-03-27T16:12:16.537253Z","iopub.status.idle":"2024-03-27T16:12:16.545858Z","shell.execute_reply.started":"2024-03-27T16:12:16.537206Z","shell.execute_reply":"2024-03-27T16:12:16.544308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# print the data_dir\nprint(data_dir)","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:21.223581Z","iopub.execute_input":"2024-03-27T16:12:21.224244Z","iopub.status.idle":"2024-03-27T16:12:21.230705Z","shell.execute_reply.started":"2024-03-27T16:12:21.224203Z","shell.execute_reply":"2024-03-27T16:12:21.229043Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# visualizing the dandelion class\n\ndandelion = list(data_dir.glob('dandelion/*'))\nprint(dandelion[0])\nPIL.Image.open(str(dandelion[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:25.553512Z","iopub.execute_input":"2024-03-27T16:12:25.553944Z","iopub.status.idle":"2024-03-27T16:12:25.710802Z","shell.execute_reply.started":"2024-03-27T16:12:25.553911Z","shell.execute_reply":"2024-03-27T16:12:25.709737Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# we will visualize for Tuplips\n\ntulips = list(data_dir.glob('tulips/*'))\nprint(tulips[3])\nPIL.Image.open(str(tulips[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:31.951170Z","iopub.execute_input":"2024-03-27T16:12:31.951652Z","iopub.status.idle":"2024-03-27T16:12:32.092945Z","shell.execute_reply.started":"2024-03-27T16:12:31.951592Z","shell.execute_reply":"2024-03-27T16:12:32.091428Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# now we will visualize for Daisy\n\ndaisy = list(data_dir.glob('daisy/*'))\nprint(daisy[0])\nPIL.Image.open(str(daisy[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:37.081285Z","iopub.execute_input":"2024-03-27T16:12:37.081766Z","iopub.status.idle":"2024-03-27T16:12:37.149861Z","shell.execute_reply.started":"2024-03-27T16:12:37.081732Z","shell.execute_reply":"2024-03-27T16:12:37.148530Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# now we will visualize for Roses\n\nroses = list(data_dir.glob('roses/*'))\nprint(roses[3])\nPIL.Image.open(str(roses[0]))","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:41.477955Z","iopub.execute_input":"2024-03-27T16:12:41.478636Z","iopub.status.idle":"2024-03-27T16:12:41.529676Z","shell.execute_reply.started":"2024-03-27T16:12:41.478581Z","shell.execute_reply":"2024-03-27T16:12:41.528563Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# take img height and img width as 180\nimg_height, img_width =180,180\n\n# take batch size as 32\nbatch_size =32\n\n# Preprocess the training data i.e., train_ds\ntrain_ds = tf.keras.preprocessing.image_dataset_from_directory(\n    data_dir,\n    label_mode ='categorical',\n    validation_split =0.2,\n    subset= 'training',\n    seed =123,\n    image_size=(img_height,img_width),\n    batch_size=batch_size\n    )","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:45.635942Z","iopub.execute_input":"2024-03-27T16:12:45.636691Z","iopub.status.idle":"2024-03-27T16:12:46.026070Z","shell.execute_reply.started":"2024-03-27T16:12:45.636637Z","shell.execute_reply":"2024-03-27T16:12:46.024759Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# preprocess the validation data i.e., val_ds\nval_ds = tf.keras.preprocessing.image_dataset_from_directory(\n    data_dir,\n    label_mode ='categorical',\n    validation_split =0.2,\n    subset= 'validation',\n    seed =123,\n    image_size=(img_height,img_width),\n    batch_size=batch_size\n    )","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:55.252355Z","iopub.execute_input":"2024-03-27T16:12:55.252918Z","iopub.status.idle":"2024-03-27T16:12:55.584289Z","shell.execute_reply.started":"2024-03-27T16:12:55.252873Z","shell.execute_reply":"2024-03-27T16:12:55.583267Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# create a variable named class_names which will be equal to trian_ds.class_names\nclass_names = ['daisy', 'dandelion', 'roses', 'sunflowers', 'tulips']\n\n# print the class_names\nprint(class_names)","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:12:59.536248Z","iopub.execute_input":"2024-03-27T16:12:59.536697Z","iopub.status.idle":"2024-03-27T16:12:59.544526Z","shell.execute_reply.started":"2024-03-27T16:12:59.536662Z","shell.execute_reply":"2024-03-27T16:12:59.542965Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nplt.figure(figsize=(10,10))\nfor images,labels in train_ds.take(1):\n  for i in range(6):\n    ax = plt.subplot(3,3,i+1)\n    plt.imshow(images[i].numpy().astype('uint8'))\n    plt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:03.311136Z","iopub.execute_input":"2024-03-27T16:13:03.311958Z","iopub.status.idle":"2024-03-27T16:13:04.253857Z","shell.execute_reply.started":"2024-03-27T16:13:03.311918Z","shell.execute_reply":"2024-03-27T16:13:04.252486Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# declare a variable named resnet_model which will be equal to sequential\nresnet_model = Sequential()\n\n# use pretrained_model\npretrained_model = keras.applications.ResNet50(include_top=False, input_shape=(180,180,3), pooling='avg',\n                                                classes=5, weights='imagenet')\n\n\nfor layer in pretrained_model.layers:\n        layer.trainable =False\n\nresnet_model.add(pretrained_model)","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:10.984281Z","iopub.execute_input":"2024-03-27T16:13:10.984808Z","iopub.status.idle":"2024-03-27T16:13:13.046987Z","shell.execute_reply.started":"2024-03-27T16:13:10.984769Z","shell.execute_reply":"2024-03-27T16:13:13.045694Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# add flatten\nresnet_model.add(Flatten())\n\n# add a Dense layer of 512 neurons and give activation as 'relu'\nresnet_model.add(Dense(512, activation='relu'))\n\n# add a dense layer of 5 neurons and give activation as 'softmax'\nresnet_model.add(Dense(5, activation='softmax'))","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:17.376879Z","iopub.execute_input":"2024-03-27T16:13:17.377277Z","iopub.status.idle":"2024-03-27T16:13:17.388089Z","shell.execute_reply.started":"2024-03-27T16:13:17.377247Z","shell.execute_reply":"2024-03-27T16:13:17.386433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"\n# call the summary attribute of the model\nresnet_model.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:23.104954Z","iopub.execute_input":"2024-03-27T16:13:23.105373Z","iopub.status.idle":"2024-03-27T16:13:23.146283Z","shell.execute_reply.started":"2024-03-27T16:13:23.105342Z","shell.execute_reply":"2024-03-27T16:13:23.144728Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# compile the model with Adam(lr=0.001) optimizer, use categorical_crossentropy as loss, and metrics will be equal to accuracy\nresnet_model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate=0.001), metrics=['accuracy'])    ","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:28.516864Z","iopub.execute_input":"2024-03-27T16:13:28.517335Z","iopub.status.idle":"2024-03-27T16:13:28.532101Z","shell.execute_reply.started":"2024-03-27T16:13:28.517301Z","shell.execute_reply":"2024-03-27T16:13:28.530717Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"history = resnet_model.fit(train_ds, validation_data=val_ds, epochs=10)\n# train upto 10 epochs\n# fit the model in history variable","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:13:34.309309Z","iopub.execute_input":"2024-03-27T16:13:34.309879Z","iopub.status.idle":"2024-03-27T16:55:35.475104Z","shell.execute_reply.started":"2024-03-27T16:13:34.309839Z","shell.execute_reply":"2024-03-27T16:55:35.474182Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(figsize=(12, 6))\n\n# Plot accuracy\nplt.subplot(1, 2, 1)\nplt.plot(history.history['accuracy'], label='Training Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.title('Model Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.legend()\n\n# Plot loss\nplt.subplot(1, 2, 2)\nplt.plot(history.history['loss'], label='Training Loss')\nplt.plot(history.history['val_loss'], label='Validation Loss')\nplt.title('Model Loss')\nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.legend()\n\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:56:48.125822Z","iopub.execute_input":"2024-03-27T16:56:48.127037Z","iopub.status.idle":"2024-03-27T16:56:48.873088Z","shell.execute_reply.started":"2024-03-27T16:56:48.126983Z","shell.execute_reply":"2024-03-27T16:56:48.871569Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# declare a variable named resnet_model which will be equal to sequential\nmodel = Sequential()\n\n# use pretrained_model\npretrained_model = keras.applications.ResNet50(include_top=False, pooling='avg',\n                                                classes=5, weights='imagenet')\n\n\nfor layer in pretrained_model.layers:\n        layer.trainable =False\n\nmodel.add(pretrained_model)\nmodel.add(Dense(256, activation='relu'))\nmodel.add(Dropout(0.6))\nmodel.add(Dense(5, activation='softmax'))\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:56:57.585020Z","iopub.execute_input":"2024-03-27T16:56:57.585460Z","iopub.status.idle":"2024-03-27T16:56:59.093606Z","shell.execute_reply.started":"2024-03-27T16:56:57.585425Z","shell.execute_reply":"2024-03-27T16:56:59.092445Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss='categorical_crossentropy', optimizer=Adam(learning_rate=0.001), metrics=['accuracy'])\n\nresnet2 = model.fit(train_ds, validation_data=val_ds, epochs=10)\n","metadata":{"execution":{"iopub.status.busy":"2024-03-27T16:57:04.158321Z","iopub.execute_input":"2024-03-27T16:57:04.158872Z","iopub.status.idle":"2024-03-27T17:39:16.563369Z","shell.execute_reply.started":"2024-03-27T16:57:04.158830Z","shell.execute_reply":"2024-03-27T17:39:16.561590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plt.figure(1, figsize = (12,3))\n\nplt.subplot(121)\nplt.plot(resnet2.history['accuracy'])\nplt.plot(resnet2.history['val_accuracy'])\nplt.title('model accuracy')\nplt.ylabel('accuracy')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'])\n\nplt.subplot(122)\nplt.plot(resnet2.history['loss'])\nplt.plot(resnet2.history['val_loss'])\nplt.title('model loss')\nplt.ylabel('loss')\nplt.xlabel('epoch')\nplt.legend(['train', 'validation'])\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-03-27T17:39:37.630938Z","iopub.execute_input":"2024-03-27T17:39:37.631394Z","iopub.status.idle":"2024-03-27T17:39:38.149920Z","shell.execute_reply.started":"2024-03-27T17:39:37.631358Z","shell.execute_reply":"2024-03-27T17:39:38.148689Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"**Conclusion**:\nwe embarked on a journey to classify flower species using Transfer Learning with Convolutional Neural Networks (CNNs). Here's a summary of our workflow:\n\n1. **Data Examination:** We started by examining the dataset, which consisted of five classes of flower species: rose, daisy, dandelion, sunflower, and tulip. Each class contained more than 800 images.\n\n2. **Input Pipeline:** We built an input pipeline to preprocess the image data, including resizing, normalization, and augmentation.\n\n3. **Model Building:** Utilizing Transfer Learning, we employed a pre-trained CNN model (such as ResNet or MobileNet) as the base model and added a few additional layers on top for fine-tuning. This allowed us to leverage the pre-trained model's learned features while adapting to our specific task.\n\n4. **Model Training:** We trained our model on the training data while validating its performance on the validation set. We compiled the model with appropriate loss function, optimizer, and metrics and trained it for several epochs.\n\n5. **Model Evaluation:** After training, we evaluated the model's performance on the test set to assess its generalization ability. We visualized the model's accuracy and loss over epochs to understand its training progress.\n\nThroughout this project, we harnessed the power of deep learning to classify flower species accurately. Such models have vast applications in various domains, including agriculture, botany, and pharmaceuticals. By continuing to refine and optimize our models, we can unlock even more insights from image data and contribute to solving real-world challenges.","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}