如何将张量元素划分为特定的索引

时间:2020-04-28 16:13:31

标签: python tensorflow

我有一个这样的张量:

out = [[ 3,  6,  5,  4],
       [ 6,  5, 10, 13],
       [ 5, 10,  6, 22],
       [ 4, 13, 22,  9]]

这是一个对称矩阵。我想要做的是将每个元素除以对角线相同索引中的值。因此,此矩阵中对角线的值为:

index0 = 3
index1 = 5
index2 = 6
index3 = 9

结果将如下所示:

[[3      ,  6/(3*5) ,  5/(3*6) ,  4/(3*9) ]
 [6/(3*5),  5       ,  10/(5*6),  13/(5*9)]
 [5/(3*6),  10/(5*6),  6       ,  22/(6*9)]
 [4/(3*9),  13/(5*9),  22/(6*9),  9       ]]

让我浏览第一行:

3是对角线中的值,因此我们将跳过它

6/3*56index 0 and 1的值,因此我将6除以index0 and 1中的对角线值。

5/3*65是索引0 and 2的值,因此我将其除以索引0 and 2处的对角线值

4/3*94是索引0 and 3的值,因此我将其除以索引0 and 3处的对角线值

3 个答案:

答案 0 :(得分:3)

可以在tensorflow(或numpy)中执行以下操作。

  1. 我们采用原始矩阵,对角线为零。
  2. 我们将结果矩阵除以对角向量。
  3. 我们对2的结果进行转置,然后再将其除以对角矢量。
  4. 我们添加在步骤1中清零的对角线。
import tensorflow as tf

out = [[ 3,  6,  5,  4],
       [ 6,  5, 10, 13],
       [ 5, 10,  6, 22],
       [ 4, 13, 22,  9]]

tensor = tf.constant(out, dtype=tf.float32)

diag_indices = tf.tile(tf.range(tf.shape(tensor)[0])[..., None], [1, 2])
diag = tf.gather_nd(tensor, diag_indices) # [3. 5. 6. 9.]

diag_matrix = tf.linalg.tensor_diag(diag)
zero_diag_matrix = tensor - diag_matrix
res = tf.transpose(zero_diag_matrix / diag) / diag + diag_matrix

with tf.Session() as sess:
    print(res.eval())
# [[3.         0.4        0.27777776 0.14814815]
#  [0.4        5.         0.33333334 0.28888887]
#  [0.27777776 0.3333333  6.         0.4074074 ]
#  [0.14814815 0.28888887 0.4074074  9.        ]]

答案 1 :(得分:2)

使用numpy,您可以执行以下操作:

import numpy as np

out = out.astype(float)
# diagonal elements in out
d = np.copy(np.diagonal(out))
# Indices of lower triangular matriX
tril_ix = np.tril_indices_from(out, k=-1)
# cumulative sum of the diagonal values
# over the first axis on a square matrix
dx = np.cumsum(np.diag(d), 1) 
# replicate ove lower triangular
dx[tril_ix] += np.rot90(dx, k=1)[::-1][tril_ix]
# same but accumulating the diagonal elements
# upwards on the y axis
dy = np.cumsum(np.diag(d)[::-1],0)[::-1]
# replicate ove rlower triangular
dy[tril_ix] += np.rot90(dy, k=1)[::-1][tril_ix]
# mask where to apply the product
m = dy!=0
# perform div and mult
out[m] = out[m]/(dx[m]*dy[m])
np.fill_diagonal(out, d)

print(out)

array([[3.        , 0.4       , 0.27777778, 0.14814815],
       [0.4       , 5.        , 0.33333333, 0.28888889],
       [0.27777778, 0.33333333, 6.        , 0.40740741],
       [0.14814815, 0.28888889, 0.40740741, 9.        ]])

答案 2 :(得分:1)

这是张量流版本。

import tensorflow as tf
import numpy as np

out = tf.Variable([[ 3,  6,  5,  4],
                   [ 6,  5, 10, 13],
                   [ 5, 10,  6, 22],
                   [ 4, 13, 22,  9]], dtype=tf.float32)

# this solution only works for square matrices
assert out.shape[-2] == out.shape[-1]

out_diag = tf.linalg.diag_part(out)
res = tf.Variable(tf.zeros(out.shape, dtype=tf.float32))

for i in tf.range(out.shape[0]):
    _ = res[..., (i+1):, i].assign(out[..., (i+1):, i] / out_diag[..., (i+1):] / out_diag[..., i])
    _ = res[..., i, (i+1):].assign(out[..., i, (i+1):] / out_diag[..., (i+1):] / out_diag[..., i])

print(res)