2

私はできると思います: np.zeros((), dtype=dt).strides、しかし、dtypeが: のような大きな配列型の場合、これは効率的ではないようです('<f8', (200, 100))。numpy で dtype からストライドに直接移行する方法はありますか?

4

2 に答える 2

3

「完全な」配列を作成しなくても、構造化配列内のサブ配列のストライドを実際に取得できます。

ドキュメントによると、構造化配列内のサブ配列は連続していて、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属性を持つフィールドはありますか?

于 2015-09-30T19:40:01.347 に答える
2

私はあなたが配列について話していると思います:

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

配列自体は、1 つの項目で 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')

orのstrideslike 属性が見当たりません。に基づいてを計算する関数があるかもしれませんが、おそらく隠されています。モジュールを検索できます。そこで発見です。dtdt[0]numpystridesshapenp.lib.stride_tricksas_strided

(200,100)形状から、float648 バイトを取得すると、通常の (既定の) 歩幅は(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)

訂正、フィールドのストライドは、アレイ全体のストライドとフィールドのストライドの組み合わせです。multifield 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) と連結されます。

于 2015-09-30T19:13:54.447 に答える