The Functional API handles exactly what the Sequential API cannot: architectures with branching, multiple inputs/outputs, or skip connections โ treating each layer as a callable function applied to a tensor, rather than a fixed, linear stacking order.
The Core Pattern
from tensorflow import keras
from tensorflow.keras import layers
inputs = keras.Input(shape=(784,))
x = layers.Dense(128, activation='relu')(inputs) # layers are CALLED like functions on tensors
x = layers.Dense(64, activation='relu')(x)
outputs = layers.Dense(10, activation='softmax')(x)
model = keras.Model(inputs=inputs, outputs=outputs) # explicitly wire up the input/output tensors
A Residual Connection โ Exactly What Sequential Can't Express
inputs = keras.Input(shape=(64,))
x = layers.Dense(64, activation='relu')(inputs)
x = layers.Dense(64, activation='relu')(x)
residual_output = layers.Add()([inputs, x]) # x + F(x) -- the exact ResNet pattern
model = keras.Model(inputs=inputs, outputs=residual_output)
This is precisely the same limitation flagged for PyTorch's nn.Sequential in PyTorch Layers โ a residual connection needs the original input to be reused later in the network, something a strictly linear layer stack can't express. The Functional API's "layers as callables on tensors" pattern makes this straightforward, since any previously-created tensor (like the original inputs) can be referenced again later.
Multiple Inputs and Outputs
image_input = keras.Input(shape=(224, 224, 3))
text_input = keras.Input(shape=(100,))
image_features = layers.Conv2D(32, 3, activation='relu')(image_input)
image_features = layers.GlobalAveragePooling2D()(image_features)
text_features = layers.Dense(64, activation='relu')(text_input)
combined = layers.Concatenate()([image_features, text_features])
output = layers.Dense(10, activation='softmax')(combined)
model = keras.Model(inputs=[image_input, text_input], outputs=output) # a genuinely MULTIMODAL model
This is exactly the multimodal fusion pattern from Multimodal Learning, expressed directly in Keras โ something the Sequential API, with its single linear input-to-output chain, simply cannot represent.
Common Mistakes
- Confusing the Functional API's "calling a layer" syntax with actually running the model โ
layers.Dense(64)(x)both creates the layer and connects it toxin one line, which can look unusual coming from Sequential's separateadd()pattern. - Forgetting to pass the correct list of input/output tensors to
keras.Model()โ the model's actual computational structure is defined entirely by which tensors get passed here, not by the order layers were created in code.
Interview Relevance
Q: "Why can't a residual connection be implemented using Keras's Sequential API?" A residual connection requires reusing the original input tensor later in the network (\(x + F(x)\)), but the Sequential API enforces a strictly linear chain where each layer's output feeds directly and only into the next layer โ there's no mechanism to reference an earlier tensor again. The Functional API solves this by treating layers as callable functions on tensors, letting any previously created tensor be reused freely wherever needed.
Practice Question
How would you use the Functional API to build a model with two separate output heads โ one for classification, one for regression โ sharing the same early layers?