![](/img/trans.png)
[英]Given a byte buffer, dtype, shape and strides, how to create Numpy ndarray
[英]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命令顯示x
和y
占用大約相同的空間:
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
一樣的屬性dt
或dt[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.