Master-log orchestration layer for KerasTuner. One CSV per tuning run, strategy-agnostic configuration, structured results.
Project description
kt-masterlog
Master-log orchestration layer for KerasTuner. One CSV per tuning run, strategy-agnostic configuration, structured results.
The problem
KerasTuner scatters trial data across per-trial directories. Comparing hyperparameters against metrics across trials means writing custom aggregation scripts every time. Switching strategies (Bayesian → Hyperband → Random) requires swapping classes and rewriting constructor arguments. There's no structured result object — you print things, then lose them.
What this does
MasterEpochLogger — A Keras callback that writes one flat CSV row per epoch per trial: trial ID, all hyperparameter values, and all metrics in a single file. Load it into pandas and you have your entire tuning run in one DataFrame.
make_logging_tuner() — Dynamically subclasses any KerasTuner strategy to inject the logger automatically. No separate subclass per strategy.
TunerConfig — A serializable dataclass holding every tuning knob. JSON-roundtrippable for reproducibility. Diffable across experiments.
optimize() — Single-call orchestrator. Takes a model builder and a config, returns a TuningResult with the best model, hyperparameters, timing, and the path to the master CSV.
Install
With pip:
pip install kt-masterlog
With uv:
uv add kt-masterlog
Or from source:
git clone https://github.com/techspeque/kt-masterlog.git
cd kt-masterlog
# pip
pip install -e ".[dev]"
# uv
uv sync --group dev
Quickstart
from kt_masterlog import optimize, TunerConfig
def build_model(hp):
lr = hp.Choice("lr", [1e-3, 3e-4, 1e-4])
units = hp.Choice("units", [64, 128, 256])
model = tf.keras.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(units, activation="relu"),
tf.keras.layers.Dense(10, activation="softmax"),
])
model.compile(
optimizer=tf.keras.optimizers.Adam(lr),
loss="sparse_categorical_crossentropy",
metrics=["accuracy"],
)
return model
result = optimize(
builder_fn=build_model,
train_data=x_train,
val_data=(x_val, y_val),
config=TunerConfig(
project_name="mnist_sweep",
max_trials=20,
),
search_kwargs={"y": y_train},
)
print(result.best_hps) # {'lr': 0.0003, 'units': 128}
print(result.elapsed_formatted) # '0:04:12'
# Best model is compiled and ready for production training
result.model.fit(x_train, y_train, epochs=20, validation_data=(x_val, y_val))
Switching strategies
# Bayesian (default)
config = TunerConfig(project_name="sweep", strategy="bayesian", max_trials=30)
# Hyperband
config = TunerConfig(
project_name="sweep",
strategy="hyperband",
strategy_kwargs={"max_epochs": 50, "factor": 3},
)
# Random search
config = TunerConfig(project_name="sweep", strategy="random", max_trials=50)
Custom strategies
from kt_masterlog import STRATEGY_REGISTRY
STRATEGY_REGISTRY["my_tuner"] = MyCustomTunerClass
config = TunerConfig(project_name="sweep", strategy="my_tuner")
Config serialization
config = TunerConfig(project_name="experiment_42", max_trials=30)
# Save
config.to_json("config.json")
# Load
config = TunerConfig.from_json("config.json")
The master CSV
Each row in the master CSV contains:
| trial_id | epoch | hp_1 | hp_2 | ... | loss | val_loss | accuracy | val_accuracy |
|---|---|---|---|---|---|---|---|---|
| 0001 | 1 | 0.001 | 128 | ... | 0.82 | 0.91 | 0.72 | 0.68 |
| 0001 | 2 | 0.001 | 128 | ... | 0.65 | 0.74 | 0.78 | 0.75 |
| 0002 | 1 | 0.0003 | 64 | ... | 0.79 | 0.85 | 0.74 | 0.71 |
Add experiment-level metadata via extra_fields:
config = TunerConfig(
project_name="sweep",
extra_fields={"dataset": "utkface", "git_sha": "a1b2c3d"},
)
API reference
optimize(builder_fn, train_data, val_data, config, ...)
Run a hyperparameter search. Returns a TuningResult.
| Parameter | Type | Description |
|---|---|---|
builder_fn |
callable(hp) → Model |
KerasTuner model builder |
train_data |
Dataset / tuple | Training data |
val_data |
Dataset / tuple | Validation data |
config |
TunerConfig |
Tuning configuration |
steps_per_epoch |
int, optional |
Steps per epoch (for generators/datasets) |
validation_steps |
int, optional |
Validation steps (for generators/datasets) |
search_kwargs |
dict, optional |
Extra kwargs for tuner.search() |
TunerConfig
All fields have defaults except project_name. See config.py for the full list.
TuningResult
| Attribute | Type | Description |
|---|---|---|
.model |
tf.keras.Model |
Best model (compiled, untrained) |
.best_hps |
dict |
Best hyperparameter values |
.elapsed_seconds |
float |
Search wall-clock time |
.elapsed_formatted |
str |
Human-readable time |
.master_csv_path |
str |
Path to the master CSV |
.tuner |
kt.Tuner |
Underlying KerasTuner instance |
.summary() |
str |
Printable summary |
.save_summary(path) |
— | Write summary + config to JSON |
MasterEpochLogger
Standalone Keras callback. Use directly if you don't need the full orchestrator:
from kt_masterlog import MasterEpochLogger
logger = MasterEpochLogger(
csv_path="training_log.csv",
trial_id="run_1",
hps={"lr": 0.001},
extra_fields={"tag": "baseline"},
)
model.fit(..., callbacks=[logger])
make_logging_tuner(base_class)
Wrap any KerasTuner class with master-log injection:
from kt_masterlog import make_logging_tuner
import keras_tuner as kt
LoggingHyperband = make_logging_tuner(kt.Hyperband)
tuner = LoggingHyperband(..., master_csv_path="log.csv")
Requirements
- Python 3.12 (tested; 3.13+ may work but is not yet verified)
- TensorFlow ≥ 2.12
- KerasTuner ≥ 1.4
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kt_masterlog-0.2.0.tar.gz.
File metadata
- Download URL: kt_masterlog-0.2.0.tar.gz
- Upload date:
- Size: 101.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40a86777292694709f36973fc3788515b2771b81d7ac509bb55256e38643692a
|
|
| MD5 |
d3cc9bf502bbc4bff8e99addf709fe19
|
|
| BLAKE2b-256 |
ca9a4da3126a98a292d0760770a132a9e20544f72fe3822e1bcaaa87ccba6bfc
|
File details
Details for the file kt_masterlog-0.2.0-py3-none-any.whl.
File metadata
- Download URL: kt_masterlog-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.14 {"installer":{"name":"uv","version":"0.11.14","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6a63f599c22bea25315137a0836378b68937f43d1a2af9cd7736eef599e453b5
|
|
| MD5 |
223faca5878e8d65dc5898ff917564ce
|
|
| BLAKE2b-256 |
b4154a6daf68928ede3d5f7e33b4fe8ab2d67d865b9a29b2894d6bd9944244ba
|