⬡ Hub
Skip to content

Keras: Building Sequential and Functional Models

Keras provides a high-level API for building and training deep learning models. It offers two main ways to define a neural network architecture: the Sequential API and the Functional API. Understanding both is crucial for building a wide range of models.

1. The Sequential API

The Sequential API is the simplest way to build models in Keras. It is used for models where each layer has exactly one input tensor and one output tensor. It's suitable for building simple, feedforward neural networks (stack of layers).

Creating a Sequential Model

You can create a Sequential model by passing a list of layer instances to its constructor, or by adding layers step-by-step using the .add() method.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np

# Option 1: Pass a list of layers to the Sequential constructor
model_list = keras.Sequential([
    layers.InputLayer(input_shape=(784,)), # Explicit input layer for clarity, or just specify input_shape in first Dense
    layers.Dense(128, activation='relu'),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax') # Output layer for 10-class classification
])
print("Model built with list of layers:")
model_list.summary()


# Option 2: Add layers sequentially using .add()
model_add = keras.Sequential()
model_add.add(layers.InputLayer(input_shape=(784,)))
model_add.add(layers.Dense(128, activation='relu'))
model_add.add(layers.Dense(64, activation='relu'))
model_add.add(layers.Dense(10, activation='softmax'))
print("\nModel built with .add() method:")
model_add.summary()

Compiling and Training a Sequential Model

Once the model architecture is defined, you need to compile it and then train it with data.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np

# Load and preprocess sample data (e.g., MNIST for demonstration)
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, 784).astype('float32') / 255.0 # Flatten and normalize
x_test = x_test.reshape(-1, 784).astype('float32') / 255.0

# Define the Sequential model
model = keras.Sequential([
    layers.InputLayer(input_shape=(784,)),
    layers.Dense(128, activation='relu'),
    layers.Dense(10, activation='softmax')
])

# Compile the model
# optimizer: Algorithm to update weights (e.g., 'adam', 'sgd')
# loss: Function to minimize during training (e.g., 'sparse_categorical_crossentropy' for integer labels)
# metrics: Metrics to monitor during training and evaluation
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Train the model
print("\nTraining Sequential Model...")
history = model.fit(x_train, y_train, epochs=3, batch_size=32, validation_split=0.1, verbose=1)

# Evaluate the model
loss, accuracy = model.evaluate(x_test, y_test, verbose=0)
print(f"\nSequential Model Test Accuracy: {accuracy:.4f}")

2. The Functional API

The Functional API is a more flexible way to build models. It can handle models with non-linear topology, shared layers, and multiple inputs/outputs. This API is used to define models as directed acyclic graphs (DAGs) of layers.

Creating a Functional Model

In the Functional API, you define layers as callable objects, and you connect them by calling a layer on the output of another layer.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np

# 1. Define the input layer (always start with Input)
input_tensor = keras.Input(shape=(784,), name='input_layer')

# 2. Define layers and connect them by calling them on previous outputs
x = layers.Dense(128, activation='relu', name='hidden_layer_1')(input_tensor)
x = layers.Dense(64, activation='relu', name='hidden_layer_2')(x)

# 3. Define the output layer
output_tensor = layers.Dense(10, activation='softmax', name='output_layer')(x)

# 4. Create the model by specifying its inputs and outputs
model_functional = keras.Model(inputs=input_tensor, outputs=output_tensor, name='my_functional_model')

print("Model built with Functional API:")
model_functional.summary()

# Plot the model (requires graphviz and pydot)
# keras.utils.plot_model(model_functional, show_shapes=True, show_layer_names=True, to_file='functional_model.png')

Functional Model with Multiple Inputs and Outputs

This is where the Functional API truly shines.

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import numpy as np

# Define two distinct input layers
input_a = keras.Input(shape=(64,), name='input_a')
input_b = keras.Input(shape=(128,), name='input_b')

# Process input_a
x = layers.Dense(32, activation='relu')(input_a)
x = layers.Dense(16, activation='relu')(x)

# Process input_b
y = layers.Dense(64, activation='relu')(input_b)
y = layers.Dense(16, activation='relu')(y)

# Concatenate the processed inputs
combined = layers.concatenate([x, y])

# Further layers on the combined output
z = layers.Dense(8, activation='relu')(combined)

# Define two distinct output layers
output_c = layers.Dense(1, activation='sigmoid', name='output_c')(z) # Binary classification
output_d = layers.Dense(5, activation='softmax', name='output_d')(z) # Multi-class classification

# Create the model with multiple inputs and outputs
model_multi_io = keras.Model(inputs=[input_a, input_b], outputs=[output_c, output_d], name='multi_io_model')

print("\nModel built with Functional API (Multiple IO):")
model_multi_io.summary()

# Compile the model with multiple losses and metrics
model_multi_io.compile(optimizer='adam',
                       loss={'output_c': 'binary_crossentropy', 'output_d': 'sparse_categorical_crossentropy'},
                       metrics={'output_c': 'accuracy', 'output_d': 'accuracy'})

# Create dummy data for training
dummy_input_a_train = np.random.rand(100, 64).astype('float32')
dummy_input_b_train = np.random.rand(100, 128).astype('float32')
dummy_output_c_train = np.random.randint(0, 2, size=(100, 1)).astype('float32')
dummy_output_d_train = np.random.randint(0, 5, size=(100, 1)).astype('float32')

print("\nTraining Multi-IO Model (dummy data)...")
history_multi_io = model_multi_io.fit(
    {'input_a': dummy_input_a_train, 'input_b': dummy_input_b_train},
    {'output_c': dummy_output_c_train, 'output_d': dummy_output_d_train},
    epochs=1, batch_size=32, verbose=1
)

Further Topics:

  • Custom Layers and Models (subclassing Model and Layer)
  • Regularization (Dropout, L1/L2)
  • Batch Normalization
  • Callbacks (EarlyStopping, ModelCheckpoint)
  • Transfer Learning

Understanding the Sequential and Functional APIs empowers you to build a wide spectrum of deep learning models in Keras, from simple feedforward networks to complex multi-input/multi-output architectures.