Numpy中无需循环的多轴argmax
在本文中,我们将介绍使用Numpy在多个轴上无需循环执行argmax的方法。Argmax是返回数组中最大值的索引的函数。有时候需要找到多轴上的最大值,并且想要避免使用循环。这就是本文要解决的问题。
阅读更多:Numpy 教程
问题描述
我们有一个三维数组,每个维度的大小为5,3,4。我们需要找到每个纵向切片的最大元素,并返回其索引。
import numpy as np
np.random.seed(42)
a = np.random.randint(0, 20, (5, 3, 4))
print(a)
打印的数组如下所示:
[[[ 6 19 14 10]
[ 7 6 18 10]
[10 3 7 2]]
[[ 1 11 5 1]
[11 12 8 8]
[14 3 2 13]]
[[ 7 16 4 14]
[18 3 16 17]
[ 8 3 11 2]]
[[ 1 0 7 6]
[14 7 2 15]
[ 6 19 18 7]]
[[ 2 11 1 5]
[19 14 19 12]
[ 7 17 7 13]]]
我们想要得到的是每个纵向切片的最大元素的索引,即得到如下的结果:
array([[1, 0, 0],
[1, 1, 2],
[1, 1, 1],
[1, 2, 1],
[1, 1, 1]])
解决方案
我们可以使用argmax
执行单轴的最大值操作,但是如何在多轴上操作呢?我们可以使用transpose
和reshape
函数改变数组的维度。这里我们需要先确定我们要对哪些轴执行操作。对于当前的问题,我们需要的是对第二个和第三个轴执行操作,并返回一个只有两个轴的数组,每一行表示每个纵向切片的最大元素的索引。
b = a.transpose(1, 2, 0) # 将第二个和第三个轴移动到前面,并将第一个轴移动到最后
print(b.shape) # (3, 4, 5)
上述代码中,我们使用了transpose
函数将第二个和第三个轴移动到前面,并将第一个轴移动到最后。这样我们得到了一个新的数组b
,其形状为(3, 4, 5)
,对应于我们要对第二个和第三个轴执行操作。
现在我们需要将最后一个轴(即原来的第一个轴)移动到第二个位置,这可以通过reshape
函数来实现。
c = b.reshape(b.shape[0], -1)
print(c.shape) # (3, 20)
上述代码中,我们使用了reshape
函数将(3, 4, 5)
的数组b
改变形状为(3, 20)
的数组c
,其中-1
表示自动计算大小。
现在我们可以执行argmax
函数来得到每个纵向切片的最大元素的索引。
idx = c.argmax(axis=1).reshape((b.shape[0], b.shape[1]))
print(idx)
上述代码中,我们使用了argmax
函数在第二个轴上执行操作,并使用reshape
函数将得到的结果改变形状为(3, 4)
,即每行表示每个纵向切片的最大元素的索引。
最后我们需要将得到的结果再次转换为原始数组的形式。我们需要将最后一个轴(即原来的第一个轴)移动回最后,然后对第二个和第三个轴执行transpose
函数。这可以通过以下代码实现:
result = np.zeros((a.shape[1], a.shape[2]), dtype=np.int64)
result[np.arange(a.shape[1])[:, None], np.arange(a.shape[2])] = idx
result = result.transpose()
print(result)
上述代码中,我们首先使用zeros
函数创建一个值全为0、形状为(3, 4)
的数组result
。然后使用np.arange
函数创建一个行向量和一个列向量,这样就可以得到一个二维坐标数组。我们使用这个坐标数组和idx
数组的值来为result
数组赋值。最后,通过对result
数组执行transpose
函数来得到原始数组形式的结果。
完整的代码如下所示:
import numpy as np
np.random.seed(42)
a = np.random.randint(0, 20, (5, 3, 4))
print(a)
b = a.transpose(1, 2, 0)
c = b.reshape(b.shape[0], -1)
idx = c.argmax(axis=1).reshape((b.shape[0], b.shape[1]))
result = np.zeros((a.shape[1], a.shape[2]), dtype=np.int64)
result[np.arange(a.shape[1])[:, None], np.arange(a.shape[2])] = idx
result = result.transpose()
print(result)
总结
本文介绍了如何使用Numpy在多个轴上执行argmax操作,并且不需要使用循环。我们需要使用transpose
和reshape
函数来改变数组的维度。通过这种方式,我们可以获取到我们想要的结果,而且比使用循环更加高效。