Jesse A. Green / notebook

Keras User Guide

Generated May 2026 from keras-team/keras at b800fdf

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

Keras 3.15.0 is a multi-backend deep learning framework for Python. Write your model once and run it on TensorFlow, JAX, PyTorch, NumPy, or OpenVINO without changing a single line of model code. Keras provides a high-level, intuitive API for building, training, evaluating, and deploying neural networks of any scale, from quick prototypes to production systems.


1. Quick Start

Build and train a neural network in under 20 lines:

import keras
from keras import layers

# Build a simple classifier
model = keras.Sequential([
    layers.Input(shape=(784,)),
    layers.Dense(128, activation="relu"),
    layers.Dropout(0.3),
    layers.Dense(10, activation="softmax"),
])

# Compile with optimizer, loss, and metrics
model.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)

# Load built-in dataset
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape(-1, 784).astype("float32") / 255.0
x_test = x_test.reshape(-1, 784).astype("float32") / 255.0

# Train
model.fit(x_train, y_train, epochs=5, batch_size=32, validation_split=0.1)

# Evaluate
loss, accuracy = model.evaluate(x_test, y_test)
print(f"Test accuracy: {accuracy:.4f}")

Tip

Keras defaults to TensorFlow as its backend. To switch to JAX or PyTorch, set the KERAS_BACKEND environment variable before importing Keras (see Section 3).

Your First Image Classifier with a Pre-trained Model

Transfer learning gets you high accuracy with minimal data:

import keras
from keras import layers

# Load pre-trained MobileNetV2 (without top classification layer)
base_model = keras.applications.MobileNetV2(
    weights="imagenet",
    include_top=False,
    input_shape=(224, 224, 3),
)
base_model.trainable = False  # Freeze base weights

# Add custom classification head
model = keras.Sequential([
    base_model,
    layers.GlobalAveragePooling2D(),
    layers.Dense(128, activation="relu"),
    layers.Dropout(0.5),
    layers.Dense(5, activation="softmax"),  # 5 classes
])

model.compile(
    optimizer="adam",
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)

# Load images from directory structure
train_ds = keras.utils.image_dataset_from_directory(
    "data/train",
    image_size=(224, 224),
    batch_size=32,
)

model.fit(train_ds, epochs=10)
model.save("my_classifier.keras")

2. Installation

Requirements

  • Python 3.9 or later
  • One backend framework installed (TensorFlow, JAX, or PyTorch)

Install Keras with a Backend

Install Keras alongside your preferred backend:

# TensorFlow backend (default)
pip install keras tensorflow

# JAX backend (CPU)
pip install keras jax

# JAX backend (GPU — NVIDIA CUDA)
pip install keras jax[cuda12]

# PyTorch backend
pip install keras torch torchvision

Important

Keras 3.x is a standalone package. If you previously used tf.keras from TensorFlow 2.x, you now import Keras separately with import keras. The tf.keras namespace redirects to the standalone Keras package starting with TensorFlow 2.16.

Verify Installation

import keras
print(keras.__version__)   # 3.15.0
print(keras.config.backend())  # "tensorflow" (or whichever you configured)
3.15.0
tensorflow

Optional Dependencies

Package Purpose
pydot + Graphviz keras.utils.plot_model() — architecture visualization
h5py Legacy HDF5 model saving
pillow Image preprocessing layers and image_dataset_from_directory
pandas CSVLogger callback, tabular data loading
scipy Sparse matrix support in various layers

Note

For GPU acceleration, follow the official installation instructions for your backend framework (e.g., CUDA toolkit for TensorFlow/JAX, or PyTorch's CUDA builds). Keras itself has no GPU-specific dependencies — the backend handles device management.


3. Configuration

Choosing a Backend

Keras supports five backends. Set the backend before importing Keras:

Option 1: Environment variable (recommended)

# Linux/macOS
export KERAS_BACKEND=jax
python my_script.py

# Windows (PowerShell)
$env:KERAS_BACKEND = "jax"
python my_script.py

# Windows (cmd)
set KERAS_BACKEND=jax
python my_script.py

Option 2: Configuration file

Edit ~/.keras/keras.json:

{
    "floatx": "float32",
    "epsilon": 1e-7,
    "backend": "jax",
    "image_data_format": "channels_last",
    "nnx_enabled": false
}

Option 3: Runtime switching

import keras
keras.config.set_backend("torch")

Warning

Switching backends at runtime with set_backend() after models or tensors have been created can lead to undefined behavior. Set the backend once at the start of your script or rely on the environment variable.

Backend Value Best For
TensorFlow tensorflow Production serving, TF ecosystem, mobile/edge deployment
JAX jax Research, XLA compilation, TPU workloads, functional transforms
PyTorch torch PyTorch ecosystem integration, dynamic computation graphs
NumPy numpy Inference-only (no training), debugging, testing
OpenVINO openvino Intel hardware inference optimization

Global Configuration API

Tune Keras behavior at runtime using keras.config:

import keras

# Mixed precision for faster GPU training
keras.config.set_dtype_policy("mixed_float16")

# Change default float precision
keras.config.set_floatx("float64")
print(keras.config.floatx())  # "float64"

# Set image data ordering
keras.config.set_image_data_format("channels_first")  # NCHW layout

# Flash attention (enabled by default, requires float16/bfloat16)
keras.config.enable_flash_attention()
print(keras.config.is_flash_attention_enabled())  # True

# Debugging: cap training runs
keras.config.set_max_epochs(2)
keras.config.set_max_steps_per_epoch(10)

Environment Variables Reference

Variable Purpose Example
KERAS_BACKEND Select backend jax, torch, tensorflow, numpy, openvino
KERAS_HOME Override config directory /custom/path (default: ~/.keras)
KERAS_MAX_EPOCHS Cap training epochs 2 (useful for debugging)
KERAS_MAX_STEPS_PER_EPOCH Cap steps per epoch 10
KERAS_NNX_ENABLED Enable Flax NNX features (JAX) true

Reproducibility

Lock random seeds across all backends:

keras.utils.set_random_seed(42)

This sets seeds for Python's random, NumPy, and the active backend's random number generator in a single call.


4. Core Usage

Building Models

Keras offers three ways to build models, each suited to different complexity levels.

Sequential API

For linear layer stacks where each layer has exactly one input and one output:

from keras import layers, Sequential

model = Sequential([
    layers.Input(shape=(28, 28, 1)),
    layers.Conv2D(32, kernel_size=3, activation="relu"),
    layers.MaxPooling2D(pool_size=2),
    layers.Conv2D(64, kernel_size=3, activation="relu"),
    layers.MaxPooling2D(pool_size=2),
    layers.Flatten(),
    layers.Dense(128, activation="relu"),
    layers.Dropout(0.5),
    layers.Dense(10, activation="softmax"),
])

model.summary()

Add or remove layers dynamically:

model = Sequential()
model.add(layers.Dense(64, activation="relu", input_shape=(100,)))
model.add(layers.Dense(10, activation="softmax"))

model.pop()  # Remove the last layer
model.add(layers.Dense(5, activation="softmax"))  # Replace it

Functional API

For models with branches, multiple inputs/outputs, or shared layers:

import keras
from keras import layers

# Multi-input model
text_input = keras.Input(shape=(100,), name="text")
image_input = keras.Input(shape=(224, 224, 3), name="image")

# Text branch
x1 = layers.Embedding(10000, 64)(text_input)
x1 = layers.LSTM(128)(x1)

# Image branch
x2 = layers.Conv2D(32, 3, activation="relu")(image_input)
x2 = layers.GlobalAveragePooling2D()(x2)

# Merge
merged = layers.Concatenate()([x1, x2])
output = layers.Dense(1, activation="sigmoid")(merged)

model = keras.Model(inputs=[text_input, image_input], outputs=output)

Tip

The Functional API lets you inspect and reuse intermediate layers. Access any layer's output with model.get_layer("layer_name").output and use it to build new models — invaluable for feature extraction and transfer learning.

Subclassing

For maximum flexibility and custom forward-pass logic:

import keras
from keras import layers

class TransformerBlock(keras.Model):
    def __init__(self, embed_dim, num_heads, ff_dim, dropout_rate=0.1):
        super().__init__()
        self.attention = layers.MultiHeadAttention(
            num_heads=num_heads, key_dim=embed_dim
        )
        self.ffn = keras.Sequential([
            layers.Dense(ff_dim, activation="relu"),
            layers.Dense(embed_dim),
        ])
        self.norm1 = layers.LayerNormalization()
        self.norm2 = layers.LayerNormalization()
        self.dropout1 = layers.Dropout(dropout_rate)
        self.dropout2 = layers.Dropout(dropout_rate)

    def call(self, inputs, training=False):
        attn_output = self.attention(inputs, inputs)
        attn_output = self.dropout1(attn_output, training=training)
        out1 = self.norm1(inputs + attn_output)

        ffn_output = self.ffn(out1)
        ffn_output = self.dropout2(ffn_output, training=training)
        return self.norm2(out1 + ffn_output)

Compiling Models

Configure the training process:

model.compile(
    optimizer=keras.optimizers.Adam(learning_rate=1e-3),
    loss="categorical_crossentropy",
    metrics=["accuracy", keras.metrics.AUC(name="auc")],
)

Common loss functions:

Task Loss Output Activation
Binary classification "binary_crossentropy" sigmoid
Multi-class (integer labels) "sparse_categorical_crossentropy" softmax
Multi-class (one-hot labels) "categorical_crossentropy" softmax
Regression "mse" or "mae" linear (none)

Training

history = model.fit(
    x_train, y_train,
    epochs=20,
    batch_size=64,
    validation_split=0.2,       # Hold out 20% for validation
    callbacks=[
        keras.callbacks.EarlyStopping(
            monitor="val_loss",
            patience=3,
            restore_best_weights=True,
        ),
        keras.callbacks.ReduceLROnPlateau(
            monitor="val_loss",
            factor=0.5,
            patience=2,
        ),
    ],
)

Access training history:

print(history.history.keys())
# dict_keys(['loss', 'accuracy', 'val_loss', 'val_accuracy'])

import matplotlib.pyplot as plt
plt.plot(history.history["loss"], label="train")
plt.plot(history.history["val_loss"], label="val")
plt.legend()
plt.show()

Evaluation and Prediction

# Evaluate on test set
test_loss, test_acc = model.evaluate(x_test, y_test, batch_size=64)
print(f"Test accuracy: {test_acc:.4f}")

# Predict on new data
predictions = model.predict(x_new)
predicted_classes = predictions.argmax(axis=-1)

Saving and Loading Models

# Save entire model (architecture + weights + optimizer state)
model.save("my_model.keras")

# Load it back
loaded_model = keras.saving.load_model("my_model.keras")

# Save/load weights only
model.save_weights("weights.weights.h5")
model.load_weights("weights.weights.h5")

Note

The .keras format is the recommended save format. It uses a ZIP archive containing the model config (JSON) and weights (H5). Legacy HDF5 (.h5) saving is still supported but not recommended for new code.

Exporting for Production

Export models for serving and deployment:

# Export as SavedModel (TensorFlow Serving, TFLite)
export_archive = keras.export.ExportArchive()
export_archive.track(model)
export_archive.add_endpoint(
    name="serve",
    fn=model.call,
    input_signature=[keras.InputSpec(shape=(None, 784), dtype="float32")],
)
export_archive.write_out("exported_model")

5. Common Tasks

Image Classification with Data Augmentation

import keras
from keras import layers

# Data augmentation pipeline
augmentation = keras.Sequential([
    layers.RandomFlip("horizontal"),
    layers.RandomRotation(0.1),
    layers.RandomZoom(0.1),
    layers.RandomBrightness(0.2),
    layers.RandomContrast(0.2),
])

# Load data from directory
train_ds = keras.utils.image_dataset_from_directory(
    "data/train",
    image_size=(224, 224),
    batch_size=32,
    label_mode="categorical",
)

val_ds = keras.utils.image_dataset_from_directory(
    "data/val",
    image_size=(224, 224),
    batch_size=32,
    label_mode="categorical",
)

# Build model with augmentation
inputs = keras.Input(shape=(224, 224, 3))
x = augmentation(inputs)
x = keras.applications.EfficientNetB0(
    include_top=False, weights="imagenet"
)(x)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dropout(0.3)(x)
outputs = layers.Dense(10, activation="softmax")(x)

model = keras.Model(inputs, outputs)
model.compile(
    optimizer=keras.optimizers.Adam(1e-3),
    loss="categorical_crossentropy",
    metrics=["accuracy"],
)
model.fit(train_ds, validation_data=val_ds, epochs=20)

Tip

Augmentation layers like RandomFlip, RandomRotation, and RandomZoom only apply during training. At inference time they pass data through unchanged, so you can include them directly in your model without worrying about test-time distortion.

Text Classification with Preprocessing

import keras
from keras import layers

# Built-in text preprocessing
max_tokens = 20000
max_length = 200

vectorizer = layers.TextVectorization(
    max_tokens=max_tokens,
    output_mode="int",
    output_sequence_length=max_length,
)

# Adapt to training text
train_texts = ["This movie was great", "Terrible film", ...]
vectorizer.adapt(train_texts)

# Build model
model = keras.Sequential([
    keras.Input(shape=(1,), dtype="string"),
    vectorizer,
    layers.Embedding(max_tokens, 128),
    layers.Bidirectional(layers.LSTM(64)),
    layers.Dense(64, activation="relu"),
    layers.Dropout(0.5),
    layers.Dense(1, activation="sigmoid"),
])

model.compile(
    optimizer="adam",
    loss="binary_crossentropy",
    metrics=["accuracy"],
)

Time Series Forecasting

import keras
from keras import layers

# Create windowed dataset from time series
dataset = keras.utils.timeseries_dataset_from_array(
    data=time_series_values,
    targets=time_series_values[window_size:],
    sequence_length=window_size,
    batch_size=32,
)

# LSTM model for forecasting
model = keras.Sequential([
    layers.Input(shape=(window_size, num_features)),
    layers.LSTM(64, return_sequences=True),
    layers.LSTM(32),
    layers.Dense(1),
])

model.compile(optimizer="adam", loss="mse")
model.fit(dataset, epochs=50)

Transfer Learning with Fine-Tuning

Two-phase training: train the head, then fine-tune deeper layers.

import keras
from keras import layers

# Phase 1: Feature extraction
base = keras.applications.ResNet50(
    weights="imagenet", include_top=False, input_shape=(224, 224, 3)
)
base.trainable = False

model = keras.Sequential([
    base,
    layers.GlobalAveragePooling2D(),
    layers.Dense(256, activation="relu"),
    layers.Dropout(0.5),
    layers.Dense(10, activation="softmax"),
])

model.compile(
    optimizer=keras.optimizers.Adam(1e-3),
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)
model.fit(train_ds, epochs=10, validation_data=val_ds)

# Phase 2: Fine-tune top layers of the base
base.trainable = True
for layer in base.layers[:-20]:
    layer.trainable = False  # Only fine-tune last 20 layers

model.compile(
    optimizer=keras.optimizers.Adam(1e-5),  # Lower learning rate
    loss="sparse_categorical_crossentropy",
    metrics=["accuracy"],
)
model.fit(train_ds, epochs=10, validation_data=val_ds)

Important

When fine-tuning, always recompile the model after changing trainable attributes. Use a significantly lower learning rate (10x--100x smaller) to avoid destroying the pre-trained features.

Mixed Precision Training

Speed up training on modern GPUs with mixed precision:

import keras

# Enable mixed precision globally
keras.config.set_dtype_policy("mixed_float16")

# Build your model normally — layers auto-cast
model = keras.Sequential([
    keras.Input(shape=(784,)),
    keras.layers.Dense(512, activation="relu"),
    keras.layers.Dense(10, activation="softmax", dtype="float32"),  # Keep output in float32
])

# Use loss scaling for numerical stability
optimizer = keras.optimizers.Adam(1e-3)
optimizer = keras.optimizers.LossScaleOptimizer(optimizer)

model.compile(optimizer=optimizer, loss="sparse_categorical_crossentropy", metrics=["accuracy"])

Warning

Flash attention requires float16 or bfloat16 inputs. If you use float32 precision with MultiHeadAttention, flash attention is automatically bypassed. Mixed precision is the recommended approach for attention-heavy models like transformers.

Custom Training Loop

For full control over the training process:

import keras

model = keras.Sequential([
    keras.layers.Dense(64, activation="relu"),
    keras.layers.Dense(10),
])
optimizer = keras.optimizers.Adam(1e-3)
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)

for epoch in range(10):
    for step, (x_batch, y_batch) in enumerate(train_dataset):
        with keras.backend.GradientTape() if hasattr(keras.backend, "GradientTape") else None:
            # Use trainable_variables and gradient computation
            pass

    # Simpler: use train_on_batch for step-by-step control
    for x_batch, y_batch in train_dataset:
        loss = model.train_on_batch(x_batch, y_batch)

Learning Rate Schedules

from keras.optimizers.schedules import CosineDecay, ExponentialDecay

# Cosine decay with warmup
schedule = CosineDecay(
    initial_learning_rate=1e-3,
    decay_steps=10000,
    alpha=1e-6,  # Minimum learning rate
)

# Exponential decay
schedule = ExponentialDecay(
    initial_learning_rate=1e-3,
    decay_steps=1000,
    decay_rate=0.9,
)

optimizer = keras.optimizers.Adam(learning_rate=schedule)

Model Quantization

Reduce model size for deployment:

# Quantize Dense layers to int8
model = keras.Sequential([
    keras.layers.Dense(512, activation="relu"),
    keras.layers.Dense(10, activation="softmax"),
])
model.build(input_shape=(None, 784))

# Quantize individual layers
model.layers[0].quantize("int8")

# Combine with LoRA for efficient fine-tuning
model.layers[0].enable_lora(rank=4)

Supported quantization modes for Dense, EinsumDense, and Embedding layers include int8, int4, float8, AWQ, and GPTQ.

Using scikit-learn with Keras

Wrap Keras models for scikit-learn pipelines:

from keras.wrappers import SKLearnClassifier
from sklearn.model_selection import cross_val_score

def build_model():
    model = keras.Sequential([
        keras.layers.Dense(64, activation="relu", input_shape=(20,)),
        keras.layers.Dense(3, activation="softmax"),
    ])
    model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
    return model

classifier = SKLearnClassifier(model=build_model, epochs=10, batch_size=32)
scores = cross_val_score(classifier, X, y, cv=5)
print(f"Accuracy: {scores.mean():.4f} (+/- {scores.std():.4f})")

Wrapping JAX, Flax, and PyTorch Code

Integrate external framework code into Keras models:

# Wrap a JAX function as a Keras layer
jax_layer = keras.utils.JaxLayer(jax_function, params=initial_params)

# Wrap a PyTorch nn.Module
import torch.nn as nn

torch_module = nn.Linear(64, 10)
keras_layer = keras.utils.TorchModuleWrapper(torch_module)

Audio Processing

from keras import layers

# Mel spectrogram preprocessing
mel_layer = layers.MelSpectrogram(
    sample_rate=16000,
    fft_length=2048,
    num_mel_bins=128,
)

# STFT spectrogram
stft_layer = layers.STFTSpectrogram(
    sequence_length=2048,
    sequence_stride=512,
)

model = keras.Sequential([
    keras.Input(shape=(16000,)),  # 1 second of audio at 16kHz
    mel_layer,
    layers.Conv2D(32, 3, activation="relu"),
    layers.GlobalAveragePooling2D(),
    layers.Dense(10, activation="softmax"),
])

Using Callbacks Effectively

Save Best Model During Training

checkpoint = keras.callbacks.ModelCheckpoint(
    filepath="best_model.keras",
    monitor="val_accuracy",
    mode="max",
    save_best_only=True,
    verbose=1,
)

model.fit(x_train, y_train, epochs=50, validation_split=0.2, callbacks=[checkpoint])

TensorBoard Logging

tensorboard = keras.callbacks.TensorBoard(
    log_dir="./logs",
    histogram_freq=1,
    write_graph=True,
)
model.fit(x_train, y_train, epochs=10, callbacks=[tensorboard])

Then view logs:

tensorboard --logdir=./logs

Combine Multiple Callbacks

callbacks = [
    keras.callbacks.EarlyStopping(monitor="val_loss", patience=5, restore_best_weights=True),
    keras.callbacks.ReduceLROnPlateau(monitor="val_loss", factor=0.2, patience=3),
    keras.callbacks.ModelCheckpoint("best.keras", save_best_only=True),
    keras.callbacks.CSVLogger("training_log.csv"),
    keras.callbacks.TerminateOnNaN(),
    keras.callbacks.BackupAndRestore(backup_dir="./backup"),
]

model.fit(x_train, y_train, epochs=100, validation_split=0.2, callbacks=callbacks)

Tip

BackupAndRestore saves training state (epoch number, optimizer state) to disk each epoch. If training is interrupted, calling model.fit() again with the same callback resumes from the last completed epoch rather than starting over.

Backend-Agnostic Operations

Write numerical code that works on any backend:

import keras
from keras import ops

# NumPy-compatible operations
x = ops.numpy.linspace(0, 1, 100)
y = ops.numpy.sin(x * 2 * ops.numpy.pi)

# Neural network operations
logits = ops.numpy.random.normal(shape=(32, 10))
probs = ops.nn.softmax(logits, axis=-1)

# Image operations
images = ops.numpy.random.normal(shape=(4, 224, 224, 3))
resized = ops.image.resize(images, size=(112, 112))

# Control flow
result = ops.core.cond(
    pred=ops.numpy.sum(x) > 0,
    true_fn=lambda: x * 2,
    false_fn=lambda: x,
)

Built-in Datasets

Keras ships with several classic datasets for prototyping:

# Image datasets
(x, y), (x_test, y_test) = keras.datasets.mnist.load_data()
(x, y), (x_test, y_test) = keras.datasets.fashion_mnist.load_data()
(x, y), (x_test, y_test) = keras.datasets.cifar10.load_data()
(x, y), (x_test, y_test) = keras.datasets.cifar100.load_data()

# Text datasets
(x, y), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=10000)
(x, y), (x_test, y_test) = keras.datasets.reuters.load_data(num_words=10000)

# Tabular datasets
(x, y), (x_test, y_test) = keras.datasets.california_housing.load_data()
(x, y), (x_test, y_test) = keras.datasets.boston_housing.load_data()

Visualizing Model Architecture

# Print text summary
model.summary()

# Generate architecture diagram (requires pydot + Graphviz)
keras.utils.plot_model(
    model,
    to_file="model_architecture.png",
    show_shapes=True,
    show_layer_names=True,
    show_dtype=True,
)

6. Troubleshooting

Error: Could not find matching concrete function to call loaded from the SavedModel

Cause: The model was saved with a different input signature than what you're passing during inference.

Solution:

  1. Check the expected input shape: loaded_model.input_shape
  2. Reshape your input data to match
  3. If exporting, explicitly specify the input signature via ExportArchive.add_endpoint()

Prevention: Always verify input shapes match before saving and loading.

Error: ValueError: Input 0 of layer "dense" is incompatible with the layer: expected axis -1 of input shape to have value N, but received input with shape (batch, M)

Cause: A shape mismatch between what a layer expects and what it receives, usually after a Flatten or between model components.

Solution:

  1. Run model.summary() to inspect shapes at each layer
  2. Add or fix Reshape/Flatten layers to produce the expected dimensions

Prevention: Use model.summary() after building to verify the shape chain before training.

Error: RuntimeError: You must compile your model before training/testing. Use model.compile()

Cause: Calling model.fit(), model.evaluate(), or model.predict() before model.compile().

Solution:

  1. Call model.compile(optimizer=..., loss=...) before training
  2. After loading a model with load_model(), the compiled state is restored automatically

Prevention: Always compile immediately after model construction.

Error: OOM when allocating tensor with shape [...] on /device:GPU:0

Cause: The model or batch size exceeds GPU memory.

Solution:

  1. Reduce batch_size in model.fit()
  2. Use mixed precision: keras.config.set_dtype_policy("mixed_float16")
  3. Use a smaller model architecture
  4. For TensorFlow backend, enable memory growth:
    import tensorflow as tf
    gpus = tf.config.list_physical_devices("GPU")
    for gpu in gpus:
        tf.config.experimental.set_memory_growth(gpu, True)
    

Prevention: Start with small batch sizes and increase gradually. Monitor GPU memory with nvidia-smi.

Error: ValueError: Failed to convert a NumPy array to a Tensor (Unsupported object type float)

Cause: Input data contains mixed types or Python objects instead of uniform numeric arrays.

Solution:

  1. Ensure arrays are a consistent numeric dtype: x = x.astype("float32")
  2. Check for None values or nested lists of inconsistent length

Prevention: Always normalize data types before passing to model.fit().

Error: ModuleNotFoundError: No module named 'keras'

Cause: Keras is not installed, or the wrong environment is active.

Solution:

  1. Install Keras: pip install keras
  2. Verify the correct Python environment: which python && pip list | grep keras

Prevention: Use virtual environments and install Keras explicitly.

Error: ValueError: Unknown backend: "xyz". Available backends are: tensorflow, jax, torch, numpy, openvino

Cause: Invalid value for KERAS_BACKEND environment variable or keras.json.

Solution:

  1. Set a valid backend value: tensorflow, jax, torch, numpy, or openvino
  2. Install the corresponding backend package

Prevention: Check ~/.keras/keras.json for typos.

Error: ValueError: Layer weight shape (64, 128) is not compatible with provided weight shape (128, 64)

Cause: Loading weights from a model with different architecture.

Solution:

  1. Ensure the model architecture matches exactly: same layers, same units, same order
  2. Use model.save("model.keras") / load_model() instead of save_weights() when the architecture may differ
  3. For transfer learning, use by_name=True: model.load_weights("weights.h5", by_name=True)

Prevention: Save full models (.keras) rather than weights-only when possible.

Error: Deserialization of Lambda layers or torch.nn.Module is disallowed

Cause: Security restriction prevents deserializing arbitrary code from saved models.

Solution:

  1. If you trust the model source, enable unsafe deserialization:
    keras.config.enable_unsafe_deserialization()
    model = keras.saving.load_model("model_with_lambda.keras")
    
  2. Refactor to use named layers/functions instead of Lambda

Prevention: Avoid Lambda layers in models intended for saving. Use custom layer subclasses with get_config().

Caution

Only call enable_unsafe_deserialization() for models you created or fully trust. Untrusted models with Lambda layers can execute arbitrary code during loading.

Error: train_on_batch returns cumulative metric values after load_model

Cause: This is a known issue where metric state accumulates incorrectly after loading a saved model.

Solution:

  1. Reset metrics before resuming training: model.reset_metrics()
  2. Or use model.fit() with appropriate initial_epoch instead of train_on_batch()

Prevention: Call model.reset_metrics() after load_model() if using train_on_batch().

Issue: Backend Gradient Differences

Cause: Numerical differences between TensorFlow, JAX, and PyTorch backends can produce slightly different gradient values, especially with operations like Conv1D + Flatten using channels_first format.

Solution:

  1. Use channels_last (the default) for maximum cross-backend consistency
  2. Accept small numerical differences (within 1e-5) as normal
  3. For exact reproducibility, pin a single backend

Prevention: Test on your target backend early in development.

Issue: Traceback Too Verbose

Solution: Filter Keras internal frames from stack traces:

keras.config.enable_traceback_filtering()

This hides Keras internal call stack frames and shows only your code.


7. FAQ

Q: How is Keras 3 different from tf.keras in TensorFlow 2.x?

Keras 3 is a standalone, multi-backend framework. It runs on TensorFlow, JAX, PyTorch, NumPy, and OpenVINO. Starting with TensorFlow 2.16, tf.keras points to the standalone Keras package. The API is largely the same, but you now import keras directly and can choose any backend.

Q: Which backend should I choose?

TensorFlow is the default and best supported for production deployment (TF Serving, TFLite, mobile). JAX excels at research workloads, XLA compilation, and TPU usage. PyTorch is ideal if you need to interoperate with existing PyTorch code. NumPy is inference-only but useful for debugging. Choose based on your deployment target and ecosystem needs.

Q: Can I use multiple backends in the same script?

No. Keras uses one backend per Python process. Set it once at the start via KERAS_BACKEND or keras.config.set_backend(). If you need multiple backends, use separate scripts or subprocesses.

Q: How do I use Keras with a GPU?

Install the GPU-enabled version of your backend (e.g., tensorflow[and-cuda], jax[cuda12], torch with CUDA). Keras automatically uses available GPUs through the backend. No Keras-specific GPU configuration is needed.

Q: What model save format should I use?

Use the .keras format (model.save("model.keras")). It bundles architecture, weights, and optimizer state in a portable ZIP file. Legacy HDF5 (.h5) is supported but not recommended for new projects.

Q: Can I convert my Keras model to ONNX?

Yes. Use keras.export.ExportArchive to export the model, then convert to ONNX using the appropriate backend tool (e.g., tf2onnx for TensorFlow backend, torch.onnx.export for PyTorch backend).

Q: How do I freeze layers for transfer learning?

Set layer.trainable = False on layers you want to freeze. For a pre-trained base model, base_model.trainable = False freezes all its layers. After changing trainable attributes, recompile the model.

Q: What is mixed precision and when should I use it?

Mixed precision (keras.config.set_dtype_policy("mixed_float16")) trains with float16 for speed while keeping critical computations in float32 for numerical stability. Use it on GPUs with Tensor Cores (NVIDIA V100, A100, RTX 30xx/40xx/50xx series) for 2-3x speedups.

Q: How does BackupAndRestore work?

The BackupAndRestore callback saves training state (current epoch, optimizer variables) to a directory each epoch. If your training script restarts, calling model.fit() with the same callback automatically resumes from the last completed epoch. This is essential for long training runs on preemptible instances.

Q: Can I use Keras layers in a PyTorch training loop?

Yes, when using the PyTorch backend. Keras layers are valid torch.nn.Module subclasses. You can mix Keras layers with native PyTorch modules and use standard PyTorch training loops with torch.optim and loss.backward().

Q: How do I pad variable-length sequences?

Use keras.utils.pad_sequences():

padded = keras.utils.pad_sequences(sequences, maxlen=100, padding="post")

This pads shorter sequences with zeros and truncates longer ones.

Q: What pre-trained models are available?

Keras ships with ImageNet-pretrained models including VGG16/19, ResNet50/101/152, InceptionV3, Xception, MobileNet/V2/V3, DenseNet, NASNet, EfficientNet (B0-B7), EfficientNetV2, and ConvNeXt variants. Access them via keras.applications.*.

Q: How do I debug a model that won't converge?

Start by checking: (1) data preprocessing (normalize inputs, verify labels), (2) learning rate (try 1e-3 as a starting point), (3) model capacity (too small or too large for the data), (4) loss function matches your task, (5) use keras.config.set_max_epochs(2) and keras.config.set_max_steps_per_epoch(5) for quick iteration.

Q: What is the keras.ops module for?

keras.ops provides backend-agnostic math operations. keras.ops.numpy.* mirrors NumPy, keras.ops.nn.* provides neural network primitives, keras.ops.image.* handles image operations, and keras.ops.linalg.* provides linear algebra. Code written with keras.ops runs identically on all backends.

Q: How do I use Flax NNX features with the JAX backend?

Set KERAS_NNX_ENABLED=true or configure "nnx_enabled": true in ~/.keras/keras.json. Check status with keras.config.is_nnx_enabled(). This enables Flax NNX integration for JAX-specific features.