Subclassed Keras models are useful when a network needs Python control flow or a custom forward path that does not fit a plain Sequential stack or Functional API graph. A subclass keeps layer objects on the model and puts the forward pass in call(), while still using the built-in compile(), fit(), predict(), and trainable-variable tracking APIs.
The class should create child layers in __init__() and use them in call(). Keras tracks layers assigned as attributes, and the first model call builds their variables for the observed input shape. Keep backend-specific operations out of call() unless the project is intentionally tied to one backend.
A small scoring model on the JAX backend exercises the subclass through model building, one training epoch, and prediction. Replace the sample arrays and layer sizes with project data after the class shape, variable tracking, and output shape are proven.
import os os.environ["KERAS_BACKEND"] = "jax" import keras import numpy as np keras.utils.set_random_seed(11) x_train = np.array( [ [0.0, 0.0, 0.1], [0.0, 1.0, 0.4], [1.0, 0.0, 0.6], [1.0, 1.0, 0.9], ], dtype="float32", ) y_train = np.array([0.0, 1.0, 1.0, 0.0], dtype="float32")
Set KERAS_BACKEND before the first import keras. With KERAS_BACKEND set to jax, the Python environment must have both Keras and JAX installed.
Related: How to install Keras with pip
Related: How to set the Keras backend
class FraudScoreModel(keras.Model): def __init__(self, hidden_units=8): super().__init__(name="fraud_score_model") self.hidden = keras.layers.Dense(hidden_units, activation="relu") self.dropout = keras.layers.Dropout(0.1) self.score = keras.layers.Dense(1, activation="sigmoid") def call(self, inputs, training=False): x = self.hidden(inputs) x = self.dropout(x, training=training) return self.score(x)
The training argument lets layers such as Dropout behave differently during fit() and prediction without changing the public model call.
model = FraudScoreModel(hidden_units=8) sample_scores = model(x_train[:2], training=False)
The first call builds the child layer variables. For subclassed models, call the model once with representative input before inspecting build state or trainable variables.
model.compile( optimizer=keras.optimizers.Adam(learning_rate=0.05), loss=keras.losses.BinaryCrossentropy(), metrics=[keras.metrics.BinaryAccuracy(name="accuracy")], )
A subclassed model can use compile() when call() returns a tensor that matches the selected loss and target shape.
Related: How to compile a model in Keras
history = model.fit(x_train, y_train, epochs=1, batch_size=4, verbose=0)
predictions = model.predict(x_train[:2], verbose=0)
print(f"backend: {keras.backend.backend()}") print(f"model name: {model.name}") print(f"built: {model.built}") print(f"sample output shape: {sample_scores.shape}") print(f"trainable variables: {len(model.trainable_variables)}") print("history keys:", ", ".join(sorted(history.history.keys()))) print(f"prediction shape: {predictions.shape}") print("prediction sample:", [float(f"{value:.4f}") for value in predictions[:, 0]])
$ python subclass_model.py backend: jax model name: fraud_score_model built: True sample output shape: (2, 1) trainable variables: 4 history keys: accuracy, loss prediction shape: (2, 1) prediction sample: [0.4741, 0.5877]