tensorflow
numpy
fft
computational-differences
fft-comparison

The result of fft in tensorflow is different from numpy

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

Seeing different FFT values between TensorFlow and NumPy is common and usually explained by dtype, axis, length, or normalization differences rather than a broken implementation. Both libraries compute mathematically equivalent transforms when inputs and options truly match. This guide provides a reproducible comparison checklist and practical fixes.

Core Topic Sections

Match dtypes first

NumPy often defaults to float64 pathways, while TensorFlow workflows frequently use float32. That alone can cause visible numeric differences, especially for long signals.

Use explicit complex dtypes in both libraries:

python
1import numpy as np
2import tensorflow as tf
3
4x_np = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float64)
5x_tf = tf.constant([1.0, 2.0, 3.0, 4.0], dtype=tf.float64)
6
7fft_np = np.fft.fft(x_np.astype(np.complex128))
8fft_tf = tf.signal.fft(tf.cast(x_tf, tf.complex128)).numpy()
9
10print(np.allclose(fft_np, fft_tf, atol=1e-12))

Without dtype alignment, tiny and sometimes not-so-tiny differences are expected.

Ensure same axis and shape

Multi-dimensional arrays can produce mismatches if transforms run along different axes.

NumPy and TensorFlow defaults may differ by function choice and input rank context. Always specify axis or use equivalent 1D input slices explicitly.

python
1arr_np = np.random.randn(8, 16)
2arr_tf = tf.constant(arr_np, dtype=tf.float64)
3
4fft_np = np.fft.fft(arr_np, axis=1)
5fft_tf = tf.signal.fft(tf.cast(arr_tf, tf.complex128)).numpy()  # default last axis
6
7print(np.allclose(fft_np, fft_tf, atol=1e-10))

When comparing, verify transformed dimension is truly the same.

Align transform length and padding rules

If one side pads or truncates and the other side does not, outputs differ structurally and numerically.

Use explicit FFT length controls when required. For example, NumPy accepts n, and TensorFlow has length-aware APIs in related operations such as real FFT variants.

python
1x = np.array([1, 2, 3], dtype=np.float64)
2
3fft_np_n8 = np.fft.fft(x, n=8)
4x_tf = tf.constant(x, dtype=tf.float64)
5fft_tf_n8 = tf.signal.fft(tf.cast(tf.pad(x_tf, [[0, 5]]), tf.complex128)).numpy()
6
7print(np.allclose(fft_np_n8, fft_tf_n8, atol=1e-10))

Length mismatch is one of the most frequent comparison errors.

Check normalization convention

Different FFT ecosystems may use different normalization defaults such as forward, backward, or orthonormal scaling conventions.

When comparing libraries, normalize outputs consistently before concluding they differ unexpectedly.

Simple normalization check:

  1. Compare raw outputs.
  2. Compare after dividing by signal length when appropriate.
  3. Compare inverse transform round-trip error.

Normalization mismatch can look like a major error while being only a scale factor difference.

Real FFT versus complex FFT confusion

Do not compare rfft output from one library against full complex fft output from another without conversion. Real FFT emits only non-redundant frequency bins.

Use equivalent function families:

  1. np.fft.rfft with tf.signal.rfft
  2. np.fft.fft with tf.signal.fft

Function mismatch leads to shape and spectrum interpretation differences.

Device and kernel differences

TensorFlow may run FFT on GPU kernels while NumPy often runs CPU routines. Both should be close numerically, but floating-point reduction order can differ and produce tiny deltas.

For strict debugging, force consistent device or compare with tolerance rather than exact equality.

python
print(np.max(np.abs(fft_np - fft_tf)))
print(np.allclose(fft_np, fft_tf, rtol=1e-9, atol=1e-10))

Use domain-appropriate tolerances, not byte-level equality.

Build a reliable comparison helper

A reusable helper reduces repeated mistakes.

python
1import numpy as np
2import tensorflow as tf
3
4
5def compare_fft(x: np.ndarray, atol: float = 1e-10) -> bool:
6    x_np = np.asarray(x, dtype=np.float64)
7    x_tf = tf.constant(x_np, dtype=tf.float64)
8
9    y_np = np.fft.fft(x_np.astype(np.complex128))
10    y_tf = tf.signal.fft(tf.cast(x_tf, tf.complex128)).numpy()
11
12    return np.allclose(y_np, y_tf, atol=atol)
13
14print(compare_fft(np.random.randn(32)))

This enforces consistent dtype and function pairing by default.

Common Pitfalls

  • Comparing float32 TensorFlow output with float64 NumPy output directly.
  • Using different transform axes in multidimensional input arrays.
  • Forgetting to align FFT length, padding, or truncation behavior.
  • Comparing real FFT output against full complex FFT output.
  • Expecting exact bitwise equality instead of tolerance-based numeric equivalence.

Summary

  • Most TensorFlow versus NumPy FFT differences come from configuration mismatches.
  • Align dtype, axis, transform length, and function family before comparison.
  • Check normalization conventions to avoid scale-factor confusion.
  • Use tolerance-based comparisons for floating-point workflows.
  • Build reusable comparison helpers to keep FFT validation consistent.

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.