backend before importKERAS_BACKEND must be set before import keras; it cannot change after
keras.ops, not tf.* or torch.*the one swap that keeps a custom layer portable across backends
built-ins are portable alreadya model of only built-in layers runs on all four backends unchanged
weights go in build()and without get_config() the layer cannot be reloaded
keras.random, not Python randomstateless RNG is what makes custom layers work under JAX tracing
.keras or .h5, never baresave("path") raises; export() is what makes a SavedModel
load_model can't read SavedModeluse keras.layers.TFSMLayer for that
from_logits must matcha softmax layer plus from_logits=True trains on nonsense, silently
loss_fn(y_true, y_pred)true label first
clipnorm is on the optimizernot in the training loop
metrics are statefulreset_state() each epoch or you average over all of training
adapt() on features onlypass ds.map(lambda x, y: x), not the whole dataset
augmentation layers self-disableactive in training, bypassed at inference — no flag needed
keras-preprocessing is archivedfinal release 1.1.2 (2020); in Keras 3 it survives only under _legacy
Tokenizer → TextVectorizationand it belongs inside the model, so the vocabulary can't drift
Sequence → PyDatasetsame two methods, new name, better multiprocessing
on torch, a layer IS an nn.Moduleso torch optimizers, DDP and state_dict() just work
torch backend needs zero_grad()gradients accumulate; forgetting it is the classic bug there
training=True, not model.train()the Keras kwarg is what switches Dropout and BatchNorm
a raw loop is never portableoverride compute_loss or train_step if you want to keep backends open
freeze, train head, then unfreezeand recompile after unfreezing or the change is silently ignored
base(inputs, training=False)freezing alone does not stop BatchNorm updating its running stats
match the backbone's preprocess_inputeach family expects its own input range; the wrong one quietly costs accuracy
decay_steps counts stepsnot epochs — steps_per_epoch * epochs
sample learning rates log-uniformlylinear sampling wastes most tuner trials at the top of the range
rotation_range=20 ≠ RandomRotation(20)degrees became a fraction of a full turn; 20 → about 0.056
install TensorFlow anywaytf.data and several preprocessing layers need it on every backend
on JAX, no side effects in call()a print or an append runs once at trace time and never again
overfit one batch firstif it can't, the bug is the model or the loss — not the data
quantize, then enable_lorathat order is QLoRA; adapters stay full precision
don't load untrusted .h5Keras 3.12.3 was a security release hardening exactly that path