如何在不使用 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:
我有一个矩阵,我想读取矩阵的每一行并使用 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: