Quick Reference · machine learning in Python · TensorFlow 2.21 (Mar 2026)

tensorflow + tensorflow_hub · keras_hub

One sentence explains most of TensorFlow: your code runs eagerly, line by line, until @tf.function traces it once into a graph — and from then on the graph runs, not your Python. Everything else — the speed, the retracing, the print statements that fire only once — follows from that. Keras 3 is the front door; tf.* is the floor beneath it.
setup & inspect tensors & shapes graph & autodiff Keras: build & train tf.data & preprocessing pretrained, save & deploy gotcha / removed most common
Cross-checked against: tensorflow.org (guide + API docs) · keras.io (Keras 3 + KerasHub) · blog.tensorflow.org (2.20 / 2.21) · github.com/tensorflow (releases, hub#903) · kaggle.com/models
The shape of a TensorFlow program
A · THE HIGH ROAD — KERAS DOES THE LOOP FOR YOU tf.data.Dataset batch · shuffle · prefetch keras.Model Sequential / Functional / sub .compile(...) optimizer · loss · metrics .fit(ds, epochs) the whole loop, one call .save("m.keras") .export() for serving or drop down a level ↓ B · THE LOW ROAD — YOU WRITE THE LOOP with tf.GradientTape() as tape: loss = loss_fn(y, model(x, training=True)) grads = tape.gradient(loss, model.trainable_variables) ← the tape records every op on a watched tensor ← then plays it backwards, once opt.apply_gradients(zip(grads, vars)) C · WHERE THE PRETRAINED MODELS LIVE NOW the stack Keras 3 — backend: tensorflow | jax | torch tensorflow — tensors, tf.data, tf.function XLA · kernels · CPU / GPU / TPU tensorflow_hub frozen at 0.16.1 · Jan 2024 hub.load() still works hub.KerasLayer ✗ Keras 3 breaks on TF 2.16+ moved keras_hub .from_preset() · the successor was KerasNLP Kaggle Models tfhub.dev redirects here since Nov 2023 the bridge keras.layers.TFSMLayer loads any SavedModel into Keras 3 as a layer inference only
# the whole library in fourteen lines
import tensorflow as tf, keras

ds = tf.data.Dataset.from_tensor_slices((X, y)) \
       .shuffle(1024).batch(32).prefetch(tf.data.AUTOTUNE)

model = keras.Sequential([
    keras.layers.Dense(128, activation="relu"),
    keras.layers.Dense(10),          # logits, no softmax
])
model.compile(optimizer="adam",
              loss=keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=["accuracy"])   # from_logits MUST match the last layer
model.fit(ds, epochs=5, validation_data=val_ds)
model.save("m.keras")               # .keras or .h5 — a bare path raises
Read this once and most of the reference below is just filling in the blanks.
PART I

tensorflow  ·  the core

Tensors, the graph, autodiff, tf.data and Keras 3. Since TF 2.16 pip install tensorflow brings Keras 3, and tf.keras is Keras 3 — the old Keras 2 lives on separately as tf_keras.
01Install & verifyonce per env
02The import mapwhat to import
03Create tensorsthe raw material
04Attributes & dtypeswhat a tensor knows
05Shape surgeryrearranging
06Broadcastingthe silent bug factory
07Index, slice, reducegetting values out
08Math & linear algebrathe operations
09Ragged, sparse & stringsthe other tensor types
10keras.opswrite once, run anywhere
11tf.Variablethe only mutable thing
12@tf.function & graphsthe central idea
13Control flow in a graphif and while, traced
14GradientTapeautodiff by recording
15Devices & precisionwhere it runs
16tf.data · buildthe input pipeline
17Reading real filesbefore it is a tensor
18Time series & windowingsequences from a stream
19tf.data · performancekeep the GPU fed
20Preprocessing layersput it in the model
21Keras · three ways to buildpick one
22Keras · layersthe building blocks
23Write your own layersubclassing keras.layers.Layer
24Regularization & initthe knobs that stop overfitting
25Keras · losses, metrics, optimizersthe training contract
26Keras · compile & fitthe loop, for free
27Keras · callbackshooks into fit()
28Transfer learningthe recipe, in order
29Custom training loopwhen fit() is not enough
30Save, load & exportthree different things
31Deploy & distributeoff your laptop
32Debug & reproducebefore blaming the model
33TensorBoard & profilingwatching it run
PART II

tensorflow_hub  ·  the frozen module

Read this before you copy any tutorial. tensorflow_hub still installs and hub.load() still works — but the library has not shipped a release since 0.16.1 in January 2024, tfhub.dev now redirects to Kaggle Models, and its headline API hub.KerasLayer does not work under Keras 3, which is the default from TF 2.16 onward. This part covers what still works, what breaks, and how to get moving again.
H1Where it standsthe honest status
H2Install & the two APIsthe whole surface
H3hub.load()the path that still works
H4What people still pullthe surviving classics
H5The Keras 3 wallwhy tutorials fail
H6Making it work todaypick your escape
H7Caching & handlesdownloads and offline
PART III

keras_hub  ·  where it went

The successor. KerasHub is the renamed and widened KerasNLP — text, vision and multimodal presets behind one from_preset() constructor, working on all three Keras 3 backends. Plus the two other places pretrained weights live: keras.applications for classic vision, and Kaggle Models for the raw SavedModels.
K1KerasHub · the ideaone constructor
K2Task, Backbone, Preprocessorthe three classes
K3Textclassify and generate
K4LoRA, QLoRA & quantizationfine-tuning big models
K5Imagesclassify and fine-tune
K6keras.applicationsthe built-in option
K7Migration mapold call → new call

Four pictures worth the whole reference

The central mechanism, the pipeline that keeps the GPU busy, the three ways to build a model, and where the pretrained weights went.

1 · eager vs graph

The same function, twice. Eagerly, your Python runs every call. Traced, it runs once — and the graph runs thereafter. This is why print fires once and tf.print fires always.

EAGER — default call 1 → run Python call 2 → run Python call 3 → run Python debuggable, slower print() every time @tf.function call 1 → TRACE, build graph call 2 → run graph call 3 → run graph fast, no Python in the loop print() fired only on call 1 new shape or dtype → retrace

2 · why prefetch matters

Without overlap the accelerator idles while the CPU prepares the next batch. prefetch(AUTOTUNE) lets step n+1's preparation run during step n's compute.

WITHOUT prefetch — they take turns CPU prep 1 prep 2 prep 3 GPU step 1 step 2 step 3 idle idle idle half thetime wasted WITH prefetch(AUTOTUNE) — they overlap CPU prep 1 prep 2 prep 3 prep 4 GPU step 1 step 2 step 3 step 4 GPU never waits ds.map(f, AUTOTUNE).cache().shuffle(n).batch(b).prefetch(AUTOTUNE) cache after expensive deterministic work · shuffle before batch · prefetch last

3 · three ways to build a model

Same network, three levels of control. Sequential is a list; Functional is a graph you wire by calling layers on tensors; Subclassing is just Python.

Sequential Dense 128 Dense 64 Dense 10 one in, one out no branching Functional Input Dense 64 Add skip any DAG, shared layers shapes checked as you build Subclass def call(self,x): if training: ...whatever return x full control no summary() until built start Sequential · reach for Functional the moment you need a second branch all three are keras.Model — compile() and fit() work identically on each

4 · where the pretrained models went

One library split into three destinations. The dashed box is the part that still installs but no longer moves — and whose Keras layer no longer works.

tensorflow_hub 0.16.1 · Jan 2024 hub.load() ✓ hub.KerasLayer ✗ keras_hub .from_preset() · text, vision, multimodal keras.applications built in · include_top=False for features keras.layers.TFSMLayer wrap a raw SavedModel · inference only tfhub.dev → kaggle.com since Nov 2023

Worth memorizing

traced once, run manyinside @tf.function, Python side effects fire only while tracing
tf.print vs printtf.print becomes a graph op and fires every call
no dtype promotionint32 + float32 raises — TF never casts for you, unlike NumPy
from_logits must matcha softmax layer and from_logits=True trains on nonsense, silently
loss_fn(y_true, y_pred)true label first — the opposite order to most libraries
channels last(N, H, W, C), not (N, C, H, W)
shuffle before batchthe other order only shuffles the order of whole batches
prefetch last, always.prefetch(AUTOTUNE) is what stops the GPU idling
v.assign(x), not v = xrebinding the name throws the tf.Variable away
no zero_grada fresh GradientTape each step means gradients never accumulate
grads of Nonethe tape lost the chain — a .numpy(), an int dtype, or an op outside the tape
broadcasting aligns right(N,1) against (N,) becomes (N,N) and the loss quietly averages N² pairs
.keras or .h5, never baremodel.save("path") raises in Keras 3; use .export() for SavedModel
load_model can't read SavedModeluse keras.layers.TFSMLayer instead
metrics are statefulreset_state() each epoch or you average across all of training
hub.KerasLayer is Keras 2broken on TF 2.16+; hub.load() is fine, and keras_hub is the successor
keras.ops, not tf.*inside a custom layer, that one swap is what makes it run on JAX and PyTorch too
weights go in build()and without get_config() the layer cannot be reloaded
freeze and training=Falsetrainable=False alone still lets BatchNorm update its running statistics
recompile after unfreezingtrainable is read at compile time — otherwise nothing changes
quantize, then enable_lorathat order is QLoRA; the adapters must stay in full precision
window before you shuffleshuffling a time series first destroys the ordering the windows depend on
clipnorm lives on the optimizernot in the training loop, unlike PyTorch
set_memory_growth earlyor TF pre-allocates the whole GPU the moment it initialises
estimators and tf.litetf.estimator gone in 2.16; tf.lite deprecated in favour of LiteRT