【问题标题】:Numpy indexing logic regarding axis关于轴的 Numpy 索引逻辑
【发布时间】:2017-02-18 23:04:22
【问题描述】:

当我们有一个numpy 数组,并且想要沿一个轴执行操作时,为什么axis=1 相当于跨 工作,而axis=0 相当于向下工作

如下例所示,创建numpy 数组需要通过 kwarg size 指定维度:

np.random.randint: (low, high=None, size=None, dtype='l')

这是一个元组,例如(形式:size=(number_of_rows, number_of_columns)

>>> import numpy as np

>>> a = np.random.randint(0, 20, (3, 4))

>>> a
array([[16,  7,  4,  7],
       [ 4, 10,  8,  5],
       [ 7,  1, 15,  7]])

>>> np.sum(a, axis=0)
array([27, 18, 27, 19])

>>> np.sum(a, axis=1)
array([34, 27, 30])

>>> a.shape[0]
3

>>> a.shape[1]
4

的求和是通过设置axis=1来执行的,我期望axis=0

这样做有充分的理由吗?每次使用它都会让我感到困惑,直到我习惯了它。为什么它与(在我看来!)索引数组的标准方式相矛盾,就像代码中带有 shape 属性的示例一样?

更新

这里还有一些(令人困惑的?)代码,表明axis=0 适用于一维数组,正如人们所预料的那样。

>>> b
array([1, 2, 3, 2, 3, 4])

>>> np.sum(b, axis=0)
15

>>> np.sum(b, axis=1)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    np.sum(b, axis=1)
  File "/usr/local/lib/python3.6/site-packages/numpy/core/fromnumeric.py", line 1814, in sum
    out=out, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/numpy/core/_methods.py", line 32, in _sum
    return umr_sum(a, axis, dtype, out, keepdims)
ValueError: 'axis' entry is out of bounds

我希望这是默认设置,因为一维数组实际上只能在一个方向上求和。 感谢您在 cmets 中的输入。我认为斯蒂芬关于表现的答案是正确的。是在 numpy 中产生这个小怪癖,成为常态。

【问题讨论】:

  • 几个月前我回答了这个问题。我得查一下。暂时忘记第 v 行的列名。如果a 是1d,a.sum(axis=0) 做什么?使用 2d 时,什么扩展是一致的?用 3d 吗?
  • 这有帮助吗:stackoverflow.com/questions/41733479/…;那里的海报试图在 3d 案例中理解 axis。在某些方面,这比 2d 情况更清楚。 sum(axis=i) 删除 ith 维度,并保留其余部分。

标签: python arrays numpy indexing


【解决方案1】:

您认为 numpy“减少”操作的 axis 参数,即减少维数的操作 - 通常是一维操作是不合逻辑的。您的论点是,给定一个二维数组,“幸存”维度不是指定的维度。很明显,您正在使用短语 summing across

请允许我证明这种批评是站不住脚的。更一致的概念是沿一个轴求和,而不是指定幸存的轴,而是由reduce操作消耗的轴。

要看到这个,想想 3d 或 100d。如果您平均一堆图像,您会得到一个平均图像,因此您正在平均 沿 在此过程中消耗的堆叠轴。根据您的逻辑-您将根据幸存的轴 x 和 y 指定此过程-这显然是被误导的,想想 100d-您必须枚举 99 个幸存轴来描述沿单个轴的单个减少。

如果您对数学感到满意,您也可以轻松地说服自己,积分或求和变量是后来消失的变量。矩阵乘法:求和维度是结果中没有特征的那个 AB = C -> c_jl = sum_k=1^n a_jk b_kl

类似地将形状 (M, N) 视为行数,列数在 2d 中有效,但在其他任何地方都没有。在 3d 中它将变成 number-of-x-y-planes, number-of-x-z-planes, number-of-y-z-planes, 在 100d number-of-x1-x2-x3-...-x99-hyperplanes, number -of-x0-x2-x3-...-x99-hyperplanes, ... 更好地将 (M, N) 视为列长度、行长度。

我可以继续这样下去,但如果到现在你还不相信,那么我看不出有什么能说服你。

【讨论】:

  • 您的观点:“更好地将 (M, N) 视为列长和行长”,以及上面来自@hpaulj 的评论中的链接帮助了我。
  • 另外,我并没有批评任何关于 numpy 的事情,也没有声称它不合逻辑 - 我要求对一些让我感到困惑的事情做出解释,因为它似乎不一致(基于我有限的经验)。
  • @DexterMorgan 完全没问题。也许我误读了你的音调。对于那个很抱歉。希望我的布道不是太说教;-)
  • 我喜欢你关于集成的类比。完美的!我第一次认为我理解了类似 sum 操作的轴逻辑。
【解决方案2】:

数组索引是numpy 中常见的混淆来源。在numpy docs 中有关于这个话题的精彩讨论。

混乱的根源:

首先要了解的是 索引二维数组有两个相互冲突的约定。 矩阵表示法使用第一个索引来指示正在选择的行和 第二个索引来指示选择了哪一列。这是对面的 人们通常认为的图像的几何导向约定 第一个索引表示 x 位置(即列),第二个索引表示 y 位置(即行)。仅这一点就是很多混乱的根源。 面向矩阵的用户和面向图像的用户期望两种不同的东西 关于索引。

答案:

就像 numpy 中的许多其他内容一样,问题的答案是因为:性能

如果这是真的,为什么不选择 最符合您期望的索引顺序?特别是,为什么不定义 按行排序的图像使用图像约定? (这有时被称为 作为 Fortran 约定与 C 约定,因此是“C”和“FORTRAN” numpy 中数组排序的顺序选项。)这样做的缺点是 潜在的性能惩罚。顺序访问数据很常见, 在数组操作中隐式或通过循环遍历 图片。完成后,将以非最佳顺序访问数据。

【讨论】:

  • np.meshgrid` 采用indexing 参数,可让您在ijxy 样式之间进行选择。基本上它只是切换它返回的I,J 元组的顺序。但在我看来,混淆与涉及sum 等函数中的axis 参数的混淆不同。至于性能,在 1000x1000 阵列上,sum(axis=1) 快 1.4 倍(差别不大)。
猜你喜欢
  • 2017-12-28
  • 2014-04-16
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 2015-05-17
  • 2021-07-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多