【问题标题】:Numpy: use reshape or newaxis to add dimensionsNumpy:使用 reshape 或 newaxis 添加维度
【发布时间】:2015-04-07 18:28:24
【问题描述】:

ndarray.reshapenumpy.newaxis 均可用于向数组添加新维度。他们似乎都创建了一个视图,是否有任何理由或优势使用一个而不是另一个?

>>> b
array([ 1.,  1.,  1.,  1.])
>>> c = b.reshape((1,4))
>>> c *= 2
>>> c
array([[ 2.,  2.,  2.,  2.]])
>>> c.shape
(1, 4)
>>> b
array([ 2.,  2.,  2.,  2.])
>>> d = b[np.newaxis,...]
>>> d
array([[ 2.,  2.,  2.,  2.]])
>>> d.shape
(1, 4)
>>> d *= 2
>>> b
array([ 4.,  4.,  4.,  4.])
>>> c
array([[ 4.,  4.,  4.,  4.]])
>>> d
array([[ 4.,  4.,  4.,  4.]])
>>> 

`

【问题讨论】:

  • b.reshape(1,-1) 是方便的快捷方式。

标签: python numpy


【解决方案1】:

使用numpy.newaxis 而不是ndarray.reshape 的一个原因是当您有多个“未知”维度可供操作时。因此,例如,对于以下数组:

>>> arr.shape
(10, 5)

这行得通:

>>> arr[:, np.newaxis, :].shape
(10, 1, 5)

但这不是:

>>> arr.reshape(-1, 1, -1)
...
ValueError: can only specify one unknown dimension

【讨论】:

    【解决方案2】:

    我看不出有太大差异的证据。您可以对非常大的数组进行时间测试。基本上都摆弄形状,可能还有步伐。 __array_interface__ 是访问此信息的好方法。例如:

    In [94]: b.__array_interface__
    Out[94]: 
    {'data': (162400368, False),
     'descr': [('', '<f8')],
     'shape': (5,),
     'strides': None,
     'typestr': '<f8',
     'version': 3}
    
    In [95]: b[None,:].__array_interface__
    Out[95]: 
    {'data': (162400368, False),
     'descr': [('', '<f8')],
     'shape': (1, 5),
     'strides': (0, 8),
     'typestr': '<f8',
     'version': 3}
    
    In [96]: b.reshape(1,5).__array_interface__
    Out[96]: 
    {'data': (162400368, False),
     'descr': [('', '<f8')],
     'shape': (1, 5),
     'strides': None,
     'typestr': '<f8',
     'version': 3}
    

    两者都创建一个视图,使用与原始相同的data 缓冲区。形状相同,但 reshape 不会改变 stridesreshape 允许您指定 order

    .flags 显示C_CONTIGUOUS 标志的差异。

    reshape 可能会更快,因为它所做的更改更少。但无论哪种方式,操作都不应该对较大计算的时间产生太大影响。

    例如大号b

    In [123]: timeit np.outer(b.reshape(1,-1),b)
    1 loops, best of 3: 288 ms per loop
    In [124]: timeit np.outer(b[None,:],b)
    1 loops, best of 3: 287 ms per loop
    

    有趣的观察:b.reshape(1,4).strides -&gt; (32, 8)

    这是我的猜测。 .__array_interface__ 显示底层属性,.strides 更像是一个属性(尽管它可能都隐藏在 C 代码中)。默认基础值为None,当需要计算(或用.strides 显示)时,它会根据形状和项目大小计算它。 32 是到第一行 (4x8) 末端的距离。 np.ones((2,4)).strides 具有相同的 (32,8)(和 None__array_interface__

    另一方面,b[None,:] 正在为广播做准备。广播时,重复使用现有值。这就是(0,8) 中的0 所做的。

    In [147]: b1=np.broadcast_arrays(b,np.zeros((2,1)))[0]
    
    In [148]: b1.shape
    Out[148]: (2, 5000)
    
    In [149]: b1.strides
    Out[149]: (0, 8)
    
    In [150]: b1.__array_interface__
    Out[150]: 
    {'data': (3023336880L, False),
     'descr': [('', '<f8')],
     'shape': (2, 5),
     'strides': (0, 8),
     'typestr': '<f8',
     'version': 3}
    

    b1np.ones((2,5)) 显示相同,但​​只有 5 个项目。

    np.broadcast_arrays/numpy/lib/stride_tricks.py 中的一个函数。它使用来自同一文件的as_strided。这些函数直接使用 shape 和 strides 属性。

    【讨论】:

    • 酷,...__array_interface__。 !!
    • b.reshape(1,4).strides -&gt; (32, 8), b[None,...].strides -&gt;(0, 8)
    • 有趣。我对此添加了一些想法。
    • ...preparing the array for broadcasting 听起来不错。因此,第一个步幅维度/值类型的零强制它在广播期间从头开始。这也可以解释C_CONTIGUOUS 的区别。
    猜你喜欢
    • 2019-01-17
    • 2010-10-31
    • 2017-06-10
    • 2017-06-10
    • 2020-06-24
    • 2017-08-19
    • 2013-06-28
    相关资源
    最近更新 更多