为啥将张量对象更改为 tf.constant 有效

Posted

技术标签:

【中文标题】为啥将张量对象更改为 tf.constant 有效【英文标题】:why changing the tensor object to tf.constant works为什么将张量对象更改为 tf.constant 有效 【发布时间】:2019-11-01 15:31:49 【问题描述】:

我有两个代码,它们做同样的事情,但输出不同。

这是第一个代码:

import tensorflow as tf
tf.reset_default_graph()
input_tf = tf.Variable([ [9.968594,  8.655439,  0.,        0.       ],
                         [0.,        8.3356,    0.,        8.8974   ],
                         [0.,        0.,        6.103182,  7.330564 ],
                         [6.609862,  0.,        3.0614321, 0.       ],
                         [9.497023,  0.,        3.8914037, 0.       ],
                         [0.,        8.457685,  8.602337,  0.       ],
                         [0.,        0.,        5.826657,  8.283971 ],
                         [0.,        0.,        0.,        0.       ]])
rows_tf = tf.constant (
[[1, 2, 5],
 [1, 2, 5],
 [1, 2, 5],
 [1, 4, 6],
 [1, 4, 6],
 [2, 3, 6],
 [2, 3, 6],
 [2, 4, 7]])
columns_tf = tf.constant(
[[1],
 [2],
 [3],
 [2],
 [3],
 [2],
 [3],
 [2]])
rows_tf = tf.reshape(rows_tf, shape=[-1, 1])
print(rows_tf.shape)
columns_tf = tf.reshape(
    tf.tile(columns_tf, multiples=[1, 3]),
    shape=[-1, 1])
print(columns_tf.shape)
sparse_indices = tf.reshape(
    tf.concat([rows_tf, columns_tf], axis=-1),
    shape=[-1, 2])
print(sparse_indices.shape)
v = tf.gather_nd(input_tf, sparse_indices)
v = tf.reshape(v, [-1, 3])

print(rows_tf.shape) (8,3)
print(columns_tf.shape) (8,1)
print(rows_tf.shape) (24,1)
print(columns_tf.shape) (24,1)

这给了我想要的输出:

[[8.3356    0.        8.457685 ]
 [0.        6.103182  8.602337 ]
 [8.8974    7.330564  0.       ]
 [0.        3.8914037 5.826657 ]
 [8.8974    0.        8.283971 ]
 [6.103182  3.0614321 5.826657 ]
 [7.330564  0.        8.283971 ]
 [6.103182  3.8914037 0.       ]], shape=(8, 3), dtype=float32)

我有另一个代码是计算“rows_tf”和“columns_tf”的过程。 所以,rows_tfcolumns_tf 不是常数,而是其他计算的结果(它们的形状和值相同)。

这是我的代码的第二部分,它没有给出上面的代码:

import tensorflow as tf

tf.enable_eager_execution()
n = 2
tf_a1 = tf.Variable([    [9.968594,  8.655439,  0.,        0.       ],
                         [0.,        8.3356,    0.,        8.8974   ],
                         [0.,        0.,        6.103182,  7.330564 ],
                         [6.609862,  0.,        3.0614321, 0.       ],
                         [9.497023,  0.,        3.8914037, 0.       ],
                         [0.,        8.457685,  8.602337,  0.       ],
                         [0.,        0.,        5.826657,  8.283971 ]])

tf_a2 = tf.constant([[2, 5, 1],
                     [1, 6, 4],
                     [0, 0, 0],
                     [2, 3, 6],
                     [4, 2, 4]])
N, M = tf_a1.shape
input_tf = tf.concat([tf_a1, tf.zeros((1, tf_a1.shape[1]), tf_a1.dtype)], axis=0)

tf_a2 = tf.sort(tf_a2, axis=1)
first_col_change = tf.zeros([tf_a2.shape[0], 1], dtype=tf.int32)
last_cols_change = tf.cast(tf.equal(tf_a2[:, 1:], tf_a2[:, :-1]), tf.int32)
change_bool = tf.concat([first_col_change, last_cols_change], axis=-1)
not_change_bool = 1 - change_bool
tf_a2_changed = tf_a2 * not_change_bool + change_bool * N

# y,x = tf.where(tf.count_nonzero(a1p[a2], axis=1) >= n)
idx = tf.where(tf.count_nonzero(tf.gather(input_tf, tf_a2_changed, axis=0), axis=1) >= n)
x, y = idx[:, 0], idx[:, 1]

rows_tf = tf.gather(tf_a2, y, axis=0)
columns_tf = tf.cast(x[:, None],tf.int32)

out = tf.Variable(tf.zeros_like(input_tf, dtype=tf.int32))

rows_tf = tf.reshape(rows_tf, shape=[-1, 1])

columns_tf = tf.reshape(
    tf.tile(columns_tf, multiples=[1, 3]),
    shape=[-1, 1])
sparse_indices = tf.reshape(
    tf.concat([rows_tf, columns_tf], axis=-1),
    shape=[-1, 2])

v = tf.gather_nd(input_tf, sparse_indices)
v = tf.reshape(v, [-1, 3])
print(v)


  print(rows_tf.shape) (8,3)
  print(columns_tf.shape) (8,1)
  print(rows_tf.shape) (24,1)
  print(columns_tf.shape) (24,1)

在这段代码中

rows_tf = tf.Tensor(
[[1 2 5]
 [1 2 5]
 [1 2 5]
 [1 4 6]
 [1 4 6]
 [2 3 6]
 [2 3 6]
 [2 4 4]], shape=(8, 3), dtype=int32)

columns_tf= tf.Tensor(
[[1]
 [2]
 [3]
 [2]
 [3]
 [2]
 [3]
 [2]], shape=(8, 1), dtype=int32)

所以,我的意思是在第一个代码中,我唯一要做的就是创建一个常量张量,而不是包含生成这些张量的代码。那为什么他们的结果不一样呢?

这是这段代码的输出:

tf.Tensor(
[[0.       9.497023 0.      ]
 [9.968594 9.968594 9.968594]
 [0.       6.609862 0.      ]
 [8.655439 8.655439 8.655439]
 [0.       0.       0.      ]
 [0.       0.       0.      ]
 [7.330564 0.       8.283971]
 [0.       0.       0.      ]], shape=(8, 3), dtype=float32)

为什么会发生这种情况?如果您将第一个代码的rows_tfcolumns_tf 更改为constant tensor,它将给出正确的结果!(我还应该提到第二个代码中的rows_tfcolumns_tf 正是第一个代码中的代码)。在第一个代码中,为了使其可重现,我将张量定义为常量张量。

提前致谢!

【问题讨论】:

您是否打印出rows_tfcolumns_tf 以检查它们在第一个sn-p 中是否实际上相同?因为当我尝试时,它们并不相同。 @ImperishableNight 感谢您的跟进。是的,它们完全相同,我们有两个rows_tfcolumns_tf。第一个rows_tf 是(8,3),它与常数相同,也是`columns_tf' ia (8,1)。请注意,您应该打印出第一个 rows_tf 和 columns_tf,因为它们与第一个 sn-p 上的常量相同。两个 sn-p 都有第二个。 我只能通过将x, y = idx[:, 0], idx[:, 1] 更改为y, x = idx[:, 0], idx[:, 1] 来使它们相同。有问题吗? 当我将 x, y 更改为 y, x 时,我得到了正确的输出(与第一个 sn-p 的输出相同)。 谢谢,我已经用有关第二个代码的一些信息更新了我的问题。以及 rows_tf 和 columns_tf 的形状。所以正确的sn-p在问题中,xy不应该改变,问题的目的是这里的冲突是什么。 【参考方案1】:

问题中的第二个 sn-p 是错误的,它没有为 rows_tfcolumns_tf 提供相同的值。问题是这一行:

x, y = idx[:, 0], idx[:, 1]

应该是:

y, x = idx[:, 0], idx[:, 1]

进行此更正后,sn-p 会给出rows_tfcolumns_tf 的正确值,以及正确的最终答案。

【讨论】:

以上是关于为啥将张量对象更改为 tf.constant 有效的主要内容,如果未能解决你的问题,请参考以下文章

tf.concat 不同长度的张量

TensorFlow之tf.unstack学习循环神经网络中用到!

tf.constant

秩标量矢量矩阵

1-tensorflow2简介及张量

为啥结果打印 b'hello,Python!' ,当我使用张量流? [复制]