tensorflow
matrix manipulation
machine learning
deep learning
programming

Manipulating matrix elements in tensorflow

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Matrix manipulation is central to TensorFlow workflows because model inputs, weights, activations, and gradients are all tensors. Even simple tasks like selecting a row, replacing invalid values, or applying conditional logic can become error-prone when shapes are dynamic or operations broadcast in unexpected ways. A strong mental model of TensorFlow indexing and update APIs saves time and prevents subtle bugs that only appear at runtime.

In eager mode, many operations feel NumPy-like, but training code often runs inside @tf.function, where tensor shapes and side effects behave differently. This article focuses on practical matrix element operations that work in both eager and graph execution, with examples you can adapt in preprocessing, custom layers, and loss functions.

Core Sections

Read and slice matrix elements safely

Use explicit indexing and slicing so shape intent is obvious.

python
1import tensorflow as tf
2
3m = tf.constant([
4    [10, 20, 30],
5    [40, 50, 60],
6    [70, 80, 90]
7], dtype=tf.int32)
8
9first_row = m[0]           # [10, 20, 30]
10second_col = m[:, 1]       # [20, 50, 80]
11center = m[1, 1]           # 50
12sub = m[0:2, 1:3]          # [[20, 30], [50, 60]]

For dynamic pipelines, inspect shapes with tf.shape(m) rather than relying only on static shape metadata.

Update selected elements with scatter operations

TensorFlow tensors are immutable, so updates return a new tensor. For sparse replacements, use tf.tensor_scatter_nd_update.

python
1x = tf.constant([[1., 2.], [3., 4.], [5., 6.]])
2indices = tf.constant([[0, 1], [2, 0]])   # update x[0,1] and x[2,0]
3updates = tf.constant([99., -5.])
4
5updated = tf.tensor_scatter_nd_update(x, indices, updates)
6# [[1., 99.], [3., 4.], [-5., 6.]]

This is useful for post-processing logits, building masks, or applying correction rules from metadata.

Apply element-wise conditional logic

Use tf.where for branching per element without Python loops.

python
scores = tf.constant([[0.2, 0.9], [1.4, -0.3], [0.7, 0.1]])
clipped = tf.where(scores < 0.0, 0.0, scores)
thresholded = tf.where(clipped > 1.0, 1.0, clipped)

tf.where keeps operations vectorized and differentiable, which matters in model training.

Boolean masks and gather operations

When you need only rows or elements meeting a condition, combine mask creation with gather.

python
1values = tf.constant([[5, 1], [2, 9], [8, 3], [1, 1]], dtype=tf.int32)
2row_sum = tf.reduce_sum(values, axis=1)
3keep_mask = row_sum >= 10
4
5selected_rows = tf.boolean_mask(values, keep_mask)
6# [[2, 9], [8, 3]]

For column- or index-driven extraction, tf.gather and tf.gather_nd are often clearer than advanced slicing.

Reshape, transpose, and broadcast intentionally

Shape bugs come from accidental broadcasting. Validate dimensions before arithmetic.

python
1a = tf.reshape(tf.range(12), (3, 4))
2b = tf.constant([1, 10, 100, 1000])
3
4scaled = a * b  # b broadcasts across rows
5transposed = tf.transpose(scaled)

Broadcasting is powerful, but it can silently produce valid yet incorrect outputs. Add assertions for critical paths.

python
tf.debugging.assert_equal(tf.shape(a)[1], tf.shape(b)[0])

Matrix updates in model code

Inside custom training logic, use TensorFlow ops exclusively. Mixing Python-side mutation with tensors under @tf.function creates hard-to-debug behavior.

python
1@tf.function
2def normalize_rows(x):
3    row_max = tf.reduce_max(x, axis=1, keepdims=True)
4    row_min = tf.reduce_min(x, axis=1, keepdims=True)
5    return (x - row_min) / tf.maximum(row_max - row_min, 1e-6)

This keeps operations traceable, differentiable, and optimized by TensorFlow runtime.

Common Pitfalls

  • Attempting in-place tensor mutation like NumPy arrays, which fails because TensorFlow tensors are immutable.
  • Using Python loops over tensor elements in performance-critical paths instead of vectorized TensorFlow ops.
  • Forgetting shape checks before broadcasting, causing logically wrong math with no runtime exception.
  • Calling .numpy() inside training functions, which breaks graph execution and device portability.
  • Using scatter update indices with wrong rank/order, producing misapplied updates that are hard to detect.

Summary

Effective matrix manipulation in TensorFlow depends on choosing the right primitive for the task: slicing for reads, scatter ops for sparse updates, tf.where for conditional element logic, and mask/gather operations for filtered selection. Keep everything tensor-native inside model code, especially under @tf.function, and validate shapes around broadcasting. With these habits, matrix operations remain predictable, fast, and compatible with both eager debugging and graph-optimized training.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.