LoginSignup
1
0

More than 1 year has passed since last update.

numpy.lib.stride_tricks.as_stridedの使い方と仕組みを簡単に

Last updated at Posted at 2022-10-02

できること

numpyがサポートするndarrayオブジェクト(配列)をバイト単位で変形できる。reshapeメソッドでは形状の変更のみだが、as_stridedメソッドを使うとより手の込んだ変形ができる。

a = np.arange(10, dtype=np.float64)
b = as_strided(a, (5, 2), (8, 8))
print(a)

->

\begin{pmatrix}
0 & 1 \\
1 & 2 \\
2 & 3 \\
... & ... \\
8 & 9 \\


\end{pmatrix}

ライブラリの使い方

①インポート

import numpy as np
from numpy.lib.stride_tricks import as_strided

②メソッド呼び出し

as_strided(ndarray, shape, strides)

戻り値:ndarrayオブジェクト(※注意)

引数について:
ndarray→変形元のndarrayオブジェクト。例えばnp.arange(100)とか。
shape→変形後の配列の形状。ndarray.reshape()と同様に指定すればよい。例えばshape=(3,3)ならば3行3列のndarrayが返される。
strides→バイト単位でndarrayを見た時に値を参照する間隔。例えばstrides=(8,8)ならば行、列が増えるごとに8バイトずつ変形前の配列の値を読んでいく。

仕組み

例として以下のようなndarray配列を考える。各要素はfloat型とする。

\begin{pmatrix}
0.0 & 1.0 \\
2.0 & 3.0
\end{pmatrix}

この時メモリ上でこの配列は次のように保存される。
0.0,1.0,2.0,3.0
これをバイトに直すと
\x00\x00\x00\x00\x00\x00\x00\x00,\x01\x00\x00\x00\x00\x00\x00\x00,\x02\x00\x00\x00\x00\x00\x00\x00,\x03\x00\x00\x00\x00\x00\x00\x00
float型は8bytesなので8*4=32bytes長となっている。

ではメモリ上のndarrayの要素にアクセスするにはどのようにしているか?
例えば、上の(2,1)要素の2.0にアクセスするならば
2x8 bytes+1x8 bytes=24 bytes目から8bytesを読み込めば良い。
この行と列の要素ごとの間隔をstrides, 1要素のバイト数をitemsizeという。上の例ならばstrides=(8,8)でitemsize=8となる。
この2要素はndarray生成時に設定される情報で、ndarray.itemsize, ndarray.stridesで確認できる。

これを踏まえた上で
as_strided(ndarray, shape, strides)
のstirdes引数が意味するのは
変形後の配列の各要素が参照する変形前の配列のバイト間隔。

例. x = (0.0, 1.0, 2.0, ... , 9.0)とする。
as_strided(x, (3,2), (16,8))とした場合、
変形後の配列の(3,2)要素にはitemsize=8とした時、
16x3 + 2x8 =64バイト目の値、つまり7.0が入る。
(1,2)要素には
16x1 + 2x8 =32バイト目の値、つまり3.0が入る

注意

as_stridedが返すオブジェクトは実際にはndarrayではない。元のndarrayの要素へのポインタ(参照)値をもつだけ。なので、as_stridedが返した配列の要素に代入するような操作を行うと、参照元の変形前配列の要素も同様に変更されてしまう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0