In TensorFlow 2.21, what does tf.keras resolve to, and how do you get Keras 2 back?
answer
- one library moved out of the other
- tf.keras is an alias now
- check the printed Keras version
- legacy Keras is its own package
- an env var read at import time
basics
~20 stf.keras in TensorFlow 2.21 is Keras 3, not the Keras 2 that older TensorFlow bundled. To get Keras 2 semantics back you install the separate tf_keras package and set the environment variable TF_USE_LEGACY_KERAS=1 before importing TensorFlow.
solid answer
~40 sSince TensorFlow 2.16, `tf.keras` is no longer a Keras 2 implementation living inside the TensorFlow package — it is the standalone, multi-backend **Keras 3** library exposed through a TensorFlow-facing namespace. So in TF 2.21, `import keras` and `tf.keras` give you the same Keras 3 API surface, and `tf.keras.__version__` prints a 3.x version. Keras 2 has not vanished: it was moved into its own PyPI package, `tf_keras`. If you set `TF_USE_LEGACY_KERAS=1` **before** `import tensorflow`, TensorFlow routes `tf.keras` back to that legacy package. That switch is process-wide and all-or-nothing — you cannot mix a `tf_keras` layer into a Keras 3 model, because they are two unrelated class hierarchies. The practical consequence for an interview: any "tf.keras" answer you give has to say which side of that seam it assumes.
code
python · 4 linesimport tensorflow as tf
print(tf.__version__) # 2.21.x
print(tf.keras.__version__) # 3.x -> tf.keras is Keras 3go deeper
Know that tf.keras and keras reach the same library on a modern TensorFlow install, and that printing tf.keras.__version__ tells you which Keras you have. Do not repeat tutorial claims about Keras being "part of" TensorFlow.
Be ready to explain the inversion: Keras 3 is a standalone multi-backend library that TensorFlow depends on, tf.keras aliases it, and Keras 2 is the separate tf_keras package selected by TF_USE_LEGACY_KERAS=1 read at TensorFlow import time.
Expect to diagnose environments, not just describe them. Show that you log the TensorFlow and Keras versions at job startup, that the legacy switch is process-wide, and that mismatched environment variables across hosts explain "same code, different behaviour" incidents.
Own the position that the legacy flag is a time-boxed pin on a maintenance-only package, not an architecture. Be ready to argue when a fleet standardises on Keras 3, how you stop new code from depending on Keras 2 internals, and who pays for the migration.
## The one-sentence version In TensorFlow 2.21, `tf.keras` is **Keras 3** wearing a TensorFlow-shaped namespace, and Keras 2 survives only as a separate, opt-in package called `tf_keras`. ## What actually changed For most of the TF 2.x era, Keras shipped *inside* TensorFlow. `tf.keras` was a Keras 2 implementation whose tensors were `tf.Tensor`, whose graph mode was TensorFlow's, and whose only backend was TensorFlow. A separate `keras` PyPI package also existed, and in practice it was a thin re-export of the same code. Starting with TensorFlow 2.16, that inversion happened: Keras became an independent, **multi-backend** library again (Keras 3), able to run on TensorFlow, JAX or PyTorch, and TensorFlow started *depending on it* rather than containing it. `tf.keras` is now an alias namespace onto that installed Keras 3 package. TensorFlow 2.21 is on the far side of that change. So in a fresh TF 2.21 environment: - `import keras` and `tf.keras` reach the same library. - `tf.keras.__version__` reports 3.x, not 2.x. - Models are `keras.Model`, layers are `keras.layers.Layer`, and their internals are backend-agnostic rather than TensorFlow-specific. ## The legacy escape hatch Keras 2 was not deleted; it was extracted into the PyPI package `tf_keras`. Two steps switch to it: 1. `pip install tf_keras` 2. Set the environment variable `TF_USE_LEGACY_KERAS=1` With that variable set, TensorFlow points `tf.keras` at `tf_keras` instead of Keras 3. Two details matter and both are asked: - **Ordering.** The variable is read while TensorFlow is being imported. Setting it after `import tensorflow as tf` (or from a notebook cell after the kernel already imported TF) does nothing. In code you set it with `os.environ[...]` at the very top of the entry point, before any TF import; in production you usually set it in the container environment instead. - **It is a process-wide switch, not a per-model one.** Everything that goes through `tf.keras` in that process becomes Keras 2. You cannot build a Keras 3 `Model` out of `tf_keras` layers or vice versa — they are separate class hierarchies with separate base classes, and mixing them fails with type errors or silently unregistered weights. ## Why anyone still sets it The usual reasons are downstream: a pinned training script that relies on Keras 2 saving behaviour, a custom layer that reaches into Keras 2 internals, an in-house library that subclasses Keras 2 classes, or another ecosystem package whose released version still expects the Keras 2 object model. `TF_USE_LEGACY_KERAS=1` buys time on all of those without pinning TensorFlow itself to an old release — which is the real appeal, since you may want the newer TF runtime, ops and CUDA support. It is a **pin, not a plan**: `tf_keras` is a maintenance-only package, and new Keras features (backend portability, `keras.ops`, the newer saving format) only exist on the Keras 3 side. ## How to detect which side you are on At runtime, print the version rather than guessing: ``` import tensorflow as tf print(tf.__version__, tf.keras.__version__) ``` A `3.x` Keras version means Keras 3; a `2.x` one means the legacy package is active. This is the first thing to check when an error message mentions a Keras class you thought you knew, or when the same script behaves differently on two machines — a stray `TF_USE_LEGACY_KERAS` in one environment produces exactly that symptom. ## What changes for you when tf.keras is Keras 3 The headline items a TensorFlow user notices: - Symbolic tensors from `keras.Input` are `KerasTensor` objects, not `tf.Tensor`, so raw TensorFlow ops cannot be applied to them while wiring a functional model. - Saving defaults changed: `model.save()` writes the `.keras` archive (legacy `.h5` is still accepted), and producing a TensorFlow SavedModel directory is now `model.export()`. - `save_weights` expects a `.weights.h5` filename. - Layer code that only calls `tf.*` ops still works fine **under the TensorFlow backend**, but is no longer portable to other backends. ## How to answer in an interview Say the seam out loud: "In TF 2.16 and later — so 2.21 — `tf.keras` *is* Keras 3; Keras 2 lives in the `tf_keras` package behind `TF_USE_LEGACY_KERAS=1`, which must be set before importing TensorFlow, and it is a whole-process switch." That single sentence tells the interviewer you have upgraded a real codebase rather than read a tutorial written for TF 2.10.
- Where exactly must TF_USE_LEGACY_KERAS be set for it to take effect?Before TensorFlow is imported in that process. TensorFlow reads it during import to decide what `tf.keras` points at, so setting it in a shell/container environment, or via `os.environ` at the very top of the entry point, works; setting it after `import tensorflow` — or in a later notebook cell — silently does nothing.
- Can you use a tf_keras layer inside a Keras 3 model?No. `tf_keras` and `keras` are two independent class hierarchies with their own `Layer`/`Model` base classes, weight tracking and serialization. Composing them raises type errors or produces a model whose weights are never tracked or trained. Pick one per process; migrate a component fully rather than half.
- How would you confirm at runtime which Keras a job actually loaded?Print `tf.keras.__version__` (and `tf.__version__`) at startup and log it. A 3.x value means Keras 3, a 2.x value means the legacy `tf_keras` package is active. Logging it turns "works on my machine" into a one-line diagnosis when a stray environment variable differs between hosts.
saying these in an interview costs you the question
- Assumes TensorFlow 2.21 still bundles Keras 2 under tf.keras
- Thinks tf.keras and keras are different implementations in TF 2.21
- Says pip install keras==2.x restores the old tf.keras
- Sets TF_USE_LEGACY_KERAS after importing tensorflow
- Mixes tf_keras layers into a Keras 3 model