如何在不使用 numpy 或 tensorflow 中的任何循环的情况下获取矩阵行?

How to get rows of matrix without using any loops in numpy or tensorflow?

我有一个矩阵,我想读取矩阵的每一行并使用 tf.nn.top_k 找到每一行的前 k 个值。

如何在不使用循环或列表理解的情况下获取矩阵的每一行。我想使用 Tensorflow 或 numpy,我正在考虑应用广播。

如果我将索引放在一个数组中,例如,如果矩阵中有 10 行,我将有:

indices = [0,1,2,3......,9]

然后我就可以申请广播了?

您可以通过多种不同的方式执行此操作。下面的方式使用了numpy的argsort.

import numpy as np

a = np.random.randint(0, 1000, (4, 4))
a

returns

array([[712, 654, 871, 934],
       [639, 587, 216, 952],
       [853, 311, 598, 222],
       [466, 957, 306, 359]])

然后我们可以得到参数的降序并使用它们来提取相应的元素:

o = np.argsort(a)[:, ::-1]
a[np.arange(4)[:, None], o[:, :2]]

returns

array([[934, 871],
       [952, 639],
       [853, 598],
       [957, 466]])

来自 tf.nn.top_k

的文档

Finds values and indices of the k largest entries for the last dimension.

所以,你可以直接将你的张量传递给这个函数,它会从最后一个维度找到 k largest 个元素。无需使用循环。

说(就像这里的另一个答案一样):

a = np.random.randint(0, 1000, (4,4))

那么你可以简单地做:

np.sort(a)[:,-1:-3:-1]

您在其中放置了一个数字,而不是 3 索引,该数字与您想要获得的最高值的数量有关。

编辑: 为了解决您的评论: 首先,我更改为 float 数据类型(以处理 1/3 值):

a = 1000*np.random.random((4,4))

然后我得到索引:

idx = a.argsort().argsort()

将 1/3 分配给前两个值:

a[idx>=2] = 1./3.

并将零分配给休息:

a[idx<2] = 0

瞧瞧。

这是执行此操作的张量流方法。

#+BEGIN_SRC python :results output org drawer
import numpy as np
import tensorflow as tf

mat = np.random.randint(0, 1000, (4, 4))
print(mat)

# All tensorflow from here
tmat = tf.convert_to_tensor(mat)

k = 3

# ki are the indices within each row
kv, ki = tf.nn.top_k(tmat, k)
kmin = tf.reduce_min(kv, axis=1)[:, None]

newmat = tf.where(tmat < kmin, tf.zeros_like(tmat, dtype=tf.float64), tf.ones_like(tmat) / k)

with tf.Session() as sess:
    print(newmat.eval())
#+END_SRC

#+RESULTS:
:RESULTS:
[[ 97 805   0 104]
 [920 340 905  24]
 [439 243 705 161]
 [146 650 542 284]]
[[0.33333333 0.33333333 0.         0.33333333]
 [0.33333333 0.33333333 0.33333333 0.        ]
 [0.33333333 0.33333333 0.33333333 0.        ]
 [0.         0.33333333 0.33333333 0.33333333]]
:END: