<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Alex Neal Albinda</title>
    <description>The latest articles on Forem by Alex Neal Albinda (@alasdiel).</description>
    <link>https://forem.com/alasdiel</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3073309%2Fdccbfa31-b45e-40f1-9e2c-e61fc4654e2a.png</url>
      <title>Forem: Alex Neal Albinda</title>
      <link>https://forem.com/alasdiel</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/alasdiel"/>
    <language>en</language>
    <item>
      <title>Cat or Dog? — Building a Binary Image Classifier with TensorFlow</title>
      <dc:creator>Alex Neal Albinda</dc:creator>
      <pubDate>Thu, 24 Apr 2025 13:49:47 +0000</pubDate>
      <link>https://forem.com/up_min_sparcs/cat-or-dog-building-a-binary-image-classifier-with-tensorflow-54da</link>
      <guid>https://forem.com/up_min_sparcs/cat-or-dog-building-a-binary-image-classifier-with-tensorflow-54da</guid>
      <description>&lt;p&gt;&lt;strong&gt;This article is co-authored by &lt;a class="mentioned-user" href="https://dev.to/eerrynnee"&gt;@eerrynnee&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colab.research.google.com/drive/1lfnJEcXCY8V0Gdg-cTu_1j_K7vZzDwsP?usp=sharing" rel="noopener noreferrer"&gt;Interactive version of the article on Google Colab&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this a cat or a dog?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;A simple question — unless you're asking a computer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A few years ago, the idea of teaching a machine to recognize objects in photos might’ve sounded too far-fetched. These days, it’s something you can do in an afternoon, right from your browser.&lt;/p&gt;

&lt;p&gt;This article walks you through how to build a basic &lt;strong&gt;binary image classifier&lt;/strong&gt;, one that can tell whether an image contains a &lt;strong&gt;cat&lt;/strong&gt; or a &lt;strong&gt;dog&lt;/strong&gt;. No deep dives into theory, no expensive hardware required. Just some &lt;strong&gt;Python&lt;/strong&gt;, a &lt;strong&gt;cloud notebook&lt;/strong&gt;, and a &lt;strong&gt;dataset full of furry creatures&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We’ll start by understanding how &lt;strong&gt;image data&lt;/strong&gt; is represented, then &lt;strong&gt;build a model&lt;/strong&gt; using &lt;strong&gt;TensorFlow&lt;/strong&gt; and &lt;strong&gt;Keras&lt;/strong&gt;, and finally train it on &lt;strong&gt;real-world images&lt;/strong&gt;. Along the way, we’ll also reflect on what it means to teach machines to “see”.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is image classification?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Image classification&lt;/strong&gt; is a type of &lt;strong&gt;supervised learning&lt;/strong&gt; where the model learns to associate an &lt;strong&gt;input image&lt;/strong&gt; with a &lt;strong&gt;specific category&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Binary classification&lt;/strong&gt; divides unknown data points into two groups and labels images using an either-or logic. In our case: &lt;strong&gt;cats and dogs&lt;/strong&gt;. The model's output is either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;0 for cat&lt;/li&gt;
&lt;li&gt;1 for dog&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is TensorFlow?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt; is an &lt;strong&gt;open-source platform&lt;/strong&gt; developed by &lt;strong&gt;Google&lt;/strong&gt; for &lt;strong&gt;machine learning&lt;/strong&gt; and &lt;strong&gt;deep learning applications&lt;/strong&gt;. It serves as both a symbolic math library and a robust framework for building complex machine learning models.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt; offers excellent graph representation, supports a variety of backends including GUI and ASIC, and is known for its high performance and strong community support. It also allows easy debugging of graph components and is highly extensible for custom model development.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;Keras&lt;/strong&gt; is a &lt;strong&gt;high-level neural network library&lt;/strong&gt; that runs on top of &lt;strong&gt;TensorFlow&lt;/strong&gt; and provides a user-friendly API for &lt;br&gt;
building deep learning models.&lt;/p&gt;

&lt;p&gt;Designed for simplicity and speed, &lt;strong&gt;Keras&lt;/strong&gt; is ideal for beginners and researchers alike. It offers support for multiple backends, includes a collection of pre-trained models, and enjoys strong community support, making it a go-to tool for rapid prototyping and implementation of neural networks.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Images as Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When we look at a photo, we instantly see a scene: maybe a cat curled on a rug or a golden retriever wagging its tail. But for a computer, an &lt;strong&gt;image&lt;/strong&gt; is a &lt;strong&gt;grid of numbers&lt;/strong&gt;, and not a visual moment.&lt;/p&gt;

&lt;p&gt;Every image is made up of pixels, and each pixel holds numerical values that describe its color. These values are typically represented using three color channels: Red, Green, and Blue (RGB). You can think of each channel as a grayscale image that highlights one component of color.&lt;/p&gt;

&lt;p&gt;So when you load an image into your program, it's actually being read as a 3-dimensional array:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Height&lt;/strong&gt; - the number of vertical pixels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Width&lt;/strong&gt; - the number of horizontal pixels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Channels&lt;/strong&gt; - usually 3 for RGB (sometimes 1 for grayscale, or 4 for RGBA if there's transparency)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, a &lt;strong&gt;200x200&lt;/strong&gt; image with &lt;strong&gt;3 channels&lt;/strong&gt; would be stored as a &lt;strong&gt;200×200×3 matrix&lt;/strong&gt; — and every number inside it ranges from &lt;strong&gt;0 to 255&lt;/strong&gt;, representing &lt;strong&gt;intensity&lt;/strong&gt; (0 = no light, 255 = full light).&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Obtaining the Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In &lt;strong&gt;supervised machine learning&lt;/strong&gt;, particularly in &lt;strong&gt;image classification&lt;/strong&gt; tasks, the performance of a model is heavily influenced by the &lt;strong&gt;quality&lt;/strong&gt; and &lt;strong&gt;size&lt;/strong&gt; of the dataset it is trained on. For this project, the model is trained on a &lt;strong&gt;publicly available dataset&lt;/strong&gt; containing images of &lt;strong&gt;cats and dogs&lt;/strong&gt; obtained from Kaggle.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;What is Kaggle?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Kaggle&lt;/strong&gt; is a platform for data science and machine learning specialists where they may &lt;strong&gt;compete to build the best models for solving specific issues&lt;/strong&gt; or &lt;strong&gt;analyzing specific data&lt;/strong&gt;.  The site also allows users to &lt;strong&gt;collaborate on projects&lt;/strong&gt;, &lt;strong&gt;share code and data sets&lt;/strong&gt;, and &lt;strong&gt;learn from one another's work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We use a dataset titled &lt;a href="https://www.kaggle.com/datasets/salader/dogs-vs-cats" rel="noopener noreferrer"&gt;"dogs vs cats"&lt;/a&gt; from Kaggle, uploaded by the user "salader".&lt;/p&gt;

&lt;p&gt;It consists of colored JPEG images of cats and dogs, each labeled according to its category. The visual diversity within the dataset such as different breeds, postures, and lighting conditions, makes it a valuable resource for training image classification models.&lt;/p&gt;

&lt;p&gt;In total, the dataset contains around &lt;strong&gt;12500 images per class&lt;/strong&gt;. This balanced composition is ideal for &lt;strong&gt;binary classification&lt;/strong&gt; tasks, as it helps prevent model bias toward a particular class. Both classes are sorted into their &lt;strong&gt;respective test and training directories&lt;/strong&gt;, which simplifies the &lt;strong&gt;preprocessing process&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Why Use Google Colab?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To efficiently work with this dataset and build models, we will use a tool called Google Colab.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Google Colab&lt;/strong&gt; is a cloud-based &lt;strong&gt;Jupyter notebook&lt;/strong&gt; environment that runs entirely in your browser.&lt;/p&gt;

&lt;p&gt;It’s ideal for personal machine learning projects because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No setup is required&lt;/li&gt;
&lt;li&gt;Free access to GPUs&lt;/li&gt;
&lt;li&gt;Easy integration with Google Drive&lt;/li&gt;
&lt;li&gt;Supports real-time collaboration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Kaggle API setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To utilize the dataset we need from Kaggle, we need to get an &lt;strong&gt;API token&lt;/strong&gt; from kaggle.com.&lt;/p&gt;

&lt;p&gt;To get an &lt;strong&gt;API token&lt;/strong&gt;, you need to first register for a &lt;strong&gt;free&lt;/strong&gt; Kaggle account &lt;a href="https://www.kaggle.com/account/login?phase=startRegisterTab" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once you have a Kaggle account, navigate to the &lt;strong&gt;settings&lt;/strong&gt; of your account, and scroll down.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zllt9ffns2lfxmpa0vu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3zllt9ffns2lfxmpa0vu.png" alt="Profile top right" width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3hpunj480i152bls18c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs3hpunj480i152bls18c.png" alt="Settings" width="441" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcthz4lzy0j18h7wz89b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdcthz4lzy0j18h7wz89b.png" alt="API Key Creation" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on &lt;strong&gt;Create New Token&lt;/strong&gt;, and it should download the &lt;code&gt;kaggle.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;If we open &lt;code&gt;kaggle.json&lt;/code&gt; on a text editor, for example, &lt;strong&gt;Visual Studio Code&lt;/strong&gt;, we would find two &lt;strong&gt;key-value pairs&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"reallycooluser"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"12345678909876345678"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can input these two values,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KAGGLE_KEY = 12345678909876345678
KAGGLE_USERNAME = reallycooluser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into Google Colab's built in &lt;strong&gt;Secrets&lt;/strong&gt; feature that lets us store our sensitive info, like our &lt;strong&gt;Kaggle API key&lt;/strong&gt;, privately.&lt;/p&gt;

&lt;p&gt;Even if the notebook resets, we can still use the same Kaggle token without having to reupload it.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Secrets&lt;/strong&gt; feature of Google Colab is found on the left sidebar, with a key icon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2ftdapc51ld3z5l3f9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw2ftdapc51ld3z5l3f9o.png" alt="Google Colab Secrets feature" width="599" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To access the Kaggle API using the Secrets feature, we run the following code block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Imports the Kaggle.com key and username from the Google Colab Secrets
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;google.colab&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;userdata&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="c1"&gt;# assuming you followed the naming convention from above:
# KAGGLE_KEY = key
# KAGGLE_USERNAME = username
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KAGGLE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userdata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;KAGGLE_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;KAGGLE_USERNAME&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userdata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;KAGGLE_USERNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this &lt;strong&gt;binary classification model&lt;/strong&gt;, we will be using &lt;a href="https://www.kaggle.com/datasets/salader/dogs-vs-cats/" rel="noopener noreferrer"&gt;this dataset&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Downloads the dataset from kaggle.com
&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;&lt;span class="n"&gt;kaggle&lt;/span&gt; &lt;span class="n"&gt;datasets&lt;/span&gt; &lt;span class="n"&gt;download&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;salader&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;dogs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;vs&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cats&lt;/span&gt;

&lt;span class="c1"&gt;# Unzip the files
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ZipFile&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dogs-vs-cats.zip&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;zip_ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;zip_ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extractall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Take note that you have to run this again whenever you reset the Google Colab runtime.
# This stores the dataset into a virtual disk for the Colab Runtime
# Once the runtime stops, either by being idle, closing the tab or stopping the runtime directly, the memory of this dataset will be wiped completely.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Preprocessing: ImageDataGenerator&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before training our model, we need to prepare our images to be read as data.&lt;/p&gt;

&lt;p&gt;We have to first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resize each image to a uniform shape&lt;/strong&gt;, as our model requires all the images to be the same size.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Normalize pixel values&lt;/strong&gt;, as pixels on most images range from 0 to 255 for each color channel on RGB. Larger values can slow down the model's learning process, so we normalize the pixel values to a smaller range.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we create the &lt;strong&gt;training and validation data generators&lt;/strong&gt;, to be used by our model.&lt;/p&gt;

&lt;p&gt;Keras offers &lt;strong&gt;ImageDataGenerator&lt;/strong&gt;, which lets us preprocess the data as we need it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Data preprocessing with ImageDataGenerator
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.preprocessing.image&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ImageDataGenerator&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;


&lt;span class="n"&gt;directory_for_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data/dogs_vs_cats&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;# define the parent directory as a variable
&lt;/span&gt;
&lt;span class="c1"&gt;# tip from authors: if you are running this on Google Colab, you can see the directory tree if you click on the folder on the left sidebar
&lt;/span&gt;
&lt;span class="c1"&gt;# this section just allows us to implement the directories for both the training data and the testing data as variables
&lt;/span&gt;&lt;span class="n"&gt;train_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory_for_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;train&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# directory for training data
&lt;/span&gt;&lt;span class="n"&gt;test_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory_for_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# directory for test data
&lt;/span&gt;

&lt;span class="n"&gt;train_datagen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImageDataGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rescale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# - rescale=1./255 - Divides every pixel value by 255, normalizing to a smaller range
&lt;/span&gt;

&lt;span class="c1"&gt;# Creating the training data generator.
# - train_directory: directory to training data.
# - target_size=(150, 150): Resizes all images to 150x150 pixels.
# - batch_size=32: Loads 32 images per batch.
# - class_mode='binary': For binary classification (Cat vs Dog), returns 0 or 1.
# - subset='training': Uses the training subset as defined by validation_split (80% of the data).
&lt;/span&gt;&lt;span class="n"&gt;train_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;train_directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Creating the validation data generator.
# Same as above, but the directory has changed to test_directory
&lt;/span&gt;&lt;span class="n"&gt;val_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;test_directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;What is a Convolutional Neural Network (CNN)?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Convolutional Neural Network (CNN)&lt;/strong&gt; is a deep learning algorithm specifically built to process and analyze visual inputs. Inspired by how humans perceive images, CNNs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect basic features like edges and colors in early layers&lt;/li&gt;
&lt;li&gt;Recognize textures, patterns, and shapes in middle layers&lt;/li&gt;
&lt;li&gt;Identify full objects in the deeper layers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of how you recognize a dog: you first spot the snout, then the ears, the fur, and finally realize it’s a dog. CNNs follow a similar process, but by only using layers of mathematical operations instead of eyes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Building the Model&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;On Keras, we can build the model layer by layer by using a &lt;strong&gt;Sequential model&lt;/strong&gt;. This is usually ideal when creating CNNs as the model &lt;strong&gt;builds up complexity layer by layer&lt;/strong&gt;, and we can use a Sequential model to stack layer by layer.&lt;/p&gt;

&lt;p&gt;For the layers, we have &lt;strong&gt;two significant layers&lt;/strong&gt; that allow us to predict what the image is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Conv2D&lt;/strong&gt;, which stands for 2D Convolutional Layer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MaxPooling2D&lt;/strong&gt;, consolidates what features were found in &lt;strong&gt;Conv2D layers&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Conv2D layer&lt;/strong&gt; is where the model actually learns the patterns found in the image. Each Conv2D layer uses &lt;strong&gt;filters&lt;/strong&gt;, also known as &lt;strong&gt;kernels&lt;/strong&gt;, that slide over the image, extracting any useful features and patterns that the image may have.&lt;/p&gt;

&lt;p&gt;As we pass through each Conv2D layer, the model creates new &lt;strong&gt;feature maps&lt;/strong&gt; that capture more details. The deeper we go, the more complex the features it learns, starting from simple edges to shapes, and eventually, full objects.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;MaxPooling2D layer&lt;/strong&gt; is where the model shrinks the data, and only keeps the most important parts. It basically compiles all the important features from the feature maps created by the &lt;strong&gt;Conv2D layers&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we &lt;strong&gt;flatten&lt;/strong&gt; the &lt;strong&gt;2D feature maps&lt;/strong&gt; to one single &lt;strong&gt;1D vector&lt;/strong&gt;.&lt;br&gt;
This &lt;strong&gt;1D vector&lt;/strong&gt; passes through an initial dense layer that evaluates the vector.&lt;br&gt;
The output of this &lt;strong&gt;dense layer&lt;/strong&gt; passes through &lt;strong&gt;another&lt;/strong&gt; &lt;strong&gt;dense layer&lt;/strong&gt; to get a number between &lt;strong&gt;0 and 1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Currently, &lt;strong&gt;0 is for cat&lt;/strong&gt; and &lt;strong&gt;1 is for dog&lt;/strong&gt;, as &lt;strong&gt;Keras' ImageDataGenerator&lt;/strong&gt; assigns the classes based on their &lt;strong&gt;lexicographic order&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If the output of the &lt;strong&gt;final dense layer&lt;/strong&gt; is &lt;strong&gt;above 0.5&lt;/strong&gt; means that the model &lt;strong&gt;predicted a dog&lt;/strong&gt;. If its output is &lt;strong&gt;0.5 until 0&lt;/strong&gt;, the model &lt;strong&gt;predicts a cat&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Sequential&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.layers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Flatten&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dense&lt;/span&gt;

&lt;span class="c1"&gt;# Model Architecture
&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="c1"&gt;# Sequential basically means to instruct it to build the model layer by layer
&lt;/span&gt;    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Flatten&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;# Flattens the 2D feature maps to one single vector
&lt;/span&gt;    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# Processes the vector, basically makes the final decision on what the image is
&lt;/span&gt;    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sigmoid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Binary output with a sigmoid activation function
&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Compiling the Model&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we've built our model architecture from the previous block, we can now &lt;strong&gt;compile&lt;/strong&gt; all the layers into &lt;strong&gt;one unified model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compiling&lt;/strong&gt; is a crucial step in the process of training a neural network because it defines how the model will learn from the data.&lt;/p&gt;

&lt;p&gt;For demonstration purposes, we will be using the &lt;strong&gt;Stochastic Gradient Descent (SGD)&lt;/strong&gt; optimizer, one of the simplest and most commonly used optimizers in machine learning.&lt;/p&gt;

&lt;p&gt;We introduce a &lt;strong&gt;new&lt;/strong&gt; concept called a &lt;strong&gt;learning rate&lt;/strong&gt; which is the &lt;strong&gt;hyperparameter&lt;/strong&gt; that controls how much a model's parameters &lt;strong&gt;adjust&lt;/strong&gt; during each iteration of the optimizer.&lt;/p&gt;

&lt;p&gt;To put it simply, &lt;strong&gt;learning rate&lt;/strong&gt; is how fast the model tries to learn through each step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model Compiling
&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.optimizers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SGD&lt;/span&gt;

&lt;span class="c1"&gt;# Hyperparameter that controls how much a model's parameters adjust during each iteration of the optimizer
# Basically how fast the model reads through each step
# Too high? The model might miss the best solution. Too low? It might take forever to learn.
# Learning rate is generally really low.
&lt;/span&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;SGD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;learning_rate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;# Stochastic Gradient Descent
&lt;/span&gt;              &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binary_crossentropy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# Loss function used for binary output models
&lt;/span&gt;              &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accuracy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;# Tells Keras to track the accuracy
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Training the Model&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have &lt;strong&gt;compiled&lt;/strong&gt; the model, it's time to train it!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Training&lt;/strong&gt; is probably the most &lt;strong&gt;time-consuming part&lt;/strong&gt; of this whole process, as the model goes through many &lt;strong&gt;rounds of trial and error&lt;/strong&gt;, tweaking itself, to get better at telling which is which.&lt;/p&gt;

&lt;p&gt;We call each round an &lt;strong&gt;epoch&lt;/strong&gt;, basically a lap around the training data, where the model &lt;strong&gt;makes predictions&lt;/strong&gt;, &lt;strong&gt;checks how wrong it was&lt;/strong&gt;, and &lt;strong&gt;adjusts accordingly&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model Training
&lt;/span&gt;
&lt;span class="c1"&gt;# Training the model
# - train_generator: The generated data for training from preprocessing with ImageDataGenerator.
# - epochs: Amount of laps the model makes to read through the data.
# - validation_data=val_generator: The generated data for validation from preprocessing with ImageDataGenerator.
# - verbose=1: Completely optional, but shows the progress bar for model training.
&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;train_generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;validation_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;val_generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If you're using Google Colab, the authors highly recommend going to Runtime on the header above and changing your Runtime type to T4 GPU. (FREE, but limited)
# It will reset the current runtime, but the epochs will go by much much faster.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Model Train and Validation Graph for Analysis
&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

&lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;accuracy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;val_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;val_accuracy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;loss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;val_loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;val_loss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;epochs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;summarize_diagnostics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Training&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val_acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;orange&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Validation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Training and Validation Accuracy&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;figure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;blue&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Training&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;plot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;val_loss&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;orange&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Validation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Training and Validation Loss&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;legend&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;summarize_diagnostics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Testing the Model&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have our &lt;strong&gt;trained model&lt;/strong&gt;, we can test it against image inputs. We will pull &lt;strong&gt;random images&lt;/strong&gt; from the dataset, and see if the model can predict it correctly.&lt;/p&gt;

&lt;p&gt;Each run of the code block below will give us a random image from the dataset, and the model we trained will try to &lt;strong&gt;predict&lt;/strong&gt; if it is a &lt;strong&gt;cat&lt;/strong&gt; or a &lt;strong&gt;dog&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.preprocessing.image&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;load_img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;img_to_array&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;

&lt;span class="c1"&gt;# Set the directory for our images
&lt;/span&gt;&lt;span class="n"&gt;train_dog_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data/dogs_vs_cats/train/dogs&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;  &lt;span class="c1"&gt;# Path to dog images
&lt;/span&gt;&lt;span class="n"&gt;train_cat_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data/dogs_vs_cats/train/cats&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;  &lt;span class="c1"&gt;# Path to cat images
&lt;/span&gt;
&lt;span class="c1"&gt;# Get list of all filenames in the directories
&lt;/span&gt;&lt;span class="n"&gt;dog_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_dog_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cat_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_cat_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Select a random image from either the dog or cat folder
&lt;/span&gt;&lt;span class="n"&gt;random_image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;choice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dog_images&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;cat_images&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;image_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_dog_dir&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random_image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dog_images&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;train_cat_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;random_image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load and preprocess the image
&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_img&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;img_to_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;  &lt;span class="c1"&gt;# Normalize pixel values to [0, 1]
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Make a prediction
&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Dog&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Cat&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Display the image and prediction
&lt;/span&gt;&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;axis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;off&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Prediction: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;plt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;show&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Predicted Label: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, Prediction Value: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prediction&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Occasionally, you may run into outputs like this:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5aj66cq96jzic36ure4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5aj66cq96jzic36ure4.png" alt="False prediction of a dog as a cat with a prediction value of 0.44" width="540" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wait, but that's not a cat...&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;And you would be &lt;strong&gt;correct!&lt;/strong&gt; Unfortunately, our model can only do so much before it fails against an image input.&lt;/p&gt;

&lt;p&gt;If you observe above, it was actually pretty close to predicting a dog, where the prediction value for a dog is &lt;strong&gt;greater than 0.5&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The only way we can go from here is to try and &lt;strong&gt;fully optimize&lt;/strong&gt; the next trained model.&lt;/p&gt;

&lt;p&gt;This is an example of a scenario called &lt;strong&gt;underfitting&lt;/strong&gt;, where the model &lt;strong&gt;failed&lt;/strong&gt; to &lt;strong&gt;learn&lt;/strong&gt; enough features to make an &lt;strong&gt;accurate prediction&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Quick notes before moving on&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;High accuracy in the training does not necessarily mean that your model will perform well. It could be a scenario called &lt;strong&gt;overfitting&lt;/strong&gt;, meaning your model is &lt;strong&gt;memorizing the data too well&lt;/strong&gt;, to the point that it would do &lt;strong&gt;terrible&lt;/strong&gt; against &lt;strong&gt;new data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Underfitting&lt;/strong&gt; is the opposite, where it doesn't learn any meaningful patterns in the data.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Optimization&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Hyperparameters&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Hyperparameters&lt;/strong&gt; are parameters that control the learning process of the model. Think of it as like configuration settings for the model's learning process.&lt;/p&gt;

&lt;p&gt;Altering these hyperparameters would change how the model learns, which influences the final output model. The two most commonly altered &lt;strong&gt;hyperparameters&lt;/strong&gt; for each trained model would be &lt;strong&gt;epochs&lt;/strong&gt; and &lt;strong&gt;learning rate&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Epochs&lt;/strong&gt; is, in simple terms, how many times the model goes through the training process, basically how many laps of &lt;strong&gt;trial-and-error&lt;/strong&gt; it will go through.&lt;/p&gt;

&lt;p&gt;Too many epochs can make the model &lt;strong&gt;overfit&lt;/strong&gt;, meaning it fits its given dataset too well.&lt;/p&gt;

&lt;p&gt;Too little epochs can make it &lt;strong&gt;underfit&lt;/strong&gt;, meaning it doesn't learn from or doesn't fit its given dataset.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Learning Rate&lt;/strong&gt; is how fast a model's parameters adjust during each iteration of the optimizer, in this case, the &lt;strong&gt;Stochastic Gradient Descent&lt;/strong&gt; optimizer.&lt;/p&gt;

&lt;p&gt;Too high of a learning rate can make the model &lt;strong&gt;underfit&lt;/strong&gt;.&lt;br&gt;
  Too low of a learning rate can make the model training &lt;strong&gt;very slow&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Model architecture&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One of the ways we can do to try and &lt;strong&gt;improve&lt;/strong&gt; future models is by altering its &lt;strong&gt;architecture&lt;/strong&gt;. This is also another type of &lt;strong&gt;hyperparameter&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, here we added a smaller convolutional layer at the start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Flatten&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sigmoid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or we could alter it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="nc"&gt;Flatten&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;relu&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;sigmoid&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The possibilities are almost &lt;strong&gt;limitless&lt;/strong&gt;! Do note that this alters the overall way the model actually sees the input, which &lt;strong&gt;could&lt;/strong&gt; actually make the model &lt;strong&gt;perform worse&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Image augmentation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Another way to prevent our model from overfitting would be to implement &lt;strong&gt;image augmentation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;generalization technique&lt;/strong&gt; to prevent overfitting by performing random changes to the images.&lt;/p&gt;

&lt;p&gt;For example we could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zoom into and out the image&lt;/li&gt;
&lt;li&gt;Flip the image&lt;/li&gt;
&lt;li&gt;Rotate the image&lt;/li&gt;
&lt;li&gt;and apply a lot more augmentations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps the model adapt to &lt;strong&gt;noise&lt;/strong&gt; that builds up from the background, how the animal is sitting, different lighting, varying angles, and a lot more. Augmentations to the image make it really focus on the important shapes found in the images, making it &lt;strong&gt;more adaptable&lt;/strong&gt; to &lt;strong&gt;newer data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is somewhat of a &lt;strong&gt;double-edged sword&lt;/strong&gt; as too much augmentations could create even more noise.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keras&lt;/strong&gt; actually allows us to do image augmentation using the &lt;strong&gt;ImageDataGenerator&lt;/strong&gt; from earlier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# COPY OF Data preprocessing with ImageDataGenerator
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tensorflow.keras.preprocessing.image&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ImageDataGenerator&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;


&lt;span class="n"&gt;directory_for_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;data/dogs_vs_cats&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;# define the parent directory as a variable
&lt;/span&gt;
&lt;span class="c1"&gt;# tip from authors: you can see the directory tree if you click on the folder on the left sidebar
&lt;/span&gt;
&lt;span class="n"&gt;train_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory_for_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;train&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# directory for training data
&lt;/span&gt;&lt;span class="n"&gt;test_directory&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;directory_for_images&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# directory for test data
&lt;/span&gt;

&lt;span class="c1"&gt;# Image data generator from Keras
# - rescale=1./255 - Divides every pixel value by 255
# - rotation_range=30 - Rotates the image randomly, up to 30 degrees
# - zoom_range=0.2 - Zooms the image in and out by 0.2x
# - horizontal_flip=True - flips the image 50% of the time horizontally
# - vertical_flip=True - flips the image 50% of the time vertically
&lt;/span&gt;&lt;span class="n"&gt;train_datagen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ImageDataGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;rescale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;rotation_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;zoom_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;# zoom in/out
&lt;/span&gt;    &lt;span class="n"&gt;horizontal_flip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# flip horizontally
&lt;/span&gt;    &lt;span class="n"&gt;vertical_flip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;       &lt;span class="c1"&gt;# flip vertically
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;




&lt;span class="c1"&gt;# Creating the training data generator.
# - train_directory: directory to training data.
# - target_size=(150, 150): Resizes all images to 150x150 pixels.
# - batch_size=32: Loads 32 images per batch.
# - class_mode='binary': For binary classification (Cat vs Dog), returns 0 or 1.
# - subset='training': Uses the training subset as defined by validation_split (80% of the data).
&lt;/span&gt;&lt;span class="n"&gt;train_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;train_directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Creating the validation data generator.
# Same as above, but the directory has changed
&lt;/span&gt;&lt;span class="n"&gt;val_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;test_directory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;class_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;binary&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Since we are running a Jupyter notebook over Google Colab,
# running the Training the Model section should just work with the new augmented data if you run this first.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Trying to get a computer to tell the difference between cats and dogs sounds simple, but in reality, it's far from a one-click task. There's a lot that goes into teaching a program to recognize patterns in pictures, from picking the right set of photos, to choosing how many times it should practice, to deciding how much to let it adjust each time. It's a balancing act, and depending on what choices you make, the results can really change.&lt;/p&gt;

&lt;p&gt;There are so many knobs and dials to tweak when it comes to training models. You can switch up the dataset, try different numbers of epochs, adjust the learning rate (go fast or take it slow!), or even rethink the model architecture altogether. Want to go deeper? Try throwing in more image augmentation, flip those cats, zoom those dogs, rotate like there’s no tomorrow! Every little change can lead to big discoveries (and possibly better accuracy too). And hey, why stop at just cats and dogs? The world is full of things to classify—muffins vs. chihuahuas, anyone?&lt;/p&gt;

&lt;p&gt;If you've made it this far, don't stop here. Keep experimenting, keep tinkering, and most of all, have fun with it. Who says technology can't be playful?&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.superannotate.com/blog/image-classification-basics" rel="noopener noreferrer"&gt;https://www.superannotate.com/blog/image-classification-basics&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/difference-between-tensorflow-and-keras/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/difference-between-tensorflow-and-keras/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kaggle.com/datasets/salader/dogs-vs-cats/" rel="noopener noreferrer"&gt;https://www.kaggle.com/datasets/salader/dogs-vs-cats/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tensorflow.org/api_docs/python" rel="noopener noreferrer"&gt;https://www.tensorflow.org/api_docs/python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.geeksforgeeks.org/underfitting-and-overfitting-in-machine-learning/" rel="noopener noreferrer"&gt;https://www.geeksforgeeks.org/underfitting-and-overfitting-in-machine-learning/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.ibm.com/think/topics/convolutional-neural-networks" rel="noopener noreferrer"&gt;https://www.ibm.com/think/topics/convolutional-neural-networks&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>deeplearning</category>
      <category>tensorflow</category>
    </item>
  </channel>
</rss>
