繁体   English   中英

我如何从numpy中的dtype获得进展?

[英]How do I get the strides from a dtype in numpy?

我想我可以做到: np.zeros((), dtype=dt).strides ,但是当dtype是一个大数组类型,例如('<f8', (200, 100)) np.zeros((), dtype=dt).strides ,这似乎并不高效。 有没有办法直接从dtype过渡到numpy中的步幅?

您实际上可以在结构化数组中获得子数组的步幅,而无需创建“完整”数组。

根据文档,结构化数组内的子数组必须连续且C顺序。 注意第一个示例上方的句子:

子数组始终具有C连续的内存布局。

因此,对于没有字段的结构化数组(例如您的示例中的字段),您可以这样做(作为不可读的单行):

import numpy as np

x = np.dtype(('<f8', (200, 100)))

strides = x.base.itemsize * np.r_[1, np.cumprod(x.shape[::-1][:-1])][::-1]

避免代码打高尔夫球:

shape = list(x.shape)

# First, let's make the strides for an array with an itemsize of 1 in C-order
tmp_strides = shape[::-1]
tmp_strides[1:] = list(np.cumprod(tmp_strides[:-1]))
tmp_strides[0] = 1

# Now adjust it for the real itemsize:
tmp_strides = x.base.itemsize * np.array(tmp_strides)

# And convert it to a tuple, reversing it back for proper C-order
strides = tuple(tmp_strides[::-1])

但是,当有多个字段时,这将变得更加复杂。 通常,您需要进行适当的检查。 例如:dtype是否具有shape属性? 它有字段吗? 是否有字段具有shape属性?

我认为您在谈论一个数组:

In [257]: dt=np.dtype([('f0',float, (200,100))])
In [258]: x=np.zeros((),dtype=dt)

数组本身为0d,只有一项。

In [259]: x.strides
Out[259]: ()

该项目的形状和步幅由dtype确定:

In [260]: x['f0'].strides
Out[260]: (800, 8)
In [261]: x['f0'].shape
Out[261]: (200, 100)

但是,构造x与构造具有相同形状的普通float数组有什么不同吗?

In [262]: y=np.zeros((200,100),float)
In [263]: y.strides
Out[263]: (800, 8)

如果不实际构造电位y就无法大步向前。

Ipython whos命令显示xy占用大约相同的空间:

x          ndarray       : 1 elems, type `[('f0', '<f8', (200, 100))]`,
   160000 bytes (156.25 kb)
y          ndarray       200x100: 20000 elems, type `float64`, 
   160000 bytes (156.25 kb)

一个令人困扰的问题是,这样的x['f0']是否具有y所有属性。 您可能阅读了所有属性,但是可能会更改的内容受到限制。


您可以解析dtype:

In [309]: dt=np.dtype([('f0',float, (200,100))])
In [310]: dt.fields
Out[310]: mappingproxy({'f0': (dtype(('<f8', (200, 100))), 0)})
In [311]: dt[0]
Out[311]: dtype(('<f8', (200, 100)))
In [312]: dt[0].shape
Out[312]: (200, 100)
In [324]: dt[0].base
Out[324]: dtype('float64')

我没有看到一个strides一样的属性dtdt[0] 可能有一些numpy函数根据shape计算strides ,但可能已隐藏。 您可以搜索np.lib.stride_tricks模块。 那就是找到as_strided的地方。

根据(200,100)形状,并且float64占用8个字节,可以计算出正常(默认)跨度为(8*100, 8) (200,100) (8*100, 8)

对于没有进一步嵌套的dtype,这似乎起作用:

In [374]: dt[0]
Out[374]: dtype(('<f8', (200, 100)))
In [375]: tuple(np.array(dt[0].shape[1:]+(1,))*dt[0].base.itemsize)
Out[375]: (800, 8)

让我们使用此dtype制作更复杂的数组

In [346]: x=np.zeros((3,1),dtype=dt)
In [347]: x.shape
Out[347]: (3, 1)
In [348]: x.strides
Out[348]: (160000, 160000)

它的步幅取决于形状和项目itemsize 但是场的形状和步幅是4d。 我们可以说它们存在而没有实际访问该领域吗?

In [349]: x['f0'].strides
Out[349]: (160000, 160000, 800, 8)

大步前进:

In [350]: x[0,0]['f0'].strides
Out[350]: (800, 8)

双重嵌套怎么样?

In [390]: dt1=np.dtype([('f0',np.dtype([('f00',int,(3,4))]), (20,10))])
In [391]: z=np.zeros((),dt1)
In [392]: z['f0']['f00'].shape
Out[392]: (20, 10, 3, 4)
In [393]: z['f0']['f00'].strides
Out[393]: (480, 48, 16, 4)
In [399]: (np.cumprod(np.array((10,3,4,1))[::-1])*4)[::-1]
Out[399]: array([480,  48,  16,   4], dtype=int32)

更正后,对于一个字段的跨步是将整个数组的跨步与对该字段的跨步相结合。 可以通过多字段dtype看到

In [430]: dt=np.dtype([('f0',float, (3,4)),('f1',int),('f2',int,(2,))])
In [431]: x=np.zeros((3,2),dt)
In [432]: x.shape
Out[432]: (3, 2)
In [433]: x.strides
Out[433]: (216, 108)
In [434]: x['f0'].shape
Out[434]: (3, 2, 3, 4)
In [435]: x['f0'].strides
Out[435]: (216, 108, 32, 8)

(216,108)整个数组(itemsize为108),与f0字段(32,8) (itemsize 8)的跨越关联。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM