理解Python中的轴

6 投票
3 回答
2786 浏览
提问于 2025-04-18 04:38

我看到有一些代码在使用 numpy.apply_along_axis,每次我都得测试一下这些代码,才能明白它是怎么工作的,因为我还没搞懂 Python 中的 axis 这个概念。

比如,我测试了这个参考中的简单代码。

我发现,在第一个例子中,它是取了矩阵每一行的第一列,而在第二个例子中,整个行被考虑了。

于是我自己做了一个例子,想看看在一个包含多个矩阵的数组中,这个功能是怎么运作的(这也是我想搞清楚 axis 的原因),这个数组也可以看作是一个三维矩阵,每一行就是一个矩阵,对吧?

a = [[[1,2,3],[2,3,4]],[[4,5,6],[9,8,7]]]

import numpy
data = numpy.array([b for b in a])

def my_func(x):
    return (x[0] + x[-1]) * 0.5

b = numpy.apply_along_axis(my_func, 0, data)
b = numpy.apply_along_axis(my_func, 1, data)

这给了我:

array([[ 2.5,  3.5,  4.5],
       [ 5.5,  5.5,  5.5]])

还有:

array([[ 1.5,  2.5,  3.5],
       [ 6.5,  6.5,  6.5]])

对于第一个结果,我得到了我预期的结果。但对于第二个,我本以为会得到:

array([[ 2.,  3.],
       [ 5.,  8.]])

然后我想,也许应该用 axis=2,测试后我得到了之前的结果。所以,我在想这个功能是怎么运作的,才能正确使用它。

谢谢。

3 个回答

1

也许检查一下你数组的形状可以帮助你搞清楚哪个轴是什么;

print data.shape

>> (2,2,3)

这意味着调用

numpy.apply_along_axis(my_func, 2, data)

确实应该得到一个2x2的矩阵,也就是

array([[ 2.,  3.],
      [ 5.,  8.]])

因为第三个轴(索引为2)的长度是3,而其他两个轴的长度都是2。

2

假设有一个形状为 (2,2,3)数组。可以看到,轴 0轴 1轴 2 分别有 2、2 和 3 个数据值。

这些就是数组中元素的索引。

[
    [
        [(0,0,0) (0,0,1), (0,0,2)],
        [(0,1,0) (0,1,1), (0,1,2)]
    ],
    [
        [(1,0,0) (1,0,1), (1,0,2)],
        [(1,1,0) (1,1,1), (1,1,2)]
    ]
]

现在如果你在某个轴上进行操作,那么只改变这个轴上的索引,同时保持其他两个轴的索引不变

举个例子:如果我们在 轴 0 上应用某个操作 F,那么结果中的元素会是

[
    [F((0,0,0),(1,0,0)), F((0,0,1),(1,0,1)), F((0,0,2),(1,0,2))],
    [F((0,1,0),(1,1,0)), F((0,1,1),(1,1,1)), F((0,1,2),(1,1,2))]
]

轴 1 上:

[
    [F((0,0,0),(0,1,0)), F((0,0,1),(0,1,1)), F((0,0,2),(0,1,2))],
    [F((0,1,0),(1,1,0)), F((0,1,1),(1,1,1)), F((0,1,2),(1,1,2))]
]

轴 2 上:

[
    [F((0,0,0),(0,0,1),(0,0,2)), F((0,1,0),(0,1,1),(0,1,2))],
    [F((1,0,0),(1,0,1),(1,0,2)), F((1,1,0),(1,1,1),(1,1,2))]
]

另外,结果数组的形状可以通过在给定数据的形状中省略掉指定的轴来推断出来。

2

首先,data=numpy.array(a) 这行代码就已经足够了,不需要再用 numpy.array([b for b in a])

现在,data 是一个三维的 ndarray,它的形状是 (2,2,3),有三个轴 0, 1, 2。第一个轴的长度是2,第二个轴的长度也是2,第三个轴的长度是3。

因此,numpy.apply_along_axis(my_func, 0, data)numpy.apply_along_axis(my_func, 1, data) 都会得到一个形状为 (2,3) 的二维数组。在这两种情况下,形状都是 (2,3),这对应于剩下的两个轴,分别是第二和第三轴,或者第一和第三轴。

numpy.apply_along_axis(my_func, 2, data) 会返回你展示的 (2,2) 形状的数组,其中 (2,2) 是前两个轴的形状,因为你是沿着第三个轴进行操作的(通过给出索引 2)。

理解这个的方式是,无论你沿哪个轴进行操作,那个轴都会被“压缩”成你 my_func 的形状,在这个例子中,它返回的是一个单一的值。剩下的轴的顺序和形状将保持不变。

另一种理解方式是:apply_along_axis 的意思是对那个轴上的值应用这个函数,针对剩下的轴的每一种组合。获取结果后,再把它们整理回剩下的轴的形状。所以,如果 my_func 返回一个包含4个值的 tuple

def my_func(x):
    return (x[0] + x[-1]) * 2,1,1,1

我们可以预期 numpy.apply_along_axis(my_func, 0, data).shape 会是 (4,2,3)

撰写回答