Keras vs. TensorFlow – Which one is better and which one should I learn?

Should I be using Keras vs. TensorFlow for my project? Is TensorFlow or Keras better? Should I invest my time studying TensorFlow? Or Keras?

The above are all examples of questions I hear echoed throughout my inbox, social media, and even in-person conversations with deep learning researchers, practitioners, and engineers.

I even receive questions related to my book, Deep Learning for Computer Vision with Python where readers are asking why I’m covering “just” Keras — what about TensorFlow?

It’s unfortunate.

Because it’s the wrong question to be asking.

As of mid-2017, Keras was actually fully adopted and integrated into TensorFlow. This TensorFlow + Keras integration means that you can:

  1. Define your model using the easy to use interface of Keras
  2. And then drop down into TensorFlow if you need (1) specific TensorFlow functionality or (2) need to implement a custom feature that Keras does not support but TensorFlow does.

In short:

You can insert TensorFlow code directly into your Keras model or training pipeline!

Don’t get me wrong. I’m not saying that you don’t need to understand a bit of TensorFlow for certain applications — this is especially true if you’re performing novel research and need custom implementations. I’m just saying that if you’re spinning your wheels:

  1. Just getting started studying deep learning…
  2. Trying to decide on which library to use for your next project…
  3. Wondering if Keras or TensorFlow is “better”…

…then it’s time those wheels got some traction.

Stop worrying and just get started. My suggestion would be to use Keras to start and then drop down into TensorFlow for any specific functionality you may need.

In today’s post, I’ll show you how you can train both (1) a neural network using strict Keras and (2) a model using the Keras + TensorFlow integration (with custom features) built directly into the TensorFlow library.

To learn more about Keras vs. Tensorflow, just keep reading!

Looking for the source code to this post?
Jump right to the downloads section.

Keras vs. TensorFlow – Which one is better and which one should I learn?

In the remainder of today’s tutorial, I’ll continue to discuss the Keras vs. TensorFlow argument and how it’s the wrong question to be asking.

From there we’ll implement a Convolutional Neural Network (CNN) using both the standard keras  module along with the tf.keras  module baked right into TensorFlow.

We’ll train these CNNs on an example dataset and then examine the results — as you’ll find out, Keras and TensorFlow live together in harmony.

And perhaps most importantly, you’ll learn why the Keras vs. TensorFlow argument doesn’t make much sense anymore.

If you’re asking “Keras vs. TensorFlow”, you’re asking the wrong question

Figure 1: “Should I use Keras or Tensorflow?”

Asking whether you should be using Keras or TensorFlow is the wrong question — and in fact, the question doesn’t even make sense anymore. Even though it’s been over a year since TensorFlow announced that Keras will be integrated into official TensorFlow releases, I’m still surprised by the number of deep learning practitioners who are unaware that they can access Keras via the tf.keras  sub-module.

And more to the point — that the Keras + TensorFlow integration is seamless, allowing you to drop raw TensorFlow code directly into your Keras model.

Using Keras inside of TensorFlow gives you the best of both worlds:

  1. You can use the simple, intuitive API provided by Keras to create your models.
  2. The Keras API itself is similar to scikit-learn’s, arguably the “gold standard” of machine learning APIs.
  3. The Keras API is modular, Pythonic, and super easy to use.
  4. And when you need a custom layer implementation, a more complex loss function, etc., you can drop down into TensorFlow and have the code integrate with your Keras model automatically.

In prior years, deep learning researchers, practitioners, and engineers often had to choose:

  1. Do I go with the easy to use, but perhaps harder to customize Keras library?
  2. Or do I utilize the significantly harder TensorFlow API, write an order of magnitude more code, and not to mention, work with a less than easy to follow API?

Luckily, we don’t have to choose anymore.

If you find yourself in a situation asking “Should I use Keras vs. TensorFlow?”, take a step back — you’re asking the wrong question — you can have both.

Keras is built into TensorFlow via the “tf.keras” module

Figure 3: As you can see, by importing TensorFlow (as tf) and subsequently calling tf.keras, I’ve demonstrated in a Python shell that Keras is actually part of TensorFlow.

Including Keras inside tf.keras  allows you to to take the following simple feedforward neural network using the standard Keras package:

And then implement the same network using the  tf.keras  submodule which is part of TensorFlow:

Does this mean that you have to use tf.keras ? Is the standard Keras package now obsolete? No, of course not.

Keras as a library will still operate independently and separately from TensorFlow so there is a possibility that the two will diverge in the future; however, given that Google officially supports both Keras and TensorFlow, that divergence seems extremely unlikely.

The point is this:

If you’re comfortable writing code using pure Keras, go for it, and keep doing it.

But if you find yourself working in TensorFlow, you should start leveraging the Keras API:

  1. It’s built right into TensorFlow
  2. It’s easier to use
  3. And when you need pure TensorFlow to implement a specific feature or functionality, it can be dropped right into your Keras model.

There is no more Keras vs. TensorFlow argument — you get to have both and you get the best of both worlds.

Our example dataset

Figure 4: The CIFAR-10 dataset has 10 classes and is used for today’s demonstration (image credit).

For the sake of simplicity, we are going to be training two separate Convolutional Neural Networks (CNNs) on the CIFAR-10 dataset using:

  1. Keras with a TensorFlow backend
  2. The Keras submodule inside tf.keras

I’ll also be showing how to include custom TensorFlow code within your actual Keras model.

The CIFAR-10 dataset itself consists of 10 separate classes with 50,000 training images and 10,000 testing images. A sample is shown in Figure 4.

Our project structure

Our project structure today can be viewed in the terminal with the tree  command:

The pyimagesearch  module is included with the downloads associated with this blog post. It is not pip-installable, but it is included in the “Downloads”. Let’s review the two important Python files part of the module:

  • : This is our strict Keras implementation of MiniVGGNet , a deep learning model based on VGGNet .
  • : This is our TensorFlow + Keras (i.e., tf.keras ) implementation of MiniVGGNet .

The root of the project folder contains two Python files:

  • : This is the first training script we’ll implement using strict Keras.
  • : The TensorFlow + Keras version of the training script is nearly identical; we’ll walk through it, highlighting differences, as well.

Each of the scripts will generate a respective training accuracy/loss plot as well:

  • plot_keras.png
  • plot_tf.png

As you can see from the directory structure, we’re going to be demonstrating the implementation + training of MiniVGGNet  for both Keras and TensorFlow (with the tf.keras  module) today.

Training a network with Keras

Figure 5: The MiniVGGNet CNN network architecture implemented using Keras.

The first step in training our network is to implement the network architecture itself in Keras.

I’ll assume you are already familiar with the fundamentals of training a neural network with Keras — if you are not, please refer to this introductory post.

Open up the  file and insert the following code:

We begin with a bunch of Keras imports required to build our model.

From there, we define our MiniVGGNetKeras  class:

We define the build  method on Line 12, and define our inputShape  and input . We’ll assume “channels last” ordering which is why depth  is the last value in the inputShape  tuple.

Let’s start defining the body of the Convolutional Neural Network:

Examining the code block, you’ll notice we are stacking a series of convolutional, ReLU activation, and batch normalization layers prior to applying a pooling layer to reduce the spatial dimensions of the volume. Dropout is also applied to reduce overfitting.

For a brief review of the layer types and terminology, be sure to check out my previous Keras tutorial where they are explained. And for in-depth study, you should pick up a copy of my deep learning book, Deep Learning for Computer Vision with Python.

Let’s add the fully-connected (FC) layers to the network:

Our FC and Softmax classifier are appended onto the network. We then define the neural network model  and return  it to the calling function.

Now that we’ve implemented our CNN in Keras, let’s create the driver script that will be used to train it.

Open up  and insert the following code:

We import  our required packages on Lines 2-13.

Notice the following:

  • On Line 3 the backend for Matplotlib is set to "Agg"  so that we can save our training plots as image files.
  • On Line 6 we import the MiniVGGNetKeras  class.
  • We’re using the scikit-learn’s  LabelBinarizer  for “one-hot” encoding and its classification_report  to print classification accuracy statistics (Lines 7 and 8).
  • Our dataset is conveniently imported on Line 10. If you want to learn how to use custom datasets, I suggest you refer to this previous Keras tutorial or this post which shows how to a real-world of example with Keras.

Our only command line argument (our output --plot  path) is parsed on Lines 16-19.

Let’s load CIFAR-10 and encode the labels:

We load and extract our training and testing splits on Lines 24 and 25) as well as convert to floating point + scale the data on Lines 26 and 27.

We encode our labels and initialize the actual labelNames  on Lines 30-36.

Next, let’s train the model:

The training parameters and optimization method are set (Lines 40-46).

Then we use our  method to initialize our model  and compile  it (Lines 47-50).

And subsequently, we kick off the training procedure (Lines 54 and 55).

Let’s evaluate the network and generate a plot:

Here we evaluate the network on our testing split of the data and generate a classification_report . Finally, we assemble and export our plot.

Note: Usually, I would serialize and export our model here so that it can be put to use in an image or video processing script, but we aren’t going to do that today as that is outside the scope of the tutorial.

To run our script, make sure you use the “Downloads” section of the blog post to download the source code.

From there, open up a terminal and execute the following command:

Each epoch is taking a little over 5 minutes to complete on my CPU.

Figure 6: The accuracy/loss training curves are plotted with Matplotlib. This network was trained with Keras.

As we can see from the terminal output, we are obtaining 75% accuracy on our testing set — certainly not state-of-the-art; however, it’s far better than random guessing (1/10).

For a small network, our accuracy is actually quite good!

And as our output plot demonstrates in Figure 6, there is no overfitting occurring.

Training a network with TensorFlow and tf.keras

Figure 7: The MiniVGGNet CNN architecture built with tf.keras (a module which is built into TensorFlow) is identical to the model that we built with Keras directly. They are one and the same with the exception of the activation function which I have changed for demonstration purposes.

Now that we’ve implemented and trained a simple CNN using the Keras library, let’s learn how we can:

  1. Implement the same network architecture using TensorFlow’s tf.keras
  2. Include a TensorFlow activation function inside our Keras model that is not implemented in Keras itself.

To get started, open up the  file and we’ll implement our TensorFlow version of MiniVGGNet :

In this file, notice that the imports are replaced by a single line (Line 2). The tf.keras  sub-module contains all of our Keras functionality which we can call directly.

I’d like to call attention to the Lambda  layers — they are used to insert a custom activation function, CRELU (Concatenated ReLUs), based on the paper Understanding and Improving Convolutional Neural Networks via Concatenated Rectified Linear Units by Shang et al. These lines are highlighted in yellow.

CRELUs are not implemented in Keras but are in TensorFlow — by using TensorFlow and tf.keras  we can add CRELUs into our Keras model with just a single line of code.

Note: The CRELU has two outputs, one  positiveReLU and one negative ReLU concatenated together. For positive x values the CRELU will return [x, 0] while for negative x values CRELU will return [0, x]. For more information, please refer to the Shang et al. publication.

The next step is to implement our TensorFlow + Keras driver script to train MiniVGGNetTF .

Open up  and insert the following code:

Our imports are handled on Lines 2-12. The only changes in comparison to our Keras training script include importing the MiniVGGNetTF  class and importing tensorflow as tf  rather than Keras.

Our command line argument is parsed on Lines 15-18.

Then we load our data on Line 23 much like before.

The rest of the lines are the same — extracting training/testing splits and encoding our labels.

Let’s train our model:

The training process, taking place on Lines 39-54, is the same with the exception of those highlighted in yellow, where only minor changes are to be noted.

From there we evaluate and plot our data (Lines 58-73).

As you can see, we’ve implemented the exact same training process, only now we’re using tf.keras .

To run this script, make sure you use “Downloads” section of the blog post to grab the code.

From there, open up a terminal and execute the following command:

After training completes you have a training plot that look similar to the following:

Figure 8: The deep learning training plot shows our accuracy and loss curves. The CNN was trained with the Keras module which is built into TensorFlow.

By swapping in the CRELU for the RELU activation function we obtain 76% accuracy; however, that 1% increase may be due to the random initialization of the weights in the network — further experiments with cross-validation would be required to demonstrate that CRELU was indeed responsible for this increase of accuracy.

However, the raw accuracy is not the important aspect of this section.

Instead, focus on how we were able to swap in a TensorFlow activation function in-place of a standard Keras activation function inside of a Keras model!

You could do the same with your own custom activation functions, loss/cost functions, or layer implementations as well.


In today’s blog post we discussed questions surrounding Keras vs. TensorFlow, including:

  • Should I be using Keras vs. TensorFlow for my project?
  • Is TensorFlow or Keras better?
  • Should I invest my time studying TensorFlow? Or Keras?

Ultimately, we found that trying to decide between Keras and TensorFlow is starting to become more and more irrelevant.

The Keras library has been integrated directly into TensorFlow via the tf.keras  module.

Essentially, you can code your model and training procedures using the easy to use Keras API and then custom implementations into the model or training process using pure TensorFlow!

If you’re spinning your wheels trying to just get started with deep learning, trying to decide between Keras or TensorFlow for your next project, or simply wondering if Keras or TensorFlow is “better”…then it’s time you seek some traction.

My advice to you is simple:

  • Just get started.
  • Type either import keras  or import tensorflow as tf  (so you have access to tf.keras ) into your Python project and get to work.
  • TensorFlow can be directly integrated into your model or training process so there’s no need to compare features, functionality, or ease of use all of TensorFlow and Keras are available for you to use in your projects.

I hope you enjoyed today’s blog post!

If you are interested in getting started with computer vision and deep learning, I would suggest you take a look at my book, Deep Learning for Computer Vision with Python. Inside the book, I utilize Keras and TensorFlow to teach you deep learning applied to computer vision applications.

And if you would like to download the source code today’s tutorial (and be notified when future blog posts are published here on PyImageSearch), just enter your email address in the form below!


If you would like to download the code and images used in this post, please enter your email address in the form below. Not only will you get a .zip of the code, I’ll also send you a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL! Sound good? If so, enter your email address and I’ll send you the code immediately!

, , , , ,

30 Responses to Keras vs. TensorFlow – Which one is better and which one should I learn?

  1. Sundaresh October 8, 2018 at 10:54 am #

    Hi Adrian

    Thanks a lot for this insightful article. I have (and judging from the questions you’ve received, others too) always wrestled with questions regarding what exactly Keras and TF is. Well, I can’t say I am completely clear, yet, but am getting there. Some clarificatory questions:

    i) Out of the two, is it correct to think of one as the computational engine (where stuff actually processes) and the other as a sort of toolkit (which calls the stuff to get processed) ? If so, which one is which ? My guess is that TF is the toolkit and Keras is the computational backend ?

    ii) I also read in your earlier blog posts that there used to be TF integration with Kaffe, but this has been abandoned in favor of Keras. Can you share your insights regarding why this is so ? Is Kaffe no longer available, or is it no longer mentioned because Keras has more capabilities ?


    • Adrian Rosebrock October 8, 2018 at 10:59 am #

      1. Yes, Keras itself relies on a “backend” such as TensorFlow, Theano, CNTK, etc. to perform the actual “computational heavy lifting”.

      2. Caffe still exists but additional functionality has been forked to Caffe2. TensorFlow was never part of Caffe though. We still use Caffe, especially researchers; however, practitioners, especially Python practitioners prefer a programming-friendly library such as TensorFlow, Keras, PyTorch, or mxnet.

  2. Gagandeep Singh October 8, 2018 at 11:35 am #

    Hi Adrian,
    Amazing blog as always, thank you so much. Can you also put some light on how to effectively use tensorboard with keras or tf.keras for better visualization?
    Also, is keras/tf.keras a good platform to use pre-trained models weights? I find it very difficult to use existing weights. It took me days, just to get started with inception-v3 pre-trained models and I realized that these checkpoints are very specific to the code from which they were created. For this, I have tried Tflearn, TensorLayer but found keras to be best of all.


    • Adrian Rosebrock October 8, 2018 at 12:05 pm #

      It is very, very easy to use Keras with pre-trained networks, in particular the ones that are part of keras.applications. Inside you’ll actually find Inception V3 which has been pre-trained on ImageNet. A good starting point for you would be this tutorial.

      It’s also very easy to use Keras and TensorBoard together. There is actually a TensorBoard callback that you can pass into your call to .fit.

      • Gagandeep Singh October 9, 2018 at 1:28 am #

        I have been doing the same thing as you stated but keras.applications has limited models to offer. I wish I could use some from tensorflow model zoo ( specially the RCNN.
        Thanks again!

        • Adrian Rosebrock October 9, 2018 at 6:01 am #

          You could always load the TensorFlow network and then classify input images with the model without using any Keras code. Or is your goal to actually train the RCNN with Keras rather than TensorFlow?

  3. IEVHENII October 8, 2018 at 12:29 pm #

    Thanks so much for your explanation.

    • Adrian Rosebrock October 8, 2018 at 1:41 pm #

      I’m happy to help however I can 🙂

  4. Joshua Arulsamy October 8, 2018 at 12:43 pm #

    Amazing blog post!

    • Adrian Rosebrock October 8, 2018 at 1:41 pm #

      Thanks Joshua! 😀

  5. Wayan Dadang October 8, 2018 at 1:04 pm #

    Thanks for your article Mr.

    • Adrian Rosebrock October 8, 2018 at 1:40 pm #

      Thanks Wayan, I’m glad you found it helpful!

  6. Amit Pandey October 8, 2018 at 1:52 pm #

    Hi Adrian,
    My question is about the difference between a Keras Tensor and Tensorflow Tensor. I don’t have enough programming experience with using Keras. With the above integration between keras and tensorflow, can we very easily use tf.get_variable(), or tf.constant() and very easily pass it to the tf.keras layers if need be?
    also, in your experience how often do you need to use tensorflow ops or variables when writing your custom layers or loss functions with tf.keras?

    • Adrian Rosebrock October 8, 2018 at 3:06 pm #

      1. Francois Chollet, the creator of Keras, has a great example that answers your question on the official blog. Be sure to give it a read.

      2. It honestly depends on what exactly I’m implementing.

      • AMIT PANDEY October 8, 2018 at 3:09 pm #

        Thanks a lot, Adrian. I will definitely give it a read. Lovely Post.

  7. mohamed October 8, 2018 at 2:28 pm #

    Wonderful return Adrian.
    What I wish you would explain to us someday
    Is to detect objects with deep learning
    I’m talking about smaller objects. What are things like RPN and Roi obj?

    • Adrian Rosebrock October 8, 2018 at 3:03 pm #

      Hi Mohamed — I actually show how you can train and use Faster R-CNNs, which are excellent detecting small objects in images/video, inside my book, Deep Learning for Computer Vision with Python.

      • mohamed October 8, 2018 at 3:59 pm #

        Excellent Adrian
        I also like the latter Faster R-CNN and
        mask R-CNN
        Thank you

  8. Matthew Teow October 9, 2018 at 1:01 am #

    Thank you. A great blog, all the time.

    • Adrian Rosebrock October 9, 2018 at 6:02 am #

      Thanks Matthew 🙂

  9. Mark C October 9, 2018 at 2:11 am #

    Hi sorry for the previous post i see you have done an article how to predict on a custom dataset. If possible perhaps one with text instead of image dataset such as spam detection from kaggle. I would like to predict whether an inputted custom sentence is spam or not

    • Adrian Rosebrock October 9, 2018 at 6:00 am #

      Hey Mark, I don’t do much work with text classification. My main area of expertise is images. You should talk with my friend Jason over at Machine Learning Mastery.

  10. Kelemu October 9, 2018 at 5:24 am #

    First thanks,Really it is very interesting special like me we can’t get enough resource. I follow your blogs and get fantastic knowledge from you. again and again thank you

    • Adrian Rosebrock October 9, 2018 at 5:55 am #

      Thank you for being a PyImageSearch follower, Kelemu! I’m so happy you are getting value out of the posts 🙂 Enjoy them!

  11. segovia October 10, 2018 at 1:53 pm #

    Great tutorial as usual! And I really appreciate that you used raw python codes instead of in IDE or Jupyter Notebook, so that I can just type in the codes in my terminal and run them easily.

    I do have another question though: After I trained these models, how do I used it to recognize my own photos, that are taken, say from my webcam or smartphone? I really want to learn how to ‘send a new image’ into this model. Thanks!

    • Adrian Rosebrock October 12, 2018 at 9:11 am #

      You can simply call the .predict function of the model. The following blog post will show you exactly how to do that 🙂

  12. Romy Bompart October 20, 2018 at 9:34 pm #

    I was trying to run this example on my raspberry pi 3 / 16GB memory card but I am having a MemoryError after running the

    • Adrian Rosebrock October 22, 2018 at 8:08 am #

      Do not use your Raspberry Pi to train a model. Your Pi doesn’t have enough RAM. Train the model on your laptop or desktop and then deploy/run the model on your Pi.

  13. Saquib June 24, 2019 at 8:47 am #

    Hey Adrian
    Thanks for this wonderful post. I’m actually a beginner in this field and i have a few doubts.
    I’m working on a self driving car project in which i have to use object detection in real time. My first question is whether i should use YOLO or SSD because i need to have accuracy and speed both in my project. And should i do everything on keras or tensorflow?

    • Adrian Rosebrock June 26, 2019 at 1:19 pm #

      I prefer SSD over YOLO as the results tend to be more accurate and the speed is still good.

      If you’d like to learn how to train your own custom deep learning object detectors you should refer to Deep Learning for Computer Vision with Python.

Before you leave a comment...

Hey, Adrian here, author of the PyImageSearch blog. I'd love to hear from you, but before you submit a comment, please follow these guidelines:

  1. If you have a question, read the comments first. You should also search this page (i.e., ctrl + f) for keywords related to your question. It's likely that I have already addressed your question in the comments.
  2. If you are copying and pasting code/terminal output, please don't. Reviewing another programmers’ code is a very time consuming and tedious task, and due to the volume of emails and contact requests I receive, I simply cannot do it.
  3. Be respectful of the space. I put a lot of my own personal time into creating these free weekly tutorials. On average, each tutorial takes me 15-20 hours to put together. I love offering these guides to you and I take pride in the content I create. Therefore, I will not approve comments that include large code blocks/terminal output as it destroys the formatting of the page. Kindly be respectful of this space.
  4. Be patient. I receive 200+ comments and emails per day. Due to spam, and my desire to personally answer as many questions as I can, I hand moderate all new comments (typically once per week). I try to answer as many questions as I can, but I'm only one person. Please don't be offended if I cannot get to your question
  5. Do you need priority support? Consider purchasing one of my books and courses. I place customer questions and emails in a separate, special priority queue and answer them first. If you are a customer of mine you will receive a guaranteed response from me. If there's any time left over, I focus on the community at large and attempt to answer as many of those questions as I possibly can.

Thank you for keeping these guidelines in mind before submitting your comment.

Leave a Reply