Most real architectures branch or merge; the functional API expresses them while keeping summary, plotting and saving.
In the functional API you create symbolic inputs with keras.Input, call layers on them like functions, and wrap the result in keras.Model(inputs=..., outputs=...). Each call returns a symbolic KerasTensor with a known shape, so shape errors appear while you build the model, not during training.
It handles what Sequential cannot:
- Multiple inputs, such as text plus tabular metadata, merged with
layers.concatenateorlayers.add. - Multiple outputs, each with its own loss (and optional
loss_weights), passed tocompileas a dict keyed by output layer names. - Skip connections (
x = layers.add([x, shortcut])), as in ResNets. - Shared layers: calling the same layer object on two inputs reuses its weights, as in siamese networks.
The model is a static graph of layers, so Keras can show it with summary() or keras.utils.plot_model, serialise it fully, and let you extract intermediate outputs with keras.Model(model.input, model.get_layer("name").output).
When feeding data, pass dicts keyed by input names ({"text": ..., "meta": ...}) for clarity. Functional models are themselves layers, so you can call one model inside another.
Example
import keras
from keras import layers
text_in = keras.Input(shape=(100,), dtype="int32", name="text") # token ids
meta_in = keras.Input(shape=(5,), name="meta")
t = layers.Embedding(10_000, 32)(text_in)
t = layers.GlobalAveragePooling1D()(t)
m = layers.Dense(16, activation="relu")(meta_in)
h = layers.concatenate([t, m])
priority = layers.Dense(1, activation="sigmoid", name="priority")(h)
dept = layers.Dense(4, name="dept")(h) # logits
model = keras.Model(inputs=[text_in, meta_in], outputs=[priority, dept])
model.compile(optimizer="adam",
loss={"priority": "binary_crossentropy",
"dept": keras.losses.SparseCategoricalCrossentropy(from_logits=True)})
print([tuple(o.shape) for o in model.outputs]) # [(None, 1), (None, 4)]
# model.fit({"text": x_text, "meta": x_meta}, {"priority": y_p, "dept": y_d})Remember
- Call layers on
keras.Inputtensors, thenkeras.Model(inputs, outputs) - Supports multi-input/output, skip connections and shared layers
- Name inputs and outputs and pass dicts to compile and fit
Watch out for
- Creating a new layer object for each branch when you meant to share weights.