2

I have a matrix g of shape [4, 4, 2, 2] where I need to find the rank of g[0, 0], g[1, 1], g[2, 2] and g[3, 3] which are all 2x2 matrices. I used the tf.rank operator but it treats g as a single array and computes the rank and returns a single value for the whole matrix. What I need is a 2x2 matrix of ranks of the corresponding g[i, j]'s. Following is a MWE:

import tensorflow as tf
import numpy as np

a = np.array([
 [[[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]], [[-2., -2.], [-2., -2.]], [[-3., -3.], [-3., -3.]]], 
 [[[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]], [[-2., -2.], [-2., -2.]]],
 [[[ 2., 2.], [ 2., 2.]], [[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]]],
 [[[ 3., 3.], [ 3., 3.]], [[ 2., 2.], [ 2., 2.]], [[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]]]
])
rank = tf.rank(a)  # Returns a number

Apart from using a for loop is there any way to get this rank matrix? Thanks.

learner
  • 3,168
  • 3
  • 18
  • 35
  • In TensorFlow terms, the [rank](https://www.tensorflow.org/api_docs/python/tf/rank) is simply the number of dimensions of a tensor. Are you referring to the [rank in the linear algebra sense](https://en.wikipedia.org/wiki/Rank_(linear_algebra))? – jdehesa Feb 10 '20 at 13:03
  • @jdehesa I was not aware of that. Yes, I do mean the rank in linear algebra sense. Thanks. – learner Feb 10 '20 at 13:08

1 Answers1

1

I don't think there is any function to compute matrix rank in TensorFlow. One possibility is to use tf.linalg.svd and count the number of nonzero singular values:

import tensorflow as tf

EPS = 1e-6
a = tf.ones((4, 4, 2, 2), tf.float32)
s = tf.linalg.svd(a, full_matrices=False, compute_uv=False)
r = tf.math.count_nonzero(tf.abs(s) > EPS, axis=-1)
print(r.numpy())
# [[1 1 1 1]
#  [1 1 1 1]
#  [1 1 1 1]
#  [1 1 1 1]]
jdehesa
  • 58,456
  • 7
  • 77
  • 121
  • if you set `a` to be `[[[[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]], [[-2., -2.], [-2., -2.]], [[-3., -3.], [-3., -3.]]], [[[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]], [[-2., -2.], [-2., -2.]]], [[[ 2., 2.], [ 2., 2.]], [[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]], [[-1., -1.], [-1., -1.]]], [[[ 3., 3.], [ 3., 3.]], [[ 2., 2.], [ 2., 2.]], [[ 1., 1.], [ 1., 1.]], [[ 0., 0.], [ 0., 0.]]]]`, you get `r` to have `2`'s on the diagonal whereas it should have been `0`'s. – learner Feb 10 '20 at 13:49
  • @learner Sorry, the comparison with `EPS` was the other way around (you need the number of singular values _larger_ than epsilon). – jdehesa Feb 10 '20 at 14:05
  • can you maybe look at [this](https://stackoverflow.com/questions/60167217/gradient-not-defined-tensorflow) question? It is sort of a follow up question, thanks. – learner Feb 11 '20 at 13:33