TensorFlow — Common Interview Questions and Answers
1. What is TensorFlow?
TensorFlow is Google’s open-source deep learning framework (2015). TF 2.x is eager-by-default with Keras as the official high-level API. Strong in production, mobile/edge (TFLite), browser (TF.js), and TPU training. Mindshare for new research has shifted to PyTorch, but TF remains widely deployed and well-supported.
2. What changed between TF 1.x and TF 2.x?
| TF 1.x | TF 2.x | |
|---|---|---|
| Execution | static graphs (tf.Session, tf.placeholder) |
eager by default |
| Performance | always graph-compiled | opt-in via @tf.function |
| API | many overlapping APIs (tf.layers, tf.estimator, tf.contrib) |
Keras as the canonical high-level API |
| Debugging | painful (graph errors, no Python stack) | regular Python debugging |
TF 1.x is legacy. New code should be TF 2.x with tf.keras. If you see tf.Session, tf.placeholder, feed_dict — that’s 1.x.
3. What’s the difference between tf.Tensor and tf.Variable?
tf.Tensor— immutable n-dimensional array. Outputs of computations.tf.Variable— mutable tensor. Used for model parameters (weights, biases). Can be modified with.assign()/.assign_add(). Trainable by default.
w = tf.Variable(tf.zeros([10, 5]))
w.assign_add(tf.ones([10, 5])) # in-place update allowed
4. What is Keras and how does it relate to TF?
Keras is the official high-level API for TF (since TF 2.0). Provides:
keras.Model,keras.layers.*— composable building blocks.model.compile,model.fit,model.evaluate,model.predict— training loop hidden.- Sequential, Functional, and Subclassing APIs for defining models.
Keras 3 (2023+) is multi-backend — same Keras code runs on TF, JAX, or PyTorch by setting KERAS_BACKEND env var.
5. What are the three ways to build a Keras model?
-
Sequential — linear stack, simplest:
model = keras.Sequential([ layers.Dense(128, activation="relu"), layers.Dense(10), ]) -
Functional — DAG with multi-input/multi-output support:
inputs = keras.Input(shape=(784,)) x = layers.Dense(128, activation="relu")(inputs) outputs = layers.Dense(10)(x) model = keras.Model(inputs, outputs) -
Subclassing — full PyTorch-like flexibility:
class Net(keras.Model): def __init__(self): super().__init__() self.fc1 = layers.Dense(128, activation="relu") self.fc2 = layers.Dense(10) def call(self, x): return self.fc2(self.fc1(x))
Most production code uses Sequential or Functional. Subclassing is for custom logic.
6. What’s tf.GradientTape?
TF’s autograd mechanism. Context manager that records operations on watched tensors so you can compute gradients later:
x = tf.Variable(2.0)
with tf.GradientTape() as tape:
y = x ** 3 + 2 * x
dy_dx = tape.gradient(y, x) # 14
Variables are watched automatically. Tensors need tape.watch(tensor). By default, a tape is consumed after one .gradient() call — use persistent=True to call it multiple times.
7. What does @tf.function do?
Traces a Python function into a TF computation graph that can be optimized and run faster on GPU/TPU. First call traces; subsequent calls run the compiled graph.
@tf.function
def train_step(xb, yb):
with tf.GradientTape() as tape:
loss = loss_fn(yb, model(xb, training=True))
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
return loss
Gotcha: Python side effects (print, mutations) only run during tracing, not on every call. Use tf.print for runtime printing.
Gotcha: Different input shapes/dtypes trigger retracing. If you call with many different shapes, performance suffers — set input_signature to lock the trace.
8. What’s the difference between eager and graph mode?
- Eager (TF 2 default) — ops run immediately, Python control flow works, easy to debug.
- Graph — ops are compiled into a TF graph; the graph runs as a unit. Faster, optimizable, but harder to debug.
In TF 2.x you write eager code, then opt into graph mode for tight loops via @tf.function. Best of both worlds: develop in eager, deploy / hot-path in graph.
9. What’s tf.data.Dataset?
TF’s input pipeline API. Composable, lazy, parallelized. Designed to overlap data prep with GPU/TPU compute.
ds = tf.data.Dataset.from_tensor_slices((x, y))
ds = (
ds.shuffle(10_000)
.map(augment, num_parallel_calls=tf.data.AUTOTUNE)
.batch(64)
.prefetch(tf.data.AUTOTUNE)
)
for xb, yb in ds:
train_step(xb, yb)
Key helpers: .shuffle, .batch, .map, .prefetch, .cache, .interleave. AUTOTUNE lets TF pick parallelism dynamically.
10. How do you save and load a Keras model?
Two main formats:
# Recommended: TF SavedModel (a directory)
model.save("path/to/model")
loaded = keras.models.load_model("path/to/model")
# Or .keras file (single file, also recommended)
model.save("model.keras")
# Just weights
model.save_weights("weights.h5")
model.load_weights("weights.h5")
The full save includes architecture, weights, optimizer state, training config. For deployment, SavedModel is the canonical format (TF Serving consumes it).
11. How do you train with a custom loop?
optimizer = keras.optimizers.AdamW(1e-3)
loss_fn = keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metric = keras.metrics.SparseCategoricalAccuracy()
@tf.function
def train_step(xb, yb):
with tf.GradientTape() as tape:
logits = model(xb, training=True)
loss = loss_fn(yb, logits)
grads = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(grads, model.trainable_variables))
metric.update_state(yb, logits)
return loss
for epoch in range(EPOCHS):
metric.reset_state()
for xb, yb in train_ds:
train_step(xb, yb)
print(f"Epoch {epoch}: acc={metric.result():.3f}")
Note training=True passed to model() — Keras layers need it explicitly in custom loops (Dropout, BatchNorm depend on it).
12. What’s tf.distribute.Strategy?
TF’s distributed training API. Different strategies for different setups:
MirroredStrategy— multi-GPU on one machine (data parallel).MultiWorkerMirroredStrategy— multi-GPU across machines.TPUStrategy— TPU pods.ParameterServerStrategy— async parameter server (rare now).
strategy = tf.distribute.MirroredStrategy()
with strategy.scope():
model = build_model()
model.compile(...)
model.fit(...) # automatically distributed
Wrap model creation in strategy.scope(); the rest of the training code is unchanged.
13. What’s TFLite?
TensorFlow Lite — TF’s runtime for mobile, embedded, and microcontroller deployment. Converts a SavedModel to a .tflite file that runs on Android/iOS/edge hardware with a small footprint.
converter = tf.lite.TFLiteConverter.from_saved_model("model")
converter.optimizations = [tf.lite.Optimize.DEFAULT] # quantization
tflite_model = converter.convert()
with open("model.tflite", "wb") as f:
f.write(tflite_model)
Supports int8 / float16 quantization, delegate-based hardware acceleration (NNAPI, GPU, Hexagon DSP). One of TF’s strongest production stories.
14. What’s TensorFlow Serving?
A high-performance model server for serving SavedModels via gRPC or REST. Battle-tested at Google scale. Supports model versioning, A/B testing, hot-reload.
docker run -p 8501:8501 \
-v /path/to/model:/models/my_model \
-e MODEL_NAME=my_model \
tensorflow/serving
curl -X POST http://localhost:8501/v1/models/my_model:predict \
-d '{"instances": [[1.0, 2.0, 3.0]]}'
For LLMs, vLLM / TensorRT-LLM are now preferred over TF Serving.
15. What’s TFX?
TensorFlow Extended — end-to-end production ML pipeline platform. Components:
- ExampleGen — ingest data.
- StatisticsGen / SchemaGen — analyze and validate data.
- Transform — preprocessing as part of the graph.
- Trainer — model training.
- Evaluator — evaluate against baseline.
- Pusher — deploy validated models.
Used internally at Google for production ML. Heavy and opinionated; smaller teams often prefer simpler stacks (Airflow / Prefect + custom orchestration).
16. How do you do transfer learning in TF?
base = keras.applications.MobileNetV2(
input_shape=(224, 224, 3),
include_top=False, # drop the original classification head
weights="imagenet",
)
base.trainable = False # freeze
model = keras.Sequential([
base,
layers.GlobalAveragePooling2D(),
layers.Dense(NUM_CLASSES),
])
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy")
model.fit(...)
# Then unfreeze for fine-tuning
base.trainable = True
model.compile(optimizer=keras.optimizers.Adam(1e-5), loss=...) # lower LR
model.fit(...)
Standard pattern: freeze base, train head; then unfreeze and fine-tune end-to-end with a tiny LR.
17. What are common TF gotchas?
@tf.functionPython side effects —print(), mutations only run during tracing. Usetf.print.- Retracing on every call — Python ints/lists trigger new traces; use tensors or
input_signature. - Creating
tf.Variableinside@tf.function— raises; create variables outside. training=True/Falsein custom loops — must pass explicitly for Dropout/BatchNorm.- TF 1.x code in tutorials — anything with
tf.Session/tf.placeholderis legacy. - GPU memory allocation — TF grabs all GPU memory by default. Limit with
tf.config.experimental.set_memory_growth. - Mixing TF and Keras APIs — stick to
tf.keras.*, not standalonekeraspackage (different versions exist).
18. How do you deploy a TF model to the browser?
Convert to TensorFlow.js format and load in the browser:
pip install tensorflowjs
tensorflowjs_converter --input_format=tf_saved_model model/ web_model/
import * as tf from '@tensorflow/tfjs';
const model = await tf.loadGraphModel('web_model/model.json');
const output = model.predict(input);
TF.js runs via WebGL (GPU) or WASM (CPU). Useful for client-side privacy-preserving inference, demos, edge cases.
19. What’s the difference between TF and JAX?
Both are Google projects; both compile to XLA. Differences:
- TF — object-oriented Keras, eager-by-default, mature ecosystem, production tooling.
- JAX — functional, pure functions transformed by
jit/grad/vmap/pmap. Closer to NumPy. Used heavily in DeepMind / research.
JAX is faster for research-grade code and TPU workloads but has a smaller ecosystem. TF is the more “batteries-included” choice for production.
Keras 3 supports JAX as a backend — you can write Keras code and run it on JAX for the speed/TPU benefits.
20. When would you pick TF over PyTorch?
- TPU training — Google’s accelerators; TF/JAX are canonical here.
- Mobile / edge deployment — TFLite is more mature than PyTorch Mobile / ExecutorTorch.
- Browser inference — TF.js is best-in-class.
- Existing TFX pipelines — don’t migrate working production infra.
- Team already has TF expertise — switching costs matter.
For most other cases (especially LLMs, research, HF transformers), PyTorch is the default. See 03_pytorch_vs_tensorflow.md for the full comparison.
Quick reference: the mental model
| Concept | Quick definition |
|---|---|
tf.Tensor |
immutable n-d array |
tf.Variable |
mutable, trainable tensor (model parameters) |
keras.Model |
high-level model with .fit / .compile / .save |
keras.layers.Layer |
base class for layers (use call()) |
tf.GradientTape |
autograd context — records ops for gradients |
@tf.function |
trace Python to TF graph for speed |
tf.data.Dataset |
input pipeline (lazy, composable, parallel) |
tf.distribute.Strategy |
distributed training wrapper |
| TFLite | mobile / edge deployment format |
| TF Serving | gRPC/REST model server |
| TFX | end-to-end production ML pipelines |
| Keras 3 | multi-backend (TF / JAX / PyTorch) |
Interview angle
- “Where does TensorFlow still lead?” - deployment maturity: TF Serving, TF Lite for mobile and embedded, and TF.js. If the target is a phone or an edge device, that tooling is more mature than the PyTorch equivalent.
- “Eager or graph mode?” - TF 2 is eager by default for debuggability, with
@tf.functionto trace a graph for performance. That decorator is where most TF-specific bugs live, because Python side effects inside a traced function run only during tracing. - “Keras versus raw TensorFlow?” - Keras is the high-level API and the right default; drop to raw TF for custom training loops or unusual gradient handling. Keras 3 also runs on multiple backends, which weakens the framework lock-in argument.
- “Would you start a new project in TensorFlow?” - usually not, unless the deployment target demands TF Lite or the team already runs a TF stack. Pretrained weights and research code overwhelmingly target PyTorch.