【问题标题】:Convert the strictly upper triangular part of a matrix into an array in Tensorflow将矩阵的严格上三角部分转换为 Tensorflow 中的数组
【发布时间】:2017-05-21 17:58:10
【问题描述】:

我试图将矩阵的严格上三角部分转换为 Tensorflow 中的数组。这是一个例子:

输入:

[[1, 2, 3],
 [4, 5, 6],
 [7, 8, 9]]

输出:

[2, 3, 6]

我尝试了以下代码,但没有成功(报错):

def upper_triangular_to_array(A):
    mask = tf.matrix_band_part(tf.ones_like(A, dtype=tf.bool), 0, -1)
    return tf.boolean_mask(A, mask)

谢谢!

【问题讨论】:

  • 您收到的错误是什么?

标签: python tensorflow


【解决方案1】:

以下答案与@Cech_Cohomology 的答案密切相关,但在此过程中不使用 Numpy,仅使用 TensorFlow。

import tensorflow as tf

# The matrix has size n-by-n
n = 3

# A is the matrix
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

ones = tf.ones_like(A)
mask_a = tf.matrix_band_part(ones, 0, -1) # Upper triangular matrix of 0s and 1s
mask_b = tf.matrix_band_part(ones, 0, 0)  # Diagonal matrix of 0s and 1s
mask = tf.cast(mask_a - mask_b, dtype=tf.bool) # Make a bool mask

upper_triangular_flat = tf.boolean_mask(A, mask)

sess = tf.Session()
print(sess.run(upper_triangular_flat))

这个输出:

[2 3 6]

这种方法的好处是在运行图的时候不需要给feed_dict

【讨论】:

  • 这是一个很好的答案。但是,如果您想为每个样本或批次执行此操作,您如何实现它以忽略第一个维度?换句话说,给出 [None, N*(N-1)/2] 的形状,其中 N 是原始矩阵的大小(而 N*(N-1)/2 是上层元素的数量)三角形)
【解决方案2】:

我终于想出了如何使用 Tensorflow 做到这一点。

想法是将占位符定义为布尔掩码,然后在运行时使用 numpy 将布尔矩阵传递给布尔掩码。我在下面分享我的代码:

import tensorflow as tf
import numpy as np

# The matrix has size n-by-n
n = 3
# define a boolean mask as a placeholder
mask = tf.placeholder(tf.bool, shape=(n, n))
# A is the matrix
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    npmask = np.triu(np.ones((n, n), dtype=np.bool_), 1)
    A_upper_triangular = tf.boolean_mask(A, mask)
    print(sess.run(A_upper_triangular, feed_dict={mask: npmask}))

我的 Python 版本是 3.6,我的 Tensorflow 版本是 0.12.0rc1。上面代码的输出是

[2, 3, 6]

这个方法可以进一步推广。我们可以使用 numpy 构造任何类型的掩码,然后将掩码传递给 Tensorflow 以提取感兴趣的张量部分。

【讨论】:

    【解决方案3】:

    如果您使用的是 python 2.7,那么对于 NxN 元素数组,您可以使用带有条件的列表推导:

    def upper_triangular_to_array(A):
        N = A.shape[0]
        return np.array([p for i, p in enumerate(A.flatten()) if i > (i / N) * (1 + N)])
    

    此函数要求 A 是一个二维方形 numpy 数组才能返回正确的结果。它还依赖于整数的地板除法,如果您使用 python 3.x,则需要对其进行更正

    【讨论】:

    • OP 想要一个tensorflow 解决方案,你不能使用 numpy
    • 感谢 kiliantics 和 @martianwars。我终于自己想出了一个 Tensorflow 解决方案,并将我的代码贴在上面。
    猜你喜欢
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    相关资源
    最近更新 更多