編集:それはnp.apply_along_axis
のように見えます。例:
import numpy as np
def f(x):
return x * x.sum()
X = np.arange(12).reshape(2, 2, 3)
np.apply_along_axis(f, -1, X)
# array([[[ 0, 3, 6],
# [ 36, 48, 60]],
#
# [[126, 147, 168],
# [270, 300, 330]]])
以下の元の応答のパフォーマンスに関する注意事項が引き続き適用されます。
オリジナルの応答:
そこにはビルトインこのためませんが、Pythonは、このようなコンテキストマネージャを自分で定義することは簡単になります。
import numpy as np
from contextlib import wraps
def row_vectorize(f):
@wraps(f)
def wrapped_f(X):
X = np.asarray(X)
rows = X.reshape(-1, X.shape[-1])
return np.reshape([f(row) for row in rows],
X.shape[:-1] + (-1,))
return wrapped_f
@row_vectorize
def func(row):
return row * row.sum()
今、あなたは、任意の非ゼロ次元の配列にこれを使用することができます:たとえば
>>> X_1D = np.arange(3)
>>> func(X_1D)
array([0, 3, 6])
>>> X_2D = np.arange(6).reshape(2, 3)
>>> func(X_2D)
array([[ 0, 3, 6],
[36, 48, 60]])
>>> X_3D = np.arange(12).reshape((2, 2, 3))
>>> func(X_3D)
array([[[ 0, 3, 6],
[ 36, 48, 60]],
[[126, 147, 168],
[270, 300, 330]]])
は、性能面、np.vectorize
は非常に似た何かをやっています。
配列全体に適用されるカスタム関数のループを高速化する必要がある場合は、numpyの要素ごとの操作と集計操作の点でメソッドを構築することができます。あなたがより複雑な操作を持っている場合は、配列の行全体に適用したいと思います
def func2(X):
return X * X.sum(-1, keepdims=True)
:たとえば、この関数は、上の行ベクトル化機能と同じことを実現しますが、大入力にはるかに高速になりますループのパフォーマンスがボトルネックである場合、最良のオプションはおそらくnumbaまたはcythonを使用することです。
私はちょうど読んでいます: "vectorize関数は、パフォーマンスのためではなく便宜上提供されています。実装は本質的にforループです。"とにかくその機能はそれほど有用ではありません。 – Michael
ベクトル化には "機能にとらわれない"方法がありません。これはパフォーマンスを大幅に向上させます( 'np.vectorize'は文法上の砂糖です)。入力引数として配列を受け入れるために 'fct'を書き換えることも、コンパイルされた実装(例えばCython、numba)に切り替えることもできます。 –
@ ali_mの提案に追加するには、numbaの一般化されたufunc http://numba.pydata.org/numba-doc/dev/user/vectorize.html#the-guvectorize-Decoratorを試してみてください。速度の向上を除けば、それはあなたが望むインテリジェントなブロードキャストを行います。 – DavidW