TensorFlow: Take L2 norm over multiple dimensions

Viewed 5437

I have a TensorFlow placeholder with 4 dimensions representing a batch of images. Each image is 32 x 32 pixels, and each pixel has 3 color channels. The first dimensions represents the number of images.

X = tf.placeholder(tf.float32, [None, 32, 32, 3])

For each image, I would like to take the L2 norm of all the image's pixels. Thus, the output should be a tensor with one dimension (i.e. one value per image). The tf.norm() (documentation) accepts an axis parameter, but it only lets me specify up to two axes over which to take the norm, when I would like to take the norm over axes 1, 2, and 3. How do I do this?

n = tf.norm(X, ord=2, axis=0)          # n.get_shape() is (?, ?, 3), not (?)
n = tf.norm(X, ord=2, axis=[1,2,3])    # ValueError
3 Answers

I tried Salvador's answer but it looks like that returns one number for the whole minibatch instead of one number per image. So it looks like we may be stuck with doing the norm per dimension.

import tensorflow as tf
import numpy as np

batch = tf.constant(np.random.rand(3, 2, 3, 6))

x = tf.norm(batch, axis=3)
x = tf.norm(x, axis=2)
x = tf.norm(x, axis=1)

with tf.Session() as sess:
    result = sess.run(x)
print(result)

This might introduce a small amount of numerical instability but in theory it's the same as taking the norm of the whole image at once.

You might also think about only taking the norm over the x and y axes so that you get one norm per channel. There's a reason why that's supported by tensorflow and this isn't.

You can compute the L2-norm by yourself like this:

tf.sqrt(tf.reduce_sum(tf.pow(images,2), axis=(1,2,3)))
Related