The Keras Functional API builds a model from symbolic input tensors and layer calls instead of a plain layer list. It fits models that need named inputs, branches, merges, shared layers, or several outputs while keeping the result compatible with normal Keras model APIs.
A functional model starts with keras.Input(), passes those symbolic tensors through layers, and finishes with keras.Model(inputs=…, outputs=…). The resulting graph can be inspected with model.summary() and plotting while still accepting the same predict(), compile(), fit(), and save APIs used by other model types.
A two-input scoring model makes the branch wiring visible. Numeric features and one-hot category features pass through separate branches, merge through Concatenate, and produce one sigmoid score that can be checked with a small prediction batch.
Steps to create a functional Keras model:
- Create functional_model.py with backend selection and imports.
- functional_model.py
import os os.environ["KERAS_BACKEND"] = "jax" import keras import numpy as np from keras import layers keras.utils.set_random_seed(42)
Set KERAS_BACKEND before import keras. Use tensorflow or torch only when those backend packages are installed for the project.
Related: How to set the Keras backend - Define the symbolic input tensors for each branch.
numeric_input = keras.Input(shape=(4,), name="numeric_features") category_input = keras.Input(shape=(3,), name="category_features")
The shape value excludes the batch dimension. A shape of (4,) accepts batches of four numeric features.
- Pass each input through its own layer stack.
numeric_branch = layers.Dense(8, activation="relu", name="numeric_projection")(numeric_input) category_branch = layers.Dense(4, activation="relu", name="category_projection")(category_input)
- Merge the branches and create the model output.
features = layers.Concatenate(name="combined_features")( [numeric_branch, category_branch] ) features = layers.Dense(6, activation="relu", name="hidden_features")(features) score = layers.Dense(1, activation="sigmoid", name="risk_score")(features)
- Instantiate the functional model from the input and output tensors.
model = keras.Model( inputs=[numeric_input, category_input], outputs=score, name="risk_score_functional", )
keras.Model() can receive lists, tuples, or dictionaries of tensors for multi-input or multi-output models.
- Add a prediction batch and print the summary details.
model.summary() numeric_batch = np.array( [ [0.10, 0.80, 0.35, 0.20], [0.90, 0.15, 0.55, 0.70], ], dtype="float32", ) category_batch = np.array( [ [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], ], dtype="float32", ) prediction = model.predict([numeric_batch, category_batch], verbose=0) print(f"backend: {keras.backend.backend()}") print(f"inputs: {[tensor.name for tensor in model.inputs]}") print(f"output layer: {model.layers[-1].name}") print(f"prediction shape: {prediction.shape}") print(f"first prediction: {float(prediction[0, 0]):.4f}")
- Run the script and confirm the graph plus prediction shape.
$ python functional_model.py Model: "risk_score_functional" ┏━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ Connected to ┃ ┡━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━┩ │ numeric_features │ (None, 4) │ 0 │ - │ │ (InputLayer) │ │ │ │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ category_features │ (None, 3) │ 0 │ - │ │ (InputLayer) │ │ │ │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ numeric_projection │ (None, 8) │ 40 │ numeric_features… │ │ (Dense) │ │ │ │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ category_projection │ (None, 4) │ 16 │ category_feature… │ │ (Dense) │ │ │ │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ combined_features │ (None, 12) │ 0 │ numeric_projecti… │ │ (Concatenate) │ │ │ category_project… │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ hidden_features │ (None, 6) │ 78 │ combined_feature… │ │ (Dense) │ │ │ │ ├─────────────────────┼───────────────────┼────────────┼───────────────────┤ │ risk_score (Dense) │ (None, 1) │ 7 │ hidden_features[… │ └─────────────────────┴───────────────────┴────────────┴───────────────────┘ Total params: 141 (564.00 B) Trainable params: 141 (564.00 B) Non-trainable params: 0 (0.00 B) backend: jax inputs: ['numeric_features', 'category_features'] output layer: risk_score prediction shape: (2, 1) first prediction: 0.4898
The summary should show both input layers, the Concatenate layer, and the named risk_score output layer. The prediction shape should match two rows with one score per row.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.