Custom training step in TensorFlow - ML Experiment: Train & Evaluate
import tensorflow as tf # Load MNIST dataset (x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data() # Normalize and expand dims x_train = x_train.astype('float32') / 255.0 x_test = x_test.astype('float32') / 255.0 x_train = x_train[..., tf.newaxis] x_test = x_test[..., tf.newaxis] train_ds = tf.data.Dataset.from_tensor_slices((x_train, y_train)).shuffle(10000).batch(64) test_ds = tf.data.Dataset.from_tensor_slices((x_test, y_test)).batch(64) # Define simple model model = tf.keras.Sequential([ tf.keras.layers.Conv2D(32, 3, activation='relu'), tf.keras.layers.Flatten(), tf.keras.layers.Dense(128, activation='relu'), tf.keras.layers.Dense(10) ]) loss_object = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True) optimizer = tf.keras.optimizers.Adam() train_loss = tf.keras.metrics.Mean(name='train_loss') train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='train_accuracy') val_loss = tf.keras.metrics.Mean(name='val_loss') val_accuracy = tf.keras.metrics.SparseCategoricalAccuracy(name='val_accuracy') @tf.function def train_step(images, labels): with tf.GradientTape() as tape: predictions = model(images, training=True) loss = loss_object(labels, predictions) gradients = tape.gradient(loss, model.trainable_variables) optimizer.apply_gradients(zip(gradients, model.trainable_variables)) train_loss(loss) train_accuracy(labels, predictions) @tf.function def val_step(images, labels): predictions = model(images, training=False) v_loss = loss_object(labels, predictions) val_loss(v_loss) val_accuracy(labels, predictions) EPOCHS = 3 for epoch in range(EPOCHS): train_loss.reset_states() train_accuracy.reset_states() val_loss.reset_states() val_accuracy.reset_states() for images, labels in train_ds: train_step(images, labels) for val_images, val_labels in test_ds: val_step(val_images, val_labels) print(f'Epoch {epoch + 1}, ' f'Loss: {train_loss.result():.4f}, ' f'Accuracy: {train_accuracy.result() * 100:.2f}%, ' f'Val Loss: {val_loss.result():.4f}, ' f'Val Accuracy: {val_accuracy.result() * 100:.2f}%')
Before: Training accuracy: 98%, Validation accuracy: 96%, Training loss: 0.05, Validation loss: 0.08
After: Training accuracy: ~98%, Validation accuracy: ~96.5%, Training loss: ~0.05, Validation loss: ~0.07
Practice
What is the main purpose of a custom training step in TensorFlow?
Solution
Step 1: Understand the role of a training step
A training step controls how the model updates its weights using data batches.Step 2: Identify what custom training step changes
Custom training steps let you write your own logic for learning, including gradient calculation and weight updates.Final Answer:
To define exactly how the model learns from each batch of data -> Option DQuick Check:
Custom training step = control learning process [OK]
- Thinking it builds model architecture
- Confusing with data loading
- Assuming it only visualizes outputs
Which of the following is the correct way to start recording operations for gradient calculation in a custom training step?
def train_step(inputs):
# What goes here?
...
Solution
Step 1: Recall TensorFlow's gradient recording method
TensorFlow usestf.GradientTape()to record operations for automatic differentiation.Step 2: Match correct syntax for gradient recording
The correct syntax to start recording iswith tf.GradientTape() as tape:.Final Answer:
with tf.GradientTape() as tape: -> Option BQuick Check:
Gradient recording uses tf.GradientTape [OK]
- Using tf.Session() which is for old TF versions
- Confusing tf.Variable() with gradient recording
- Using tf.data.Dataset() incorrectly here
What will be the output of the following custom training step code snippet?
import tensorflow as tf
model = tf.keras.Sequential([tf.keras.layers.Dense(1)])
optimizer = tf.keras.optimizers.SGD(learning_rate=0.1)
@tf.function
def train_step(x, y):
with tf.GradientTape() as tape:
predictions = model(x, training=True)
loss = tf.reduce_mean(tf.square(y - predictions))
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss
x = tf.constant([[1.0], [2.0]])
y = tf.constant([[3.0], [5.0]])
loss_value = train_step(x, y).numpy()
print(round(loss_value, 2))
Solution
Step 1: Calculate initial predictions and loss
Model starts with random weights near zero, so predictions ~0. Loss = mean squared error between y and predictions = mean of [9, 25] = 17.Step 2: After one gradient update with learning rate 0.1, loss reduces
One step reduces loss roughly to around 4.0 (not zero yet).Final Answer:
4.0 -> Option CQuick Check:
One step reduces loss from ~17 to ~4 [OK]
- Assuming loss becomes zero immediately
- Ignoring initial random weights
- Confusing loss with prediction values
Identify the error in this custom training step code and select the fix:
def train_step(x, y):
with tf.GradientTape() as tape:
predictions = model(x)
loss = tf.reduce_mean(tf.square(y - predictions))
gradients = tape.gradient(loss)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
return loss
Solution
Step 1: Check tape.gradient usage
tape.gradient requires two arguments: loss and variables to differentiate with respect to.Step 2: Identify missing argument
Code misses the second argument (model.trainable_variables), causing error.Final Answer:
Pass model.trainable_variables as second argument to tape.gradient -> Option AQuick Check:
tape.gradient(loss, variables) needs variables [OK]
- Forgetting second argument in tape.gradient
- Removing GradientTape context
- Changing loss function unnecessarily
You want to track both loss and accuracy in a custom training step for a classification model. Which code snippet correctly updates and returns these metrics?
loss_metric = tf.keras.metrics.Mean()
accuracy_metric = tf.keras.metrics.SparseCategoricalAccuracy()
@tf.function
def train_step(x, y):
with tf.GradientTape() as tape:
logits = model(x, training=True)
loss = loss_fn(y, logits)
gradients = tape.gradient(loss, model.trainable_variables)
optimizer.apply_gradients(zip(gradients, model.trainable_variables))
# What goes here?
...
Solution
Step 1: Understand metric update methods
TensorFlow metrics useupdate_state()to add new values for tracking.Step 2: Correctly update and return metric results
Useloss_metric.update_state(loss)andaccuracy_metric.update_state(y, logits), then return theirresult().Final Answer:
loss_metric.update_state(loss); accuracy_metric.update_state(y, logits); return loss_metric.result(), accuracy_metric.result() -> Option AQuick Check:
Use update_state() and result() for metrics [OK]
- Assigning metric variables instead of updating
- Using non-existent add() method
- Resetting metrics inside training step
Ready to prove it?
Pass the test and this pattern moves unknown
