簡體   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