Hyperparameter tuning tests several model configurations against the same validation signal before committing to a final training run. In Keras projects, KerasTuner can drive that search while the model-building function stays close to normal Keras code.
A bounded RandomSearch is enough for a local tuning smoke test. It samples a few values for hidden units, dropout, and learning rate, writes each trial under a project directory, and ranks the trials by val_accuracy.
The script selects the JAX backend before importing Keras so the run does not depend on TensorFlow in a minimal environment. Replace the synthetic arrays with project training and validation splits, keep the held-out test split separate, and raise max_trials only after the script records the expected trial files.
Related: How to install Keras with pip
Related: How to set the Keras backend
Related: How to compile a model in Keras
tune_dense_classifier.py
.
import os from pathlib import Path os.environ["KERAS_BACKEND"] = "jax" import keras import keras_tuner import numpy as np keras.utils.set_random_seed(17) rng = np.random.default_rng(17) x = rng.normal(size=(240, 4)).astype("float32") y = ( (0.8 * x[:, 0] - 0.4 * x[:, 1] + 0.3 * x[:, 2] + 0.1 * x[:, 3]) > 0 ).astype("float32") x_train, x_val, x_test = x[:160], x[160:200], x[200:] y_train, y_val, y_test = y[:160], y[160:200], y[200:]
Install Keras, KerasTuner, NumPy, and the selected backend in the same Python environment before running the script. Put the backend setting before any keras or keras_tuner import.
Related: How to set the Keras backend
def build_model(hp): units = hp.Int("units", min_value=4, max_value=16, step=4) dropout = hp.Choice("dropout", values=[0.0, 0.2]) learning_rate = hp.Choice("learning_rate", values=[0.01, 0.03]) model = keras.Sequential( [ keras.layers.Input(shape=(4,)), keras.layers.Dense(units, activation="relu"), keras.layers.Dropout(dropout), keras.layers.Dense(1, activation="sigmoid"), ] ) model.compile( optimizer=keras.optimizers.Adam(learning_rate=learning_rate), loss=keras.losses.BinaryCrossentropy(), metrics=[keras.metrics.BinaryAccuracy(name="accuracy")], jit_compile=False, ) return model
hp.Int() and hp.Choice() define the values KerasTuner can sample for each trial. Disable jit_compile for a short CPU smoke test if backend compilation time would hide the tuning result.
Related: How to compile a model in Keras
Related: How to disable JIT compilation in Keras
tuner = keras_tuner.RandomSearch( build_model, objective="val_accuracy", max_trials=3, seed=17, overwrite=True, directory="tuner_runs", project_name="dense_classifier", ) tuner.search( x_train, y_train, validation_data=(x_val, y_val), epochs=4, batch_size=16, verbose=0, )
overwrite=True starts a fresh demo run when the same directory already exists. Remove it when a real tuning job should resume or preserve earlier trials.
best_hp = tuner.get_best_hyperparameters(num_trials=1)[0] best_trial = tuner.oracle.get_best_trials(num_trials=1)[0] best_model = tuner.hypermodel.build(best_hp) x_final = np.concatenate([x_train, x_val]) y_final = np.concatenate([y_train, y_val]) history = best_model.fit(x_final, y_final, epochs=4, batch_size=16, verbose=0) _, accuracy = best_model.evaluate(x_test, y_test, verbose=0) print(f"backend: {keras.config.backend()}") print(f"trials run: {len(tuner.oracle.trials)}") print(f"best units: {best_hp.get('units')}") print(f"best dropout: {best_hp.get('dropout')}") print(f"best learning_rate: {best_hp.get('learning_rate')}") print(f"best val_accuracy: {best_trial.score:.4f}") print(f"test accuracy: {accuracy:.4f}") print(f"history keys: {', '.join(sorted(history.history.keys()))}") print(f"trial directory: {Path('tuner_runs/dense_classifier').as_posix()}")
Rebuilding the model from best_hp keeps the final fit separate from the validation trials. Keep a test split outside the tuner search so the final metric is not part of trial selection.
$ python3 tune_dense_classifier.py backend: jax trials run: 3 best units: 12 best dropout: 0.0 best learning_rate: 0.03 best val_accuracy: 0.9750 test accuracy: 1.0000 history keys: accuracy, loss trial directory: tuner_runs/dense_classifier
$ ls tuner_runs/dense_classifier oracle.json trial_0 trial_1 trial_2 tuner0.json
Each trial_* directory stores the sampled hyperparameters and checkpoint files for one configuration. Keep this directory with experiment artifacts when the tuning results need to be reviewed later.