2017-12-02 9 views
1

numpyの配列arr(before, at, after)の形に変形したい場合はaxisarrとします。これをもっと速くするには?i番目の軸の前後に軸を結合する

軸は正規化されている:0 <= axis < arr.ndim

プログラム:

import numpy as np 
def f(arr, axis): 
    shape = arr.shape 
    before = int(np.product(shape[:axis])) 
    at = shape[axis] 
    return arr.reshape(before, at, -1) 

テスト:

a = np.arange(2 * 3 * 4 * 5).reshape(2, 3, 4, 5) 
print(f(a, 2).shape) 

結果:

(6, 4, 5) 
+0

%のはtimeit(F(2).shape)ループ当たり489ナノ秒± 8.14マイクロ秒(平均±標準偏差7回、各100000ループ)あなたは本当にスピードに興味がありますか? ;) – NaN

+0

金曜日の夜です。私は退屈だと思います。 'arr + = np.arange(arr.size、dtype = arr.dtype)'のようなものは同じ意味で少し狂っていますが、多くの人がそれを行います。これはC++の単なるループです... –

+0

reduceatを下から使用するループあたり5.08μs±234ns(平均実行時間は7回、ループ回数は100000回です)ので、より多くの時間を手に入れます; – NaN

答えて

2

shapeはタプルであり、望ましい結果もタプルです。 np.prodまたはその他の配列関数を使用するように配列を変換/変換するには時間がかかります。したがって、普通のPythonコードで同じことができれば、時間を節約することができます。 shapeと例えば

In [309]: shape 
Out[309]: (2, 3, 4, 5) 
In [310]: np.prod(shape) 
Out[310]: 120 
In [311]: functools.reduce(operator.mul,shape) 
Out[311]: 120 

In [312]: timeit np.prod(shape) 
13.6 µs ± 30.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 
In [313]: timeit functools.reduce(operator.mul,shape) 
647 ns ± 12.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 

Pythonのバージョンが著しく高速です。 functoolsoperatorをインポートして、sum(Python3)の倍数を得る必要がありました。

または新規の形状タプル取得する:

In [314]: axis=2 
In [315]: (functools.reduce(operator.mul,shape[:axis]),shape[axis],-1) 
Out[315]: (6, 4, -1) 
In [316]: timeit (functools.reduce(operator.mul,shape[:axis]),shape[axis],-1) 
739 ns ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 

提案reduceatを比較する:

In [318]: tuple(np.multiply.reduceat(shape, (0, axis, axis+1))) 
Out[318]: (6, 4, 5) 
In [319]: timeit tuple(np.multiply.reduceat(shape, (0, axis, axis+1))) 
11.3 µs ± 21.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 
+0

イニシャライザでは、axis = 0で動作します。 '(functools.reduce(operator.mul、shape [:axis]、1)、shape [axis]、 - 1)' https://stackoverflow.com/questions/33945882/reduce-function-doesnt-handle-an-空リスト- –

+0

@hpaulj私もそれを使うかもしれません;-) –

+0

@hamsteronwheelsは依然として左に厄介な1を挿入します。 OTOH、場合によっては望ましいこともある –

1

をあなたの軸がmiddに実際にある場合ルあなたがゼロ番目または最後の軸をたい場合はしかし、特殊なケースにありますnp.multiply.reduceat

shape = (2, 3, 4, 5, 6) 
axis = 2 
np.multiply.reduceat(shape, (0, axis, axis+1)) 
# array([ 6, 4, 30]) 
axis = 3 
np.multiply.reduceat(shape, (0, axis, axis+1)) 
# array([24, 5, 6]) 

を使用することができます。

関連する問題