Tensorflow 更有效地索引矩阵(避免tf.gather)?
给定两个矩阵A和B(维数为nxk)以及A的指数iA=(a1,a2…aM)和B的指数iB=(b1,b2…bM),我需要执行以下操作:Tensorflow 更有效地索引矩阵(避免tf.gather)?,tensorflow,Tensorflow,给定两个矩阵A和B(维数为nxk)以及A的指数iA=(a1,a2…aM)和B的指数iB=(b1,b2…bM),我需要执行以下操作: lp = 0 for a in iA: for b in iB: lp += np.sum(A[a,] * B[b,]) 在张量流中。索引列表有重复,因此我们多次绘制同一行 我当前的实现如下所示: lp = tf.reduce_sum(tf.multiply(tf.gather(A, iA), tf.gather(B, iB)), 1)
lp = 0
for a in iA:
for b in iB:
lp += np.sum(A[a,] * B[b,])
在张量流中。索引列表有重复,因此我们多次绘制同一行
我当前的实现如下所示:
lp = tf.reduce_sum(tf.multiply(tf.gather(A, iA), tf.gather(B, iB)), 1)
但是,梯度的计算速度非常慢(可能是因为我使用的是tf.gather)。可以假设iA是按升序排序的(因此可以重用特定的行a[a,],直到“a”更改为止)。
有更好的方法吗?感谢您的帮助
编辑:A和B是tf。变量在这里,每次迭代都会改变。预计算不是一个选项。但iA和iB是常数,不会改变
编辑:M>>N.K的大小不是一个真正的问题。根据索引的密度,只需预先计算计数数组可能是一个好主意。在努比,那将是
counts = np.zeros_like(A)
np.add.at(counts, iA, 1)
np.add.at(counts, iB, 1)
然后,您可以通过简单地乘以此值并求和来计算索引和:
lp = np.sum(counts * A * B)
但是,如果
iA
和iB
都非常稀疏,这将产生相当大的性能开销。如果iA
或iB
不是固定的,而是每次迭代都会发生变化,则同样适用。根据索引的密度,只需预先计算计数数组就可以了。在努比,那将是
counts = np.zeros_like(A)
np.add.at(counts, iA, 1)
np.add.at(counts, iB, 1)
然后,您可以通过简单地乘以此值并求和来计算索引和:
lp = np.sum(counts * A * B)
但是,如果
iA
和iB
都非常稀疏,这将产生相当大的性能开销。如果iA
或iB
不是固定的,而是每次迭代都会更改,则同样适用。作为对我答案的注释。你能告诉我们你们的尺码吗?也就是说,N,K,M有多大?M>>N。K的大小不是一个真正的问题。作为对我答案的评论。你能告诉我们你们的尺码吗?也就是说,N,K,M有多大?M>>N。K的大小并不是一个真正的问题。只要可以预先计算计数,我的解决方案仍然可以正常工作。这是一个选择吗?嗨。谢谢你的回答,但我想这个问题有点模棱两可。A和B是Tensorflow的tf.变量,在每次传递过程中都会更新,因此lp无法预计算。iA和IB是指数,所以我想答案的第二部分可能没有真正的帮助。预计算计数实际上不是一个选项。谢谢你的时间!非常感谢。此外,iA和iB并不稀少。但是,它们是固定的,在每次迭代期间不会更改。:)只要可以预先计算计数
,我的解决方案仍然可以正常工作。这是一个选择吗?嗨。谢谢你的回答,但我想这个问题有点模棱两可。A和B是Tensorflow的tf.变量,在每次传递过程中都会更新,因此lp无法预计算。iA和IB是指数,所以我想答案的第二部分可能没有真正的帮助。预计算计数实际上不是一个选项。谢谢你的时间!非常感谢。此外,iA和iB并不稀少。但是,它们是固定的,在每次迭代期间不会更改。:)