{"id":8997,"date":"2021-03-17T19:06:45","date_gmt":"2021-03-17T13:36:45","guid":{"rendered":"https:\/\/www.h2kinfosys.com\/blog\/?p=8997"},"modified":"2025-10-27T02:37:06","modified_gmt":"2025-10-27T06:37:06","slug":"transfer-learning-in-keras-with-examples","status":"publish","type":"post","link":"https:\/\/www.h2kinfosys.com\/blog\/transfer-learning-in-keras-with-examples\/","title":{"rendered":"Transfer learning in Keras with Examples"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\"><strong>Introduction: The Power of Transfer Learning in AI<\/strong><\/h3>\n\n\n\n<p>In today\u2019s era of Artificial Intelligence, achieving high model accuracy often requires enormous datasets and significant computational power. However, not every organization or learner has access to millions of labeled images or high-end GPUs. This is where <strong>Transfer Learning<\/strong> comes to the rescue.<\/p>\n\n\n\n<p>Transfer Learning enables developers to leverage pre-trained models such as VGG16, ResNet, or Inceptionthat have already been trained on massive datasets like ImageNet. By reusing these models, you can adapt them for your own tasks, saving time, effort, and computational resources.<\/p>\n\n\n\n<p>If you\u2019ve ever enrolled in an <strong><a href=\"https:\/\/www.h2kinfosys.com\/courses\/artificial-intelligence-online-training-course-details\/\">Artificial intelligence certification course<\/a><\/strong> or explored <strong>online courses for artificial intelligence<\/strong>, you\u2019ve likely encountered Transfer Learning in deep learning modules. It\u2019s one of the most practical and efficient techniques for model optimization and fast experimentation.<\/p>\n\n\n\n<p>Training a deep neural network on a large dataset takes a lot of time. For instance, the popular AlexNet took 5 to 6 days for training and did that with two GPUs. Not everyone has access to these computational requirements to train such a dataset and even at that, the time it takes. Transfer learning provides a way of avoiding these long training times when building a neural network. This popular technique involves re-using the weights of an already trained model that was built by a robust dataset. An example of such a dataset would be the training data in the ImageNet competition that contained more than 1 million dataset. The models that performed well on this kind of data can then be downloaded and reused in a new computer vision problem. That is transfer learning. In this tutorial, we will take a look at what transfer learning is about and how to build a CNN using transfer learning.<\/p>\n\n\n\n<p>By the end of this tutorial, you will discover the following:<\/p>\n\n\n\n<p>Let\u2019s get started.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What is Transfer Learning<\/h2>\n\n\n\n<p>Transfer learning is the act of reusing an already built model that was trained on a dataset to solve a particular problem in another closely related problem. Tranfer learning is an important concept for data scientists to understand because not only does it save the time required for training the data. But it also allows you to make use of powerful models without needing so much computing power. It is basically a weight initialization scheme where the weights of a model that has done well on a data is used in another data.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using Transfer Learning for Image Recognition<\/h2>\n\n\n\n<p>During the ImageNet challenge that lasted for 9 years, a lot of high performing image classification models were built. As of the last year of the competition, the winning model had an error rate of less than 5%, way better than human capabilities. These models have paved the way for the massive advancement that deep learning has brought especially through image recognition. What\u2019s more interesting is that the models have been released to the public for personal consumption under a permissive license. Examples of such models include VGGNet, ResNet, Xception, DenseNet etc.&nbsp;<\/p>\n\n\n\n<p>The availability of these models have formed the bedrock for transfer learning. Researchers do not have to reinvent the wheel by training models over and over again. Since these models were trained on over 1 million dataset and with over 1000 classes, they have proved to generalise well on new dataset that seeks to perform a similar task.&nbsp;<\/p>\n\n\n\n<p>The model can be accessed through APIs and are downloadable for free. Going forward in this tutorial, we will see how to use one of these <a href=\"https:\/\/www.h2kinfosys.com\/blog\/how-to-install-keras-and-use-to-build-deep-neural-network\/\" class=\"rank-math-link\">models in Keras<\/a>.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use Pretrained Models&nbsp;<\/h2>\n\n\n\n<p>The possibilities with transfer learning are limitless. We can also apply them to as far as we know. Generally speaking, using pretrained models follows 3 patterns:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Building a classifier: The models from ImageNet can be downloaded and without training, used immediately for classifying new images.&nbsp;<\/li>\n\n\n\n<li>Used a feature extractor: This is perhaps the most popular use case. Since convolutional neural networks identify images by learning progressively after each layer, the layers preceding the output layer can be reused for other similar tasks. In cases where the task is not so similar, the earlier layers which, at that point, identify lines, shadows, etc can be used for the basic pattern recognition. Further stacking these initial layers on a new set of layers gives you the ability to use great initial weights for pattern recognition then your own layers for the purpose you had in mind.&nbsp;<\/li>\n<\/ul>\n\n\n\n<p>On the hand, if you hope to perform a similar model like the pre-trained model at your disposal. You can take out the input layer to fit the sort of data you wish to pass in. In addition, you will take out the output layer to fit the number of classes your data contains. Finally, you will leave all the hidden layers as-is, without training.&nbsp;<\/p>\n\n\n\n<p>Using this approach, you can classify other images that were not contained in the ImageNet dataset with good accuracy. As earlier mentioned, this saves you computational power and training time since you would not need to train the model.&nbsp;<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Using the models for weight initialization: This involves using a portion of the pretrained model and using its weights initialization. In order words, that portion of the pretrained model is not trained by you. Their weights are initialized and used as is or are trained with a much lower learning rate so that the model still behaves like a weight initialization setup.&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Using Pre-trained models in Keras<\/h2>\n\n\n\n<p>Keras offers a myriad of powerful pre-trained models especially from the <a href=\"https:\/\/en.wikipedia.org\/wiki\/ImageNet\" class=\"rank-math-link\" rel=\"nofollow noopener\" target=\"_blank\">ImageNet competitions<\/a>. They can be accepted from the Applications API of Keras. The models can either be used on the pre-trained weights or without. One thing to point out is that it is good practice to prepare the models in ways that the pre-trained model would expect. For instance, the pretrained model may expect the image to be scaled within some range or the pixel within a particular value. To make the best of the model, you need to make sure the input data are in the format they expect. Some of the pre-trained models available in Keras include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>XCeption<\/li>\n\n\n\n<li>VGG16<\/li>\n\n\n\n<li>VGG19<\/li>\n\n\n\n<li>ResNet50<\/li>\n\n\n\n<li>ResNet101<\/li>\n\n\n\n<li>InceptionV3<\/li>\n\n\n\n<li>MobileNet<\/li>\n\n\n\n<li>DenseNet etc.<\/li>\n<\/ul>\n\n\n\n<p>Each of those models has its different architecture, number of parameters to be trained on and by extension top accuracy. Going forward, we will use the VGGNet16 model to classify images of our own.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using the VGGNet16 Model as an Object Detector<\/h2>\n\n\n\n<p>In this section, we will use the VGGNet model to classify a completely new image. To be sure the VGGNet model has not seen the image, the picture to be fed into the model was taken by me. It is an image of one of the cups in my home. Here is the picture of my beautiful cup.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/sTDIn5BK6czLJsB9u-m-VcLma4a6IbJ6rKL0NC3Vp8XESJuAoc5detOT9wtNobOX2CvCX4Qtel21vr7R3Jnv13MrbNIy-yhb-4z6H08wIthMXhce8mjglvufpLOzgx0ftFbvGphn\" alt=\"\" title=\"\"><\/figure>\n\n\n\n<p>Now let\u2019s use the VGGNet model to classify the image.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Sep 1: Load the file as an image.&nbsp;<\/h3>\n\n\n\n<p>The load_img() function of Keras is used for this purpose.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">from keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions\nfrom keras import Input\nfrom keras.preprocessing.image import load_img, img_to_array\n&nbsp;\n#load the image\nmy_image = load_img('cup.jpeg', target_size=(224, 224))\n<\/pre>\n\n\n\n<p>Observe two things. First the image was saved as cup.jpeg in the exact file location where the jupyter notebook is. Second a parameter called target_size was set to (224, 224). This is the shape of the image the VGGNet model expects. Since my phone camera may have higher pixels, it is important to reduce its pixels to such a shape.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Convert the image to array<\/h3>\n\n\n\n<p>It is no longer news that all machine learning models work with numbers. The images therefore need to be converted to an array before being fed into the model. Once again, a Keras function called img_to_array() is used for this purpose.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#convert the image to an array\nmy_image = img_to_array(my_image)\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Reshape and preprocess the array the array<\/h3>\n\n\n\n<p>Since it is coloured image, the actual image size is a 3-dimensional array of shape (3, 224, 224). The VGGNet however requires a 4-dimensional array of (1, 3, 224, 224). The extra one dimensional is to accommodate the fact that numerous samples\/batches of images can be passed into the model at once. Also, there is a need to prepare the image for the model. The preprocess_input function is used for this purpose. Let\u2019s reshape the image and preprocess it for the model.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#reshape the image\nmy_image = my_image.reshape((1, my_image.shape[0], my_image.shape[1], my_image.shape[2]))\n#preprocess the image to be in the best form for the model\nmy_image = preprocess_input(my_image)\n<\/pre>\n\n\n\n<p>Step 4: Instantiate the model and make predictions on the image (array).&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#instantiate the model\nmodel = VGG16()\n#make predictions\nprediction = model.predict(my_image)\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Interpret the result&nbsp;<\/h3>\n\n\n\n<p>The predict() method returns the probabilities of each of the classes in the dataset. To convert the probabilities to the actual label, the decode_predictions() function is used. Now all the labels are returns sorted in descending order of their probabilities. But what we care about is the label with the highest probabilities, i.e the first label returned. The first item can be accessed through indexing as seen in the block of code below.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#change the probabilities to actual labels\nprediction = decode_predictions(prediction)\n#return the label with the highest probability\nitem = prediction[0][0]\n&nbsp;\n# print the result\nprint(f\"{item[1]} with a probability of {int(item[2]*100)}%\")<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\ncoffee_mug with a probability of 25%\n<\/code><\/pre>\n\n\n\n<p>As seen, the model predicts a coffee mug, going beyond just the general name but with a pretty accurate description.&nbsp; Here is the entire code for the model.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#import necessary libraries\nfrom keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions\nfrom keras import Input\nfrom keras.preprocessing.image import load_img, img_to_array\n&nbsp;\n#load the image\nmy_image = load_img('cup.jpeg', target_size=(224, 224))\n&nbsp;\n#convert the image to an array\nmy_image = img_to_array(my_image)\n&nbsp;\n#reshape the image\nmy_image = my_image.reshape((1, my_image.shape[0], my_image.shape[1], my_image.shape[2]))\n#preprocess the image to be in the best form for the model\nmy_image = preprocess_input(my_image)\n&nbsp;\n#instantiate the model\nmodel = VGG16()\n#make predictions\nprediction = model.predict(my_image)\n&nbsp;\n#change the probabilities to actual labels\nprediction = decode_predictions(prediction)\n#return the label with the highest probability\nitem = prediction[0][0]\n&nbsp;\n# print the result\nprint(f\"{item[1]} with a probability of {int(item[2]*100)}%\")<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Using Transfer Learning for Image Classification<\/h2>\n\n\n\n<p>In this section, we will go ahead to use the VGGNet model to build an image classifier model. The model will predict whether it is sunny, rainy, sunrise or cloudy based on the image passed to it. The dataset could be downloaded <a href=\"https:\/\/data.mendeley.com\/datasets\/4drtyfjtfy\/1\" rel=\"nofollow noopener\" target=\"_blank\">here<\/a>.&nbsp;<\/p>\n\n\n\n<p>The idea is to use the VGGNet architecture except that the first layer would be chopped off, the last layer that would be flattened and a connected layer with 4 nodes will be added. This of course makes sense, since the model we want to predict contains only 4 classes.<\/p>\n\n\n\n<p>See how the dataset is arranged on my PC and how the cloudy pictures are.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/RtkbR51lvTF-51VJrq79eSjq8H3ED5fVxbrq7F1XYmgKZsGirAdWxyNuIFY4nvPdmgkYOHQhGXBTCa_eIm33bXmExnDhlUydkvv8XFU14CW4JdPyB_QFzOKq7h6Qf6afonleSZd0\" alt=\"\" title=\"\"><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/QNgvxfR5-EDDxEEKa-sH5q6akVucC_HIqAvFOHB-L4YX3LHejgUEOqmow_q7_DeICDNrTGy1pePtkQkDzZVtwUFHzXNGaWL6C36Q3aIMg4m6iv37xB_sklZE4C_20GXGUHZiAZ3z\" alt=\"\" title=\"\"><\/figure>\n\n\n\n<p><img fetchpriority=\"high\" decoding=\"async\" width=\"624\" height=\"376\" src=\"https:\/\/lh4.googleusercontent.com\/mX0M7JCaczwq57sDIrFr0Zjl0kHMsDSFigWg3DMwVxHL5N4dkveGE1dmKGp384UKSD1F89EyGazBoCjStJlPaPVJ9ILPw2b1M5AboucQ3jV7aU9pQItm1qsiv6ZWLUUQnGZV2Mli\" alt=\"\" title=\"\">To begin, we import all necessary libraries.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#import all necessary libraries\nimport numpy as np\nimport matplotlib.pyplot as plt\nfrom glob import glob\nfrom keras.models import Model\nfrom keras.applications.vgg16 import VGG16, preprocess_input, decode_predictions\nfrom keras import Input\nfrom keras.preprocessing.image import load_img, img_to_array, ImageDataGenerator\nfrom keras.layers import Dense, Flatten<\/pre>\n\n\n\n<p>First thing is to instantiate the VGGNet model taking the imagenet weights. The first layer is not included because the data to be fed into the network is different. Next, we flatten the last late so that a fully connected layer which would serve as the output layer can be stacked on top of it. The functional API is used to create the model. The input shape is the shape the VGGNet model expects while the output is the fully connected layer with 4 nodes that represents each class. To have an overview of what the model looks like, you can use the summary() method. The code showcases how to implement the above explanation.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#instantiate the VGG model\nvgg = VGG16(weights='imagenet', include_top=False)\n\n#ensure the layers are not trained. In order words, the weights are used as is\nfor layer in vgg.layers:\n&nbsp;&nbsp;&nbsp;&nbsp;layer.trainable = False\n&nbsp;&nbsp;&nbsp;&nbsp;\n#flatten the last layer and add a fully connected layer as output\nhidden = Flatten()(vgg.output)\noutputs = Dense(4, activation='softmax')(hidden)\n&nbsp;\n#create the model\nmodel = Model(inputs=vgg.input, outputs=outputs)\n&nbsp;\n#check the model architecture\nmodel.summary()\n<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\nModel: \"model\"\n_________________________________________________________________\nLayer (type)                 Output Shape              Param #   \n=================================================================\ninput_11 (InputLayer)        &#91;(None, 224, 224, 3)]     0         \n_________________________________________________________________\nblock1_conv1 (Conv2D)        (None, 224, 224, 64)      1792      \n_________________________________________________________________\nblock1_conv2 (Conv2D)        (None, 224, 224, 64)      36928     \n_________________________________________________________________\nblock1_pool (MaxPooling2D)   (None, 112, 112, 64)      0         \n_________________________________________________________________\nblock2_conv1 (Conv2D)        (None, 112, 112, 128)     73856     \n_________________________________________________________________\nblock2_conv2 (Conv2D)        (None, 112, 112, 128)     147584    \n_________________________________________________________________\nblock2_pool (MaxPooling2D)   (None, 56, 56, 128)       0         \n_________________________________________________________________\nblock3_conv1 (Conv2D)        (None, 56, 56, 256)       295168    \n_________________________________________________________________\nblock3_conv2 (Conv2D)        (None, 56, 56, 256)       590080    \n_________________________________________________________________\nblock3_conv3 (Conv2D)        (None, 56, 56, 256)       590080    \n_________________________________________________________________\nblock3_pool (MaxPooling2D)   (None, 28, 28, 256)       0         \n_________________________________________________________________\nblock4_conv1 (Conv2D)        (None, 28, 28, 512)       1180160   \n_________________________________________________________________\nblock4_conv2 (Conv2D)        (None, 28, 28, 512)       2359808   \n_________________________________________________________________\nblock4_conv3 (Conv2D)        (None, 28, 28, 512)       2359808   \n_________________________________________________________________\nblock4_pool (MaxPooling2D)   (None, 14, 14, 512)       0         \n_________________________________________________________________\nblock5_conv1 (Conv2D)        (None, 14, 14, 512)       2359808   \n_________________________________________________________________\nblock5_conv2 (Conv2D)        (None, 14, 14, 512)       2359808   \n_________________________________________________________________\nblock5_conv3 (Conv2D)        (None, 14, 14, 512)       2359808   \n_________________________________________________________________\nblock5_pool (MaxPooling2D)   (None, 7, 7, 512)         0         \n_________________________________________________________________\nflatten_4 (Flatten)          (None, 25088)             0         \n_________________________________________________________________\ndense_4 (Dense)              (None, 4)                 100356    \n=================================================================\nTotal params: 14,815,044\nTrainable params: 100,356\nNon-trainable params: 14,714,688\n_______________________________________________________________\n<\/code><\/pre>\n\n\n\n<p>The next step is to compile the model. The model was compiled using the categorical cross entropy loss, accuracy metrics and an adam optimizer.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#compile the model\nmodel.compile(optimizer='adam', loss='categorical_crossentropy', metrics='accuracy')<\/pre>\n\n\n\n<p>Now that model architecture has been successfully built, the next step is to define the datasets that would be passed into the model. The dataset has been split into Train and Test folders on my machine. In Keras, we use the ImageGenerator class to perform the necessary data preprocessing and augmentation to have a more robust data to be trained on. For instance, if a model is trained to identify a cup from only one angle, there is a tendency for wrong prediction if the angle at which the picture was taken changes. Hence, horizontal and vertical flip was activated, alongside some zoon and all. Note that the data augmentation is only necessary for the train data. The test data only need to be normalized such that the pixel values range from 0 to 1.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#generate the train and test data&nbsp;\ntrain_data_gen = ImageDataGenerator(rescale=1.0\/255,&nbsp;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;shear_range=0.5,\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zoom_range=0.7,&nbsp;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;horizontal_flip=True,\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vertical_flip=True)\n&nbsp;\ntest_data_gen = ImageDataGenerator(rescale=1.0\/255)\n&nbsp;\ntrain_data = train_data_gen.flow_from_directory('Weather\/Train',\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target_size=(224, 224),\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class_mode='categorical')\n&nbsp;\ntest_data = test_data_gen.flow_from_directory('Weather\/Test',\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;target_size=(224, 224),\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class_mode='categorical')\n<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\nFound 925 images belonging to 4 classes.\nFound 200 images belonging to 4 classes.\n<\/code><\/pre>\n\n\n\n<p>As seen, it discovers the 4 classes and the respective number of images contained in the dataset.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#fit the model\nhistory = model.fit_generator(train_data, validation_data=test_data, epochs=5)\n<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\nEpoch 1\/5\n29\/29 &#91;==============================] - 342s 12s\/step - loss: 1.5313 - accuracy: 0.4267 - val_loss: 1.0044 - val_accuracy: 0.5400\nEpoch 2\/5\n29\/29 &#91;==============================] - 330s 11s\/step - loss: 0.6061 - accuracy: 0.7654 - val_loss: 0.2769 - val_accuracy: 0.9350\nEpoch 3\/5\n29\/29 &#91;==============================] - 330s 11s\/step - loss: 0.4741 - accuracy: 0.8202 - val_loss: 0.4416 - val_accuracy: 0.8700\nEpoch 4\/5\n29\/29 &#91;==============================] - 334s 12s\/step - loss: 0.3433 - accuracy: 0.8863 - val_loss: 0.2776 - val_accuracy: 0.9250\nEpoch 5\/5\n29\/29 &#91;==============================] - 338s 12s\/step - loss: 0.3262 - accuracy: 0.8750 - val_loss: 0.1970 - val_accuracy: 0.9400<\/code><\/pre>\n\n\n\n<p>As seen, in five epochs, it has an accuracy of 87.9% and a validation accuracy of 94%.<\/p>\n\n\n\n<p>Now, let&#8217;s test the model on a completely new image. It is a beautiful morning, just about 9am here and the sun is rising. I decided to go out and take a picture of the sunrise. Here is the lovely picture.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/u4XKf1p2kwK3Of6a-2a_GdPzTpNSRAmRDP_hNckOUsYW0Y7PMQiUxJ1m5bsVxrCqMTD8VFK65XiBfJqGxbjTOgQWxIQY61s_xPR98Lb4EdpJhxbzP1AM2_wlZGcWWBr__hIb3rLr\" alt=\"\" title=\"\"><\/figure>\n\n\n\n<p>Because I took this picture myself, I can be sure this image was not in the training data. We can write the line of code below to preprocess the image and pass it to our model for prediction. The predict() method returns the list of probabilities for each class.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">#load the image\nmy_image = load_img('weather_test.jpeg', target_size=(224, 224))\n&nbsp;\n#preprocess the image\nmy_image = img_to_array(my_image)\nmy_image = my_image.reshape((1, my_image.shape[0], my_image.shape[1], my_image.shape[2]))\nmy_image = preprocess_input(my_image)\n&nbsp;\n#make the prediction\nprediction = model.predict(my_image)<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\narray(&#91;&#91;3.4296335e-28, 1.6078907e-13, 3.4901095e-19, 1.0000000e+00]],\n      dtype=float32)\n\n<\/code><\/pre>\n\n\n\n<p>To make a clearer result, let\u2019s round up the prediction to whole numbers.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">[np.round(x) for x in prediction]\n<\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>Output:\n&#91;array(&#91;0., 0., 0., 1.], dtype=float32)]\n<\/code><\/pre>\n\n\n\n<p>As seen, the fourth class is the predicted class. See the image below for the classes arrangement.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/CCkPI3z3ufaYZoniLB6RPbv22GKb77xdJl9AOJjYpYrK0LafciXXbtwBGihK0y1qPysH-vWjhHYpCdjFA9TIKi2UUQEogKzcUwC00Q605AlT1yATI9opjm_YEKpU3I9WIrGDsks-\" alt=\"\" title=\"\"><\/figure>\n\n\n\n<p>The fourth class is Sunrise which means the model prediction was correct. This is how to use transfer learning for other image classification problems.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">In summary,&nbsp;<\/h2>\n\n\n\n<p>This tutorial has introduced you to transfer learning and why it is important. We went ahead to build a model for object detection and image classification using the weights from the popular VGGNet model. If you have any questions, feel free to leave them in the comment section and I\u2019d do my best to answer them.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction: The Power of Transfer Learning in AI In today\u2019s era of Artificial Intelligence, achieving high model accuracy often requires enormous datasets and significant computational power. However, not every organization or learner has access to millions of labeled images or high-end GPUs. This is where Transfer Learning comes to the rescue. Transfer Learning enables developers [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":9005,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[498],"tags":[],"class_list":["post-8997","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-artificial-intelligence-tutorials"],"_links":{"self":[{"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/posts\/8997","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/comments?post=8997"}],"version-history":[{"count":2,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/posts\/8997\/revisions"}],"predecessor-version":[{"id":31333,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/posts\/8997\/revisions\/31333"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/media\/9005"}],"wp:attachment":[{"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/media?parent=8997"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/categories?post=8997"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.h2kinfosys.com\/blog\/wp-json\/wp\/v2\/tags?post=8997"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}