【问题标题】:How to divide a tensor elements to specific indixes如何将张量元素划分为特定索引
【发布时间】:2020-04-28 16:13:31
【问题描述】:

我有一个这样的张量:

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*5, 6index 0 and 1 的值,所以我将6 除以index0 and 1 的对角线值。

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

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

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    它可以在 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.        ]]
    
    

    【讨论】:

    • 太棒了!更简单
    • @Vlad 非常感谢,我想知道我们也可以使用 scatter_nd 来做到这一点吗?
    • @sariii,绝不是微不足道的。我认为这只会使事情变得过于复杂。
    • 我看到我试图通过scatter_nd 来做,但做不到。您的解决方案看起来简单易懂,再次感谢 :)
    【解决方案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.        ]])
    

    【讨论】:

    • 在解决这个问题时看到 tensorflow 不支持将项目分配给张量切片,真是令人震惊。好吧,numpy 做到了!您知道如何在 tensorflow 中以矢量化方式解决它吗?
    • 不,对 tf 了解不够,我希望你能找到一个有用的 numpy 方法 :) @TirthPatel
    • 当然,这很有帮助,但 TensorFlow 通常是在 GPU 上的深度学习或机器学习模型中执行自动微分的选择。我认为 tensorflow 只能通过在 tensorflow 张量上使用 tensorflow 函数执行的操作来区分。 numpy 操作会破坏自动差异库以执行微分。一旦支持张量切片上的项目分配,很高兴看到 tensorflow 版本。
    • 我自己也很困惑。让我们把它留给一些 tf 老手 :)
    • 看看我的解决方案,伙计们。同样可以应用于 numpy。
    【解决方案3】:

    这是一个张量流版本。

    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)
    

    【讨论】:

    • 非常感谢您,由于某种原因我不能使用for loop,但感谢您发布解决方案
    • 不客气@sarii。 tf.for 循环适用于 Windows 和 Linux 机器上的 tensorflow 2.x 版本。你用的是什么 tensorflow 版本?
    • 我正在使用tf 14,但原因是我的矩阵会很大。我不想循环导致性能问题
    猜你喜欢
    • 2019-01-13
    • 2021-01-25
    • 1970-01-01
    • 2019-02-06
    • 2017-01-18
    • 2021-01-05
    • 2021-09-14
    • 2021-04-21
    • 2021-05-25
    相关资源
    最近更新 更多