【问题标题】:Why are 0d arrays in Numpy considered scalar?为什么 Numpy 中的 0d 数组被视为标量?
【发布时间】:2019-10-13 11:54:51
【问题描述】:

某种意义上,这已经有an excellent answer

人们不应该想太多。这最终对个人的心理健康和长寿有好处。

心理健康长寿固然不错,但是这个人的自尊心又如何,试图变得聪明却被 numpy 残忍地否认了:

考虑以下我们从一些字节数据开始的地方:

a = np.linspace(0,255,6, dtype=np.uint8)
a
# array([  0,  51, 102, 153, 204, 255], dtype=uint8)

假设我们想要添加一些东西并提升类型,所以它不会环绕。对于标量,这是行不通的:

b = np.uint16(1)

a + b
# array([  1,  52, 103, 154, 205,   0], dtype=uint8)

但是对于数组,它确实:

c = np.ones(1, np.uint16)

a + c
# array([  1,  52, 103, 154, 205, 256], dtype=uint16)

所以我想让我们做一个数组。

b[...]
# array(1, dtype=uint16)
np.isscalar(b[...])
# False

但是,唉:

a + b[...]
# array([  1,  52, 103, 154, 205,   0], dtype=uint8)

为什么这个 0d 数组在这里表现得像一个标量?

【问题讨论】:

  • 实际上np.isscalar(b)b=np.uint(16) 为我返回了True。你用的是什么版本? Numpy 1.15 在这里。
  • np.isscalar(b[...]) 怎么样(确保不要错过省略号)?
  • 这是False...!但是医生说你应该几乎在任何地方都使用ndim
  • np.isscalar(b[...]) 在 Numpy 1.16.3 上为 False,因为 b[...] 确实是一个 numpy 数组。我认为这个答案 (stackoverflow.com/a/42191121/10640534) 会有所帮助。
  • 因为一个0维数组是一个ndarray实例只包含一个数组标量

标签: python numpy scalar type-promotion


【解决方案1】:

https://docs.scipy.org/doc/numpy/reference/ufuncs.html#casting-rules

最后一段:

混合标量数组操作使用一组不同的转换规则,以确保标量不能“向上转换”数组,除非标量属于根本不同类型的数据(即,在数据类型层次结构中的不同层次结构下) ) 比数组。此规则使您可以在代码中使用标量常量(作为 Python 类型,在 ufunc 中对其进行相应解释),而不必担心标量常量的精度是否会导致大(小精度)数组向上转换。

我认为这意味着以下表达式具有相同的效果:

In [56]: np.add(a,1)                                                                 
Out[56]: array([  1,  52, 103, 154, 205,   0], dtype=uint8)
In [57]: np.add(a,np.array(1))                                                       
Out[57]: array([  1,  52, 103, 154, 205,   0], dtype=uint8)

要做到这一点,0d 不能“向上转型”。但是列表的行为类似于一维数组,并且会“向上转换”

In [60]: np.add(a,[1])                                                               
Out[60]: array([  1,  52, 103, 154, 205, 256])
In [61]: np.add(a,np.array([1]))                                                     
Out[61]: array([  1,  52, 103, 154, 205, 256])

https://docs.scipy.org/doc/numpy/reference/arrays.scalars.html

数组标量包括np.uint8(1)

数组标量对象的数组优先级为 NPY_SCALAR_PRIORITY (-1,000,000.0)。

In [67]: np.uint8(1).__array_priority__                                              
Out[67]: -1000000.0
In [68]: np.array(1,'uint8').__array_priority__                                      
Out[68]: 0.0

数组标量具有与数组完全相同的方法。这些方法的默认行为是在内部将标量转换为等效的 0 维数组并调用相应的数组方法。

np.isscalar 会:

        (isinstance(num, generic)
        or type(num) in ScalarType
        or isinstance(num, numbers.Number))

np.isscalar 建议使用np.ndim(x) == 0。这首先检查.ndim 属性(0d 数组就是这种情况),如果失败,则尝试np.asarray(x).ndim。所以从这个意义上说,任何可以做成 0d 数组的东西都可以称为“标量”。这可能过于宽泛,因为字典很重要:npdim({})

【讨论】:

  • 我的全部观点是,根据 numpy 自己的“官方”测试isscalarnp.array(1) 不是标量,因此,从技术上讲,您从文档中引用的内容并不适用。
  • np.array(1),一个 0d 数组,不是 array scalar,通过功能测试或 array scalars 文档。但在计算上它们是相似的,因为数组标量在使用之前被“提升”为 0d 数组。
猜你喜欢
  • 2010-10-20
  • 1970-01-01
  • 2021-11-14
  • 2014-06-27
  • 1970-01-01
  • 2020-07-01
  • 2012-01-13
  • 2019-03-05
  • 2020-08-13
相关资源
最近更新 更多