πŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
πŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
HTML MASTER CLASS /// LEARN TAGS /// BUILD STRUCTURE /// SEMANTIC WEB /// HTML MASTER CLASS /// LEARN TAGS ///

Introduction to Keras in Python

Learn about Introduction to Keras in this comprehensive Python tutorial. Understand the philosophy of Keras, its relationship with TensorFlow, and the shift to Keras Core (Multi-backend).

⚑ Total XP: 0|πŸ’» tensorflow XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

System Hub

Core logic.

Quick Quiz //

What does layers.Dense(units=64, activation='relu') create?


πŸš€ LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
πŸŽ“ COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Listen up. If you're building deep learning models, understanding Introduction to Keras in Python is non-negotiable. This is where graphs get compiled, gradients get computed, and raw data turns into intelligence.

1Why Keras Sits on Top of TensorFlow

Writing every layer of a neural network as raw matrix multiplication and bias addition is technically possible in TensorFlow, but it doesn't scale past a handful of layers. Every weight matrix, every bias vector, and every activation function has to be created, tracked, and wired together by hand, which turns even a simple model into dozens of lines of low-level tensor code.

Keras exists to remove that repetition. Instead of writing out w * x + b and picking an activation function manually, you describe the same layer declaratively: layers.Dense(units=32, activation='relu'). Keras handles weight initialization, shape inference between layers, and the underlying matrix math, while you focus on the architecture β€” how many layers, how many units, which activations.

This is the trade this module is about: TensorFlow Core gives you full control over every tensor operation, and Keras gives that control back to you as building blocks, so you spend your time designing models instead of re-deriving linear algebra for every layer.

βœ•
β€”
+
# Raw TensorFlow: w * x + b
# Keras: Dense(units=32)
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

2From Independent Library to tf.keras

Keras was originally an independent library created by FranΓ§ois Chollet, first released in 2015 as a wrapper that could sit on top of multiple backends (Theano, then TensorFlow). It was so beautifully designed β€” clear naming, a small consistent API surface, sensible defaults β€” that Google officially adopted it as the default high-level API when TensorFlow 2.0 shipped in 2019, exposing it as tf.keras.

That merger mattered because it ended years of confusion about which high-level API to use with TensorFlow. Before 2.0, developers juggled tf.layers, tf.estimator, and standalone Keras, each with slightly different conventions. Folding Keras directly into the tensorflow package meant one canonical way to define models, while still giving you full access to TensorFlow's lower-level ops, tf.data pipelines, distribution strategies, and TPU/GPU acceleration whenever you need to drop below the Keras abstraction.

In practice this means from tensorflow import keras and from tensorflow.keras import layers are not importing a separate third-party project β€” they're importing the same TensorFlow install, so a Dense layer you build automatically benefits from TensorFlow's graph optimizations, tf.function tracing, and hardware acceleration without any extra configuration.

βœ•
β€”
+
from tensorflow import keras
from tensorflow.keras import layers

# Keras makes Deep Learning accessible to humans.
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

3What Keras Actually Sits On Top Of

Today, Keras is not a competitor to TensorFlow β€” it's TensorFlow's official high-level API. Every layers.Dense, layers.Conv2D, or keras.Model you write compiles down to the same TensorFlow ops graph you would get from writing raw tensor math by hand. Keras just gives that graph a human-readable shape: layers instead of matrix multiplications, models instead of collections of loose tensors.

This matters for how you should think about debugging and performance. Because Keras models are ordinary TensorFlow graphs underneath, tools like TensorBoard, tf.function tracing, and TensorFlow Profiler all work on Keras models exactly as they would on hand-written TensorFlow code. There's no separate 'Keras runtime' with its own quirks to learn β€” you're always debugging TensorFlow.

The practical upshot is that you can move fluidly between abstraction levels: prototype quickly with layers.Dense(64, activation='relu'), then drop down to tf.matmul and custom tf.GradientTape training loops for the specific piece of a model that needs finer control, without leaving the TensorFlow ecosystem.

βœ•
β€”
+
# The Merger
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

4The Dense Layer, Unpacked

Keras abstracts away the complex math into simple 'Layers'. The most common is the Dense layer, also called a fully connected layer, because every input neuron connects to every output neuron. Writing layers.Dense(units=64, activation='relu') creates a layer that will produce 64 output values from whatever input it receives.

Under the hood, a Dense layer is exactly two learnable tensors: a weight matrix W and a bias vector b. When data flows through, the layer computes output = activation(input @ W + b) β€” a matrix multiplication, a bias addition, and then a nonlinear activation function like ReLU applied elementwise. The units argument only fixes the output size; the weight matrix's input dimension is inferred automatically the first time the layer actually sees data.

This is why you rarely specify the input size explicitly for anything but the first layer in a model β€” Keras defers building W and b until it knows the shape of the incoming tensor, then allocates and initializes them (using a sensible default like Glorot/Xavier initialization) automatically.

βœ•
β€”
+
# Create a layer with 64 neurons and ReLU activation
layer = layers.Dense(units=64, activation="relu")
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

5What `layers.Dense(units=64)` Really Builds

When you write layers.Dense(units=64) in Keras, what are you actually creating under the hood? You're creating a standard fully-connected neural network layer: a weight matrix whose shape is (input_dim, 64) and a bias vector of shape (64,). Neither exists yet at the moment you write that line β€” Keras waits until the layer is first called on real data before it knows what input_dim should be.

Once the layer is built, calling it on an input tensor performs input @ W + b, then applies the activation function you specified. Every one of the 64 output units is connected to every value in the input, which is exactly what 'fully connected' or 'dense' means β€” and also why parameter counts grow quickly: a Dense layer going from 784 inputs (a flattened 28x28 image) to 64 units already has 784*64 + 64 = 50,240 trainable parameters.

Those weights and biases are what actually get updated during training. Everything else in a Keras model β€” the Sequential or Functional wiring, the compile step, the fit loop β€” exists to get gradients back to matrices like this one and nudge them toward values that reduce the loss.

βœ•
β€”
+
# The Dense Layer
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

6Sequential API vs Functional API

Keras provides two primary ways to build models: the Sequential API for a simple, straight line of layers, and the Functional API for complex, branching graphs. keras.Sequential([layer1, layer2, layer3]) stacks layers one after another, where each layer takes exactly one input and produces exactly one output that feeds the next layer.

The Functional API treats layers as callables applied to tensors: x = layers.Dense(64)(inputs) then outputs = layers.Dense(10)(x), followed by keras.Model(inputs, outputs). Because you're explicitly wiring tensors together, you can create architectures Sequential can't express β€” multiple inputs, multiple outputs, skip connections, or two branches that merge back together with layers.Concatenate().

Neither API is 'better' in the abstract β€” Sequential is less code and easier to read for a straightforward stack, while Functional is what you reach for the moment your architecture stops being a single linear path, such as a model that takes both an image and a tabular feature vector as separate inputs.

βœ•
β€”
+
# The choice determines how you connect your layers together.
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

7Choosing Sequential for a Linear Stack

Which Keras API should you use if you want to build a simple, straightforward neural network where data flows linearly from layer 1 to layer 2 to layer 3? The Sequential API. keras.Sequential([layers.Dense(64, activation='relu'), layers.Dense(32, activation='relu'), layers.Dense(10, activation='softmax')]) is all it takes to define a three-layer classifier where each layer's output is the next layer's only input.

Sequential's constraint is also its advantage: because it assumes a single unbroken chain, Keras can validate and connect the layers automatically without you writing a single line of tensor-wiring code. There's no risk of accidentally skipping a layer or connecting the wrong tensors, because there's only one path data can take.

The moment you need a second input (like combining an image with metadata), a second output (like predicting a category and a numeric value from the same trunk), or a skip connection (like in a ResNet block), Sequential can no longer express the architecture β€” that's your signal to switch to the Functional API instead.

βœ•
β€”
+
# API Choice
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

8Backend Isolation: Why It Matters

Now, prepare yourself β€” this checkpoint is about backend isolation, the idea that the code describing your model's architecture should be separate from the math engine that actually executes it. For most of Keras's history that separation was theoretical, since TensorFlow was effectively the only backend anyone used in practice.

Backend isolation is what makes it possible for the exact same layers.Dense(64, activation='relu') call to eventually run on top of TensorFlow, PyTorch, or JAX without you rewriting a single line of model code. Keras achieves this by keeping its layer and model APIs backend-agnostic: operations like matrix multiplication or convolution are dispatched through an internal ops abstraction rather than calling tf.matmul directly.

Understanding this distinction matters because it explains what does and doesn't port between backends: your Keras model definitions are portable, but any code you write that calls TensorFlow APIs directly (like tf.data.Dataset pipelines or custom tf.function training steps) is TensorFlow-specific and won't automatically run on another backend.

βœ•
β€”
+
# SYSTEM WARNING:
# ADA Protocol initiating...
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

9Keras 3.0: Multi-Backend by Design

Keras 3.0 was a ground-up rewrite that turned backend isolation from a theoretical benefit into a practical one. Keras is no longer tied strictly to TensorFlow β€” it can now run identically on top of TensorFlow, PyTorch, or JAX, chosen with keras.config.set_backend('jax') or the KERAS_BACKEND environment variable.

This matters beyond novelty. JAX's XLA-first design gives Keras 3 models strong performance on TPUs for research workloads; PyTorch support lets teams standardized on PyTorch's ecosystem (and its dataloaders, deployment tooling) still use Keras's high-level layer API; and TensorFlow remains the default for teams already invested in tf.data, TensorFlow Serving, and TFLite for mobile/edge deployment.

Critically, switching backends doesn't require rewriting your model. The same Sequential/Functional code you write in this module runs unchanged on all three engines β€” only the underlying tensor operations and gradient computation change, which is exactly the backend-isolation guarantee the previous checkpoint described.

βœ•
β€”
+
# ADA initializing backend multi-framework checks...
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

10Clearing Up the Backend Requirement

A junior developer installs Keras 3.0 and asks: 'Do I have to use TensorFlow as the backend engine for this Keras code?' The answer is no. With Keras 3.0, Keras is a multi-backend API β€” you write your model code once, and configure it to run on the TensorFlow, PyTorch, or JAX math engine underneath.

The confusion is understandable because pip install tensorflow still pulls in tf.keras, and a fresh pip install keras defaults to TensorFlow as its backend unless told otherwise. But that default is a convenience, not a hard dependency β€” setting the KERAS_BACKEND environment variable to 'torch' or 'jax' before importing Keras switches the execution engine without touching a single layer definition.

The practical takeaway for this developer: install whichever backend your infrastructure already uses, set KERAS_BACKEND accordingly, and write Keras model code exactly the way this module teaches β€” the portability is Keras's job, not something you need to engineer yourself.

βœ•
β€”
+
# DEFEND THE SYSTEM
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

11Recap: The Keras Framework Architecture

Framework architecture understood: Keras is TensorFlow's official high-level API, wrapping raw tensor math into declarative Dense layers with automatically-managed weight matrices and bias vectors. It offers two model-building styles β€” Sequential for a straight chain of layers, Functional for branching, multi-input, or multi-output graphs β€” and since version 3.0, the same model code can run on TensorFlow, PyTorch, or JAX thanks to backend isolation.

With that mental model in place, the next step is putting it into practice: actually stacking layers into a Sequential model, compiling it with a loss function and optimizer, and running data through it. That's where the abstractions covered here β€” layers, weight matrices, backend-agnostic ops β€” turn into a trainable neural network.

βœ•
β€”
+
print("System secured.\
Keras initialized.")
localhost:3000
Jupyter Notebook / Console Output
Model Code Executed
Graph compiled successfully.

12Step-by-Step Breakdown

Module 02: Keras. Writing raw TensorFlow math equations for every layer of a Neural Network is exhausting. We need a higher-level API.

Keras was originally an independent library created by FranΓ§ois Chollet. It was so beautifully designed that Google officially merged it into TensorFlow 2.0 as tf.keras.

What is the relationship between Keras and TensorFlow today?

  • β†’They are fierce competitors owned by different companies.
  • β†’Keras acts as the official high-level API for TensorFlow, providing simple, human-readable building blocks (like Layers and Models) that sit on top of TensorFlow's raw math engine.
  • β†’Keras is the C++ backend for TensorFlow.

Keras abstracts away the complex math into simple "Layers". The most common is the Dense layer (also called a Fully Connected layer).

When you write layers.Dense(units=64) in Keras, what are you actually creating under the hood?

  • β†’A database connection.
  • β†’A standard fully-connected Neural Network layer containing a mathematical weight matrix and bias vector that will connect to every neuron in the previous layer.
  • β†’A specific type of GPU.

Keras provides two primary ways to build models: The Sequential API (simple, straight line) and the Functional API (complex, branching graphs).

Which Keras API should you use if you want to build a simple, straightforward Neural Network where data flows linearly from layer 1 to layer 2 to layer 3?

  • β†’The Functional API.
  • β†’The Sequential API.
  • β†’The Subclassing API.

Now, prepare yourself. We are about to enter the ADA Defense Protocol. Ensure you understand backend isolation.

Keras 3.0 was recently released. It is a massive shift. Keras is no longer tied strictly to TensorFlow. It can now run on top of PyTorch or JAX as well.

ADA DEFENSE: A junior developer installs Keras 3.0 and asks: "Do I have to use TensorFlow as the backend engine for this Keras code?" How do you respond?

  • β†’Yes, Keras only works with TensorFlow. It is hardcoded.
  • β†’No. With Keras 3.0, Keras is a multi-backend API. You can write your Keras code once, and configure it to run on the TensorFlow, PyTorch, or JAX math engines.
  • β†’You don't need a backend at all; Keras has its own C++ engine.

Threat neutralized. Framework architecture understood. Proceeding to Model Building APIs.

Run a Real Dense Layer Forward Pass. Finish dense_forward(): every neuron computes its own weighted sum plus its own bias.

Level Up πŸš€

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Readable Model Definitions

Building models with named, declarative layers (layers.Dense(64, activation='relu', name='hidden_1')) makes a model's architecture easy for a teammate or future maintainer to audit, versus reconstructing it from raw tf.matmul calls.

model = keras.Sequential([ layers.Dense(64, activation='relu', name='hidden_1'), layers.Dense(10, activation='softmax', name='output') ])

SEO Implications

  • 1

    High-Intent Reference Content

    Searches like 'Keras Sequential vs Functional API' and 'what is tf.keras' are common among developers ramping up on deep learning, so accurate, example-driven coverage of the Keras/TensorFlow relationship has durable organic search value.

Best Practices

Default to Sequential, Reach for Functional When Needed

Start with keras.Sequential for a straightforward stack of layers; switch to the Functional API only once you need multiple inputs/outputs, shared layers, or branching β€” it costs more code for no benefit on a linear model.

Pin a Backend Explicitly in Production

Set the KERAS_BACKEND environment variable (or keras.config.set_backend) explicitly in deployment environments rather than relying on Keras 3's default, so a change in installed packages can't silently switch your execution engine.

Frequent Bugs

THE BUG

Trying to inspect model.summary() or a layer's weights immediately after creating a Sequential model, before it has ever seen input data.

THE FIX

Keras builds a layer's weight matrices lazily on first call. Either call model.build(input_shape=...) explicitly, or run one batch of real data through the model before inspecting its shapes.

Real-World Examples

Migrating a Sequential Model to Functional

A team's image classifier (Sequential) needs to also accept a numeric metadata vector alongside the image, which Sequential's single-input assumption can't express.

image_input = keras.Input(shape=(224, 224, 3))
meta_input = keras.Input(shape=(5,))

x = layers.Dense(64, activation='relu')(layers.Flatten()(image_input))
merged = layers.Concatenate()([x, meta_input])
output = layers.Dense(10, activation='softmax')(merged)

model = keras.Model(inputs=[image_input, meta_input], outputs=output)

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Inspecting model.summary() or layer weights before the model has ever seen data

# Wrong: raises an error, layers aren't built yet model = keras.Sequential([layers.Dense(64, activation='relu'), layers.Dense(10)]) model.summary() # ValueError: This model has not yet been built. # Correct: build explicitly, or call it on data first model = keras.Sequential([layers.Dense(64, activation='relu'), layers.Dense(10)]) model.build(input_shape=(None, 784)) model.summary()

The Solution //

Keras Sequential models build their weight matrices lazily on the first forward pass. Calling model.summary() right after construction raises 'This model has not yet been built' unless you either pass an explicit input_shape or run one batch through the model first.

The Error //

Defining Functional API layers but forgetting to actually call them on a tensor

# Wrong: layer created but never applied to a tensor inputs = keras.Input(shape=(784,)) hidden = layers.Dense(64, activation='relu') # not called on `inputs` outputs = layers.Dense(10, activation='softmax')(inputs) # skips `hidden` entirely # Correct: chain each layer explicitly inputs = keras.Input(shape=(784,)) x = layers.Dense(64, activation='relu')(inputs) outputs = layers.Dense(10, activation='softmax')(x) model = keras.Model(inputs, outputs)

The Solution //

In the Functional API, a layer is just a callable until you apply it to a tensor. Creating layers.Dense(64) without invoking it as x = layers.Dense(64)(previous_tensor) means that layer never gets wired into the model's graph, and Keras will raise an error when you try to build keras.Model(inputs, outputs).

Lesson Glossary

[01]Keras

An open-source software library that provides a Python interface for artificial neural networks. It acts as an interface for TensorFlow, PyTorch, and JAX.

Code Preview
// Keras context

[02]Dense Layer

A regular deeply connected neural network layer. It is the most common and frequently used layer.

Code Preview
// Dense Layer context

Continue Learning